tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-ot-layout.hh (19846B)


      1 /*
      2 * Copyright © 2007,2008,2009  Red Hat, Inc.
      3 * Copyright © 2012,2013  Google, Inc.
      4 *
      5 *  This is part of HarfBuzz, a text shaping library.
      6 *
      7 * Permission is hereby granted, without written agreement and without
      8 * license or royalty fees, to use, copy, modify, and distribute this
      9 * software and its documentation for any purpose, provided that the
     10 * above copyright notice and the following two paragraphs appear in
     11 * all copies of this software.
     12 *
     13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     17 * DAMAGE.
     18 *
     19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     24 *
     25 * Red Hat Author(s): Behdad Esfahbod
     26 * Google Author(s): Behdad Esfahbod
     27 */
     28 
     29 #ifndef HB_OT_LAYOUT_HH
     30 #define HB_OT_LAYOUT_HH
     31 
     32 #include "hb.hh"
     33 
     34 #include "hb-font.hh"
     35 #include "hb-buffer.hh"
     36 #include "hb-open-type.hh"
     37 #include "hb-ot-shape.hh"
     38 #include "hb-set-digest.hh"
     39 
     40 
     41 struct hb_ot_shape_plan_t;
     42 
     43 
     44 /*
     45 * kern
     46 */
     47 
     48 HB_INTERNAL bool
     49 hb_ot_layout_has_kerning (hb_face_t *face);
     50 
     51 HB_INTERNAL bool
     52 hb_ot_layout_has_machine_kerning (hb_face_t *face);
     53 
     54 HB_INTERNAL bool
     55 hb_ot_layout_has_cross_kerning (hb_face_t *face);
     56 
     57 HB_INTERNAL void
     58 hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
     59 	   hb_font_t *font,
     60 	   hb_buffer_t  *buffer);
     61 
     62 
     63 /* Private API corresponding to hb-ot-layout.h: */
     64 
     65 HB_INTERNAL bool
     66 hb_ot_layout_table_find_feature (hb_face_t    *face,
     67 			 hb_tag_t      table_tag,
     68 			 hb_tag_t      feature_tag,
     69 			 unsigned int *feature_index);
     70 
     71 
     72 /*
     73 * GDEF
     74 */
     75 
     76 enum hb_ot_layout_glyph_props_flags_t
     77 {
     78  /* The following three match LookupFlags::Ignore* numbers. */
     79  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH	= 0x02u,
     80  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE	= 0x04u,
     81  HB_OT_LAYOUT_GLYPH_PROPS_MARK		= 0x08u,
     82 
     83  /* The following are used internally; not derived from GDEF. */
     84  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x10u,
     85  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x20u,
     86  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x40u,
     87 
     88  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
     89 				  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
     90 				  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
     91 };
     92 HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
     93 
     94 
     95 /*
     96 * GSUB/GPOS
     97 */
     98 
     99 
    100 /* Should be called before all the substitute_lookup's are done. */
    101 HB_INTERNAL void
    102 hb_ot_layout_substitute_start (hb_font_t    *font,
    103 		       hb_buffer_t  *buffer);
    104 
    105 namespace OT {
    106  struct hb_ot_apply_context_t;
    107  struct hb_ot_layout_lookup_accelerator_t;
    108 namespace Layout {
    109 namespace GSUB_impl {
    110  struct SubstLookup;
    111 }
    112 }
    113 }
    114 
    115 HB_INTERNAL void
    116 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
    117 			const OT::Layout::GSUB_impl::SubstLookup &lookup,
    118 			const OT::hb_ot_layout_lookup_accelerator_t &accel);
    119 
    120 
    121 /* Should be called before all the position_lookup's are done. */
    122 HB_INTERNAL void
    123 hb_ot_layout_position_start (hb_font_t    *font,
    124 		     hb_buffer_t  *buffer);
    125 
    126 /* Should be called after all the position_lookup's are done, to fini advances. */
    127 HB_INTERNAL void
    128 hb_ot_layout_position_finish_advances (hb_font_t    *font,
    129 			       hb_buffer_t  *buffer);
    130 
    131 /* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
    132 HB_INTERNAL void
    133 hb_ot_layout_position_finish_offsets (hb_font_t    *font,
    134 			      hb_buffer_t  *buffer);
    135 
    136 
    137 /*
    138 * Buffer var routines.
    139 */
    140 
    141 /* buffer var allocations, used during the entire shaping process */
    142 #define unicode_props()		var2.u16[0]
    143 
    144 /* buffer var allocations, used during the GSUB/GPOS processing */
    145 #define glyph_props()		var1.u16[0] /* GDEF glyph properties */
    146 #define lig_props()		var1.u8[2] /* GSUB/GPOS ligature tracking */
    147 #define syllable()		var1.u8[3] /* GSUB/GPOS shaping boundaries */
    148 
    149 
    150 /* Loop over syllables. Based on foreach_cluster(). */
    151 #define foreach_syllable(buffer, start, end) \
    152  for (unsigned int \
    153       _count = buffer->len, \
    154       start = 0, end = _count ? _hb_next_syllable (buffer, 0) : 0; \
    155       start < _count; \
    156       start = end, end = _hb_next_syllable (buffer, start))
    157 
    158 static inline unsigned int
    159 _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
    160 {
    161  hb_glyph_info_t *info = buffer->info;
    162  unsigned int count = buffer->len;
    163 
    164  unsigned int syllable = info[start].syllable();
    165  while (++start < count && syllable == info[start].syllable())
    166    ;
    167 
    168  return start;
    169 }
    170 
    171 
    172 /* unicode_props */
    173 
    174 /* Design:
    175 * unicode_props() is a two-byte number.  The low byte includes:
    176 * - Modified General_Category: 5 bits.
    177 * - A bit each for:
    178 *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
    179 *   * Whether it's one of the four Mongolian Free Variation Selectors,
    180 *     CGJ, or other characters that are hidden but should not be ignored
    181 *     like most other Default_Ignorable()s do during GSUB matching.
    182 *   * Whether it's a grapheme continuation.
    183 *
    184 * The high-byte has different meanings, switched by the Gen-Cat:
    185 * - For Mn,Mc,Me: the modified Combining_Class.
    186 * - For Cf: whether it's ZWJ, ZWNJ, or something else.
    187 * - For Ws: index of which space character this is, if space fallback
    188 *   is needed, ie. we don't set this by default, only if asked to.
    189 *
    190 * Above I said "modified" General_Category. This is because we need to
    191 * remember Variation Selectors, and we don't have bits left. So we
    192 * change their Gen_Cat from Mn to Cf, and use a bit of the high byte to
    193 * remember them.
    194 */
    195 
    196 enum hb_unicode_props_flags_t {
    197  UPROPS_MASK_GEN_CAT	= 0x001Fu,
    198  UPROPS_MASK_IGNORABLE	= 0x0020u,
    199  UPROPS_MASK_HIDDEN	= 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters, or CGJ sometimes */
    200  UPROPS_MASK_CONTINUATION=0x0080u,
    201 
    202  /* If GEN_CAT=FORMAT, top byte masks: */
    203  UPROPS_MASK_Cf_ZWJ	= 0x0100u,
    204  UPROPS_MASK_Cf_ZWNJ	= 0x0200u,
    205  UPROPS_MASK_Cf_VS	= 0x0400u,
    206  UPROPS_MASK_Cf_AAT_DELETED	= 0x0800u
    207 };
    208 HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
    209 
    210 static inline void
    211 _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
    212 {
    213  hb_unicode_funcs_t *unicode = buffer->unicode;
    214  unsigned int u = info->codepoint;
    215  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
    216  unsigned int props = gen_cat;
    217 
    218  if (u >= 0x80u)
    219  {
    220    if (unlikely (unicode->is_default_ignorable (u)))
    221    {
    222      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
    223      props |=  UPROPS_MASK_IGNORABLE;
    224      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
    225      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
    226      /* Mongolian Free Variation Selectors need to be remembered
    227       * because although we need to hide them like default-ignorables,
    228       * they need to non-ignorable during shaping.  This is similar to
    229       * what we do for joiners in Indic-like shapers, but since the
    230       * FVSes are GC=Mn, we have use a separate bit to remember them.
    231       * Fixes:
    232       * https://github.com/harfbuzz/harfbuzz/issues/234 */
    233      else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu))) props |= UPROPS_MASK_HIDDEN;
    234      /* TAG characters need similar treatment. Fixes:
    235       * https://github.com/harfbuzz/harfbuzz/issues/463 */
    236      else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
    237      /* COMBINING GRAPHEME JOINER should not be skipped during GSUB either.
    238       * https://github.com/harfbuzz/harfbuzz/issues/554 */
    239      else if (unlikely (u == 0x034Fu))
    240      {
    241 buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
    242 props |= UPROPS_MASK_HIDDEN;
    243      }
    244    }
    245 
    246    if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (gen_cat)))
    247    {
    248      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS;
    249      props |= UPROPS_MASK_CONTINUATION;
    250      props |= unicode->modified_combining_class (u)<<8;
    251    }
    252  }
    253 
    254  info->unicode_props() = props;
    255 }
    256 
    257 static inline void
    258 _hb_glyph_info_set_general_category (hb_glyph_info_t *info,
    259 			     hb_unicode_general_category_t gen_cat)
    260 {
    261  /* Clears top-byte. */
    262  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
    263 }
    264 
    265 static inline hb_unicode_general_category_t
    266 _hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
    267 {
    268  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
    269 }
    270 
    271 static inline bool
    272 _hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
    273 {
    274  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
    275 }
    276 static inline void
    277 _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
    278 				     unsigned int modified_class)
    279 {
    280  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
    281    return;
    282  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
    283 }
    284 static inline unsigned int
    285 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
    286 {
    287  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
    288 }
    289 #define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
    290 
    291 static inline bool
    292 _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
    293 {
    294  return _hb_glyph_info_get_general_category (info) ==
    295  HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
    296 }
    297 static inline void
    298 _hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
    299 {
    300  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
    301    return;
    302  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
    303 }
    304 static inline hb_unicode_funcs_t::space_t
    305 _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
    306 {
    307  return _hb_glyph_info_is_unicode_space (info) ?
    308  (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
    309  hb_unicode_funcs_t::NOT_SPACE;
    310 }
    311 static inline bool
    312 _hb_glyph_info_is_variation_selector (const hb_glyph_info_t *info)
    313 {
    314  return _hb_glyph_info_get_general_category (info) ==
    315  HB_UNICODE_GENERAL_CATEGORY_FORMAT &&
    316  (info->unicode_props() & UPROPS_MASK_Cf_VS);
    317 }
    318 static inline void
    319 _hb_glyph_info_set_variation_selector (hb_glyph_info_t *info, bool customize)
    320 {
    321  if (customize)
    322  {
    323    _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT);
    324    info->unicode_props() |= UPROPS_MASK_Cf_VS;
    325  }
    326  else
    327  {
    328    // Reset to their original condition
    329    _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
    330  }
    331 }
    332 
    333 static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
    334 
    335 static inline bool
    336 _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
    337 {
    338  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
    339  !_hb_glyph_info_substituted (info);
    340 }
    341 static inline void
    342 _hb_glyph_info_set_default_ignorable (hb_glyph_info_t *info)
    343 {
    344  info->unicode_props() |= UPROPS_MASK_IGNORABLE;
    345 }
    346 static inline void
    347 _hb_glyph_info_clear_default_ignorable (hb_glyph_info_t *info)
    348 {
    349  info->unicode_props() &= ~ UPROPS_MASK_IGNORABLE;
    350 }
    351 static inline bool
    352 _hb_glyph_info_is_hidden (const hb_glyph_info_t *info)
    353 {
    354  return info->unicode_props() & UPROPS_MASK_HIDDEN;
    355 }
    356 static inline void
    357 _hb_glyph_info_unhide (hb_glyph_info_t *info)
    358 {
    359  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
    360 }
    361 
    362 static inline void
    363 _hb_glyph_info_set_continuation (hb_glyph_info_t *info, hb_buffer_t *buffer)
    364 {
    365  buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS;
    366  info->unicode_props() |= UPROPS_MASK_CONTINUATION;
    367 }
    368 static inline void
    369 _hb_glyph_info_clear_continuation (hb_glyph_info_t *info)
    370 {
    371  info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
    372 }
    373 static inline bool
    374 _hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
    375 {
    376  return info->unicode_props() & UPROPS_MASK_CONTINUATION;
    377 }
    378 
    379 static inline bool
    380 _hb_grapheme_group_func (const hb_glyph_info_t& a HB_UNUSED,
    381 		 const hb_glyph_info_t& b)
    382 { return _hb_glyph_info_is_continuation (&b); }
    383 
    384 #define foreach_grapheme(buffer, start, end) \
    385 foreach_group (buffer, start, end, _hb_grapheme_group_func)
    386 
    387 static inline void
    388 _hb_ot_layout_reverse_graphemes (hb_buffer_t *buffer)
    389 {
    390  // MONOTONE_GRAPHEMES was already applied and is taken care of by _hb_grapheme_group_func.
    391  // So we just check for MONOTONE_CHARACTERS here.
    392  buffer->reverse_groups (_hb_grapheme_group_func,
    393 		  buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
    394 }
    395 
    396 static inline bool
    397 _hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
    398 {
    399  return _hb_glyph_info_get_general_category (info) ==
    400  HB_UNICODE_GENERAL_CATEGORY_FORMAT;
    401 }
    402 static inline bool
    403 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
    404 {
    405  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
    406 }
    407 static inline bool
    408 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
    409 {
    410  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
    411 }
    412 static inline bool
    413 _hb_glyph_info_is_aat_deleted (const hb_glyph_info_t *info)
    414 {
    415  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_AAT_DELETED);
    416 }
    417 static inline void
    418 _hb_glyph_info_set_aat_deleted (hb_glyph_info_t *info)
    419 {
    420  _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT);
    421  info->unicode_props() |= UPROPS_MASK_Cf_AAT_DELETED;
    422  info->unicode_props() |= UPROPS_MASK_HIDDEN;
    423 }
    424 
    425 /* lig_props: aka lig_id / lig_comp
    426 *
    427 * When a ligature is formed:
    428 *
    429 *   - The ligature glyph and any marks in between all the same newly allocated
    430 *     lig_id,
    431 *   - The ligature glyph will get lig_num_comps set to the number of components
    432 *   - The marks get lig_comp > 0, reflecting which component of the ligature
    433 *     they were applied to.
    434 *   - This is used in GPOS to attach marks to the right component of a ligature
    435 *     in MarkLigPos,
    436 *   - Note that when marks are ligated together, much of the above is skipped
    437 *     and the current lig_id reused.
    438 *
    439 * When a multiple-substitution is done:
    440 *
    441 *   - All resulting glyphs will have lig_id = 0,
    442 *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
    443 *   - This is used in GPOS to attach marks to the first component of a
    444 *     multiple substitution in MarkBasePos.
    445 *
    446 * The numbers are also used in GPOS to do mark-to-mark positioning only
    447 * to marks that belong to the same component of the same ligature.
    448 */
    449 
    450 static inline void
    451 _hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
    452 {
    453  info->lig_props() = 0;
    454 }
    455 
    456 #define IS_LIG_BASE 0x10
    457 
    458 static inline void
    459 _hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
    460 				   unsigned int lig_id,
    461 				   unsigned int lig_num_comps)
    462 {
    463  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
    464 }
    465 
    466 static inline void
    467 _hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
    468 			       unsigned int lig_id,
    469 			       unsigned int lig_comp)
    470 {
    471  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
    472 }
    473 
    474 static inline void
    475 _hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
    476 {
    477  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
    478 }
    479 
    480 static inline unsigned int
    481 _hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
    482 {
    483  return info->lig_props() >> 5;
    484 }
    485 
    486 static inline bool
    487 _hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
    488 {
    489  return info->lig_props() & IS_LIG_BASE;
    490 }
    491 
    492 static inline unsigned int
    493 _hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
    494 {
    495  if (_hb_glyph_info_ligated_internal (info))
    496    return 0;
    497  else
    498    return info->lig_props() & 0x0F;
    499 }
    500 
    501 static inline unsigned int
    502 _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
    503 {
    504  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
    505      _hb_glyph_info_ligated_internal (info))
    506    return info->lig_props() & 0x0F;
    507  else
    508    return 1;
    509 }
    510 
    511 static inline uint8_t
    512 _hb_allocate_lig_id (hb_buffer_t *buffer)
    513 {
    514  uint8_t lig_id = buffer->next_serial () & 0x07;
    515  if (unlikely (!lig_id))
    516    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
    517  return lig_id;
    518 }
    519 
    520 /* glyph_props: */
    521 
    522 static inline void
    523 _hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
    524 {
    525  info->glyph_props() = props;
    526 }
    527 
    528 static inline unsigned int
    529 _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
    530 {
    531  return info->glyph_props();
    532 }
    533 
    534 static inline bool
    535 _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
    536 {
    537  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
    538 }
    539 
    540 static inline bool
    541 _hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
    542 {
    543  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
    544 }
    545 
    546 static inline bool
    547 _hb_glyph_info_is_mark (const hb_glyph_info_t *info)
    548 {
    549  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK;
    550 }
    551 
    552 static inline bool
    553 _hb_glyph_info_substituted (const hb_glyph_info_t *info)
    554 {
    555  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
    556 }
    557 
    558 static inline bool
    559 _hb_glyph_info_ligated (const hb_glyph_info_t *info)
    560 {
    561  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
    562 }
    563 
    564 static inline bool
    565 _hb_glyph_info_multiplied (const hb_glyph_info_t *info)
    566 {
    567  return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
    568 }
    569 
    570 static inline bool
    571 _hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
    572 {
    573  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
    574 }
    575 
    576 static inline void
    577 _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
    578 {
    579  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
    580 		   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
    581 }
    582 
    583 static inline void
    584 _hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
    585 {
    586  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
    587 }
    588 
    589 static inline bool
    590 _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
    591 		      hb_font_t *font HB_UNUSED,
    592 		      hb_buffer_t *buffer)
    593 {
    594  hb_glyph_info_t *info = buffer->info;
    595  unsigned int count = buffer->len;
    596  for (unsigned int i = 0; i < count; i++)
    597    _hb_glyph_info_clear_substituted (&info[i]);
    598  return false;
    599 }
    600 
    601 
    602 /* Allocation / deallocation. */
    603 
    604 static inline void
    605 _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
    606 {
    607  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
    608 }
    609 
    610 static inline void
    611 _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
    612 {
    613  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
    614 }
    615 
    616 static inline void
    617 _hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
    618 {
    619  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
    620 }
    621 
    622 static inline void
    623 _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
    624 {
    625  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
    626  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
    627 }
    628 
    629 static inline void
    630 _hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
    631 {
    632  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
    633  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
    634 }
    635 
    636 static inline void
    637 _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
    638 {
    639  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
    640  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
    641 }
    642 
    643 /* Make sure no one directly touches our props... */
    644 #undef unicode_props
    645 #undef lig_props
    646 #undef glyph_props
    647 
    648 static inline void
    649 _hb_collect_glyph_alternates_add (hb_codepoint_t from,
    650 			  hb_codepoint_t to,
    651 			  hb_map_t *alternate_count,
    652 			  hb_map_t *alternate_glyphs)
    653 {
    654  hb_codepoint_t zero = 0;
    655  hb_codepoint_t *i = &zero;
    656  alternate_count->has (from, &i);
    657  alternate_glyphs->set (from | (*i << 24), to);
    658  alternate_count->set (from, *i + 1);
    659 }
    660 
    661 
    662 #endif /* HB_OT_LAYOUT_HH */