1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  * Copyright © 2011  Codethink Limited
4  * Copyright © 2010,2011,2012  Google, Inc.
5  *
6  *  This is part of HarfBuzz, a text shaping library.
7  *
8  * Permission is hereby granted, without written agreement and without
9  * license or royalty fees, to use, copy, modify, and distribute this
10  * software and its documentation for any purpose, provided that the
11  * above copyright notice and the following two paragraphs appear in
12  * all copies of this software.
13  *
14  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18  * DAMAGE.
19  *
20  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25  *
26  * Red Hat Author(s): Behdad Esfahbod
27  * Codethink Author(s): Ryan Lortie
28  * Google Author(s): Behdad Esfahbod
29  */
30 
31 #include "hb-private.hh"
32 
33 #include "hb-unicode-private.hh"
34 
35 
36 
37 /*
38  * hb_unicode_funcs_t
39  */
40 
41 static hb_unicode_combining_class_t
hb_unicode_combining_class_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode HB_UNUSED,void * user_data HB_UNUSED)42 hb_unicode_combining_class_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
43 				hb_codepoint_t      unicode   HB_UNUSED,
44 				void               *user_data HB_UNUSED)
45 {
46   return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
47 }
48 
49 static unsigned int
hb_unicode_eastasian_width_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode HB_UNUSED,void * user_data HB_UNUSED)50 hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
51 				hb_codepoint_t      unicode   HB_UNUSED,
52 				void               *user_data HB_UNUSED)
53 {
54   return 1;
55 }
56 
57 static hb_unicode_general_category_t
hb_unicode_general_category_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode HB_UNUSED,void * user_data HB_UNUSED)58 hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
59 				 hb_codepoint_t      unicode   HB_UNUSED,
60 				 void               *user_data HB_UNUSED)
61 {
62   return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
63 }
64 
65 static hb_codepoint_t
hb_unicode_mirroring_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode HB_UNUSED,void * user_data HB_UNUSED)66 hb_unicode_mirroring_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
67 			  hb_codepoint_t      unicode   HB_UNUSED,
68 			  void               *user_data HB_UNUSED)
69 {
70   return unicode;
71 }
72 
73 static hb_script_t
hb_unicode_script_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t unicode HB_UNUSED,void * user_data HB_UNUSED)74 hb_unicode_script_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
75 		       hb_codepoint_t      unicode   HB_UNUSED,
76 		       void               *user_data HB_UNUSED)
77 {
78   return HB_SCRIPT_UNKNOWN;
79 }
80 
81 static hb_bool_t
hb_unicode_compose_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t a HB_UNUSED,hb_codepoint_t b HB_UNUSED,hb_codepoint_t * ab HB_UNUSED,void * user_data HB_UNUSED)82 hb_unicode_compose_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
83 			hb_codepoint_t      a         HB_UNUSED,
84 			hb_codepoint_t      b         HB_UNUSED,
85 			hb_codepoint_t     *ab        HB_UNUSED,
86 			void               *user_data HB_UNUSED)
87 {
88   return false;
89 }
90 
91 static hb_bool_t
hb_unicode_decompose_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t ab HB_UNUSED,hb_codepoint_t * a HB_UNUSED,hb_codepoint_t * b HB_UNUSED,void * user_data HB_UNUSED)92 hb_unicode_decompose_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
93 			  hb_codepoint_t      ab        HB_UNUSED,
94 			  hb_codepoint_t     *a         HB_UNUSED,
95 			  hb_codepoint_t     *b         HB_UNUSED,
96 			  void               *user_data HB_UNUSED)
97 {
98   return false;
99 }
100 
101 
102 static unsigned int
hb_unicode_decompose_compatibility_nil(hb_unicode_funcs_t * ufuncs HB_UNUSED,hb_codepoint_t u HB_UNUSED,hb_codepoint_t * decomposed HB_UNUSED,void * user_data HB_UNUSED)103 hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs     HB_UNUSED,
104 					hb_codepoint_t      u          HB_UNUSED,
105 					hb_codepoint_t     *decomposed HB_UNUSED,
106 					void               *user_data  HB_UNUSED)
107 {
108   return 0;
109 }
110 
111 
112 #define HB_UNICODE_FUNCS_IMPLEMENT_SET \
113   HB_UNICODE_FUNCS_IMPLEMENT (glib) \
114   HB_UNICODE_FUNCS_IMPLEMENT (icu) \
115   HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \
116   HB_UNICODE_FUNCS_IMPLEMENT (nil) \
117   /* ^--- Add new callbacks before nil */
118 
119 #define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
120 
121 /* Prototype them all */
122 #define HB_UNICODE_FUNCS_IMPLEMENT(set) \
123 extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
124 HB_UNICODE_FUNCS_IMPLEMENT_SET
125 #undef HB_UNICODE_FUNCS_IMPLEMENT
126 
127 
128 hb_unicode_funcs_t *
hb_unicode_funcs_get_default(void)129 hb_unicode_funcs_get_default (void)
130 {
131 #define HB_UNICODE_FUNCS_IMPLEMENT(set) \
132   return hb_##set##_get_unicode_funcs ();
133 
134 #if defined(HAVE_UCDN)
135   HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
136 #elif defined(HAVE_GLIB)
137   HB_UNICODE_FUNCS_IMPLEMENT(glib)
138 #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
139   HB_UNICODE_FUNCS_IMPLEMENT(icu)
140 #else
141 #define HB_UNICODE_FUNCS_NIL 1
142   HB_UNICODE_FUNCS_IMPLEMENT(nil)
143 #endif
144 
145 #undef HB_UNICODE_FUNCS_IMPLEMENT
146 }
147 
148 #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
149 #error "Could not find any Unicode functions implementation, you have to provide your own"
150 #error "Consider building hb-ucdn.c.  If you absolutely want to build without any, check the code."
151 #endif
152 
153 /**
154  * hb_unicode_funcs_create: (Xconstructor)
155  * @parent: (nullable):
156  *
157  *
158  *
159  * Return value: (transfer full):
160  *
161  * Since: 0.9.2
162  **/
163 hb_unicode_funcs_t *
hb_unicode_funcs_create(hb_unicode_funcs_t * parent)164 hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
165 {
166   hb_unicode_funcs_t *ufuncs;
167 
168   if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
169     return hb_unicode_funcs_get_empty ();
170 
171   if (!parent)
172     parent = hb_unicode_funcs_get_empty ();
173 
174   hb_unicode_funcs_make_immutable (parent);
175   ufuncs->parent = hb_unicode_funcs_reference (parent);
176 
177   ufuncs->func = parent->func;
178 
179   /* We can safely copy user_data from parent since we hold a reference
180    * onto it and it's immutable.  We should not copy the destroy notifiers
181    * though. */
182   ufuncs->user_data = parent->user_data;
183 
184   return ufuncs;
185 }
186 
187 
188 const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
189   HB_OBJECT_HEADER_STATIC,
190 
191   nullptr, /* parent */
192   true, /* immutable */
193   {
194 #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
195     HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
196 #undef HB_UNICODE_FUNC_IMPLEMENT
197   }
198 };
199 
200 /**
201  * hb_unicode_funcs_get_empty:
202  *
203  *
204  *
205  * Return value: (transfer full):
206  *
207  * Since: 0.9.2
208  **/
209 hb_unicode_funcs_t *
hb_unicode_funcs_get_empty(void)210 hb_unicode_funcs_get_empty (void)
211 {
212   return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
213 }
214 
215 /**
216  * hb_unicode_funcs_reference: (skip)
217  * @ufuncs: Unicode functions.
218  *
219  *
220  *
221  * Return value: (transfer full):
222  *
223  * Since: 0.9.2
224  **/
225 hb_unicode_funcs_t *
hb_unicode_funcs_reference(hb_unicode_funcs_t * ufuncs)226 hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
227 {
228   return hb_object_reference (ufuncs);
229 }
230 
231 /**
232  * hb_unicode_funcs_destroy: (skip)
233  * @ufuncs: Unicode functions.
234  *
235  *
236  *
237  * Since: 0.9.2
238  **/
239 void
hb_unicode_funcs_destroy(hb_unicode_funcs_t * ufuncs)240 hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
241 {
242   if (!hb_object_destroy (ufuncs)) return;
243 
244 #define HB_UNICODE_FUNC_IMPLEMENT(name) \
245   if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name);
246     HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
247 #undef HB_UNICODE_FUNC_IMPLEMENT
248 
249   hb_unicode_funcs_destroy (ufuncs->parent);
250 
251   free (ufuncs);
252 }
253 
254 /**
255  * hb_unicode_funcs_set_user_data: (skip)
256  * @ufuncs: Unicode functions.
257  * @key:
258  * @data:
259  * @destroy:
260  * @replace:
261  *
262  *
263  *
264  * Return value:
265  *
266  * Since: 0.9.2
267  **/
268 hb_bool_t
hb_unicode_funcs_set_user_data(hb_unicode_funcs_t * ufuncs,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)269 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
270 			        hb_user_data_key_t *key,
271 			        void *              data,
272 			        hb_destroy_func_t   destroy,
273 				hb_bool_t           replace)
274 {
275   return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
276 }
277 
278 /**
279  * hb_unicode_funcs_get_user_data: (skip)
280  * @ufuncs: Unicode functions.
281  * @key:
282  *
283  *
284  *
285  * Return value: (transfer none):
286  *
287  * Since: 0.9.2
288  **/
289 void *
hb_unicode_funcs_get_user_data(hb_unicode_funcs_t * ufuncs,hb_user_data_key_t * key)290 hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
291 			        hb_user_data_key_t *key)
292 {
293   return hb_object_get_user_data (ufuncs, key);
294 }
295 
296 
297 /**
298  * hb_unicode_funcs_make_immutable:
299  * @ufuncs: Unicode functions.
300  *
301  *
302  *
303  * Since: 0.9.2
304  **/
305 void
hb_unicode_funcs_make_immutable(hb_unicode_funcs_t * ufuncs)306 hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
307 {
308   if (unlikely (hb_object_is_inert (ufuncs)))
309     return;
310 
311   ufuncs->immutable = true;
312 }
313 
314 /**
315  * hb_unicode_funcs_is_immutable:
316  * @ufuncs: Unicode functions.
317  *
318  *
319  *
320  * Return value:
321  *
322  * Since: 0.9.2
323  **/
324 hb_bool_t
hb_unicode_funcs_is_immutable(hb_unicode_funcs_t * ufuncs)325 hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
326 {
327   return ufuncs->immutable;
328 }
329 
330 /**
331  * hb_unicode_funcs_get_parent:
332  * @ufuncs: Unicode functions.
333  *
334  *
335  *
336  * Return value:
337  *
338  * Since: 0.9.2
339  **/
340 hb_unicode_funcs_t *
hb_unicode_funcs_get_parent(hb_unicode_funcs_t * ufuncs)341 hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs)
342 {
343   return ufuncs->parent ? ufuncs->parent : hb_unicode_funcs_get_empty ();
344 }
345 
346 
347 #define HB_UNICODE_FUNC_IMPLEMENT(name)						\
348 										\
349 void										\
350 hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t		   *ufuncs,	\
351 				    hb_unicode_##name##_func_t	    func,	\
352 				    void			   *user_data,	\
353 				    hb_destroy_func_t		    destroy)	\
354 {										\
355   if (ufuncs->immutable)							\
356     return;									\
357 										\
358   if (ufuncs->destroy.name)							\
359     ufuncs->destroy.name (ufuncs->user_data.name);				\
360 										\
361   if (func) {									\
362     ufuncs->func.name = func;							\
363     ufuncs->user_data.name = user_data;						\
364     ufuncs->destroy.name = destroy;						\
365   } else {									\
366     ufuncs->func.name = ufuncs->parent->func.name;				\
367     ufuncs->user_data.name = ufuncs->parent->user_data.name;			\
368     ufuncs->destroy.name = nullptr;						\
369   }										\
370 }
371 
372 HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
373 #undef HB_UNICODE_FUNC_IMPLEMENT
374 
375 
376 #define HB_UNICODE_FUNC_IMPLEMENT(return_type, name)				\
377 										\
378 return_type									\
379 hb_unicode_##name (hb_unicode_funcs_t *ufuncs,					\
380 		   hb_codepoint_t      unicode)					\
381 {										\
382   return ufuncs->name (unicode);						\
383 }
384 HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
385 #undef HB_UNICODE_FUNC_IMPLEMENT
386 
387 /**
388  * hb_unicode_compose:
389  * @ufuncs: Unicode functions.
390  * @a:
391  * @b:
392  * @ab: (out):
393  *
394  *
395  *
396  * Return value:
397  *
398  * Since: 0.9.2
399  **/
400 hb_bool_t
hb_unicode_compose(hb_unicode_funcs_t * ufuncs,hb_codepoint_t a,hb_codepoint_t b,hb_codepoint_t * ab)401 hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
402 		    hb_codepoint_t      a,
403 		    hb_codepoint_t      b,
404 		    hb_codepoint_t     *ab)
405 {
406   return ufuncs->compose (a, b, ab);
407 }
408 
409 /**
410  * hb_unicode_decompose:
411  * @ufuncs: Unicode functions.
412  * @ab:
413  * @a: (out):
414  * @b: (out):
415  *
416  *
417  *
418  * Return value:
419  *
420  * Since: 0.9.2
421  **/
422 hb_bool_t
hb_unicode_decompose(hb_unicode_funcs_t * ufuncs,hb_codepoint_t ab,hb_codepoint_t * a,hb_codepoint_t * b)423 hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
424 		      hb_codepoint_t      ab,
425 		      hb_codepoint_t     *a,
426 		      hb_codepoint_t     *b)
427 {
428   return ufuncs->decompose (ab, a, b);
429 }
430 
431 /**
432  * hb_unicode_decompose_compatibility:
433  * @ufuncs: Unicode functions.
434  * @u:
435  * @decomposed: (out):
436  *
437  *
438  *
439  * Return value:
440  *
441  * Since: 0.9.2
442  **/
443 unsigned int
hb_unicode_decompose_compatibility(hb_unicode_funcs_t * ufuncs,hb_codepoint_t u,hb_codepoint_t * decomposed)444 hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
445 				    hb_codepoint_t      u,
446 				    hb_codepoint_t     *decomposed)
447 {
448   return ufuncs->decompose_compatibility (u, decomposed);
449 }
450 
451 
452 /* See hb-unicode-private.hh for details. */
453 const uint8_t
454 _hb_modified_combining_class[256] =
455 {
456   0, /* HB_UNICODE_COMBINING_CLASS_NOT_REORDERED */
457   1, /* HB_UNICODE_COMBINING_CLASS_OVERLAY */
458   2, 3, 4, 5, 6,
459   7, /* HB_UNICODE_COMBINING_CLASS_NUKTA */
460   8, /* HB_UNICODE_COMBINING_CLASS_KANA_VOICING */
461   9, /* HB_UNICODE_COMBINING_CLASS_VIRAMA */
462 
463   /* Hebrew */
464   HB_MODIFIED_COMBINING_CLASS_CCC10,
465   HB_MODIFIED_COMBINING_CLASS_CCC11,
466   HB_MODIFIED_COMBINING_CLASS_CCC12,
467   HB_MODIFIED_COMBINING_CLASS_CCC13,
468   HB_MODIFIED_COMBINING_CLASS_CCC14,
469   HB_MODIFIED_COMBINING_CLASS_CCC15,
470   HB_MODIFIED_COMBINING_CLASS_CCC16,
471   HB_MODIFIED_COMBINING_CLASS_CCC17,
472   HB_MODIFIED_COMBINING_CLASS_CCC18,
473   HB_MODIFIED_COMBINING_CLASS_CCC19,
474   HB_MODIFIED_COMBINING_CLASS_CCC20,
475   HB_MODIFIED_COMBINING_CLASS_CCC21,
476   HB_MODIFIED_COMBINING_CLASS_CCC22,
477   HB_MODIFIED_COMBINING_CLASS_CCC23,
478   HB_MODIFIED_COMBINING_CLASS_CCC24,
479   HB_MODIFIED_COMBINING_CLASS_CCC25,
480   HB_MODIFIED_COMBINING_CLASS_CCC26,
481 
482   /* Arabic */
483   HB_MODIFIED_COMBINING_CLASS_CCC27,
484   HB_MODIFIED_COMBINING_CLASS_CCC28,
485   HB_MODIFIED_COMBINING_CLASS_CCC29,
486   HB_MODIFIED_COMBINING_CLASS_CCC30,
487   HB_MODIFIED_COMBINING_CLASS_CCC31,
488   HB_MODIFIED_COMBINING_CLASS_CCC32,
489   HB_MODIFIED_COMBINING_CLASS_CCC33,
490   HB_MODIFIED_COMBINING_CLASS_CCC34,
491   HB_MODIFIED_COMBINING_CLASS_CCC35,
492 
493   /* Syriac */
494   HB_MODIFIED_COMBINING_CLASS_CCC36,
495 
496   37, 38, 39,
497   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
498   60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
499   80, 81, 82, 83,
500 
501   /* Telugu */
502   HB_MODIFIED_COMBINING_CLASS_CCC84,
503   85, 86, 87, 88, 89, 90,
504   HB_MODIFIED_COMBINING_CLASS_CCC91,
505   92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
506 
507   /* Thai */
508   HB_MODIFIED_COMBINING_CLASS_CCC103,
509   104, 105, 106,
510   HB_MODIFIED_COMBINING_CLASS_CCC107,
511   108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
512 
513   /* Lao */
514   HB_MODIFIED_COMBINING_CLASS_CCC118,
515   119, 120, 121,
516   HB_MODIFIED_COMBINING_CLASS_CCC122,
517   123, 124, 125, 126, 127, 128,
518 
519   /* Tibetan */
520   HB_MODIFIED_COMBINING_CLASS_CCC129,
521   HB_MODIFIED_COMBINING_CLASS_CCC130,
522   131,
523   HB_MODIFIED_COMBINING_CLASS_CCC132,
524   133, 134, 135, 136, 137, 138, 139,
525 
526 
527   140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
528   150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
529   160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
530   170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
531   180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
532   190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
533 
534   200, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT */
535   201,
536   202, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW */
537   203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
538   214, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE */
539   215,
540   216, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT */
541   217,
542   218, /* HB_UNICODE_COMBINING_CLASS_BELOW_LEFT */
543   219,
544   220, /* HB_UNICODE_COMBINING_CLASS_BELOW */
545   221,
546   222, /* HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT */
547   223,
548   224, /* HB_UNICODE_COMBINING_CLASS_LEFT */
549   225,
550   226, /* HB_UNICODE_COMBINING_CLASS_RIGHT */
551   227,
552   228, /* HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT */
553   229,
554   230, /* HB_UNICODE_COMBINING_CLASS_ABOVE */
555   231,
556   232, /* HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT */
557   233, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW */
558   234, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE */
559   235, 236, 237, 238, 239,
560   240, /* HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT */
561   241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
562   255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
563 };
564