xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ucd.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright (C) 2012 Grigori Goronzy <[email protected]>
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  * Permission to use, copy, modify, and/or distribute this software for any
5*2d1272b8SAndroid Build Coastguard Worker  * purpose with or without fee is hereby granted, provided that the above
6*2d1272b8SAndroid Build Coastguard Worker  * copyright notice and this permission notice appear in all copies.
7*2d1272b8SAndroid Build Coastguard Worker  *
8*2d1272b8SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*2d1272b8SAndroid Build Coastguard Worker  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*2d1272b8SAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*2d1272b8SAndroid Build Coastguard Worker  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*2d1272b8SAndroid Build Coastguard Worker  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*2d1272b8SAndroid Build Coastguard Worker  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*2d1272b8SAndroid Build Coastguard Worker  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*2d1272b8SAndroid Build Coastguard Worker  */
16*2d1272b8SAndroid Build Coastguard Worker 
17*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
18*2d1272b8SAndroid Build Coastguard Worker #include "hb-unicode.hh"
19*2d1272b8SAndroid Build Coastguard Worker #include "hb-machinery.hh"
20*2d1272b8SAndroid Build Coastguard Worker 
21*2d1272b8SAndroid Build Coastguard Worker #include "hb-ucd-table.hh"
22*2d1272b8SAndroid Build Coastguard Worker 
23*2d1272b8SAndroid Build Coastguard Worker static hb_unicode_combining_class_t
hb_ucd_combining_class(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode,void * user_data HB_UNUSED)24*2d1272b8SAndroid Build Coastguard Worker hb_ucd_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
25*2d1272b8SAndroid Build Coastguard Worker 			hb_codepoint_t unicode,
26*2d1272b8SAndroid Build Coastguard Worker 			void *user_data HB_UNUSED)
27*2d1272b8SAndroid Build Coastguard Worker {
28*2d1272b8SAndroid Build Coastguard Worker   return (hb_unicode_combining_class_t) _hb_ucd_ccc (unicode);
29*2d1272b8SAndroid Build Coastguard Worker }
30*2d1272b8SAndroid Build Coastguard Worker 
31*2d1272b8SAndroid Build Coastguard Worker static hb_unicode_general_category_t
hb_ucd_general_category(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode,void * user_data HB_UNUSED)32*2d1272b8SAndroid Build Coastguard Worker hb_ucd_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
33*2d1272b8SAndroid Build Coastguard Worker 			 hb_codepoint_t unicode,
34*2d1272b8SAndroid Build Coastguard Worker 			 void *user_data HB_UNUSED)
35*2d1272b8SAndroid Build Coastguard Worker {
36*2d1272b8SAndroid Build Coastguard Worker   return (hb_unicode_general_category_t) _hb_ucd_gc (unicode);
37*2d1272b8SAndroid Build Coastguard Worker }
38*2d1272b8SAndroid Build Coastguard Worker 
39*2d1272b8SAndroid Build Coastguard Worker static hb_codepoint_t
hb_ucd_mirroring(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode,void * user_data HB_UNUSED)40*2d1272b8SAndroid Build Coastguard Worker hb_ucd_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
41*2d1272b8SAndroid Build Coastguard Worker 		  hb_codepoint_t unicode,
42*2d1272b8SAndroid Build Coastguard Worker 		  void *user_data HB_UNUSED)
43*2d1272b8SAndroid Build Coastguard Worker {
44*2d1272b8SAndroid Build Coastguard Worker   return unicode + _hb_ucd_bmg (unicode);
45*2d1272b8SAndroid Build Coastguard Worker }
46*2d1272b8SAndroid Build Coastguard Worker 
47*2d1272b8SAndroid Build Coastguard Worker static hb_script_t
hb_ucd_script(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode,void * user_data HB_UNUSED)48*2d1272b8SAndroid Build Coastguard Worker hb_ucd_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
49*2d1272b8SAndroid Build Coastguard Worker 	       hb_codepoint_t unicode,
50*2d1272b8SAndroid Build Coastguard Worker 	       void *user_data HB_UNUSED)
51*2d1272b8SAndroid Build Coastguard Worker {
52*2d1272b8SAndroid Build Coastguard Worker   return _hb_ucd_sc_map[_hb_ucd_sc (unicode)];
53*2d1272b8SAndroid Build Coastguard Worker }
54*2d1272b8SAndroid Build Coastguard Worker 
55*2d1272b8SAndroid Build Coastguard Worker 
56*2d1272b8SAndroid Build Coastguard Worker #define SBASE 0xAC00u
57*2d1272b8SAndroid Build Coastguard Worker #define LBASE 0x1100u
58*2d1272b8SAndroid Build Coastguard Worker #define VBASE 0x1161u
59*2d1272b8SAndroid Build Coastguard Worker #define TBASE 0x11A7u
60*2d1272b8SAndroid Build Coastguard Worker #define SCOUNT 11172u
61*2d1272b8SAndroid Build Coastguard Worker #define LCOUNT 19u
62*2d1272b8SAndroid Build Coastguard Worker #define VCOUNT 21u
63*2d1272b8SAndroid Build Coastguard Worker #define TCOUNT 28u
64*2d1272b8SAndroid Build Coastguard Worker #define NCOUNT (VCOUNT * TCOUNT)
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker static inline bool
_hb_ucd_decompose_hangul(hb_codepoint_t ab,hb_codepoint_t * a,hb_codepoint_t * b)67*2d1272b8SAndroid Build Coastguard Worker _hb_ucd_decompose_hangul (hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b)
68*2d1272b8SAndroid Build Coastguard Worker {
69*2d1272b8SAndroid Build Coastguard Worker   unsigned si = ab - SBASE;
70*2d1272b8SAndroid Build Coastguard Worker 
71*2d1272b8SAndroid Build Coastguard Worker   if (si >= SCOUNT)
72*2d1272b8SAndroid Build Coastguard Worker     return false;
73*2d1272b8SAndroid Build Coastguard Worker 
74*2d1272b8SAndroid Build Coastguard Worker   if (si % TCOUNT)
75*2d1272b8SAndroid Build Coastguard Worker   {
76*2d1272b8SAndroid Build Coastguard Worker     /* LV,T */
77*2d1272b8SAndroid Build Coastguard Worker     *a = SBASE + (si / TCOUNT) * TCOUNT;
78*2d1272b8SAndroid Build Coastguard Worker     *b = TBASE + (si % TCOUNT);
79*2d1272b8SAndroid Build Coastguard Worker     return true;
80*2d1272b8SAndroid Build Coastguard Worker   } else {
81*2d1272b8SAndroid Build Coastguard Worker     /* L,V */
82*2d1272b8SAndroid Build Coastguard Worker     *a = LBASE + (si / NCOUNT);
83*2d1272b8SAndroid Build Coastguard Worker     *b = VBASE + (si % NCOUNT) / TCOUNT;
84*2d1272b8SAndroid Build Coastguard Worker     return true;
85*2d1272b8SAndroid Build Coastguard Worker   }
86*2d1272b8SAndroid Build Coastguard Worker }
87*2d1272b8SAndroid Build Coastguard Worker 
88*2d1272b8SAndroid Build Coastguard Worker static inline bool
_hb_ucd_compose_hangul(hb_codepoint_t a,hb_codepoint_t b,hb_codepoint_t * ab)89*2d1272b8SAndroid Build Coastguard Worker _hb_ucd_compose_hangul (hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab)
90*2d1272b8SAndroid Build Coastguard Worker {
91*2d1272b8SAndroid Build Coastguard Worker   if (a >= SBASE && a < (SBASE + SCOUNT) && b > TBASE && b < (TBASE + TCOUNT) &&
92*2d1272b8SAndroid Build Coastguard Worker     !((a - SBASE) % TCOUNT))
93*2d1272b8SAndroid Build Coastguard Worker   {
94*2d1272b8SAndroid Build Coastguard Worker     /* LV,T */
95*2d1272b8SAndroid Build Coastguard Worker     *ab = a + (b - TBASE);
96*2d1272b8SAndroid Build Coastguard Worker     return true;
97*2d1272b8SAndroid Build Coastguard Worker   }
98*2d1272b8SAndroid Build Coastguard Worker   else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT))
99*2d1272b8SAndroid Build Coastguard Worker   {
100*2d1272b8SAndroid Build Coastguard Worker     /* L,V */
101*2d1272b8SAndroid Build Coastguard Worker     int li = a - LBASE;
102*2d1272b8SAndroid Build Coastguard Worker     int vi = b - VBASE;
103*2d1272b8SAndroid Build Coastguard Worker     *ab = SBASE + li * NCOUNT + vi * TCOUNT;
104*2d1272b8SAndroid Build Coastguard Worker     return true;
105*2d1272b8SAndroid Build Coastguard Worker   }
106*2d1272b8SAndroid Build Coastguard Worker   else
107*2d1272b8SAndroid Build Coastguard Worker     return false;
108*2d1272b8SAndroid Build Coastguard Worker }
109*2d1272b8SAndroid Build Coastguard Worker 
110*2d1272b8SAndroid Build Coastguard Worker static int
_cmp_pair(const void * _key,const void * _item)111*2d1272b8SAndroid Build Coastguard Worker _cmp_pair (const void *_key, const void *_item)
112*2d1272b8SAndroid Build Coastguard Worker {
113*2d1272b8SAndroid Build Coastguard Worker   uint64_t& a = * (uint64_t*) _key;
114*2d1272b8SAndroid Build Coastguard Worker   uint64_t b = (* (uint64_t*) _item) & HB_CODEPOINT_ENCODE3(0x1FFFFFu, 0x1FFFFFu, 0);
115*2d1272b8SAndroid Build Coastguard Worker 
116*2d1272b8SAndroid Build Coastguard Worker   return a < b ? -1 : a > b ? +1 : 0;
117*2d1272b8SAndroid Build Coastguard Worker }
118*2d1272b8SAndroid Build Coastguard Worker static int
_cmp_pair_11_7_14(const void * _key,const void * _item)119*2d1272b8SAndroid Build Coastguard Worker _cmp_pair_11_7_14 (const void *_key, const void *_item)
120*2d1272b8SAndroid Build Coastguard Worker {
121*2d1272b8SAndroid Build Coastguard Worker   uint32_t& a = * (uint32_t*) _key;
122*2d1272b8SAndroid Build Coastguard Worker   uint32_t b = (* (uint32_t*) _item) & HB_CODEPOINT_ENCODE3_11_7_14(0x1FFFFFu, 0x1FFFFFu, 0);
123*2d1272b8SAndroid Build Coastguard Worker 
124*2d1272b8SAndroid Build Coastguard Worker   return a < b ? -1 : a > b ? +1 : 0;
125*2d1272b8SAndroid Build Coastguard Worker }
126*2d1272b8SAndroid Build Coastguard Worker 
127*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ucd_compose(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t a,hb_codepoint_t b,hb_codepoint_t * ab,void * user_data HB_UNUSED)128*2d1272b8SAndroid Build Coastguard Worker hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
129*2d1272b8SAndroid Build Coastguard Worker 		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
130*2d1272b8SAndroid Build Coastguard Worker 		void *user_data HB_UNUSED)
131*2d1272b8SAndroid Build Coastguard Worker {
132*2d1272b8SAndroid Build Coastguard Worker   // Hangul is handled algorithmically.
133*2d1272b8SAndroid Build Coastguard Worker   if (_hb_ucd_compose_hangul (a, b, ab)) return true;
134*2d1272b8SAndroid Build Coastguard Worker 
135*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t u = 0;
136*2d1272b8SAndroid Build Coastguard Worker 
137*2d1272b8SAndroid Build Coastguard Worker   if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u)
138*2d1272b8SAndroid Build Coastguard Worker   {
139*2d1272b8SAndroid Build Coastguard Worker     /* If "a" is small enough and "b" is in the U+0300 range,
140*2d1272b8SAndroid Build Coastguard Worker      * the composition data is encoded in a 32bit array sorted
141*2d1272b8SAndroid Build Coastguard Worker      * by "a,b" pair. */
142*2d1272b8SAndroid Build Coastguard Worker     uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0);
143*2d1272b8SAndroid Build Coastguard Worker     const uint32_t *v = hb_bsearch (k,
144*2d1272b8SAndroid Build Coastguard Worker 				    _hb_ucd_dm2_u32_map,
145*2d1272b8SAndroid Build Coastguard Worker 				    ARRAY_LENGTH (_hb_ucd_dm2_u32_map),
146*2d1272b8SAndroid Build Coastguard Worker 				    sizeof (*_hb_ucd_dm2_u32_map),
147*2d1272b8SAndroid Build Coastguard Worker 				    _cmp_pair_11_7_14);
148*2d1272b8SAndroid Build Coastguard Worker     if (likely (!v)) return false;
149*2d1272b8SAndroid Build Coastguard Worker     u = HB_CODEPOINT_DECODE3_11_7_14_3 (*v);
150*2d1272b8SAndroid Build Coastguard Worker   }
151*2d1272b8SAndroid Build Coastguard Worker   else
152*2d1272b8SAndroid Build Coastguard Worker   {
153*2d1272b8SAndroid Build Coastguard Worker     /* Otherwise it is stored in a 64bit array sorted by
154*2d1272b8SAndroid Build Coastguard Worker      * "a,b" pair. */
155*2d1272b8SAndroid Build Coastguard Worker     uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
156*2d1272b8SAndroid Build Coastguard Worker     const uint64_t *v = hb_bsearch (k,
157*2d1272b8SAndroid Build Coastguard Worker 				    _hb_ucd_dm2_u64_map,
158*2d1272b8SAndroid Build Coastguard Worker 				    ARRAY_LENGTH (_hb_ucd_dm2_u64_map),
159*2d1272b8SAndroid Build Coastguard Worker 				    sizeof (*_hb_ucd_dm2_u64_map),
160*2d1272b8SAndroid Build Coastguard Worker 				    _cmp_pair);
161*2d1272b8SAndroid Build Coastguard Worker     if (likely (!v)) return false;
162*2d1272b8SAndroid Build Coastguard Worker     u = HB_CODEPOINT_DECODE3_3 (*v);
163*2d1272b8SAndroid Build Coastguard Worker   }
164*2d1272b8SAndroid Build Coastguard Worker 
165*2d1272b8SAndroid Build Coastguard Worker   if (unlikely (!u)) return false;
166*2d1272b8SAndroid Build Coastguard Worker   *ab = u;
167*2d1272b8SAndroid Build Coastguard Worker   return true;
168*2d1272b8SAndroid Build Coastguard Worker }
169*2d1272b8SAndroid Build Coastguard Worker 
170*2d1272b8SAndroid Build Coastguard Worker static hb_bool_t
hb_ucd_decompose(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t ab,hb_codepoint_t * a,hb_codepoint_t * b,void * user_data HB_UNUSED)171*2d1272b8SAndroid Build Coastguard Worker hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
172*2d1272b8SAndroid Build Coastguard Worker 		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
173*2d1272b8SAndroid Build Coastguard Worker 		  void *user_data HB_UNUSED)
174*2d1272b8SAndroid Build Coastguard Worker {
175*2d1272b8SAndroid Build Coastguard Worker   if (_hb_ucd_decompose_hangul (ab, a, b)) return true;
176*2d1272b8SAndroid Build Coastguard Worker 
177*2d1272b8SAndroid Build Coastguard Worker   unsigned i = _hb_ucd_dm (ab);
178*2d1272b8SAndroid Build Coastguard Worker 
179*2d1272b8SAndroid Build Coastguard Worker   /* If no data, there's no decomposition. */
180*2d1272b8SAndroid Build Coastguard Worker   if (likely (!i)) return false;
181*2d1272b8SAndroid Build Coastguard Worker   i--;
182*2d1272b8SAndroid Build Coastguard Worker 
183*2d1272b8SAndroid Build Coastguard Worker   /* Check if it's a single-character decomposition. */
184*2d1272b8SAndroid Build Coastguard Worker   if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map))
185*2d1272b8SAndroid Build Coastguard Worker   {
186*2d1272b8SAndroid Build Coastguard Worker     /* Single-character decompositions currently are only in plane 0 or plane 2. */
187*2d1272b8SAndroid Build Coastguard Worker     if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map))
188*2d1272b8SAndroid Build Coastguard Worker     {
189*2d1272b8SAndroid Build Coastguard Worker       /* Plane 0. */
190*2d1272b8SAndroid Build Coastguard Worker       *a = _hb_ucd_dm1_p0_map[i];
191*2d1272b8SAndroid Build Coastguard Worker     }
192*2d1272b8SAndroid Build Coastguard Worker     else
193*2d1272b8SAndroid Build Coastguard Worker     {
194*2d1272b8SAndroid Build Coastguard Worker       /* Plane 2. */
195*2d1272b8SAndroid Build Coastguard Worker       i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map);
196*2d1272b8SAndroid Build Coastguard Worker       *a = 0x20000 | _hb_ucd_dm1_p2_map[i];
197*2d1272b8SAndroid Build Coastguard Worker     }
198*2d1272b8SAndroid Build Coastguard Worker     *b = 0;
199*2d1272b8SAndroid Build Coastguard Worker     return true;
200*2d1272b8SAndroid Build Coastguard Worker   }
201*2d1272b8SAndroid Build Coastguard Worker   i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map);
202*2d1272b8SAndroid Build Coastguard Worker 
203*2d1272b8SAndroid Build Coastguard Worker   /* Otherwise they are encoded either in a 32bit array or a 64bit array. */
204*2d1272b8SAndroid Build Coastguard Worker   if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map))
205*2d1272b8SAndroid Build Coastguard Worker   {
206*2d1272b8SAndroid Build Coastguard Worker     /* 32bit array. */
207*2d1272b8SAndroid Build Coastguard Worker     uint32_t v = _hb_ucd_dm2_u32_map[i];
208*2d1272b8SAndroid Build Coastguard Worker     *a = HB_CODEPOINT_DECODE3_11_7_14_1 (v);
209*2d1272b8SAndroid Build Coastguard Worker     *b = HB_CODEPOINT_DECODE3_11_7_14_2 (v);
210*2d1272b8SAndroid Build Coastguard Worker     return true;
211*2d1272b8SAndroid Build Coastguard Worker   }
212*2d1272b8SAndroid Build Coastguard Worker   i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map);
213*2d1272b8SAndroid Build Coastguard Worker 
214*2d1272b8SAndroid Build Coastguard Worker   /* 64bit array. */
215*2d1272b8SAndroid Build Coastguard Worker   uint64_t v = _hb_ucd_dm2_u64_map[i];
216*2d1272b8SAndroid Build Coastguard Worker   *a = HB_CODEPOINT_DECODE3_1 (v);
217*2d1272b8SAndroid Build Coastguard Worker   *b = HB_CODEPOINT_DECODE3_2 (v);
218*2d1272b8SAndroid Build Coastguard Worker   return true;
219*2d1272b8SAndroid Build Coastguard Worker }
220*2d1272b8SAndroid Build Coastguard Worker 
221*2d1272b8SAndroid Build Coastguard Worker 
222*2d1272b8SAndroid Build Coastguard Worker static void free_static_ucd_funcs ();
223*2d1272b8SAndroid Build Coastguard Worker 
224*2d1272b8SAndroid Build Coastguard Worker static struct hb_ucd_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucd_unicode_funcs_lazy_loader_t>
225*2d1272b8SAndroid Build Coastguard Worker {
createhb_ucd_unicode_funcs_lazy_loader_t226*2d1272b8SAndroid Build Coastguard Worker   static hb_unicode_funcs_t *create ()
227*2d1272b8SAndroid Build Coastguard Worker   {
228*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
229*2d1272b8SAndroid Build Coastguard Worker 
230*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_set_combining_class_func (funcs, hb_ucd_combining_class, nullptr, nullptr);
231*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_set_general_category_func (funcs, hb_ucd_general_category, nullptr, nullptr);
232*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_set_mirroring_func (funcs, hb_ucd_mirroring, nullptr, nullptr);
233*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_set_script_func (funcs, hb_ucd_script, nullptr, nullptr);
234*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_set_compose_func (funcs, hb_ucd_compose, nullptr, nullptr);
235*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_set_decompose_func (funcs, hb_ucd_decompose, nullptr, nullptr);
236*2d1272b8SAndroid Build Coastguard Worker 
237*2d1272b8SAndroid Build Coastguard Worker     hb_unicode_funcs_make_immutable (funcs);
238*2d1272b8SAndroid Build Coastguard Worker 
239*2d1272b8SAndroid Build Coastguard Worker     hb_atexit (free_static_ucd_funcs);
240*2d1272b8SAndroid Build Coastguard Worker 
241*2d1272b8SAndroid Build Coastguard Worker     return funcs;
242*2d1272b8SAndroid Build Coastguard Worker   }
243*2d1272b8SAndroid Build Coastguard Worker } static_ucd_funcs;
244*2d1272b8SAndroid Build Coastguard Worker 
245*2d1272b8SAndroid Build Coastguard Worker static inline
free_static_ucd_funcs()246*2d1272b8SAndroid Build Coastguard Worker void free_static_ucd_funcs ()
247*2d1272b8SAndroid Build Coastguard Worker {
248*2d1272b8SAndroid Build Coastguard Worker   static_ucd_funcs.free_instance ();
249*2d1272b8SAndroid Build Coastguard Worker }
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker hb_unicode_funcs_t *
hb_ucd_get_unicode_funcs()252*2d1272b8SAndroid Build Coastguard Worker hb_ucd_get_unicode_funcs ()
253*2d1272b8SAndroid Build Coastguard Worker {
254*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_UCD
255*2d1272b8SAndroid Build Coastguard Worker   return hb_unicode_funcs_get_empty ();
256*2d1272b8SAndroid Build Coastguard Worker #endif
257*2d1272b8SAndroid Build Coastguard Worker   return static_ucd_funcs.get_unconst ();
258*2d1272b8SAndroid Build Coastguard Worker }
259