< prev index next >

src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.hh

Print this page




   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_PRIVATE_HH
  30 #define HB_OT_LAYOUT_PRIVATE_HH
  31 
  32 #include "hb-private.hh"
  33 
  34 #include "hb-font-private.hh"
  35 #include "hb-buffer-private.hh"
  36 #include "hb-set-digest-private.hh"
  37 #include "hb-open-type-private.hh"























  38 
  39 
  40 /* Private API corresponding to hb-ot-layout.h: */
  41 
  42 HB_INTERNAL hb_bool_t
  43 hb_ot_layout_table_find_feature (hb_face_t    *face,
  44                                  hb_tag_t      table_tag,
  45                                  hb_tag_t      feature_tag,
  46                                  unsigned int *feature_index);
  47 
  48 
  49 /*
  50  * GDEF
  51  */
  52 
  53 enum hb_ot_layout_glyph_props_flags_t
  54 {
  55   /* The following three match LookupFlags::Ignore* numbers. */
  56   HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH   = 0x02u,
  57   HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE     = 0x04u,
  58   HB_OT_LAYOUT_GLYPH_PROPS_MARK         = 0x08u,
  59 
  60   /* The following are used internally; not derived from GDEF. */
  61   HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED  = 0x10u,
  62   HB_OT_LAYOUT_GLYPH_PROPS_LIGATED      = 0x20u,
  63   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED   = 0x40u,
  64 
  65   HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
  66                                           HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
  67                                           HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
  68 };
  69 HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
  70 
  71 
  72 /*
  73  * GSUB/GPOS
  74  */
  75 
  76 HB_INTERNAL hb_bool_t
  77 hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
  78                                            unsigned int          lookup_index,
  79                                            const hb_codepoint_t *glyphs,
  80                                            unsigned int          glyphs_length,
  81                                            hb_bool_t             zero_context);
  82 
  83 
  84 /* Should be called before all the substitute_lookup's are done. */
  85 HB_INTERNAL void
  86 hb_ot_layout_substitute_start (hb_font_t    *font,
  87                                hb_buffer_t  *buffer);
  88 
  89 
  90 struct hb_ot_layout_lookup_accelerator_t;

  91 
  92 namespace OT {
  93   struct hb_ot_apply_context_t;
  94   struct SubstLookup;

  95 }
  96 
  97 HB_INTERNAL void
  98 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
  99                                 const OT::SubstLookup &lookup,
 100                                 const hb_ot_layout_lookup_accelerator_t &accel);
 101 
 102 
 103 /* Should be called before all the position_lookup's are done. */
 104 HB_INTERNAL void
 105 hb_ot_layout_position_start (hb_font_t    *font,
 106                              hb_buffer_t  *buffer);
 107 
 108 /* Should be called after all the position_lookup's are done, to fini advances. */
 109 HB_INTERNAL void
 110 hb_ot_layout_position_finish_advances (hb_font_t    *font,
 111                                        hb_buffer_t  *buffer);
 112 
 113 /* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
 114 HB_INTERNAL void
 115 hb_ot_layout_position_finish_offsets (hb_font_t    *font,
 116                                       hb_buffer_t  *buffer);
 117 
 118 
 119 
 120 /*
 121  * hb_ot_layout_t
 122  */
 123 
 124 namespace OT {
 125   struct BASE;
 126   struct COLR;
 127   struct CPAL;
 128   struct GDEF;
 129   struct GSUB;
 130   struct GPOS;
 131   struct MATH;
 132   struct fvar;
 133   struct avar;
 134 }
 135 
 136 namespace AAT {
 137   struct ankr;
 138   struct kerx;
 139   struct morx;
 140   struct trak;
 141 }
 142 
 143 struct hb_ot_layout_lookup_accelerator_t
 144 {
 145   template <typename TLookup>
 146   inline void init (const TLookup &lookup)
 147   {
 148     digest.init ();
 149     lookup.add_coverage (&digest);
 150   }
 151 
 152   inline void fini (void)
 153   {
 154   }
 155 
 156   inline bool may_have (hb_codepoint_t g) const {
 157     return digest.may_have (g);
 158   }
 159 
 160   private:
 161   hb_set_digest_t digest;
 162 };
 163 
 164 struct hb_ot_layout_t
 165 {
 166   hb_blob_t *gdef_blob;
 167   hb_blob_t *gsub_blob;
 168   hb_blob_t *gpos_blob;
 169 
 170   const struct OT::GDEF *gdef;
 171   const struct OT::GSUB *gsub;
 172   const struct OT::GPOS *gpos;
 173 
 174   /* TODO Move the following out of this struct. */
 175   OT::hb_table_lazy_loader_t<struct OT::BASE> base;
 176   OT::hb_table_lazy_loader_t<struct OT::MATH> math;
 177   OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
 178   OT::hb_table_lazy_loader_t<struct OT::avar> avar;
 179 
 180   unsigned int gsub_lookup_count;
 181   unsigned int gpos_lookup_count;
 182 
 183   hb_ot_layout_lookup_accelerator_t *gsub_accels;
 184   hb_ot_layout_lookup_accelerator_t *gpos_accels;
 185 };
 186 
 187 
 188 HB_INTERNAL hb_ot_layout_t *
 189 _hb_ot_layout_create (hb_face_t *face);
 190 
 191 HB_INTERNAL void
 192 _hb_ot_layout_destroy (hb_ot_layout_t *layout);
 193 
 194 
 195 #define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
 196 
 197 
 198 /*
 199  * Buffer var routines.
 200  */
 201 
 202 /* buffer var allocations, used during the entire shaping process */
 203 #define unicode_props()         var2.u16[0]
 204 
 205 /* buffer var allocations, used during the GSUB/GPOS processing */
 206 #define glyph_props()           var1.u16[0] /* GDEF glyph properties */
 207 #define lig_props()             var1.u8[2] /* GSUB/GPOS ligature tracking */
 208 #define syllable()              var1.u8[3] /* GSUB/GPOS shaping boundaries */
 209 
 210 
 211 /* Loop over syllables. Based on foreach_cluster(). */
 212 #define foreach_syllable(buffer, start, end) \
 213   for (unsigned int \
 214        _count = buffer->len, \
 215        start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
 216        start < _count; \
 217        start = end, end = _next_syllable (buffer, start))
 218 
 219 static inline unsigned int
 220 _next_syllable (hb_buffer_t *buffer, unsigned int start)
 221 {
 222   hb_glyph_info_t *info = buffer->info;
 223   unsigned int count = buffer->len;
 224 
 225   unsigned int syllable = info[start].syllable();
 226   while (++start < count && syllable == info[start].syllable())
 227     ;
 228 
 229   return start;
 230 }
 231 
 232 
 233 /* unicode_props */
 234 
 235 /* Design:
 236  * unicode_props() is a two-byte number.  The low byte includes:
 237  * - General_Category: 5 bits.
 238  * - A bit each for:
 239  *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
 240  *   * Whether it's one of the three Mongolian Free Variation Selectors,
 241  *     CGJ, or other characters that are hidden but should not be ignored
 242  *     like most other Default_Ignorable()s do during matching.
 243  *   * One free bit right now.
 244  *
 245  * The high-byte has different meanings, switched by the Gen-Cat:
 246  * - For Mn,Mc,Me: the modified Combining_Class.
 247  * - For Cf: whether it's ZWJ, ZWNJ, or something else.
 248  * - For Ws: index of which space character this is, if space fallback
 249  *   is needed, ie. we don't set this by default, only if asked to.
 250  */
 251 
 252 enum hb_unicode_props_flags_t {
 253   UPROPS_MASK_GEN_CAT   = 0x001Fu,
 254   UPROPS_MASK_IGNORABLE = 0x0020u,
 255   UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3,
 256                                     * or TAG characters */
 257 
 258   /* If GEN_CAT=FORMAT, top byte masks: */
 259   UPROPS_MASK_Cf_ZWJ    = 0x0100u,
 260   UPROPS_MASK_Cf_ZWNJ   = 0x0200u
 261 };
 262 HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
 263 
 264 static inline void
 265 _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
 266 {
 267   hb_unicode_funcs_t *unicode = buffer->unicode;
 268   unsigned int u = info->codepoint;
 269   unsigned int gen_cat = (unsigned int) unicode->general_category (u);
 270   unsigned int props = gen_cat;
 271 
 272   if (u >= 0x80)
 273   {
 274     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;

 275     if (unlikely (unicode->is_default_ignorable (u)))
 276     {
 277       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
 278       props |=  UPROPS_MASK_IGNORABLE;
 279       if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
 280       else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
 281       /* Mongolian Free Variation Selectors need to be remembered
 282        * because although we need to hide them like default-ignorables,
 283        * they need to non-ignorable during shaping.  This is similar to
 284        * what we do for joiners in Indic-like shapers, but since the
 285        * FVSes are GC=Mn, we have use a separate bit to remember them.
 286        * Fixes:
 287        * https://github.com/harfbuzz/harfbuzz/issues/234 */
 288       else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
 289       /* TAG characters need similar treatment. Fixes:
 290        * https://github.com/harfbuzz/harfbuzz/issues/463 */
 291       else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
 292       /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
 293        * https://github.com/harfbuzz/harfbuzz/issues/554 */
 294       else if (unlikely (u == 0x034Fu))
 295       {
 296         buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
 297         props |= UPROPS_MASK_HIDDEN;
 298       }
 299     }
 300     else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
 301     {
 302       /* The above check is just an optimization to let in only things we need further
 303        * processing on. */
 304 
 305       /* Only Mn and Mc can have non-zero ccc:
 306        * https://unicode.org/policies/stability_policy.html#Property_Value
 307        * """
 308        * Canonical_Combining_Class, General_Category
 309        * All characters other than those with General_Category property values
 310        * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
 311        * property value 0.
 312        * 1.1.5+
 313        * """
 314        *
 315        * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
 316        * the "else if".
 317        */
 318       props |= unicode->modified_combining_class (info->codepoint)<<8;
 319 
 320       /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
 321        * behave correctly in non-native directionality.  They originally
 322        * are MODIFIER_SYMBOL.  Fixes:
 323        * https://github.com/harfbuzz/harfbuzz/issues/169
 324        */
 325       if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
 326       {
 327         props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
 328       }
 329     }
 330   }
 331 
 332   info->unicode_props() = props;
 333 }
 334 
 335 static inline void
 336 _hb_glyph_info_set_general_category (hb_glyph_info_t *info,
 337                                      hb_unicode_general_category_t gen_cat)
 338 {
 339   /* Clears top-byte. */
 340   info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
 341 }
 342 
 343 static inline hb_unicode_general_category_t
 344 _hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
 345 {
 346   return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
 347 }
 348 
 349 static inline bool
 350 _hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
 351 {
 352   return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
 353 }
 354 static inline void
 355 _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
 356                                              unsigned int modified_class)
 357 {
 358   if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
 359     return;
 360   info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
 361 }
 362 static inline unsigned int
 363 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
 364 {
 365   return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
 366 }
 367 
 368 
 369 /* Loop over grapheme. Based on foreach_cluster(). */
 370 #define foreach_grapheme(buffer, start, end) \
 371   for (unsigned int \
 372        _count = buffer->len, \
 373        start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
 374        start < _count; \
 375        start = end, end = _next_grapheme (buffer, start))
 376 
 377 static inline unsigned int
 378 _next_grapheme (hb_buffer_t *buffer, unsigned int start)
 379 {
 380   hb_glyph_info_t *info = buffer->info;
 381   unsigned int count = buffer->len;
 382 
 383   while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
 384     ;
 385 
 386   return start;
 387 }
 388 
 389 
 390 #define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
 391 
 392 static inline bool
 393 _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
 394 {
 395   return _hb_glyph_info_get_general_category (info) ==
 396          HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
 397 }
 398 static inline void
 399 _hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
 400 {
 401   if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
 402     return;
 403   info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
 404 }
 405 static inline hb_unicode_funcs_t::space_t
 406 _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
 407 {
 408   return _hb_glyph_info_is_unicode_space (info) ?
 409          (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
 410          hb_unicode_funcs_t::NOT_SPACE;
 411 }
 412 
 413 static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
 414 
 415 static inline hb_bool_t
 416 _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
 417 {
 418   return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
 419          !_hb_glyph_info_ligated (info);
 420 }
 421 static inline hb_bool_t
 422 _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
 423 {
 424   return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
 425           == UPROPS_MASK_IGNORABLE) &&
 426          !_hb_glyph_info_ligated (info);
 427 }
 428 static inline void
 429 _hb_glyph_info_unhide (hb_glyph_info_t *info)
 430 {
 431   info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
 432 }
 433 



































 434 static inline bool
 435 _hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
 436 {
 437   return _hb_glyph_info_get_general_category (info) ==
 438          HB_UNICODE_GENERAL_CATEGORY_FORMAT;
 439 }
 440 static inline hb_bool_t
 441 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
 442 {
 443   return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
 444 }
 445 static inline hb_bool_t
 446 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
 447 {
 448   return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
 449 }
 450 static inline hb_bool_t
 451 _hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
 452 {
 453   return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
 454 }
 455 static inline void
 456 _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
 457 {
 458   if (!_hb_glyph_info_is_unicode_format (info))
 459     return;
 460   info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
 461 }
 462 
 463 /* lig_props: aka lig_id / lig_comp
 464  *
 465  * When a ligature is formed:
 466  *
 467  *   - The ligature glyph and any marks in between all the same newly allocated
 468  *     lig_id,
 469  *   - The ligature glyph will get lig_num_comps set to the number of components
 470  *   - The marks get lig_comp > 0, reflecting which component of the ligature


 657 {
 658   HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
 659   HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
 660   HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
 661 }
 662 
 663 static inline void
 664 _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
 665 {
 666   HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
 667   HB_BUFFER_ASSERT_VAR (buffer, lig_props);
 668   HB_BUFFER_ASSERT_VAR (buffer, syllable);
 669 }
 670 
 671 /* Make sure no one directly touches our props... */
 672 #undef unicode_props0
 673 #undef unicode_props1
 674 #undef lig_props
 675 #undef glyph_props
 676 
 677 #endif /* HB_OT_LAYOUT_PRIVATE_HH */


   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 HB_INTERNAL bool
 100 hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
 101                                            unsigned int          lookup_index,
 102                                            const hb_codepoint_t *glyphs,
 103                                            unsigned int          glyphs_length,
 104                                            bool                  zero_context);
 105 
 106 
 107 /* Should be called before all the substitute_lookup's are done. */
 108 HB_INTERNAL void
 109 hb_ot_layout_substitute_start (hb_font_t    *font,
 110                                hb_buffer_t  *buffer);
 111 
 112 HB_INTERNAL void
 113 hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
 114                                     bool (*filter) (const hb_glyph_info_t *info));
 115 
 116 namespace OT {
 117   struct hb_ot_apply_context_t;
 118   struct SubstLookup;
 119   struct hb_ot_layout_lookup_accelerator_t;
 120 }
 121 
 122 HB_INTERNAL void
 123 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
 124                                 const OT::SubstLookup &lookup,
 125                                 const OT::hb_ot_layout_lookup_accelerator_t &accel);
 126 
 127 
 128 /* Should be called before all the position_lookup's are done. */
 129 HB_INTERNAL void
 130 hb_ot_layout_position_start (hb_font_t    *font,
 131                              hb_buffer_t  *buffer);
 132 
 133 /* Should be called after all the position_lookup's are done, to fini advances. */
 134 HB_INTERNAL void
 135 hb_ot_layout_position_finish_advances (hb_font_t    *font,
 136                                        hb_buffer_t  *buffer);
 137 
 138 /* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
 139 HB_INTERNAL void
 140 hb_ot_layout_position_finish_offsets (hb_font_t    *font,
 141                                       hb_buffer_t  *buffer);
 142 
 143 















































































 144 /*
 145  * Buffer var routines.
 146  */
 147 
 148 /* buffer var allocations, used during the entire shaping process */
 149 #define unicode_props()         var2.u16[0]
 150 
 151 /* buffer var allocations, used during the GSUB/GPOS processing */
 152 #define glyph_props()           var1.u16[0] /* GDEF glyph properties */
 153 #define lig_props()             var1.u8[2] /* GSUB/GPOS ligature tracking */
 154 #define syllable()              var1.u8[3] /* GSUB/GPOS shaping boundaries */
 155 
 156 
 157 /* Loop over syllables. Based on foreach_cluster(). */
 158 #define foreach_syllable(buffer, start, end) \
 159   for (unsigned int \
 160        _count = buffer->len, \
 161        start = 0, end = _count ? _hb_next_syllable (buffer, 0) : 0; \
 162        start < _count; \
 163        start = end, end = _hb_next_syllable (buffer, start))
 164 
 165 static inline unsigned int
 166 _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
 167 {
 168   hb_glyph_info_t *info = buffer->info;
 169   unsigned int count = buffer->len;
 170 
 171   unsigned int syllable = info[start].syllable();
 172   while (++start < count && syllable == info[start].syllable())
 173     ;
 174 
 175   return start;
 176 }
 177 
 178 
 179 /* unicode_props */
 180 
 181 /* Design:
 182  * unicode_props() is a two-byte number.  The low byte includes:
 183  * - General_Category: 5 bits.
 184  * - A bit each for:
 185  *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
 186  *   * Whether it's one of the three Mongolian Free Variation Selectors,
 187  *     CGJ, or other characters that are hidden but should not be ignored
 188  *     like most other Default_Ignorable()s do during matching.
 189  *   * Whether it's a grapheme continuation.
 190  *
 191  * The high-byte has different meanings, switched by the Gen-Cat:
 192  * - For Mn,Mc,Me: the modified Combining_Class.
 193  * - For Cf: whether it's ZWJ, ZWNJ, or something else.
 194  * - For Ws: index of which space character this is, if space fallback
 195  *   is needed, ie. we don't set this by default, only if asked to.
 196  */
 197 
 198 enum hb_unicode_props_flags_t {
 199   UPROPS_MASK_GEN_CAT   = 0x001Fu,
 200   UPROPS_MASK_IGNORABLE = 0x0020u,
 201   UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */
 202   UPROPS_MASK_CONTINUATION=0x0080u,
 203 
 204   /* If GEN_CAT=FORMAT, top byte masks: */
 205   UPROPS_MASK_Cf_ZWJ    = 0x0100u,
 206   UPROPS_MASK_Cf_ZWNJ   = 0x0200u
 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 >= 0x80)
 219   {
 220     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
 221 
 222     if (unlikely (unicode->is_default_ignorable (u)))
 223     {
 224       buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
 225       props |=  UPROPS_MASK_IGNORABLE;
 226       if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
 227       else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
 228       /* Mongolian Free Variation Selectors need to be remembered
 229        * because although we need to hide them like default-ignorables,
 230        * they need to non-ignorable during shaping.  This is similar to
 231        * what we do for joiners in Indic-like shapers, but since the
 232        * FVSes are GC=Mn, we have use a separate bit to remember them.
 233        * Fixes:
 234        * https://github.com/harfbuzz/harfbuzz/issues/234 */
 235       else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
 236       /* TAG characters need similar treatment. Fixes:
 237        * https://github.com/harfbuzz/harfbuzz/issues/463 */
 238       else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
 239       /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
 240        * https://github.com/harfbuzz/harfbuzz/issues/554 */
 241       else if (unlikely (u == 0x034Fu))
 242       {
 243         buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
 244         props |= UPROPS_MASK_HIDDEN;
 245       }
 246     }



















 247 
 248     if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (gen_cat)))





 249     {
 250       props |= UPROPS_MASK_CONTINUATION;
 251       props |= unicode->modified_combining_class (u)<<8;
 252     }
 253   }
 254 
 255   info->unicode_props() = props;
 256 }
 257 
 258 static inline void
 259 _hb_glyph_info_set_general_category (hb_glyph_info_t *info,
 260                                      hb_unicode_general_category_t gen_cat)
 261 {
 262   /* Clears top-byte. */
 263   info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
 264 }
 265 
 266 static inline hb_unicode_general_category_t
 267 _hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
 268 {
 269   return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
 270 }
 271 
 272 static inline bool
 273 _hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
 274 {
 275   return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
 276 }
 277 static inline void
 278 _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
 279                                              unsigned int modified_class)
 280 {
 281   if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
 282     return;
 283   info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
 284 }
 285 static inline unsigned int
 286 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
 287 {
 288   return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
 289 }























 290 #define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
 291 
 292 static inline bool
 293 _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
 294 {
 295   return _hb_glyph_info_get_general_category (info) ==
 296          HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
 297 }
 298 static inline void
 299 _hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
 300 {
 301   if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
 302     return;
 303   info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
 304 }
 305 static inline hb_unicode_funcs_t::space_t
 306 _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
 307 {
 308   return _hb_glyph_info_is_unicode_space (info) ?
 309          (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
 310          hb_unicode_funcs_t::NOT_SPACE;
 311 }
 312 
 313 static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
 314 
 315 static inline bool
 316 _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
 317 {
 318   return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
 319          !_hb_glyph_info_ligated (info);
 320 }
 321 static inline bool
 322 _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
 323 {
 324   return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
 325           == UPROPS_MASK_IGNORABLE) &&
 326          !_hb_glyph_info_ligated (info);
 327 }
 328 static inline void
 329 _hb_glyph_info_unhide (hb_glyph_info_t *info)
 330 {
 331   info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
 332 }
 333 
 334 static inline void
 335 _hb_glyph_info_set_continuation (hb_glyph_info_t *info)
 336 {
 337   info->unicode_props() |= UPROPS_MASK_CONTINUATION;
 338 }
 339 static inline void
 340 _hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
 341 {
 342   info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
 343 }
 344 static inline bool
 345 _hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
 346 {
 347   return info->unicode_props() & UPROPS_MASK_CONTINUATION;
 348 }
 349 /* Loop over grapheme. Based on foreach_cluster(). */
 350 #define foreach_grapheme(buffer, start, end) \
 351   for (unsigned int \
 352        _count = buffer->len, \
 353        start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \
 354        start < _count; \
 355        start = end, end = _hb_next_grapheme (buffer, start))
 356 
 357 static inline unsigned int
 358 _hb_next_grapheme (hb_buffer_t *buffer, unsigned int start)
 359 {
 360   hb_glyph_info_t *info = buffer->info;
 361   unsigned int count = buffer->len;
 362 
 363   while (++start < count && _hb_glyph_info_is_continuation (&info[start]))
 364     ;
 365 
 366   return start;
 367 }
 368 
 369 static inline bool
 370 _hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
 371 {
 372   return _hb_glyph_info_get_general_category (info) ==
 373          HB_UNICODE_GENERAL_CATEGORY_FORMAT;
 374 }
 375 static inline bool
 376 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
 377 {
 378   return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
 379 }
 380 static inline bool
 381 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
 382 {
 383   return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
 384 }
 385 static inline bool
 386 _hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
 387 {
 388   return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
 389 }
 390 static inline void
 391 _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
 392 {
 393   if (!_hb_glyph_info_is_unicode_format (info))
 394     return;
 395   info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
 396 }
 397 
 398 /* lig_props: aka lig_id / lig_comp
 399  *
 400  * When a ligature is formed:
 401  *
 402  *   - The ligature glyph and any marks in between all the same newly allocated
 403  *     lig_id,
 404  *   - The ligature glyph will get lig_num_comps set to the number of components
 405  *   - The marks get lig_comp > 0, reflecting which component of the ligature


 592 {
 593   HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
 594   HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
 595   HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
 596 }
 597 
 598 static inline void
 599 _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
 600 {
 601   HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
 602   HB_BUFFER_ASSERT_VAR (buffer, lig_props);
 603   HB_BUFFER_ASSERT_VAR (buffer, syllable);
 604 }
 605 
 606 /* Make sure no one directly touches our props... */
 607 #undef unicode_props0
 608 #undef unicode_props1
 609 #undef lig_props
 610 #undef glyph_props
 611 
 612 #endif /* HB_OT_LAYOUT_HH */
< prev index next >