| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
| 3 * Copyright (C) 2010 Google, Inc. | 3 * Copyright © 2010 Google, Inc. |
| 4 * | 4 * |
| 5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
| 6 * | 6 * |
| 7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
| 8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
| 9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
| 10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
| 11 * all copies of this software. | 11 * all copies of this software. |
| 12 * | 12 * |
| 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 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 | 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 17 * DAMAGE. | 17 * DAMAGE. |
| 18 * | 18 * |
| 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 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 | 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 24 * | 24 * |
| 25 * Red Hat Author(s): Behdad Esfahbod | 25 * Red Hat Author(s): Behdad Esfahbod |
| 26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 #ifndef HB_OT_LAYOUT_GSUB_PRIVATE_HH | 29 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH |
| 30 #define HB_OT_LAYOUT_GSUB_PRIVATE_HH | 30 #define HB_OT_LAYOUT_GSUB_TABLE_HH |
| 31 | 31 |
| 32 #include "hb-ot-layout-gsubgpos-private.hh" | 32 #include "hb-ot-layout-gsubgpos-private.hh" |
| 33 | 33 |
| 34 HB_BEGIN_DECLS | |
| 35 | 34 |
| 36 | 35 |
| 37 struct SingleSubstFormat1 | 36 struct SingleSubstFormat1 |
| 38 { | 37 { |
| 39 friend struct SingleSubst; | 38 friend struct SingleSubst; |
| 40 | 39 |
| 41 private: | 40 private: |
| 42 | 41 |
| 43 inline bool apply (hb_apply_context_t *c) const | 42 inline bool apply (hb_apply_context_t *c) const |
| 44 { | 43 { |
| 45 TRACE_APPLY (); | 44 TRACE_APPLY (); |
| 46 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint; | 45 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; |
| 47 unsigned int index = (this+coverage) (glyph_id); | 46 unsigned int index = (this+coverage) (glyph_id); |
| 48 if (likely (index == NOT_COVERED)) | 47 if (likely (index == NOT_COVERED)) |
| 49 return false; | 48 return false; |
| 50 | 49 |
| 51 glyph_id += deltaGlyphID; | 50 /* According to the Adobe Annotated OpenType Suite, result is always |
| 51 * limited to 16bit. */ |
| 52 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF; |
| 52 c->replace_glyph (glyph_id); | 53 c->replace_glyph (glyph_id); |
| 53 | 54 |
| 54 return true; | 55 return true; |
| 55 } | 56 } |
| 56 | 57 |
| 57 inline bool sanitize (hb_sanitize_context_t *c) { | 58 inline bool sanitize (hb_sanitize_context_t *c) { |
| 58 TRACE_SANITIZE (); | 59 TRACE_SANITIZE (); |
| 59 return coverage.sanitize (c, this) | 60 return coverage.sanitize (c, this) |
| 60 && deltaGlyphID.sanitize (c); | 61 && deltaGlyphID.sanitize (c); |
| 61 } | 62 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 73 | 74 |
| 74 struct SingleSubstFormat2 | 75 struct SingleSubstFormat2 |
| 75 { | 76 { |
| 76 friend struct SingleSubst; | 77 friend struct SingleSubst; |
| 77 | 78 |
| 78 private: | 79 private: |
| 79 | 80 |
| 80 inline bool apply (hb_apply_context_t *c) const | 81 inline bool apply (hb_apply_context_t *c) const |
| 81 { | 82 { |
| 82 TRACE_APPLY (); | 83 TRACE_APPLY (); |
| 83 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint; | 84 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; |
| 84 unsigned int index = (this+coverage) (glyph_id); | 85 unsigned int index = (this+coverage) (glyph_id); |
| 85 if (likely (index == NOT_COVERED)) | 86 if (likely (index == NOT_COVERED)) |
| 86 return false; | 87 return false; |
| 87 | 88 |
| 88 if (unlikely (index >= substitute.len)) | 89 if (unlikely (index >= substitute.len)) |
| 89 return false; | 90 return false; |
| 90 | 91 |
| 91 glyph_id = substitute[index]; | 92 glyph_id = substitute[index]; |
| 92 c->replace_glyph (glyph_id); | 93 c->replace_glyph (glyph_id); |
| 93 | 94 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 struct MultipleSubstFormat1 | 182 struct MultipleSubstFormat1 |
| 182 { | 183 { |
| 183 friend struct MultipleSubst; | 184 friend struct MultipleSubst; |
| 184 | 185 |
| 185 private: | 186 private: |
| 186 | 187 |
| 187 inline bool apply (hb_apply_context_t *c) const | 188 inline bool apply (hb_apply_context_t *c) const |
| 188 { | 189 { |
| 189 TRACE_APPLY (); | 190 TRACE_APPLY (); |
| 190 | 191 |
| 191 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin
t); | 192 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo
int); |
| 192 if (likely (index == NOT_COVERED)) | 193 if (likely (index == NOT_COVERED)) |
| 193 return false; | 194 return false; |
| 194 | 195 |
| 195 return (this+sequence[index]).apply (c); | 196 return (this+sequence[index]).apply (c); |
| 196 } | 197 } |
| 197 | 198 |
| 198 inline bool sanitize (hb_sanitize_context_t *c) { | 199 inline bool sanitize (hb_sanitize_context_t *c) { |
| 199 TRACE_SANITIZE (); | 200 TRACE_SANITIZE (); |
| 200 return coverage.sanitize (c, this) | 201 return coverage.sanitize (c, this) |
| 201 && sequence.sanitize (c, this); | 202 && sequence.sanitize (c, this); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 251 |
| 251 struct AlternateSubstFormat1 | 252 struct AlternateSubstFormat1 |
| 252 { | 253 { |
| 253 friend struct AlternateSubst; | 254 friend struct AlternateSubst; |
| 254 | 255 |
| 255 private: | 256 private: |
| 256 | 257 |
| 257 inline bool apply (hb_apply_context_t *c) const | 258 inline bool apply (hb_apply_context_t *c) const |
| 258 { | 259 { |
| 259 TRACE_APPLY (); | 260 TRACE_APPLY (); |
| 260 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint; | 261 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; |
| 261 hb_mask_t glyph_mask = c->buffer->info[c->buffer->i].mask; | 262 hb_mask_t glyph_mask = c->buffer->info[c->buffer->idx].mask; |
| 262 hb_mask_t lookup_mask = c->lookup_mask; | 263 hb_mask_t lookup_mask = c->lookup_mask; |
| 263 | 264 |
| 264 unsigned int index = (this+coverage) (glyph_id); | 265 unsigned int index = (this+coverage) (glyph_id); |
| 265 if (likely (index == NOT_COVERED)) | 266 if (likely (index == NOT_COVERED)) |
| 266 return false; | 267 return false; |
| 267 | 268 |
| 268 const AlternateSet &alt_set = this+alternateSet[index]; | 269 const AlternateSet &alt_set = this+alternateSet[index]; |
| 269 | 270 |
| 270 if (unlikely (!alt_set.len)) | 271 if (unlikely (!alt_set.len)) |
| 271 return false; | 272 return false; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 | 336 |
| 336 | 337 |
| 337 struct Ligature | 338 struct Ligature |
| 338 { | 339 { |
| 339 friend struct LigatureSet; | 340 friend struct LigatureSet; |
| 340 | 341 |
| 341 private: | 342 private: |
| 342 inline bool apply (hb_apply_context_t *c) const | 343 inline bool apply (hb_apply_context_t *c) const |
| 343 { | 344 { |
| 344 TRACE_APPLY (); | 345 TRACE_APPLY (); |
| 345 unsigned int i, j; | |
| 346 unsigned int count = component.len; | 346 unsigned int count = component.len; |
| 347 unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length); | 347 if (unlikely (count < 2)) |
| 348 if (unlikely (count < 2 || c->buffer->i + count > end)) | 348 return false; |
| 349 |
| 350 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff
er->idx, count - 1); |
| 351 if (skippy_iter.has_no_chance ()) |
| 349 return false; | 352 return false; |
| 350 | 353 |
| 351 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); | 354 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); |
| 352 bool found_non_mark = false; | 355 bool found_non_mark = false; |
| 353 | 356 |
| 354 for (i = 1, j = c->buffer->i + 1; i < count; i++, j++) | 357 for (unsigned int i = 1; i < count; i++) |
| 355 { | 358 { |
| 356 unsigned int property; | 359 unsigned int property; |
| 357 while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->l
ookup_props, &property)) | 360 |
| 358 { | 361 if (!skippy_iter.next (&property)) |
| 359 » if (unlikely (j + count - i == end)) | 362 » return false; |
| 360 » return false; | |
| 361 » j++; | |
| 362 } | |
| 363 | 363 |
| 364 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); | 364 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); |
| 365 | 365 |
| 366 if (likely (c->buffer->info[j].codepoint != component[i])) | 366 if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) |
| 367 return false; | 367 return false; |
| 368 } | 368 } |
| 369 | 369 |
| 370 if (first_was_mark && found_non_mark) | 370 if (first_was_mark && found_non_mark) |
| 371 c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE); | 371 c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE); |
| 372 | 372 |
| 373 /* Allocate new ligature id */ | 373 /* Allocate new ligature id */ |
| 374 unsigned int lig_id = allocate_lig_id (c->buffer); | 374 unsigned int lig_id = allocate_lig_id (c->buffer); |
| 375 c->buffer->info[c->buffer->i].lig_comp() = 0; | 375 c->buffer->info[c->buffer->idx].lig_comp() = 0; |
| 376 c->buffer->info[c->buffer->i].lig_id() = lig_id; | 376 c->buffer->info[c->buffer->idx].lig_id() = lig_id; |
| 377 | 377 |
| 378 if (j == c->buffer->i + i) /* No input glyphs skipped */ | 378 if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */ |
| 379 { | 379 { |
| 380 c->replace_glyphs_be16 (i, 1, (const uint16_t *) &ligGlyph); | 380 c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph); |
| 381 } | 381 } |
| 382 else | 382 else |
| 383 { | 383 { |
| 384 c->replace_glyph (ligGlyph); | 384 c->replace_glyph (ligGlyph); |
| 385 | 385 |
| 386 /* Now we must do a second loop to copy the skipped glyphs to | 386 /* Now we must do a second loop to copy the skipped glyphs to |
| 387 `out' and assign component values to it. We start with the | 387 `out' and assign component values to it. We start with the |
| 388 glyph after the first component. Glyphs between component | 388 glyph after the first component. Glyphs between component |
| 389 i and i+1 belong to component i. Together with the lig_id | 389 i and i+1 belong to component i. Together with the lig_id |
| 390 value it is later possible to check whether a specific | 390 value it is later possible to check whether a specific |
| 391 component value really belongs to a given ligature. */ | 391 component value really belongs to a given ligature. */ |
| 392 | 392 |
| 393 for (i = 1; i < count; i++) | 393 for (unsigned int i = 1; i < count; i++) |
| 394 { | 394 { |
| 395 » while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[c->buf
fer->i], c->lookup_props, NULL)) | 395 » while (c->should_mark_skip_current_glyph ()) |
| 396 { | 396 { |
| 397 » c->buffer->info[c->buffer->i].lig_comp() = i; | 397 » c->buffer->info[c->buffer->idx].lig_comp() = i; |
| 398 » c->buffer->info[c->buffer->i].lig_id() = lig_id; | 398 » c->buffer->info[c->buffer->idx].lig_id() = lig_id; |
| 399 » c->replace_glyph (c->buffer->info[c->buffer->i].codepoint); | 399 » c->replace_glyph (c->buffer->info[c->buffer->idx].codepoint); |
| 400 } | 400 } |
| 401 | 401 |
| 402 /* Skip the base glyph */ | 402 /* Skip the base glyph */ |
| 403 » c->buffer->i++; | 403 » c->buffer->idx++; |
| 404 } | 404 } |
| 405 } | 405 } |
| 406 | 406 |
| 407 return true; | 407 return true; |
| 408 } | 408 } |
| 409 | 409 |
| 410 inline uint16_t allocate_lig_id (hb_buffer_t *buffer) const { | |
| 411 uint16_t lig_id = buffer->next_serial (); | |
| 412 if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overf
lows */ | |
| 413 return lig_id; | |
| 414 } | |
| 415 | |
| 416 public: | 410 public: |
| 417 inline bool sanitize (hb_sanitize_context_t *c) { | 411 inline bool sanitize (hb_sanitize_context_t *c) { |
| 418 TRACE_SANITIZE (); | 412 TRACE_SANITIZE (); |
| 419 return ligGlyph.sanitize (c) | 413 return ligGlyph.sanitize (c) |
| 420 && component.sanitize (c); | 414 && component.sanitize (c); |
| 421 } | 415 } |
| 422 | 416 |
| 423 private: | 417 private: |
| 424 GlyphID ligGlyph; /* GlyphID of ligature to substitute */ | 418 GlyphID ligGlyph; /* GlyphID of ligature to substitute */ |
| 425 HeadlessArrayOf<GlyphID> | 419 HeadlessArrayOf<GlyphID> |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 }; | 458 }; |
| 465 | 459 |
| 466 struct LigatureSubstFormat1 | 460 struct LigatureSubstFormat1 |
| 467 { | 461 { |
| 468 friend struct LigatureSubst; | 462 friend struct LigatureSubst; |
| 469 | 463 |
| 470 private: | 464 private: |
| 471 inline bool apply (hb_apply_context_t *c) const | 465 inline bool apply (hb_apply_context_t *c) const |
| 472 { | 466 { |
| 473 TRACE_APPLY (); | 467 TRACE_APPLY (); |
| 474 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint; | 468 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; |
| 475 | 469 |
| 476 unsigned int index = (this+coverage) (glyph_id); | 470 unsigned int index = (this+coverage) (glyph_id); |
| 477 if (likely (index == NOT_COVERED)) | 471 if (likely (index == NOT_COVERED)) |
| 478 return false; | 472 return false; |
| 479 | 473 |
| 480 const LigatureSet &lig_set = this+ligatureSet[index]; | 474 const LigatureSet &lig_set = this+ligatureSet[index]; |
| 481 return lig_set.apply (c); | 475 return lig_set.apply (c); |
| 482 } | 476 } |
| 483 | 477 |
| 484 inline bool sanitize (hb_sanitize_context_t *c) { | 478 inline bool sanitize (hb_sanitize_context_t *c) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 } | 517 } |
| 524 | 518 |
| 525 private: | 519 private: |
| 526 union { | 520 union { |
| 527 USHORT format; /* Format identifier */ | 521 USHORT format; /* Format identifier */ |
| 528 LigatureSubstFormat1 format1; | 522 LigatureSubstFormat1 format1; |
| 529 } u; | 523 } u; |
| 530 }; | 524 }; |
| 531 | 525 |
| 532 | 526 |
| 533 HB_BEGIN_DECLS | |
| 534 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index); | 527 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index); |
| 535 HB_END_DECLS | |
| 536 | 528 |
| 537 struct ContextSubst : Context | 529 struct ContextSubst : Context |
| 538 { | 530 { |
| 539 friend struct SubstLookupSubTable; | 531 friend struct SubstLookupSubTable; |
| 540 | 532 |
| 541 private: | 533 private: |
| 542 inline bool apply (hb_apply_context_t *c) const | 534 inline bool apply (hb_apply_context_t *c) const |
| 543 { | 535 { |
| 544 TRACE_APPLY (); | 536 TRACE_APPLY (); |
| 545 return Context::apply (c, substitute_lookup); | 537 return Context::apply (c, substitute_lookup); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 { | 576 { |
| 585 friend struct ReverseChainSingleSubst; | 577 friend struct ReverseChainSingleSubst; |
| 586 | 578 |
| 587 private: | 579 private: |
| 588 inline bool apply (hb_apply_context_t *c) const | 580 inline bool apply (hb_apply_context_t *c) const |
| 589 { | 581 { |
| 590 TRACE_APPLY (); | 582 TRACE_APPLY (); |
| 591 if (unlikely (c->context_length != NO_CONTEXT)) | 583 if (unlikely (c->context_length != NO_CONTEXT)) |
| 592 return false; /* No chaining to this type */ | 584 return false; /* No chaining to this type */ |
| 593 | 585 |
| 594 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin
t); | 586 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo
int); |
| 595 if (likely (index == NOT_COVERED)) | 587 if (likely (index == NOT_COVERED)) |
| 596 return false; | 588 return false; |
| 597 | 589 |
| 598 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag
e> > (backtrack); | 590 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag
e> > (backtrack); |
| 599 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); | 591 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); |
| 600 | 592 |
| 601 if (match_backtrack (c, | 593 if (match_backtrack (c, |
| 602 backtrack.len, (USHORT *) backtrack.array, | 594 backtrack.len, (USHORT *) backtrack.array, |
| 603 match_coverage, this) && | 595 match_coverage, this) && |
| 604 match_lookahead (c, | 596 match_lookahead (c, |
| 605 lookahead.len, (USHORT *) lookahead.array, | 597 lookahead.len, (USHORT *) lookahead.array, |
| 606 match_coverage, this, | 598 match_coverage, this, |
| 607 1)) | 599 1)) |
| 608 { | 600 { |
| 609 c->buffer->info[c->buffer->i].codepoint = substitute[index]; | 601 c->buffer->info[c->buffer->idx].codepoint = substitute[index]; |
| 610 c->buffer->i--; /* Reverse! */ | 602 c->buffer->idx--; /* Reverse! */ |
| 611 return true; | 603 return true; |
| 612 } | 604 } |
| 613 | 605 |
| 614 return false; | 606 return false; |
| 615 } | 607 } |
| 616 | 608 |
| 617 inline bool sanitize (hb_sanitize_context_t *c) { | 609 inline bool sanitize (hb_sanitize_context_t *c) { |
| 618 TRACE_SANITIZE (); | 610 TRACE_SANITIZE (); |
| 619 if (!(coverage.sanitize (c, this) | 611 if (!(coverage.sanitize (c, this) |
| 620 && backtrack.sanitize (c, this))) | 612 && backtrack.sanitize (c, this))) |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 | 747 |
| 756 inline bool is_reverse (void) const | 748 inline bool is_reverse (void) const |
| 757 { | 749 { |
| 758 unsigned int type = get_type (); | 750 unsigned int type = get_type (); |
| 759 if (unlikely (type == SubstLookupSubTable::Extension)) | 751 if (unlikely (type == SubstLookupSubTable::Extension)) |
| 760 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); | 752 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); |
| 761 return lookup_type_is_reverse (type); | 753 return lookup_type_is_reverse (type); |
| 762 } | 754 } |
| 763 | 755 |
| 764 | 756 |
| 765 inline bool apply_once (hb_ot_layout_context_t *layout, | 757 inline bool apply_once (hb_face_t *face, |
| 766 hb_buffer_t *buffer, | 758 hb_buffer_t *buffer, |
| 767 hb_mask_t lookup_mask, | 759 hb_mask_t lookup_mask, |
| 768 unsigned int context_length, | 760 unsigned int context_length, |
| 769 unsigned int nesting_level_left) const | 761 unsigned int nesting_level_left) const |
| 770 { | 762 { |
| 771 unsigned int lookup_type = get_type (); | 763 unsigned int lookup_type = get_type (); |
| 772 hb_apply_context_t c[1] = {{0}}; | 764 hb_apply_context_t c[1] = {{0}}; |
| 773 | 765 |
| 774 c->layout = layout; | 766 c->face = face; |
| 775 c->buffer = buffer; | 767 c->buffer = buffer; |
| 768 c->direction = buffer->props.direction; |
| 776 c->lookup_mask = lookup_mask; | 769 c->lookup_mask = lookup_mask; |
| 777 c->context_length = context_length; | 770 c->context_length = context_length; |
| 778 c->nesting_level_left = nesting_level_left; | 771 c->nesting_level_left = nesting_level_left; |
| 779 c->lookup_props = get_props (); | 772 c->lookup_props = get_props (); |
| 780 | 773 |
| 781 if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c
->buffer->i], c->lookup_props, &c->property)) | 774 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer
->idx], c->lookup_props, &c->property)) |
| 782 return false; | 775 return false; |
| 783 | 776 |
| 784 if (unlikely (lookup_type == SubstLookupSubTable::Extension)) | 777 if (unlikely (lookup_type == SubstLookupSubTable::Extension)) |
| 785 { | 778 { |
| 786 /* The spec says all subtables should have the same type. | 779 /* The spec says all subtables should have the same type. |
| 787 * This is specially important if one has a reverse type! | 780 * This is specially important if one has a reverse type! |
| 788 * | 781 * |
| 789 * This is rather slow to do this here for every glyph, | 782 * This is rather slow to do this here for every glyph, |
| 790 * but it's easiest, and who uses extension lookups anyway?!*/ | 783 * but it's easiest, and who uses extension lookups anyway?!*/ |
| 791 unsigned int count = get_subtable_count (); | 784 unsigned int count = get_subtable_count (); |
| 792 unsigned int type = get_subtable(0).u.extension.get_type (); | 785 unsigned int type = get_subtable(0).u.extension.get_type (); |
| 793 for (unsigned int i = 1; i < count; i++) | 786 for (unsigned int i = 1; i < count; i++) |
| 794 if (get_subtable(i).u.extension.get_type () != type) | 787 if (get_subtable(i).u.extension.get_type () != type) |
| 795 return false; | 788 return false; |
| 796 } | 789 } |
| 797 | 790 |
| 798 unsigned int count = get_subtable_count (); | 791 unsigned int count = get_subtable_count (); |
| 799 for (unsigned int i = 0; i < count; i++) | 792 for (unsigned int i = 0; i < count; i++) |
| 800 if (get_subtable (i).apply (c, lookup_type)) | 793 if (get_subtable (i).apply (c, lookup_type)) |
| 801 return true; | 794 return true; |
| 802 | 795 |
| 803 return false; | 796 return false; |
| 804 } | 797 } |
| 805 | 798 |
| 806 inline bool apply_string (hb_ot_layout_context_t *layout, | 799 inline bool apply_string (hb_face_t *face, |
| 807 hb_buffer_t *buffer, | 800 hb_buffer_t *buffer, |
| 808 hb_mask_t mask) const | 801 hb_mask_t mask) const |
| 809 { | 802 { |
| 810 bool ret = false; | 803 bool ret = false; |
| 811 | 804 |
| 812 if (unlikely (!buffer->len)) | 805 if (unlikely (!buffer->len)) |
| 813 return false; | 806 return false; |
| 814 | 807 |
| 815 if (likely (!is_reverse ())) | 808 if (likely (!is_reverse ())) |
| 816 { | 809 { |
| 817 /* in/out forward substitution */ | 810 /* in/out forward substitution */ |
| 818 buffer->clear_output (); | 811 buffer->clear_output (); |
| 819 » buffer->i = 0; | 812 » buffer->idx = 0; |
| 820 » while (buffer->i < buffer->len) | 813 » while (buffer->idx < buffer->len) |
| 821 { | 814 { |
| 822 » if ((buffer->info[buffer->i].mask & mask) && | 815 » if ((buffer->info[buffer->idx].mask & mask) && |
| 823 » apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL)) | 816 » apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL)) |
| 824 ret = true; | 817 ret = true; |
| 825 else | 818 else |
| 826 buffer->next_glyph (); | 819 buffer->next_glyph (); |
| 827 | 820 |
| 828 } | 821 } |
| 829 if (ret) | 822 if (ret) |
| 830 » buffer->swap (); | 823 » buffer->swap_buffers (); |
| 831 } | 824 } |
| 832 else | 825 else |
| 833 { | 826 { |
| 834 /* in-place backward substitution */ | 827 /* in-place backward substitution */ |
| 835 » buffer->i = buffer->len - 1; | 828 » buffer->idx = buffer->len - 1; |
| 836 do | 829 do |
| 837 { | 830 { |
| 838 » if ((buffer->info[buffer->i].mask & mask) && | 831 » if ((buffer->info[buffer->idx].mask & mask) && |
| 839 » apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL)) | 832 » apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL)) |
| 840 ret = true; | 833 ret = true; |
| 841 else | 834 else |
| 842 » buffer->i--; | 835 » buffer->idx--; |
| 843 | 836 |
| 844 } | 837 } |
| 845 » while ((int) buffer->i >= 0); | 838 » while ((int) buffer->idx >= 0); |
| 846 } | 839 } |
| 847 | 840 |
| 848 return ret; | 841 return ret; |
| 849 } | 842 } |
| 850 | 843 |
| 851 inline bool sanitize (hb_sanitize_context_t *c) { | 844 inline bool sanitize (hb_sanitize_context_t *c) { |
| 852 TRACE_SANITIZE (); | 845 TRACE_SANITIZE (); |
| 853 if (unlikely (!Lookup::sanitize (c))) return false; | 846 if (unlikely (!Lookup::sanitize (c))) return false; |
| 854 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu
bTable> > (subTable); | 847 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu
bTable> > (subTable); |
| 855 return list.sanitize (c, this, get_type ()); | 848 return list.sanitize (c, this, get_type ()); |
| 856 } | 849 } |
| 857 }; | 850 }; |
| 858 | 851 |
| 859 typedef OffsetListOf<SubstLookup> SubstLookupList; | 852 typedef OffsetListOf<SubstLookup> SubstLookupList; |
| 860 | 853 |
| 861 /* | 854 /* |
| 862 * GSUB | 855 * GSUB -- The Glyph Substitution Table |
| 863 */ | 856 */ |
| 864 | 857 |
| 865 struct GSUB : GSUBGPOS | 858 struct GSUB : GSUBGPOS |
| 866 { | 859 { |
| 867 static const hb_tag_t Tag = HB_OT_TAG_GSUB; | 860 static const hb_tag_t Tag = HB_OT_TAG_GSUB; |
| 868 | 861 |
| 869 inline const SubstLookup& get_lookup (unsigned int i) const | 862 inline const SubstLookup& get_lookup (unsigned int i) const |
| 870 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } | 863 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } |
| 871 | 864 |
| 872 inline bool substitute_lookup (hb_ot_layout_context_t *layout, | 865 inline bool substitute_lookup (hb_face_t *face, |
| 873 hb_buffer_t *buffer, | 866 hb_buffer_t *buffer, |
| 874 unsigned int lookup_index, | 867 unsigned int lookup_index, |
| 875 hb_mask_t mask) const | 868 hb_mask_t mask) const |
| 876 { return get_lookup (lookup_index).apply_string (layout, buffer, mask); } | 869 { return get_lookup (lookup_index).apply_string (face, buffer, mask); } |
| 870 |
| 871 static inline void substitute_start (hb_buffer_t *buffer); |
| 872 static inline void substitute_finish (hb_buffer_t *buffer); |
| 877 | 873 |
| 878 inline bool sanitize (hb_sanitize_context_t *c) { | 874 inline bool sanitize (hb_sanitize_context_t *c) { |
| 879 TRACE_SANITIZE (); | 875 TRACE_SANITIZE (); |
| 880 if (unlikely (!GSUBGPOS::sanitize (c))) return false; | 876 if (unlikely (!GSUBGPOS::sanitize (c))) return false; |
| 881 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL
ist); | 877 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL
ist); |
| 882 return list.sanitize (c, this); | 878 return list.sanitize (c, this); |
| 883 } | 879 } |
| 884 public: | 880 public: |
| 885 DEFINE_SIZE_STATIC (10); | 881 DEFINE_SIZE_STATIC (10); |
| 886 }; | 882 }; |
| 887 | 883 |
| 888 | 884 |
| 885 void |
| 886 GSUB::substitute_start (hb_buffer_t *buffer) |
| 887 { |
| 888 HB_BUFFER_ALLOCATE_VAR (buffer, props_cache); |
| 889 HB_BUFFER_ALLOCATE_VAR (buffer, lig_id); |
| 890 HB_BUFFER_ALLOCATE_VAR (buffer, lig_comp); |
| 891 |
| 892 unsigned int count = buffer->len; |
| 893 for (unsigned int i = 0; i < count; i++) |
| 894 buffer->info[i].props_cache() = buffer->info[i].lig_id() = buffer->info[i].l
ig_comp() = 0; |
| 895 } |
| 896 |
| 897 void |
| 898 GSUB::substitute_finish (hb_buffer_t *buffer) |
| 899 { |
| 900 } |
| 901 |
| 902 |
| 889 /* Out-of-class implementation for methods recursing */ | 903 /* Out-of-class implementation for methods recursing */ |
| 890 | 904 |
| 891 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const | 905 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const |
| 892 { | 906 { |
| 893 TRACE_APPLY (); | 907 TRACE_APPLY (); |
| 894 return get_subtable ().apply (c, get_type ()); | 908 return get_subtable ().apply (c, get_type ()); |
| 895 } | 909 } |
| 896 | 910 |
| 897 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) | 911 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) |
| 898 { | 912 { |
| 899 TRACE_SANITIZE (); | 913 TRACE_SANITIZE (); |
| 900 if (unlikely (!Extension::sanitize (c))) return false; | 914 if (unlikely (!Extension::sanitize (c))) return false; |
| 901 unsigned int offset = get_offset (); | 915 unsigned int offset = get_offset (); |
| 902 if (unlikely (!offset)) return true; | 916 if (unlikely (!offset)) return true; |
| 903 return StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_typ
e ()); | 917 return StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_typ
e ()); |
| 904 } | 918 } |
| 905 | 919 |
| 906 inline bool ExtensionSubst::is_reverse (void) const | 920 inline bool ExtensionSubst::is_reverse (void) const |
| 907 { | 921 { |
| 908 unsigned int type = get_type (); | 922 unsigned int type = get_type (); |
| 909 if (unlikely (type == SubstLookupSubTable::Extension)) | 923 if (unlikely (type == SubstLookupSubTable::Extension)) |
| 910 return CastR<ExtensionSubst> (get_subtable()).is_reverse (); | 924 return CastR<ExtensionSubst> (get_subtable()).is_reverse (); |
| 911 return SubstLookup::lookup_type_is_reverse (type); | 925 return SubstLookup::lookup_type_is_reverse (type); |
| 912 } | 926 } |
| 913 | 927 |
| 914 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index) | 928 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
_index) |
| 915 { | 929 { |
| 916 const GSUB &gsub = *(c->layout->face->ot_layout->gsub); | 930 const GSUB &gsub = *(c->face->ot_layout->gsub); |
| 917 const SubstLookup &l = gsub.get_lookup (lookup_index); | 931 const SubstLookup &l = gsub.get_lookup (lookup_index); |
| 918 | 932 |
| 919 if (unlikely (c->nesting_level_left == 0)) | 933 if (unlikely (c->nesting_level_left == 0)) |
| 920 return false; | 934 return false; |
| 921 | 935 |
| 922 if (unlikely (c->context_length < 1)) | 936 if (unlikely (c->context_length < 1)) |
| 923 return false; | 937 return false; |
| 924 | 938 |
| 925 return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length,
c->nesting_level_left - 1); | 939 return l.apply_once (c->face, c->buffer, c->lookup_mask, c->context_length, c-
>nesting_level_left - 1); |
| 926 } | 940 } |
| 927 | 941 |
| 928 | 942 |
| 929 HB_END_DECLS | |
| 930 | 943 |
| 931 #endif /* HB_OT_LAYOUT_GSUB_PRIVATE_HH */ | 944 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ |
| OLD | NEW |