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 43typedef 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 65HB_INTERNAL hb_bool_t 66hb_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. */ 74HB_INTERNAL void 75hb_ot_layout_substitute_start (hb_font_t *font, 76 hb_buffer_t *buffer); 77 78 79struct hb_ot_layout_lookup_accelerator_t; 80 81namespace OT { 82 struct hb_apply_context_t; 83 struct SubstLookup; 84} 85 86HB_INTERNAL void 87hb_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 */ 93HB_INTERNAL void 94hb_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. */ 99HB_INTERNAL void 100hb_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 */ 104HB_INTERNAL void 105hb_ot_layout_position_finish (hb_font_t *font, 106 hb_buffer_t *buffer); 107 108 109 110/* 111 * hb_ot_layout_t 112 */ 113 114namespace OT { 115 struct GDEF; 116 struct GSUB; 117 struct GPOS; 118} 119 120struct 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 136struct 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 154HB_INTERNAL hb_ot_layout_t * 155_hb_ot_layout_create (hb_face_t *face); 156 157HB_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 179enum { 180 MASK0_ZWJ = 0x20u, 181 MASK0_ZWNJ = 0x40u, 182 MASK0_IGNORABLE = 0x80u, 183 MASK0_GEN_CAT = 0x1Fu 184}; 185 186static 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 197static 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 204static 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 210static 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 217static 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 223static 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 229static 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 235static 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 241static 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 272static 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 280static 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 288static 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 296static 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 302static 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 308static 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 314static 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 323static 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 333static 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 343static 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 349static inline unsigned int 350_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info) 351{ 352 return info->glyph_props(); 353} 354 355static 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 361static 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 367static 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 373static 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 379static 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 385static 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 391static 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 397static 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 407static 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 414static 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 421static 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 428static 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 436static 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 444static 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