OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
3 * Copyright © 2010,2012 Google, Inc. | 3 * Copyright © 2010,2012 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 |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 namespace OT { | 37 namespace OT { |
38 | 38 |
39 | 39 |
40 | 40 |
41 #define TRACE_DISPATCH(this) \ | 41 #define TRACE_DISPATCH(this) \ |
42 hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t
> trace \ | 42 hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t
> trace \ |
43 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 43 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
44 ""); | 44 ""); |
45 | 45 |
46 | |
47 #ifndef HB_DEBUG_CLOSURE | 46 #ifndef HB_DEBUG_CLOSURE |
48 #define HB_DEBUG_CLOSURE (HB_DEBUG+0) | 47 #define HB_DEBUG_CLOSURE (HB_DEBUG+0) |
49 #endif | 48 #endif |
50 | 49 |
51 #define TRACE_CLOSURE(this) \ | 50 #define TRACE_CLOSURE(this) \ |
52 hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ | 51 hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ |
53 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 52 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
54 ""); | 53 ""); |
55 | 54 |
56 struct hb_closure_context_t | 55 struct hb_closure_context_t |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB
_VOID; } | 150 inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB
_VOID; } |
152 static return_t default_return_value (void) { return HB_VOID; } | 151 static return_t default_return_value (void) { return HB_VOID; } |
153 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } | 152 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } |
154 return_t recurse (unsigned int lookup_index) | 153 return_t recurse (unsigned int lookup_index) |
155 { | 154 { |
156 if (unlikely (nesting_level_left == 0 || !recurse_func)) | 155 if (unlikely (nesting_level_left == 0 || !recurse_func)) |
157 return default_return_value (); | 156 return default_return_value (); |
158 | 157 |
159 /* Note that GPOS sets recurse_func to NULL already, so it doesn't get | 158 /* Note that GPOS sets recurse_func to NULL already, so it doesn't get |
160 * past the previous check. For GSUB, we only want to collect the output | 159 * past the previous check. For GSUB, we only want to collect the output |
161 * glyphs in the recursion. If output is not requested, we can go home now.
*/ | 160 * glyphs in the recursion. If output is not requested, we can go home now. |
| 161 * |
| 162 * Note further, that the above is not exactly correct. A recursed lookup |
| 163 * is allowed to match input that is not matched in the context, but that's |
| 164 * not how most fonts are built. It's possible to relax that and recurse |
| 165 * with all sets here if it proves to be an issue. |
| 166 */ |
162 | 167 |
163 if (output == hb_set_get_empty ()) | 168 if (output == hb_set_get_empty ()) |
164 return HB_VOID; | 169 return HB_VOID; |
165 | 170 |
166 hb_set_t *old_before = before; | 171 hb_set_t *old_before = before; |
167 hb_set_t *old_input = input; | 172 hb_set_t *old_input = input; |
168 hb_set_t *old_after = after; | 173 hb_set_t *old_after = after; |
169 before = input = after = hb_set_get_empty (); | 174 before = input = after = hb_set_get_empty (); |
170 | 175 |
171 nesting_level_left--; | 176 nesting_level_left--; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 recurse_func_t recurse_func; | 270 recurse_func_t recurse_func; |
266 unsigned int nesting_level_left; | 271 unsigned int nesting_level_left; |
267 unsigned int lookup_props; | 272 unsigned int lookup_props; |
268 const GDEF &gdef; | 273 const GDEF &gdef; |
269 bool has_glyph_classes; | 274 bool has_glyph_classes; |
270 unsigned int debug_depth; | 275 unsigned int debug_depth; |
271 | 276 |
272 | 277 |
273 hb_apply_context_t (unsigned int table_index_, | 278 hb_apply_context_t (unsigned int table_index_, |
274 hb_font_t *font_, | 279 hb_font_t *font_, |
275 » » hb_buffer_t *buffer_, | 280 » » hb_buffer_t *buffer_) : |
276 » » hb_mask_t lookup_mask_, | |
277 » » bool auto_zwj_) : | |
278 table_index (table_index_), | 281 table_index (table_index_), |
279 font (font_), face (font->face), buffer (buffer_), | 282 font (font_), face (font->face), buffer (buffer_), |
280 direction (buffer_->props.direction), | 283 direction (buffer_->props.direction), |
281 » » » lookup_mask (lookup_mask_), | 284 » » » lookup_mask (1), |
282 » » » auto_zwj (auto_zwj_), | 285 » » » auto_zwj (true), |
283 recurse_func (NULL), | 286 recurse_func (NULL), |
284 nesting_level_left (MAX_NESTING_LEVEL), | 287 nesting_level_left (MAX_NESTING_LEVEL), |
285 lookup_props (0), | 288 lookup_props (0), |
286 gdef (*hb_ot_layout_from_face (face)->gdef), | 289 gdef (*hb_ot_layout_from_face (face)->gdef), |
287 has_glyph_classes (gdef.has_glyph_classes ()), | 290 has_glyph_classes (gdef.has_glyph_classes ()), |
288 debug_depth (0) {} | 291 debug_depth (0) {} |
289 | 292 |
| 293 inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } |
| 294 inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } |
290 inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } | 295 inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } |
291 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = loo
kup_props_; } | 296 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = loo
kup_props_; } |
292 inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } | 297 inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } |
293 | 298 |
294 struct matcher_t | 299 struct matcher_t |
295 { | 300 { |
296 inline matcher_t (void) : | 301 inline matcher_t (void) : |
297 lookup_props (0), | 302 lookup_props (0), |
298 ignore_zwnj (false), | 303 ignore_zwnj (false), |
299 ignore_zwj (false), | 304 ignore_zwj (false), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 SKIP_YES, | 344 SKIP_YES, |
340 SKIP_MAYBE | 345 SKIP_MAYBE |
341 }; | 346 }; |
342 | 347 |
343 inline may_skip_t | 348 inline may_skip_t |
344 may_skip (const hb_apply_context_t *c, | 349 may_skip (const hb_apply_context_t *c, |
345 const hb_glyph_info_t &info) const | 350 const hb_glyph_info_t &info) const |
346 { | 351 { |
347 unsigned int property; | 352 unsigned int property; |
348 | 353 |
349 property = info.glyph_props(); | 354 property = _hb_glyph_info_get_glyph_props (&info); |
350 | 355 |
351 if (!c->match_properties (info.codepoint, property, lookup_props)) | 356 if (!c->match_properties (info.codepoint, property, lookup_props)) |
352 return SKIP_YES; | 357 return SKIP_YES; |
353 | 358 |
354 if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && | 359 if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && |
355 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && | 360 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && |
356 (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && | 361 (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && |
357 » » !is_a_ligature (info))) | 362 » » !_hb_glyph_info_ligated (&info))) |
358 return SKIP_MAYBE; | 363 return SKIP_MAYBE; |
359 | 364 |
360 return SKIP_NO; | 365 return SKIP_NO; |
361 } | 366 } |
362 | 367 |
363 protected: | 368 protected: |
364 unsigned int lookup_props; | 369 unsigned int lookup_props; |
365 bool ignore_zwnj; | 370 bool ignore_zwnj; |
366 bool ignore_zwj; | 371 bool ignore_zwj; |
367 hb_mask_t mask; | 372 hb_mask_t mask; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 | 553 |
549 return true; | 554 return true; |
550 } | 555 } |
551 | 556 |
552 inline bool | 557 inline bool |
553 check_glyph_property (hb_glyph_info_t *info, | 558 check_glyph_property (hb_glyph_info_t *info, |
554 unsigned int lookup_props) const | 559 unsigned int lookup_props) const |
555 { | 560 { |
556 unsigned int property; | 561 unsigned int property; |
557 | 562 |
558 property = info->glyph_props(); | 563 property = _hb_glyph_info_get_glyph_props (info); |
559 | 564 |
560 return match_properties (info->codepoint, property, lookup_props); | 565 return match_properties (info->codepoint, property, lookup_props); |
561 } | 566 } |
562 | 567 |
563 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) c
onst | 568 inline void _set_glyph_props (hb_codepoint_t glyph_index, |
| 569 » » » unsigned int class_guess = 0, |
| 570 » » » bool ligature = false) const |
564 { | 571 { |
| 572 unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) & |
| 573 HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; |
| 574 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; |
| 575 if (ligature) |
| 576 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; |
565 if (likely (has_glyph_classes)) | 577 if (likely (has_glyph_classes)) |
566 buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index); | 578 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_pr
ops (glyph_index)); |
567 else if (class_guess) | 579 else if (class_guess) |
568 buffer->cur().glyph_props() = class_guess; | 580 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess); |
569 } | 581 } |
570 | 582 |
571 inline void output_glyph (hb_codepoint_t glyph_index, | 583 inline void replace_glyph (hb_codepoint_t glyph_index) const |
572 » » » unsigned int class_guess = 0) const | |
573 { | 584 { |
574 set_class (glyph_index, class_guess); | 585 _set_glyph_props (glyph_index); |
575 buffer->output_glyph (glyph_index); | |
576 } | |
577 inline void replace_glyph (hb_codepoint_t glyph_index, | |
578 » » » unsigned int class_guess = 0) const | |
579 { | |
580 set_class (glyph_index, class_guess); | |
581 buffer->replace_glyph (glyph_index); | 586 buffer->replace_glyph (glyph_index); |
582 } | 587 } |
583 inline void replace_glyph_inplace (hb_codepoint_t glyph_index, | 588 inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const |
584 » » » » unsigned int class_guess = 0) const | |
585 { | 589 { |
586 set_class (glyph_index, class_guess); | 590 _set_glyph_props (glyph_index); |
587 buffer->cur().codepoint = glyph_index; | 591 buffer->cur().codepoint = glyph_index; |
588 } | 592 } |
| 593 inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index, |
| 594 unsigned int class_guess) const |
| 595 { |
| 596 _set_glyph_props (glyph_index, class_guess, true); |
| 597 buffer->replace_glyph (glyph_index); |
| 598 } |
| 599 inline void output_glyph (hb_codepoint_t glyph_index, |
| 600 unsigned int class_guess) const |
| 601 { |
| 602 _set_glyph_props (glyph_index, class_guess); |
| 603 buffer->output_glyph (glyph_index); |
| 604 } |
589 }; | 605 }; |
590 | 606 |
591 | 607 |
592 | 608 |
593 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const
void *data); | 609 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const
void *data); |
594 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, co
nst void *data); | 610 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, co
nst void *data); |
595 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, cons
t void *data); | 611 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, cons
t void *data); |
596 | 612 |
597 struct ContextClosureFuncs | 613 struct ContextClosureFuncs |
598 { | 614 { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data))) | 706 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data))) |
691 return false; | 707 return false; |
692 | 708 |
693 return true; | 709 return true; |
694 } | 710 } |
695 static inline bool match_input (hb_apply_context_t *c, | 711 static inline bool match_input (hb_apply_context_t *c, |
696 unsigned int count, /* Including the first glyph
(not matched) */ | 712 unsigned int count, /* Including the first glyph
(not matched) */ |
697 const USHORT input[], /* Array of input values--
start with second glyph */ | 713 const USHORT input[], /* Array of input values--
start with second glyph */ |
698 match_func_t match_func, | 714 match_func_t match_func, |
699 const void *match_data, | 715 const void *match_data, |
700 » » » » unsigned int *end_offset = NULL, | 716 » » » » unsigned int *end_offset, |
| 717 » » » » unsigned int match_positions[MAX_CONTEXT_LENGTH]
, |
701 bool *p_is_mark_ligature = NULL, | 718 bool *p_is_mark_ligature = NULL, |
702 unsigned int *p_total_component_count = NULL) | 719 unsigned int *p_total_component_count = NULL) |
703 { | 720 { |
704 TRACE_APPLY (NULL); | 721 TRACE_APPLY (NULL); |
705 | 722 |
706 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
, count - 1); | 723 if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false); |
| 724 |
| 725 hb_buffer_t *buffer = c->buffer; |
| 726 |
| 727 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, c
ount - 1); |
707 skippy_iter.set_match_func (match_func, match_data, input); | 728 skippy_iter.set_match_func (match_func, match_data, input); |
708 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); | 729 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
709 | 730 |
710 /* | 731 /* |
711 * This is perhaps the trickiest part of OpenType... Remarks: | 732 * This is perhaps the trickiest part of OpenType... Remarks: |
712 * | 733 * |
713 * - If all components of the ligature were marks, we call this a mark ligatur
e. | 734 * - If all components of the ligature were marks, we call this a mark ligatur
e. |
714 * | 735 * |
715 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categori
ze | 736 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categori
ze |
716 * it as a ligature glyph. | 737 * it as a ligature glyph. |
717 * | 738 * |
718 * - Ligatures cannot be formed across glyphs attached to different components | 739 * - Ligatures cannot be formed across glyphs attached to different components |
719 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and | 740 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and |
720 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. | 741 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. |
721 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o | 742 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o |
722 * There is an exception to this: If a ligature tries ligating with marks th
at | 743 * There is an exception to this: If a ligature tries ligating with marks th
at |
723 * belong to it itself, go ahead, assuming that the font designer knows what | 744 * belong to it itself, go ahead, assuming that the font designer knows what |
724 * they are doing (otherwise it can break Indic stuff when a matra wants to | 745 * they are doing (otherwise it can break Indic stuff when a matra wants to |
725 * ligate with a conjunct...) | 746 * ligate with a conjunct...) |
726 */ | 747 */ |
727 | 748 |
728 bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH
_PROPS_MARK); | 749 bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur()); |
729 | 750 |
730 unsigned int total_component_count = 0; | 751 unsigned int total_component_count = 0; |
731 total_component_count += get_lig_num_comps (c->buffer->cur()); | 752 total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); |
732 | 753 |
733 unsigned int first_lig_id = get_lig_id (c->buffer->cur()); | 754 unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); |
734 unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); | 755 unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); |
735 | 756 |
| 757 match_positions[0] = buffer->idx; |
736 for (unsigned int i = 1; i < count; i++) | 758 for (unsigned int i = 1; i < count; i++) |
737 { | 759 { |
738 if (!skippy_iter.next ()) return TRACE_RETURN (false); | 760 if (!skippy_iter.next ()) return TRACE_RETURN (false); |
739 | 761 |
740 unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); | 762 match_positions[i] = skippy_iter.idx; |
741 unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx])
; | 763 |
| 764 unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_i
ter.idx]); |
| 765 unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skip
py_iter.idx]); |
742 | 766 |
743 if (first_lig_id && first_lig_comp) { | 767 if (first_lig_id && first_lig_comp) { |
744 /* If first component was attached to a previous ligature component, | 768 /* If first component was attached to a previous ligature component, |
745 * all subsequent components should be attached to the same ligature | 769 * all subsequent components should be attached to the same ligature |
746 * component, otherwise we shouldn't ligate them. */ | 770 * component, otherwise we shouldn't ligate them. */ |
747 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) | 771 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) |
748 return TRACE_RETURN (false); | 772 return TRACE_RETURN (false); |
749 } else { | 773 } else { |
750 /* If first component was NOT attached to a previous ligature component, | 774 /* If first component was NOT attached to a previous ligature component, |
751 * all subsequent components should also NOT be attached to any ligature | 775 * all subsequent components should also NOT be attached to any ligature |
752 * component, unless they are attached to the first component itself! */ | 776 * component, unless they are attached to the first component itself! */ |
753 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) | 777 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) |
754 return TRACE_RETURN (false); | 778 return TRACE_RETURN (false); |
755 } | 779 } |
756 | 780 |
757 is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].gly
ph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); | 781 is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info
[skippy_iter.idx]); |
758 total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]
); | 782 total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[ski
ppy_iter.idx]); |
759 } | 783 } |
760 | 784 |
761 if (end_offset) | 785 *end_offset = skippy_iter.idx - buffer->idx + 1; |
762 *end_offset = skippy_iter.idx - c->buffer->idx + 1; | |
763 | 786 |
764 if (p_is_mark_ligature) | 787 if (p_is_mark_ligature) |
765 *p_is_mark_ligature = is_mark_ligature; | 788 *p_is_mark_ligature = is_mark_ligature; |
766 | 789 |
767 if (p_total_component_count) | 790 if (p_total_component_count) |
768 *p_total_component_count = total_component_count; | 791 *p_total_component_count = total_component_count; |
769 | 792 |
770 return TRACE_RETURN (true); | 793 return TRACE_RETURN (true); |
771 } | 794 } |
772 static inline void ligate_input (hb_apply_context_t *c, | 795 static inline void ligate_input (hb_apply_context_t *c, |
773 » » » » unsigned int count, /* Including the first glyp
h (not matched) */ | 796 » » » » unsigned int count, /* Including the first glyp
h */ |
774 » » » » const USHORT input[], /* Array of input values-
-start with second glyph */ | 797 » » » » unsigned int match_positions[MAX_CONTEXT_LENGTH
], /* Including the first glyph */ |
775 » » » » match_func_t match_func, | 798 » » » » unsigned int match_length, |
776 » » » » const void *match_data, | |
777 hb_codepoint_t lig_glyph, | 799 hb_codepoint_t lig_glyph, |
778 bool is_mark_ligature, | 800 bool is_mark_ligature, |
779 unsigned int total_component_count) | 801 unsigned int total_component_count) |
780 { | 802 { |
781 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
, count - 1); | 803 TRACE_APPLY (NULL); |
782 skippy_iter.set_match_func (match_func, match_data, input); | 804 |
783 if (skippy_iter.has_no_chance ()) return; | 805 hb_buffer_t *buffer = c->buffer; |
| 806 |
| 807 buffer->merge_clusters (buffer->idx, buffer->idx + match_length); |
784 | 808 |
785 /* | 809 /* |
786 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leav
e | 810 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leav
e |
787 * the ligature to keep its old ligature id. This will allow it to attach t
o | 811 * the ligature to keep its old ligature id. This will allow it to attach t
o |
788 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HE
H, | 812 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HE
H, |
789 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a | 813 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a |
790 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligatu
re | 814 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligatu
re |
791 * later, we don't want them to lose their ligature id/component, otherwise | 815 * later, we don't want them to lose their ligature id/component, otherwise |
792 * GPOS will fail to correctly position the mark ligature on top of the | 816 * GPOS will fail to correctly position the mark ligature on top of the |
793 * LAM,LAM,HEH ligature. See: | 817 * LAM,LAM,HEH ligature. See: |
(...skipping 10 matching lines...) Expand all Loading... |
804 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature | 828 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature |
805 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligat
ure | 829 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligat
ure |
806 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to | 830 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to |
807 * the new ligature with a component value of 2. | 831 * the new ligature with a component value of 2. |
808 * | 832 * |
809 * This in fact happened to a font... See: | 833 * This in fact happened to a font... See: |
810 * https://bugzilla.gnome.org/show_bug.cgi?id=437633 | 834 * https://bugzilla.gnome.org/show_bug.cgi?id=437633 |
811 */ | 835 */ |
812 | 836 |
813 unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; | 837 unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; |
814 unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer); | 838 unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer); |
815 unsigned int last_lig_id = get_lig_id (c->buffer->cur()); | 839 unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); |
816 unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); | 840 unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->
cur()); |
817 unsigned int components_so_far = last_num_components; | 841 unsigned int components_so_far = last_num_components; |
818 | 842 |
819 if (!is_mark_ligature) | 843 if (!is_mark_ligature) |
820 set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count)
; | 844 { |
821 c->replace_glyph (lig_glyph, klass); | 845 _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_com
ponent_count); |
| 846 if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENER
AL_CATEGORY_NON_SPACING_MARK) |
| 847 { |
| 848 _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CA
TEGORY_OTHER_LETTER); |
| 849 _hb_glyph_info_set_modified_combining_class (&buffer->cur(), 0); |
| 850 } |
| 851 } |
| 852 c->replace_glyph_with_ligature (lig_glyph, klass); |
822 | 853 |
823 for (unsigned int i = 1; i < count; i++) | 854 for (unsigned int i = 1; i < count; i++) |
824 { | 855 { |
825 if (!skippy_iter.next ()) return; | 856 while (buffer->idx < match_positions[i]) |
826 | |
827 while (c->buffer->idx < skippy_iter.idx) | |
828 { | 857 { |
829 if (!is_mark_ligature) { | 858 if (!is_mark_ligature) { |
830 unsigned int new_lig_comp = components_so_far - last_num_components + | 859 unsigned int new_lig_comp = components_so_far - last_num_components + |
831 » » » » MIN (MAX (get_lig_comp (c->buffer->cur()), 1
u), last_num_components); | 860 » » » » MIN (MAX (_hb_glyph_info_get_lig_comp (&buff
er->cur()), 1u), last_num_components); |
832 » set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); | 861 » _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_c
omp); |
833 } | 862 } |
834 c->buffer->next_glyph (); | 863 buffer->next_glyph (); |
835 } | 864 } |
836 | 865 |
837 last_lig_id = get_lig_id (c->buffer->cur()); | 866 last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); |
838 last_num_components = get_lig_num_comps (c->buffer->cur()); | 867 last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur()); |
839 components_so_far += last_num_components; | 868 components_so_far += last_num_components; |
840 | 869 |
841 /* Skip the base glyph */ | 870 /* Skip the base glyph */ |
842 c->buffer->idx++; | 871 buffer->idx++; |
843 } | 872 } |
844 | 873 |
845 if (!is_mark_ligature && last_lig_id) { | 874 if (!is_mark_ligature && last_lig_id) { |
846 /* Re-adjust components for any marks following. */ | 875 /* Re-adjust components for any marks following. */ |
847 for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) { | 876 for (unsigned int i = buffer->idx; i < buffer->len; i++) { |
848 if (last_lig_id == get_lig_id (c->buffer->info[i])) { | 877 if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { |
849 unsigned int new_lig_comp = components_so_far - last_num_components + | 878 unsigned int new_lig_comp = components_so_far - last_num_components + |
850 » » » » MIN (MAX (get_lig_comp (c->buffer->info[i]),
1u), last_num_components); | 879 » » » » MIN (MAX (_hb_glyph_info_get_lig_comp (&buff
er->info[i]), 1u), last_num_components); |
851 » set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp); | 880 » _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig
_comp); |
852 } else | 881 } else |
853 break; | 882 break; |
854 } | 883 } |
855 } | 884 } |
856 } | 885 } |
857 | 886 |
858 static inline bool match_backtrack (hb_apply_context_t *c, | 887 static inline bool match_backtrack (hb_apply_context_t *c, |
859 unsigned int count, | 888 unsigned int count, |
860 const USHORT backtrack[], | 889 const USHORT backtrack[], |
861 match_func_t match_func, | 890 match_func_t match_func, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 DEFINE_SIZE_STATIC (4); | 940 DEFINE_SIZE_STATIC (4); |
912 }; | 941 }; |
913 | 942 |
914 | 943 |
915 template <typename context_t> | 944 template <typename context_t> |
916 static inline void recurse_lookups (context_t *c, | 945 static inline void recurse_lookups (context_t *c, |
917 unsigned int lookupCount, | 946 unsigned int lookupCount, |
918 const LookupRecord lookupRecord[] /* Array o
f LookupRecords--in design order */) | 947 const LookupRecord lookupRecord[] /* Array o
f LookupRecords--in design order */) |
919 { | 948 { |
920 for (unsigned int i = 0; i < lookupCount; i++) | 949 for (unsigned int i = 0; i < lookupCount; i++) |
921 c->recurse (lookupRecord->lookupListIndex); | 950 c->recurse (lookupRecord[i].lookupListIndex); |
922 } | 951 } |
923 | 952 |
924 static inline bool apply_lookup (hb_apply_context_t *c, | 953 static inline bool apply_lookup (hb_apply_context_t *c, |
925 unsigned int count, /* Including the first glyp
h */ | 954 unsigned int count, /* Including the first glyp
h */ |
926 » » » » const USHORT input[], /* Array of input values-
-start with second glyph */ | 955 » » » » unsigned int match_positions[MAX_CONTEXT_LENGTH
], /* Including the first glyph */ |
927 » » » » match_func_t match_func, | |
928 » » » » const void *match_data, | |
929 unsigned int lookupCount, | 956 unsigned int lookupCount, |
930 » » » » const LookupRecord lookupRecord[] /* Array of L
ookupRecords--in design order */) | 957 » » » » const LookupRecord lookupRecord[], /* Array of
LookupRecords--in design order */ |
| 958 » » » » unsigned int match_length) |
931 { | 959 { |
932 TRACE_APPLY (NULL); | 960 TRACE_APPLY (NULL); |
933 | 961 |
934 unsigned int end = c->buffer->len; | 962 hb_buffer_t *buffer = c->buffer; |
935 if (unlikely (count == 0 || c->buffer->idx + count > end)) | 963 unsigned int end; |
936 return TRACE_RETURN (false); | |
937 | 964 |
938 /* TODO We don't support lookupRecord arrays that are not increasing: | 965 /* All positions are distance from beginning of *output* buffer. |
939 * Should be easy for in_place ones at least. */ | 966 * Adjust. */ |
| 967 { |
| 968 unsigned int bl = buffer->backtrack_len (); |
| 969 end = bl + match_length; |
940 | 970 |
941 /* Note: If sublookup is reverse, it will underflow after the first loop | 971 int delta = bl - buffer->idx; |
942 * and we jump out of it. Not entirely disastrous. So we don't check | 972 /* Convert positions to new indexing. */ |
943 * for reverse lookup here. | 973 for (unsigned int j = 0; j < count; j++) |
944 */ | 974 match_positions[j] += delta; |
| 975 } |
945 | 976 |
946 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
, count - 1); | 977 for (unsigned int i = 0; i < lookupCount; i++) |
947 skippy_iter.set_match_func (match_func, match_data, input); | 978 { |
948 uint8_t syllable = c->buffer->cur().syllable(); | 979 unsigned int idx = lookupRecord[i].sequenceIndex; |
| 980 if (idx >= count) |
| 981 continue; |
949 | 982 |
950 unsigned int i = 0; | 983 buffer->move_to (match_positions[idx]); |
951 if (lookupCount && 0 == lookupRecord->sequenceIndex) | |
952 { | |
953 unsigned int old_pos = c->buffer->idx; | |
954 | 984 |
955 /* Apply a lookup */ | 985 unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); |
956 bool done = c->recurse (lookupRecord->lookupListIndex); | 986 if (!c->recurse (lookupRecord[i].lookupListIndex)) |
| 987 continue; |
957 | 988 |
958 lookupRecord++; | 989 unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len (); |
959 lookupCount--; | 990 int delta = new_len - orig_len; |
960 /* Err, this is wrong if the lookup jumped over some glyphs */ | |
961 i += c->buffer->idx - old_pos; | |
962 | 991 |
963 if (!done) | 992 if (!delta) |
964 goto not_applied; | 993 continue; |
965 else | 994 |
| 995 /* Recursed lookup changed buffer len. Adjust. */ |
| 996 |
| 997 /* end can't go back past the current match position. */ |
| 998 end = MAX ((int) match_positions[idx] + 1, int (end) + delta); |
| 999 |
| 1000 unsigned int next = idx + 1; /* next now is the position after the recursed
lookup. */ |
| 1001 |
| 1002 if (delta > 0) |
966 { | 1003 { |
967 /* Reinitialize iterator. */ | 1004 if (unlikely (delta + count > MAX_CONTEXT_LENGTH)) |
968 hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1
, count - i); | 1005 » break; |
969 tmp.set_syllable (syllable); | |
970 skippy_iter = tmp; | |
971 } | |
972 } | |
973 else | |
974 { | |
975 not_applied: | |
976 /* No lookup applied for this index */ | |
977 c->buffer->next_glyph (); | |
978 i++; | |
979 } | |
980 while (i < count) | |
981 { | |
982 if (!skippy_iter.next ()) return TRACE_RETURN (true); | |
983 while (c->buffer->idx < skippy_iter.idx) | |
984 c->buffer->next_glyph (); | |
985 | |
986 if (lookupCount && i == lookupRecord->sequenceIndex) | |
987 { | |
988 unsigned int old_pos = c->buffer->idx; | |
989 | |
990 /* Apply a lookup */ | |
991 bool done = c->recurse (lookupRecord->lookupListIndex); | |
992 | |
993 lookupRecord++; | |
994 lookupCount--; | |
995 /* Err, this is wrong if the lookup jumped over some glyphs */ | |
996 i += c->buffer->idx - old_pos; | |
997 | |
998 if (!done) | |
999 » goto not_applied2; | |
1000 else | |
1001 { | |
1002 /* Reinitialize iterator. */ | |
1003 » hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx -
1, count - i); | |
1004 » tmp.set_syllable (syllable); | |
1005 » skippy_iter = tmp; | |
1006 } | |
1007 } | 1006 } |
1008 else | 1007 else |
1009 { | 1008 { |
1010 not_applied2: | 1009 /* NOTE: delta is negative. */ |
1011 /* No lookup applied for this index */ | 1010 delta = MAX (delta, (int) next - (int) count); |
1012 c->buffer->next_glyph (); | 1011 next -= delta; |
1013 i++; | |
1014 } | 1012 } |
| 1013 |
| 1014 /* Shift! */ |
| 1015 memmove (match_positions + next + delta, match_positions + next, |
| 1016 (count - next) * sizeof (match_positions[0])); |
| 1017 next += delta; |
| 1018 count += delta; |
| 1019 |
| 1020 /* Fill in new entries. */ |
| 1021 for (unsigned int j = idx + 1; j < next; j++) |
| 1022 match_positions[j] = match_positions[j - 1] + 1; |
| 1023 |
| 1024 /* And fixup the rest. */ |
| 1025 for (; next < count; next++) |
| 1026 match_positions[next] += delta; |
1015 } | 1027 } |
1016 | 1028 |
| 1029 buffer->move_to (end); |
| 1030 |
1017 return TRACE_RETURN (true); | 1031 return TRACE_RETURN (true); |
1018 } | 1032 } |
1019 | 1033 |
1020 | 1034 |
1021 | 1035 |
1022 /* Contextual lookups */ | 1036 /* Contextual lookups */ |
1023 | 1037 |
1024 struct ContextClosureLookupContext | 1038 struct ContextClosureLookupContext |
1025 { | 1039 { |
1026 ContextClosureFuncs funcs; | 1040 ContextClosureFuncs funcs; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 inputCount, input, | 1092 inputCount, input, |
1079 lookup_context.funcs.match, lookup_context.match_dat
a); | 1093 lookup_context.funcs.match, lookup_context.match_dat
a); |
1080 } | 1094 } |
1081 static inline bool context_apply_lookup (hb_apply_context_t *c, | 1095 static inline bool context_apply_lookup (hb_apply_context_t *c, |
1082 unsigned int inputCount, /* Including t
he first glyph (not matched) */ | 1096 unsigned int inputCount, /* Including t
he first glyph (not matched) */ |
1083 const USHORT input[], /* Array of input
values--start with second glyph */ | 1097 const USHORT input[], /* Array of input
values--start with second glyph */ |
1084 unsigned int lookupCount, | 1098 unsigned int lookupCount, |
1085 const LookupRecord lookupRecord[], | 1099 const LookupRecord lookupRecord[], |
1086 ContextApplyLookupContext &lookup_conte
xt) | 1100 ContextApplyLookupContext &lookup_conte
xt) |
1087 { | 1101 { |
| 1102 unsigned int match_length = 0; |
| 1103 unsigned int match_positions[MAX_CONTEXT_LENGTH]; |
1088 return match_input (c, | 1104 return match_input (c, |
1089 inputCount, input, | 1105 inputCount, input, |
1090 » » lookup_context.funcs.match, lookup_context.match_data) | 1106 » » lookup_context.funcs.match, lookup_context.match_data, |
| 1107 » » &match_length, match_positions) |
1091 && apply_lookup (c, | 1108 && apply_lookup (c, |
1092 » » inputCount, input, | 1109 » » inputCount, match_positions, |
1093 » » lookup_context.funcs.match, lookup_context.match_data, | 1110 » » lookupCount, lookupRecord, |
1094 » » lookupCount, lookupRecord); | 1111 » » match_length); |
1095 } | 1112 } |
1096 | 1113 |
1097 struct Rule | 1114 struct Rule |
1098 { | 1115 { |
1099 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &loo
kup_context) const | 1116 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &loo
kup_context) const |
1100 { | 1117 { |
1101 TRACE_CLOSURE (this); | 1118 TRACE_CLOSURE (this); |
1102 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, inp
ut[0].static_size * (inputCount ? inputCount - 1 : 0)); | 1119 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, inp
ut[0].static_size * (inputCount ? inputCount - 1 : 0)); |
1103 context_closure_lookup (c, | 1120 context_closure_lookup (c, |
1104 inputCount, input, | 1121 inputCount, input, |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 unsigned int lookupCount, | 1564 unsigned int lookupCount, |
1548 const LookupRecord lookupRecord
[], | 1565 const LookupRecord lookupRecord
[], |
1549 ChainContextClosureLookupContex
t &lookup_context) | 1566 ChainContextClosureLookupContex
t &lookup_context) |
1550 { | 1567 { |
1551 if (intersects_array (c, | 1568 if (intersects_array (c, |
1552 backtrackCount, backtrack, | 1569 backtrackCount, backtrack, |
1553 lookup_context.funcs.intersects, lookup_context.intersec
ts_data[0]) | 1570 lookup_context.funcs.intersects, lookup_context.intersec
ts_data[0]) |
1554 && intersects_array (c, | 1571 && intersects_array (c, |
1555 inputCount ? inputCount - 1 : 0, input, | 1572 inputCount ? inputCount - 1 : 0, input, |
1556 lookup_context.funcs.intersects, lookup_context.intersec
ts_data[1]) | 1573 lookup_context.funcs.intersects, lookup_context.intersec
ts_data[1]) |
1557 && intersects_array (c, | 1574 && intersects_array (c, |
1558 lookaheadCount, lookahead, | 1575 lookaheadCount, lookahead, |
1559 lookup_context.funcs.intersects, lookup_context.intersect
s_data[2])) | 1576 lookup_context.funcs.intersects, lookup_context.intersect
s_data[2])) |
1560 recurse_lookups (c, | 1577 recurse_lookups (c, |
1561 lookupCount, lookupRecord); | 1578 lookupCount, lookupRecord); |
1562 } | 1579 } |
1563 | 1580 |
1564 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex
t_t *c, | 1581 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex
t_t *c, |
1565 unsigned int backtrackCo
unt, | 1582 unsigned int backtrackCo
unt, |
1566 const USHORT backtrack[]
, | 1583 const USHORT backtrack[]
, |
1567 unsigned int inputCount,
/* Including the first glyph (not matched) */ | 1584 unsigned int inputCount,
/* Including the first glyph (not matched) */ |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 unsigned int backtrackCount, | 1623 unsigned int backtrackCount, |
1607 const USHORT backtrack[], | 1624 const USHORT backtrack[], |
1608 unsigned int inputCount, /* Inclu
ding the first glyph (not matched) */ | 1625 unsigned int inputCount, /* Inclu
ding the first glyph (not matched) */ |
1609 const USHORT input[], /* Array of
input values--start with second glyph */ | 1626 const USHORT input[], /* Array of
input values--start with second glyph */ |
1610 unsigned int lookaheadCount, | 1627 unsigned int lookaheadCount, |
1611 const USHORT lookahead[], | 1628 const USHORT lookahead[], |
1612 unsigned int lookupCount, | 1629 unsigned int lookupCount, |
1613 const LookupRecord lookupRecord[]
, | 1630 const LookupRecord lookupRecord[]
, |
1614 ChainContextApplyLookupContext &l
ookup_context) | 1631 ChainContextApplyLookupContext &l
ookup_context) |
1615 { | 1632 { |
1616 unsigned int lookahead_offset = 0; | 1633 unsigned int match_length = 0; |
| 1634 unsigned int match_positions[MAX_CONTEXT_LENGTH]; |
1617 return match_input (c, | 1635 return match_input (c, |
1618 inputCount, input, | 1636 inputCount, input, |
1619 lookup_context.funcs.match, lookup_context.match_data[1], | 1637 lookup_context.funcs.match, lookup_context.match_data[1], |
1620 » » &lookahead_offset) | 1638 » » &match_length, match_positions) |
1621 && match_backtrack (c, | 1639 && match_backtrack (c, |
1622 backtrackCount, backtrack, | 1640 backtrackCount, backtrack, |
1623 lookup_context.funcs.match, lookup_context.match_data[
0]) | 1641 lookup_context.funcs.match, lookup_context.match_data[
0]) |
1624 && match_lookahead (c, | 1642 && match_lookahead (c, |
1625 lookaheadCount, lookahead, | 1643 lookaheadCount, lookahead, |
1626 lookup_context.funcs.match, lookup_context.match_data[
2], | 1644 lookup_context.funcs.match, lookup_context.match_data[
2], |
1627 » » » lookahead_offset) | 1645 » » » match_length) |
1628 && apply_lookup (c, | 1646 && apply_lookup (c, |
1629 » » inputCount, input, | 1647 » » inputCount, match_positions, |
1630 » » lookup_context.funcs.match, lookup_context.match_data[1], | 1648 » » lookupCount, lookupRecord, |
1631 » » lookupCount, lookupRecord); | 1649 » » match_length); |
1632 } | 1650 } |
1633 | 1651 |
1634 struct ChainRule | 1652 struct ChainRule |
1635 { | 1653 { |
1636 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext
&lookup_context) const | 1654 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext
&lookup_context) const |
1637 { | 1655 { |
1638 TRACE_CLOSURE (this); | 1656 TRACE_CLOSURE (this); |
1639 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> >
(backtrack); | 1657 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> >
(backtrack); |
1640 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); | 1658 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); |
1641 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (l
ookahead); | 1659 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (l
ookahead); |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2270 lookupList; /* LookupList table */ | 2288 lookupList; /* LookupList table */ |
2271 public: | 2289 public: |
2272 DEFINE_SIZE_STATIC (10); | 2290 DEFINE_SIZE_STATIC (10); |
2273 }; | 2291 }; |
2274 | 2292 |
2275 | 2293 |
2276 } /* namespace OT */ | 2294 } /* namespace OT */ |
2277 | 2295 |
2278 | 2296 |
2279 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ | 2297 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ |
OLD | NEW |