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 |