Home | History | Annotate | Download | only in src
      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_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-private.hh"
     37 
     38 
     39 /*
     40  * GDEF
     41  */
     42 
     43 typedef enum
     44 {
     45   /* The following three match LookupFlags::Ignore* numbers. */
     46   HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH	= 0x02u,
     47   HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE	= 0x04u,
     48   HB_OT_LAYOUT_GLYPH_PROPS_MARK		= 0x08u,
     49 
     50   /* The following are used internally; not derived from GDEF. */
     51   HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED	= 0x10u,
     52   HB_OT_LAYOUT_GLYPH_PROPS_LIGATED	= 0x20u,
     53   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED	= 0x40u,
     54 
     55   HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
     56 					  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
     57 					  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
     58 } hb_ot_layout_glyph_class_mask_t;
     59 
     60 
     61 /*
     62  * GSUB/GPOS
     63  */
     64 
     65 HB_INTERNAL hb_bool_t
     66 hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
     67 					   unsigned int          lookup_index,
     68 					   const hb_codepoint_t *glyphs,
     69 					   unsigned int          glyphs_length,
     70 					   hb_bool_t             zero_context);
     71 
     72 
     73 /* Should be called before all the substitute_lookup's are done. */
     74 HB_INTERNAL void
     75 hb_ot_layout_substitute_start (hb_font_t    *font,
     76 			       hb_buffer_t  *buffer);
     77 
     78 
     79 struct hb_ot_layout_lookup_accelerator_t;
     80 
     81 namespace OT {
     82   struct hb_apply_context_t;
     83   struct SubstLookup;
     84 }
     85 
     86 HB_INTERNAL void
     87 hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
     88 				const OT::SubstLookup &lookup,
     89 				const hb_ot_layout_lookup_accelerator_t &accel);
     90 
     91 
     92 /* Should be called after all the substitute_lookup's are done */
     93 HB_INTERNAL void
     94 hb_ot_layout_substitute_finish (hb_font_t    *font,
     95 				hb_buffer_t  *buffer);
     96 
     97 
     98 /* Should be called before all the position_lookup's are done.  Resets positions to zero. */
     99 HB_INTERNAL void
    100 hb_ot_layout_position_start (hb_font_t    *font,
    101 			     hb_buffer_t  *buffer);
    102 
    103 /* Should be called after all the position_lookup's are done */
    104 HB_INTERNAL void
    105 hb_ot_layout_position_finish (hb_font_t    *font,
    106 			      hb_buffer_t  *buffer);
    107 
    108 
    109 
    110 /*
    111  * hb_ot_layout_t
    112  */
    113 
    114 namespace OT {
    115   struct GDEF;
    116   struct GSUB;
    117   struct GPOS;
    118 }
    119 
    120 struct hb_ot_layout_lookup_accelerator_t
    121 {
    122   template <typename TLookup>
    123   inline void init (const TLookup &lookup)
    124   {
    125     digest.init ();
    126     lookup.add_coverage (&digest);
    127   }
    128 
    129   inline void fini (void)
    130   {
    131   }
    132 
    133   hb_set_digest_t digest;
    134 };
    135 
    136 struct hb_ot_layout_t
    137 {
    138   hb_blob_t *gdef_blob;
    139   hb_blob_t *gsub_blob;
    140   hb_blob_t *gpos_blob;
    141 
    142   const struct OT::GDEF *gdef;
    143   const struct OT::GSUB *gsub;
    144   const struct OT::GPOS *gpos;
    145 
    146   unsigned int gsub_lookup_count;
    147   unsigned int gpos_lookup_count;
    148 
    149   hb_ot_layout_lookup_accelerator_t *gsub_accels;
    150   hb_ot_layout_lookup_accelerator_t *gpos_accels;
    151 };
    152 
    153 
    154 HB_INTERNAL hb_ot_layout_t *
    155 _hb_ot_layout_create (hb_face_t *face);
    156 
    157 HB_INTERNAL void
    158 _hb_ot_layout_destroy (hb_ot_layout_t *layout);
    159 
    160 
    161 #define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
    162 
    163 
    164 /*
    165  * Buffer var routines.
    166  */
    167 
    168 /* buffer var allocations, used during the entire shaping process */
    169 #define unicode_props0()	var2.u8[0]
    170 #define unicode_props1()	var2.u8[1]
    171 
    172 /* buffer var allocations, used during the GSUB/GPOS processing */
    173 #define glyph_props()		var1.u16[0] /* GDEF glyph properties */
    174 #define lig_props()		var1.u8[2] /* GSUB/GPOS ligature tracking */
    175 #define syllable()		var1.u8[3] /* GSUB/GPOS shaping boundaries */
    176 
    177 /* unicode_props */
    178 
    179 enum {
    180   MASK0_ZWJ       = 0x20u,
    181   MASK0_ZWNJ      = 0x40u,
    182   MASK0_IGNORABLE = 0x80u,
    183   MASK0_GEN_CAT   = 0x1Fu
    184 };
    185 
    186 static inline void
    187 _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
    188 {
    189   /* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */
    190   info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) |
    191 			   (unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) |
    192 			   (info->codepoint == 0x200Cu ? MASK0_ZWNJ : 0) |
    193 			   (info->codepoint == 0x200Du ? MASK0_ZWJ : 0);
    194   info->unicode_props1() = unicode->modified_combining_class (info->codepoint);
    195 }
    196 
    197 static inline void
    198 _hb_glyph_info_set_general_category (hb_glyph_info_t *info,
    199 				     hb_unicode_general_category_t gen_cat)
    200 {
    201   info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
    202 }
    203 
    204 static inline hb_unicode_general_category_t
    205 _hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
    206 {
    207   return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT);
    208 }
    209 
    210 static inline void
    211 _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
    212 					     unsigned int modified_class)
    213 {
    214   info->unicode_props1() = modified_class;
    215 }
    216 
    217 static inline unsigned int
    218 _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
    219 {
    220   return info->unicode_props1();
    221 }
    222 
    223 static inline hb_bool_t
    224 _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
    225 {
    226   return !!(info->unicode_props0() & MASK0_IGNORABLE);
    227 }
    228 
    229 static inline hb_bool_t
    230 _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
    231 {
    232   return !!(info->unicode_props0() & MASK0_ZWNJ);
    233 }
    234 
    235 static inline hb_bool_t
    236 _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
    237 {
    238   return !!(info->unicode_props0() & MASK0_ZWJ);
    239 }
    240 
    241 static inline void
    242 _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
    243 {
    244   info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
    245 }
    246 
    247 /* lig_props: aka lig_id / lig_comp
    248  *
    249  * When a ligature is formed:
    250  *
    251  *   - The ligature glyph and any marks in between all the same newly allocated
    252  *     lig_id,
    253  *   - The ligature glyph will get lig_num_comps set to the number of components
    254  *   - The marks get lig_comp > 0, reflecting which component of the ligature
    255  *     they were applied to.
    256  *   - This is used in GPOS to attach marks to the right component of a ligature
    257  *     in MarkLigPos,
    258  *   - Note that when marks are ligated together, much of the above is skipped
    259  *     and the current lig_id reused.
    260  *
    261  * When a multiple-substitution is done:
    262  *
    263  *   - All resulting glyphs will have lig_id = 0,
    264  *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
    265  *   - This is used in GPOS to attach marks to the first component of a
    266  *     multiple substitution in MarkBasePos.
    267  *
    268  * The numbers are also used in GPOS to do mark-to-mark positioning only
    269  * to marks that belong to the same component of the same ligature.
    270  */
    271 
    272 static inline void
    273 _hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
    274 {
    275   info->lig_props() = 0;
    276 }
    277 
    278 #define IS_LIG_BASE 0x10
    279 
    280 static inline void
    281 _hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
    282 					   unsigned int lig_id,
    283 					   unsigned int lig_num_comps)
    284 {
    285   info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
    286 }
    287 
    288 static inline void
    289 _hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
    290 				       unsigned int lig_id,
    291 				       unsigned int lig_comp)
    292 {
    293   info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
    294 }
    295 
    296 static inline void
    297 _hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
    298 {
    299   _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
    300 }
    301 
    302 static inline unsigned int
    303 _hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
    304 {
    305   return info->lig_props() >> 5;
    306 }
    307 
    308 static inline bool
    309 _hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
    310 {
    311   return !!(info->lig_props() & IS_LIG_BASE);
    312 }
    313 
    314 static inline unsigned int
    315 _hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
    316 {
    317   if (_hb_glyph_info_ligated_internal (info))
    318     return 0;
    319   else
    320     return info->lig_props() & 0x0F;
    321 }
    322 
    323 static inline unsigned int
    324 _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
    325 {
    326   if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
    327       _hb_glyph_info_ligated_internal (info))
    328     return info->lig_props() & 0x0F;
    329   else
    330     return 1;
    331 }
    332 
    333 static inline uint8_t
    334 _hb_allocate_lig_id (hb_buffer_t *buffer) {
    335   uint8_t lig_id = buffer->next_serial () & 0x07;
    336   if (unlikely (!lig_id))
    337     lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
    338   return lig_id;
    339 }
    340 
    341 /* glyph_props: */
    342 
    343 static inline void
    344 _hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
    345 {
    346   info->glyph_props() = props;
    347 }
    348 
    349 static inline unsigned int
    350 _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
    351 {
    352   return info->glyph_props();
    353 }
    354 
    355 static inline bool
    356 _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
    357 {
    358   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
    359 }
    360 
    361 static inline bool
    362 _hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
    363 {
    364   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
    365 }
    366 
    367 static inline bool
    368 _hb_glyph_info_is_mark (const hb_glyph_info_t *info)
    369 {
    370   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
    371 }
    372 
    373 static inline bool
    374 _hb_glyph_info_substituted (const hb_glyph_info_t *info)
    375 {
    376   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
    377 }
    378 
    379 static inline bool
    380 _hb_glyph_info_ligated (const hb_glyph_info_t *info)
    381 {
    382   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
    383 }
    384 
    385 static inline bool
    386 _hb_glyph_info_multiplied (const hb_glyph_info_t *info)
    387 {
    388   return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
    389 }
    390 
    391 static inline bool
    392 _hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
    393 {
    394   return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
    395 }
    396 
    397 static inline void
    398 _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
    399 {
    400   info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
    401 			   HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
    402 }
    403 
    404 
    405 /* Allocation / deallocation. */
    406 
    407 static inline void
    408 _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
    409 {
    410   HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0);
    411   HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1);
    412 }
    413 
    414 static inline void
    415 _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
    416 {
    417   HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0);
    418   HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1);
    419 }
    420 
    421 static inline void
    422 _hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
    423 {
    424   HB_BUFFER_ASSERT_VAR (buffer, unicode_props0);
    425   HB_BUFFER_ASSERT_VAR (buffer, unicode_props1);
    426 }
    427 
    428 static inline void
    429 _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
    430 {
    431   HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
    432   HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
    433   HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
    434 }
    435 
    436 static inline void
    437 _hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
    438 {
    439   HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
    440   HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
    441   HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
    442 }
    443 
    444 static inline void
    445 _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
    446 {
    447   HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
    448   HB_BUFFER_ASSERT_VAR (buffer, lig_props);
    449   HB_BUFFER_ASSERT_VAR (buffer, syllable);
    450 }
    451 
    452 /* Make sure no one directly touches our props... */
    453 #undef unicode_props0
    454 #undef unicode_props1
    455 #undef lig_props
    456 #undef glyph_props
    457 
    458 
    459 #endif /* HB_OT_LAYOUT_PRIVATE_HH */
    460