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