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 */