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