Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: third_party/harfbuzz-ng/src/hb-ot-layout-gsub-private.hh

Issue 9223010: Update harfbuzz-ng to 1a5a91dc0d8bf4b72a2f22dc6300b06ad7000b79. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Don't use -M option for 'git diff' to patch correctly Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc.
3 * Copyright (C) 2010 Google, Inc.
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod
27 */
28
29 #ifndef HB_OT_LAYOUT_GSUB_PRIVATE_HH
30 #define HB_OT_LAYOUT_GSUB_PRIVATE_HH
31
32 #include "hb-ot-layout-gsubgpos-private.hh"
33
34 HB_BEGIN_DECLS
35
36
37 struct SingleSubstFormat1
38 {
39 friend struct SingleSubst;
40
41 private:
42
43 inline bool apply (hb_apply_context_t *c) const
44 {
45 TRACE_APPLY ();
46 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
47 unsigned int index = (this+coverage) (glyph_id);
48 if (likely (index == NOT_COVERED))
49 return false;
50
51 glyph_id += deltaGlyphID;
52 c->replace_glyph (glyph_id);
53
54 return true;
55 }
56
57 inline bool sanitize (hb_sanitize_context_t *c) {
58 TRACE_SANITIZE ();
59 return coverage.sanitize (c, this)
60 && deltaGlyphID.sanitize (c);
61 }
62
63 private:
64 USHORT format; /* Format identifier--format = 1 */
65 OffsetTo<Coverage>
66 coverage; /* Offset to Coverage table--from
67 * beginning of Substitution table */
68 SHORT deltaGlyphID; /* Add to original GlyphID to get
69 * substitute GlyphID */
70 public:
71 DEFINE_SIZE_STATIC (6);
72 };
73
74 struct SingleSubstFormat2
75 {
76 friend struct SingleSubst;
77
78 private:
79
80 inline bool apply (hb_apply_context_t *c) const
81 {
82 TRACE_APPLY ();
83 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
84 unsigned int index = (this+coverage) (glyph_id);
85 if (likely (index == NOT_COVERED))
86 return false;
87
88 if (unlikely (index >= substitute.len))
89 return false;
90
91 glyph_id = substitute[index];
92 c->replace_glyph (glyph_id);
93
94 return true;
95 }
96
97 inline bool sanitize (hb_sanitize_context_t *c) {
98 TRACE_SANITIZE ();
99 return coverage.sanitize (c, this)
100 && substitute.sanitize (c);
101 }
102
103 private:
104 USHORT format; /* Format identifier--format = 2 */
105 OffsetTo<Coverage>
106 coverage; /* Offset to Coverage table--from
107 * beginning of Substitution table */
108 ArrayOf<GlyphID>
109 substitute; /* Array of substitute
110 * GlyphIDs--ordered by Coverage Index * /
111 public:
112 DEFINE_SIZE_ARRAY (6, substitute);
113 };
114
115 struct SingleSubst
116 {
117 friend struct SubstLookupSubTable;
118
119 private:
120
121 inline bool apply (hb_apply_context_t *c) const
122 {
123 TRACE_APPLY ();
124 switch (u.format) {
125 case 1: return u.format1.apply (c);
126 case 2: return u.format2.apply (c);
127 default:return false;
128 }
129 }
130
131 inline bool sanitize (hb_sanitize_context_t *c) {
132 TRACE_SANITIZE ();
133 if (!u.format.sanitize (c)) return false;
134 switch (u.format) {
135 case 1: return u.format1.sanitize (c);
136 case 2: return u.format2.sanitize (c);
137 default:return true;
138 }
139 }
140
141 private:
142 union {
143 USHORT format; /* Format identifier */
144 SingleSubstFormat1 format1;
145 SingleSubstFormat2 format2;
146 } u;
147 };
148
149
150 struct Sequence
151 {
152 friend struct MultipleSubstFormat1;
153
154 private:
155 inline bool apply (hb_apply_context_t *c) const
156 {
157 TRACE_APPLY ();
158 if (unlikely (!substitute.len))
159 return false;
160
161 if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)
162 c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH);
163 c->replace_glyphs_be16 (1, substitute.len, (const uint16_t *) substitute.arr ay);
164
165 return true;
166 }
167
168 public:
169 inline bool sanitize (hb_sanitize_context_t *c) {
170 TRACE_SANITIZE ();
171 return substitute.sanitize (c);
172 }
173
174 private:
175 ArrayOf<GlyphID>
176 substitute; /* String of GlyphIDs to substitute */
177 public:
178 DEFINE_SIZE_ARRAY (2, substitute);
179 };
180
181 struct MultipleSubstFormat1
182 {
183 friend struct MultipleSubst;
184
185 private:
186
187 inline bool apply (hb_apply_context_t *c) const
188 {
189 TRACE_APPLY ();
190
191 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin t);
192 if (likely (index == NOT_COVERED))
193 return false;
194
195 return (this+sequence[index]).apply (c);
196 }
197
198 inline bool sanitize (hb_sanitize_context_t *c) {
199 TRACE_SANITIZE ();
200 return coverage.sanitize (c, this)
201 && sequence.sanitize (c, this);
202 }
203
204 private:
205 USHORT format; /* Format identifier--format = 1 */
206 OffsetTo<Coverage>
207 coverage; /* Offset to Coverage table--from
208 * beginning of Substitution table */
209 OffsetArrayOf<Sequence>
210 sequence; /* Array of Sequence tables
211 * ordered by Coverage Index */
212 public:
213 DEFINE_SIZE_ARRAY (6, sequence);
214 };
215
216 struct MultipleSubst
217 {
218 friend struct SubstLookupSubTable;
219
220 private:
221
222 inline bool apply (hb_apply_context_t *c) const
223 {
224 TRACE_APPLY ();
225 switch (u.format) {
226 case 1: return u.format1.apply (c);
227 default:return false;
228 }
229 }
230
231 inline bool sanitize (hb_sanitize_context_t *c) {
232 TRACE_SANITIZE ();
233 if (!u.format.sanitize (c)) return false;
234 switch (u.format) {
235 case 1: return u.format1.sanitize (c);
236 default:return true;
237 }
238 }
239
240 private:
241 union {
242 USHORT format; /* Format identifier */
243 MultipleSubstFormat1 format1;
244 } u;
245 };
246
247
248 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in
249 * arbitrary order */
250
251 struct AlternateSubstFormat1
252 {
253 friend struct AlternateSubst;
254
255 private:
256
257 inline bool apply (hb_apply_context_t *c) const
258 {
259 TRACE_APPLY ();
260 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
261 hb_mask_t glyph_mask = c->buffer->info[c->buffer->i].mask;
262 hb_mask_t lookup_mask = c->lookup_mask;
263
264 unsigned int index = (this+coverage) (glyph_id);
265 if (likely (index == NOT_COVERED))
266 return false;
267
268 const AlternateSet &alt_set = this+alternateSet[index];
269
270 if (unlikely (!alt_set.len))
271 return false;
272
273 /* Note: This breaks badly if two features enabled this lookup together. */
274 unsigned int shift = _hb_ctz (lookup_mask);
275 unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
276
277 if (unlikely (alt_index > alt_set.len || alt_index == 0))
278 return false;
279
280 glyph_id = alt_set[alt_index - 1];
281
282 c->replace_glyph (glyph_id);
283
284 return true;
285 }
286
287 inline bool sanitize (hb_sanitize_context_t *c) {
288 TRACE_SANITIZE ();
289 return coverage.sanitize (c, this)
290 && alternateSet.sanitize (c, this);
291 }
292
293 private:
294 USHORT format; /* Format identifier--format = 1 */
295 OffsetTo<Coverage>
296 coverage; /* Offset to Coverage table--from
297 * beginning of Substitution table */
298 OffsetArrayOf<AlternateSet>
299 alternateSet; /* Array of AlternateSet tables
300 * ordered by Coverage Index */
301 public:
302 DEFINE_SIZE_ARRAY (6, alternateSet);
303 };
304
305 struct AlternateSubst
306 {
307 friend struct SubstLookupSubTable;
308
309 private:
310
311 inline bool apply (hb_apply_context_t *c) const
312 {
313 TRACE_APPLY ();
314 switch (u.format) {
315 case 1: return u.format1.apply (c);
316 default:return false;
317 }
318 }
319
320 inline bool sanitize (hb_sanitize_context_t *c) {
321 TRACE_SANITIZE ();
322 if (!u.format.sanitize (c)) return false;
323 switch (u.format) {
324 case 1: return u.format1.sanitize (c);
325 default:return true;
326 }
327 }
328
329 private:
330 union {
331 USHORT format; /* Format identifier */
332 AlternateSubstFormat1 format1;
333 } u;
334 };
335
336
337 struct Ligature
338 {
339 friend struct LigatureSet;
340
341 private:
342 inline bool apply (hb_apply_context_t *c) const
343 {
344 TRACE_APPLY ();
345 unsigned int i, j;
346 unsigned int count = component.len;
347 unsigned int end = MIN (c->buffer->len, c->buffer->i + c->context_length);
348 if (unlikely (count < 2 || c->buffer->i + count > end))
349 return false;
350
351 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
352 bool found_non_mark = false;
353
354 for (i = 1, j = c->buffer->i + 1; i < count; i++, j++)
355 {
356 unsigned int property;
357 while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->l ookup_props, &property))
358 {
359 if (unlikely (j + count - i == end))
360 return false;
361 j++;
362 }
363
364 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
365
366 if (likely (c->buffer->info[j].codepoint != component[i]))
367 return false;
368 }
369
370 if (first_was_mark && found_non_mark)
371 c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE);
372
373 /* Allocate new ligature id */
374 unsigned int lig_id = allocate_lig_id (c->buffer);
375 c->buffer->info[c->buffer->i].lig_comp() = 0;
376 c->buffer->info[c->buffer->i].lig_id() = lig_id;
377
378 if (j == c->buffer->i + i) /* No input glyphs skipped */
379 {
380 c->replace_glyphs_be16 (i, 1, (const uint16_t *) &ligGlyph);
381 }
382 else
383 {
384 c->replace_glyph (ligGlyph);
385
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
388 glyph after the first component. Glyphs between component
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
391 component value really belongs to a given ligature. */
392
393 for (i = 1; i < count; i++)
394 {
395 while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[c->buf fer->i], c->lookup_props, NULL))
396 {
397 c->buffer->info[c->buffer->i].lig_comp() = i;
398 c->buffer->info[c->buffer->i].lig_id() = lig_id;
399 c->replace_glyph (c->buffer->info[c->buffer->i].codepoint);
400 }
401
402 /* Skip the base glyph */
403 c->buffer->i++;
404 }
405 }
406
407 return true;
408 }
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:
417 inline bool sanitize (hb_sanitize_context_t *c) {
418 TRACE_SANITIZE ();
419 return ligGlyph.sanitize (c)
420 && component.sanitize (c);
421 }
422
423 private:
424 GlyphID ligGlyph; /* GlyphID of ligature to substitute */
425 HeadlessArrayOf<GlyphID>
426 component; /* Array of component GlyphIDs--start
427 * with the second component--ordered
428 * in writing direction */
429 public:
430 DEFINE_SIZE_ARRAY (4, component);
431 };
432
433 struct LigatureSet
434 {
435 friend struct LigatureSubstFormat1;
436
437 private:
438 inline bool apply (hb_apply_context_t *c) const
439 {
440 TRACE_APPLY ();
441 unsigned int num_ligs = ligature.len;
442 for (unsigned int i = 0; i < num_ligs; i++)
443 {
444 const Ligature &lig = this+ligature[i];
445 if (lig.apply (c))
446 return true;
447 }
448
449 return false;
450 }
451
452 public:
453 inline bool sanitize (hb_sanitize_context_t *c) {
454 TRACE_SANITIZE ();
455 return ligature.sanitize (c, this);
456 }
457
458 private:
459 OffsetArrayOf<Ligature>
460 ligature; /* Array LigatureSet tables
461 * ordered by preference */
462 public:
463 DEFINE_SIZE_ARRAY (2, ligature);
464 };
465
466 struct LigatureSubstFormat1
467 {
468 friend struct LigatureSubst;
469
470 private:
471 inline bool apply (hb_apply_context_t *c) const
472 {
473 TRACE_APPLY ();
474 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->i].codepoint;
475
476 unsigned int index = (this+coverage) (glyph_id);
477 if (likely (index == NOT_COVERED))
478 return false;
479
480 const LigatureSet &lig_set = this+ligatureSet[index];
481 return lig_set.apply (c);
482 }
483
484 inline bool sanitize (hb_sanitize_context_t *c) {
485 TRACE_SANITIZE ();
486 return coverage.sanitize (c, this)
487 && ligatureSet.sanitize (c, this);
488 }
489
490 private:
491 USHORT format; /* Format identifier--format = 1 */
492 OffsetTo<Coverage>
493 coverage; /* Offset to Coverage table--from
494 * beginning of Substitution table */
495 OffsetArrayOf<LigatureSet>
496 ligatureSet; /* Array LigatureSet tables
497 * ordered by Coverage Index */
498 public:
499 DEFINE_SIZE_ARRAY (6, ligatureSet);
500 };
501
502 struct LigatureSubst
503 {
504 friend struct SubstLookupSubTable;
505
506 private:
507 inline bool apply (hb_apply_context_t *c) const
508 {
509 TRACE_APPLY ();
510 switch (u.format) {
511 case 1: return u.format1.apply (c);
512 default:return false;
513 }
514 }
515
516 inline bool sanitize (hb_sanitize_context_t *c) {
517 TRACE_SANITIZE ();
518 if (!u.format.sanitize (c)) return false;
519 switch (u.format) {
520 case 1: return u.format1.sanitize (c);
521 default:return true;
522 }
523 }
524
525 private:
526 union {
527 USHORT format; /* Format identifier */
528 LigatureSubstFormat1 format1;
529 } u;
530 };
531
532
533 HB_BEGIN_DECLS
534 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index);
535 HB_END_DECLS
536
537 struct ContextSubst : Context
538 {
539 friend struct SubstLookupSubTable;
540
541 private:
542 inline bool apply (hb_apply_context_t *c) const
543 {
544 TRACE_APPLY ();
545 return Context::apply (c, substitute_lookup);
546 }
547 };
548
549 struct ChainContextSubst : ChainContext
550 {
551 friend struct SubstLookupSubTable;
552
553 private:
554 inline bool apply (hb_apply_context_t *c) const
555 {
556 TRACE_APPLY ();
557 return ChainContext::apply (c, substitute_lookup);
558 }
559 };
560
561
562 struct ExtensionSubst : Extension
563 {
564 friend struct SubstLookupSubTable;
565 friend struct SubstLookup;
566
567 private:
568 inline const struct SubstLookupSubTable& get_subtable (void) const
569 {
570 unsigned int offset = get_offset ();
571 if (unlikely (!offset)) return Null(SubstLookupSubTable);
572 return StructAtOffset<SubstLookupSubTable> (this, offset);
573 }
574
575 inline bool apply (hb_apply_context_t *c) const;
576
577 inline bool sanitize (hb_sanitize_context_t *c);
578
579 inline bool is_reverse (void) const;
580 };
581
582
583 struct ReverseChainSingleSubstFormat1
584 {
585 friend struct ReverseChainSingleSubst;
586
587 private:
588 inline bool apply (hb_apply_context_t *c) const
589 {
590 TRACE_APPLY ();
591 if (unlikely (c->context_length != NO_CONTEXT))
592 return false; /* No chaining to this type */
593
594 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->i].codepoin t);
595 if (likely (index == NOT_COVERED))
596 return false;
597
598 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag e> > (backtrack);
599 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad);
600
601 if (match_backtrack (c,
602 backtrack.len, (USHORT *) backtrack.array,
603 match_coverage, this) &&
604 match_lookahead (c,
605 lookahead.len, (USHORT *) lookahead.array,
606 match_coverage, this,
607 1))
608 {
609 c->buffer->info[c->buffer->i].codepoint = substitute[index];
610 c->buffer->i--; /* Reverse! */
611 return true;
612 }
613
614 return false;
615 }
616
617 inline bool sanitize (hb_sanitize_context_t *c) {
618 TRACE_SANITIZE ();
619 if (!(coverage.sanitize (c, this)
620 && backtrack.sanitize (c, this)))
621 return false;
622 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > ( backtrack);
623 if (!lookahead.sanitize (c, this))
624 return false;
625 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
626 return substitute.sanitize (c);
627 }
628
629 private:
630 USHORT format; /* Format identifier--format = 1 */
631 OffsetTo<Coverage>
632 coverage; /* Offset to Coverage table--from
633 * beginning of table */
634 OffsetArrayOf<Coverage>
635 backtrack; /* Array of coverage tables
636 * in backtracking sequence, in glyph
637 * sequence order */
638 OffsetArrayOf<Coverage>
639 lookaheadX; /* Array of coverage tables
640 * in lookahead sequence, in glyph
641 * sequence order */
642 ArrayOf<GlyphID>
643 substituteX; /* Array of substitute
644 * GlyphIDs--ordered by Coverage Index * /
645 public:
646 DEFINE_SIZE_MIN (10);
647 };
648
649 struct ReverseChainSingleSubst
650 {
651 friend struct SubstLookupSubTable;
652
653 private:
654 inline bool apply (hb_apply_context_t *c) const
655 {
656 TRACE_APPLY ();
657 switch (u.format) {
658 case 1: return u.format1.apply (c);
659 default:return false;
660 }
661 }
662
663 inline bool sanitize (hb_sanitize_context_t *c) {
664 TRACE_SANITIZE ();
665 if (!u.format.sanitize (c)) return false;
666 switch (u.format) {
667 case 1: return u.format1.sanitize (c);
668 default:return true;
669 }
670 }
671
672 private:
673 union {
674 USHORT format; /* Format identifier */
675 ReverseChainSingleSubstFormat1 format1;
676 } u;
677 };
678
679
680
681 /*
682 * SubstLookup
683 */
684
685 struct SubstLookupSubTable
686 {
687 friend struct SubstLookup;
688
689 enum {
690 Single = 1,
691 Multiple = 2,
692 Alternate = 3,
693 Ligature = 4,
694 Context = 5,
695 ChainContext = 6,
696 Extension = 7,
697 ReverseChainSingle = 8
698 };
699
700 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const
701 {
702 TRACE_APPLY ();
703 switch (lookup_type) {
704 case Single: return u.single.apply (c);
705 case Multiple: return u.multiple.apply (c);
706 case Alternate: return u.alternate.apply (c);
707 case Ligature: return u.ligature.apply (c);
708 case Context: return u.c.apply (c);
709 case ChainContext: return u.chainContext.apply (c);
710 case Extension: return u.extension.apply (c);
711 case ReverseChainSingle: return u.reverseChainContextSingle.apply (c);
712 default:return false;
713 }
714 }
715
716 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
717 TRACE_SANITIZE ();
718 switch (lookup_type) {
719 case Single: return u.single.sanitize (c);
720 case Multiple: return u.multiple.sanitize (c);
721 case Alternate: return u.alternate.sanitize (c);
722 case Ligature: return u.ligature.sanitize (c);
723 case Context: return u.c.sanitize (c);
724 case ChainContext: return u.chainContext.sanitize (c);
725 case Extension: return u.extension.sanitize (c);
726 case ReverseChainSingle: return u.reverseChainContextSingle.sanitize (c);
727 default:return true;
728 }
729 }
730
731 private:
732 union {
733 USHORT sub_format;
734 SingleSubst single;
735 MultipleSubst multiple;
736 AlternateSubst alternate;
737 LigatureSubst ligature;
738 ContextSubst c;
739 ChainContextSubst chainContext;
740 ExtensionSubst extension;
741 ReverseChainSingleSubst reverseChainContextSingle;
742 } u;
743 public:
744 DEFINE_SIZE_UNION (2, sub_format);
745 };
746
747
748 struct SubstLookup : Lookup
749 {
750 inline const SubstLookupSubTable& get_subtable (unsigned int i) const
751 { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; }
752
753 inline static bool lookup_type_is_reverse (unsigned int lookup_type)
754 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
755
756 inline bool is_reverse (void) const
757 {
758 unsigned int type = get_type ();
759 if (unlikely (type == SubstLookupSubTable::Extension))
760 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
761 return lookup_type_is_reverse (type);
762 }
763
764
765 inline bool apply_once (hb_ot_layout_context_t *layout,
766 hb_buffer_t *buffer,
767 hb_mask_t lookup_mask,
768 unsigned int context_length,
769 unsigned int nesting_level_left) const
770 {
771 unsigned int lookup_type = get_type ();
772 hb_apply_context_t c[1] = {{0}};
773
774 c->layout = layout;
775 c->buffer = buffer;
776 c->lookup_mask = lookup_mask;
777 c->context_length = context_length;
778 c->nesting_level_left = nesting_level_left;
779 c->lookup_props = get_props ();
780
781 if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c ->buffer->i], c->lookup_props, &c->property))
782 return false;
783
784 if (unlikely (lookup_type == SubstLookupSubTable::Extension))
785 {
786 /* The spec says all subtables should have the same type.
787 * This is specially important if one has a reverse type!
788 *
789 * This is rather slow to do this here for every glyph,
790 * but it's easiest, and who uses extension lookups anyway?!*/
791 unsigned int count = get_subtable_count ();
792 unsigned int type = get_subtable(0).u.extension.get_type ();
793 for (unsigned int i = 1; i < count; i++)
794 if (get_subtable(i).u.extension.get_type () != type)
795 return false;
796 }
797
798 unsigned int count = get_subtable_count ();
799 for (unsigned int i = 0; i < count; i++)
800 if (get_subtable (i).apply (c, lookup_type))
801 return true;
802
803 return false;
804 }
805
806 inline bool apply_string (hb_ot_layout_context_t *layout,
807 hb_buffer_t *buffer,
808 hb_mask_t mask) const
809 {
810 bool ret = false;
811
812 if (unlikely (!buffer->len))
813 return false;
814
815 if (likely (!is_reverse ()))
816 {
817 /* in/out forward substitution */
818 buffer->clear_output ();
819 buffer->i = 0;
820 while (buffer->i < buffer->len)
821 {
822 if ((buffer->info[buffer->i].mask & mask) &&
823 apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
824 ret = true;
825 else
826 buffer->next_glyph ();
827
828 }
829 if (ret)
830 buffer->swap ();
831 }
832 else
833 {
834 /* in-place backward substitution */
835 buffer->i = buffer->len - 1;
836 do
837 {
838 if ((buffer->info[buffer->i].mask & mask) &&
839 apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
840 ret = true;
841 else
842 buffer->i--;
843
844 }
845 while ((int) buffer->i >= 0);
846 }
847
848 return ret;
849 }
850
851 inline bool sanitize (hb_sanitize_context_t *c) {
852 TRACE_SANITIZE ();
853 if (unlikely (!Lookup::sanitize (c))) return false;
854 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu bTable> > (subTable);
855 return list.sanitize (c, this, get_type ());
856 }
857 };
858
859 typedef OffsetListOf<SubstLookup> SubstLookupList;
860
861 /*
862 * GSUB
863 */
864
865 struct GSUB : GSUBGPOS
866 {
867 static const hb_tag_t Tag = HB_OT_TAG_GSUB;
868
869 inline const SubstLookup& get_lookup (unsigned int i) const
870 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
871
872 inline bool substitute_lookup (hb_ot_layout_context_t *layout,
873 hb_buffer_t *buffer,
874 unsigned int lookup_index,
875 hb_mask_t mask) const
876 { return get_lookup (lookup_index).apply_string (layout, buffer, mask); }
877
878 inline bool sanitize (hb_sanitize_context_t *c) {
879 TRACE_SANITIZE ();
880 if (unlikely (!GSUBGPOS::sanitize (c))) return false;
881 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL ist);
882 return list.sanitize (c, this);
883 }
884 public:
885 DEFINE_SIZE_STATIC (10);
886 };
887
888
889 /* Out-of-class implementation for methods recursing */
890
891 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const
892 {
893 TRACE_APPLY ();
894 return get_subtable ().apply (c, get_type ());
895 }
896
897 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c)
898 {
899 TRACE_SANITIZE ();
900 if (unlikely (!Extension::sanitize (c))) return false;
901 unsigned int offset = get_offset ();
902 if (unlikely (!offset)) return true;
903 return StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_typ e ());
904 }
905
906 inline bool ExtensionSubst::is_reverse (void) const
907 {
908 unsigned int type = get_type ();
909 if (unlikely (type == SubstLookupSubTable::Extension))
910 return CastR<ExtensionSubst> (get_subtable()).is_reverse ();
911 return SubstLookup::lookup_type_is_reverse (type);
912 }
913
914 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index)
915 {
916 const GSUB &gsub = *(c->layout->face->ot_layout->gsub);
917 const SubstLookup &l = gsub.get_lookup (lookup_index);
918
919 if (unlikely (c->nesting_level_left == 0))
920 return false;
921
922 if (unlikely (c->context_length < 1))
923 return false;
924
925 return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
926 }
927
928
929 HB_END_DECLS
930
931 #endif /* HB_OT_LAYOUT_GSUB_PRIVATE_HH */
OLDNEW
« no previous file with comments | « third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh ('k') | third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698