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