1 | /* |
2 | * Copyright © 2012 Google, Inc. |
3 | * |
4 | * This is part of HarfBuzz, a text shaping library. |
5 | * |
6 | * Permission is hereby granted, without written agreement and without |
7 | * license or royalty fees, to use, copy, modify, and distribute this |
8 | * software and its documentation for any purpose, provided that the |
9 | * above copyright notice and the following two paragraphs appear in |
10 | * all copies of this software. |
11 | * |
12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 | * DAMAGE. |
17 | * |
18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 | * |
24 | * Google Author(s): Behdad Esfahbod |
25 | */ |
26 | |
27 | #include "hb.hh" |
28 | #include "hb-shaper.hh" |
29 | #include "hb-machinery.hh" |
30 | |
31 | |
32 | static const hb_shaper_entry_t all_shapers[] = { |
33 | #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape}, |
34 | #include "hb-shaper-list.hh" |
35 | #undef HB_SHAPER_IMPLEMENT |
36 | }; |
37 | #ifndef HB_NO_SHAPER |
38 | static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled." ); |
39 | #endif |
40 | |
41 | #if HB_USE_ATEXIT |
42 | static void free_static_shapers (); |
43 | #endif |
44 | |
45 | static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t, |
46 | hb_shapers_lazy_loader_t> |
47 | { |
48 | static hb_shaper_entry_t *create () |
49 | { |
50 | char *env = getenv ("HB_SHAPER_LIST" ); |
51 | if (!env || !*env) |
52 | return nullptr; |
53 | |
54 | hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) calloc (1, sizeof (all_shapers)); |
55 | if (unlikely (!shapers)) |
56 | return nullptr; |
57 | |
58 | memcpy (shapers, all_shapers, sizeof (all_shapers)); |
59 | |
60 | /* Reorder shaper list to prefer requested shapers. */ |
61 | unsigned int i = 0; |
62 | char *end, *p = env; |
63 | for (;;) |
64 | { |
65 | end = strchr (p, ','); |
66 | if (!end) |
67 | end = p + strlen (p); |
68 | |
69 | for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++) |
70 | if (end - p == (int) strlen (shapers[j].name) && |
71 | 0 == strncmp (shapers[j].name, p, end - p)) |
72 | { |
73 | /* Reorder this shaper to position i */ |
74 | struct hb_shaper_entry_t t = shapers[j]; |
75 | memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i)); |
76 | shapers[i] = t; |
77 | i++; |
78 | } |
79 | |
80 | if (!*end) |
81 | break; |
82 | else |
83 | p = end + 1; |
84 | } |
85 | |
86 | #if HB_USE_ATEXIT |
87 | atexit (free_static_shapers); |
88 | #endif |
89 | |
90 | return shapers; |
91 | } |
92 | static void destroy (const hb_shaper_entry_t *p) { free ((void *) p); } |
93 | static const hb_shaper_entry_t *get_null () { return all_shapers; } |
94 | } static_shapers; |
95 | |
96 | #if HB_USE_ATEXIT |
97 | static |
98 | void free_static_shapers () |
99 | { |
100 | static_shapers.free_instance (); |
101 | } |
102 | #endif |
103 | |
104 | const hb_shaper_entry_t * |
105 | _hb_shapers_get () |
106 | { |
107 | return static_shapers.get_unconst (); |
108 | } |
109 | |