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_pair_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 | |
38 | #ifdef HB_USE_ATEXIT |
39 | static void free_static_shapers (void); |
40 | #endif |
41 | |
42 | static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_pair_t, |
43 | hb_shapers_lazy_loader_t> |
44 | { |
45 | static inline hb_shaper_pair_t *create (void) |
46 | { |
47 | char *env = getenv ("HB_SHAPER_LIST" ); |
48 | if (!env || !*env) |
49 | return nullptr; |
50 | |
51 | hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers)); |
52 | if (unlikely (!shapers)) |
53 | return nullptr; |
54 | |
55 | memcpy (shapers, all_shapers, sizeof (all_shapers)); |
56 | |
57 | /* Reorder shaper list to prefer requested shapers. */ |
58 | unsigned int i = 0; |
59 | char *end, *p = env; |
60 | for (;;) |
61 | { |
62 | end = strchr (p, ','); |
63 | if (!end) |
64 | end = p + strlen (p); |
65 | |
66 | for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++) |
67 | if (end - p == (int) strlen (shapers[j].name) && |
68 | 0 == strncmp (shapers[j].name, p, end - p)) |
69 | { |
70 | /* Reorder this shaper to position i */ |
71 | struct hb_shaper_pair_t t = shapers[j]; |
72 | memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i)); |
73 | shapers[i] = t; |
74 | i++; |
75 | } |
76 | |
77 | if (!*end) |
78 | break; |
79 | else |
80 | p = end + 1; |
81 | } |
82 | |
83 | #ifdef HB_USE_ATEXIT |
84 | atexit (free_static_shapers); |
85 | #endif |
86 | |
87 | return shapers; |
88 | } |
89 | static inline void destroy (const hb_shaper_pair_t *p) |
90 | { |
91 | free ((void *) p); |
92 | } |
93 | static inline const hb_shaper_pair_t *get_null (void) |
94 | { |
95 | return all_shapers; |
96 | } |
97 | } static_shapers; |
98 | |
99 | #ifdef HB_USE_ATEXIT |
100 | static |
101 | void free_static_shapers (void) |
102 | { |
103 | static_shapers.free_instance (); |
104 | } |
105 | #endif |
106 | |
107 | const hb_shaper_pair_t * |
108 | _hb_shapers_get (void) |
109 | { |
110 | return static_shapers.get_unconst (); |
111 | } |
112 | |