2 * Copyright (C) 2007,2008 Red Hat, Inc.
4 * This is part of HarfBuzz, an OpenType Layout engine library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * Red Hat Author(s): Behdad Esfahbod
27 #ifndef HB_OT_LAYOUT_GSUB_PRIVATE_H
28 #define HB_OT_LAYOUT_GSUB_PRIVATE_H
30 #include "hb-ot-layout-private.h"
32 #include "hb-ot-layout-open-private.h"
33 #include "hb-ot-layout-gdef-private.h"
36 struct SingleSubstFormat1 {
38 friend struct SingleSubst;
41 inline bool substitute (hb_ot_layout_t *layout,
43 unsigned int context_length,
44 unsigned int nesting_level_left) const {
45 // if (get_coverage (IN_CURGLYPH()))
50 USHORT substFormat; /* Format identifier--format = 1 */
51 Offset coverage; /* Offset to Coverage table--from
52 * beginning of Substitution table */
53 SHORT deltaGlyphID; /* Add to original GlyphID to get
54 * substitute GlyphID */
56 ASSERT_SIZE (SingleSubstFormat1, 6);
58 struct SingleSubstFormat2 {
62 USHORT substFormat; /* Format identifier--format = 2 */
63 Offset coverage; /* Offset to Coverage table--from
64 * beginning of Substitution table */
65 USHORT glyphCount; /* Number of GlyphIDs in the Substitute
67 GlyphID substitute[]; /* Array of substitute
68 * GlyphIDs--ordered by Coverage Index */
70 ASSERT_SIZE (SingleSubstFormat2, 6);
72 struct MultipleSubstFormat1 {
76 USHORT substFormat; /* Format identifier--format = 1 */
77 Offset coverage; /* Offset to Coverage table--from
78 * beginning of Substitution table */
79 USHORT sequenceCount; /* Number of Sequence table offsets in
80 * the Sequence array */
81 Offset sequence[]; /* Array of offsets to Sequence
82 * tables--from beginning of
83 * Substitution table--ordered by
86 ASSERT_SIZE (MultipleSubstFormat1, 6);
92 USHORT glyphCount; /* Number of GlyphIDs in the Substitute
93 * array. This should always be
95 GlyphID substitute[]; /* String of GlyphIDs to substitute */
97 DEFINE_NULL_ASSERT_SIZE (Sequence, 2);
99 struct AlternateSubstFormat1 {
103 USHORT substFormat; /* Format identifier--format = 1 */
104 Offset coverage; /* Offset to Coverage table--from
105 * beginning of Substitution table */
106 USHORT alternateSetCount; /* Number of AlternateSet tables */
107 Offset alternateSet[]; /* Array of offsets to AlternateSet
108 * tables--from beginning of
109 * Substitution table--ordered by
112 ASSERT_SIZE (AlternateSubstFormat1, 6);
114 struct AlternateSet {
118 USHORT glyphCount; /* Number of GlyphIDs in the Alternate
120 GlyphID alternate[]; /* Array of alternate GlyphIDs--in
123 DEFINE_NULL_ASSERT_SIZE (AlternateSet, 2);
125 struct LigatureSubstFormat1 {
129 USHORT substFormat; /* Format identifier--format = 1 */
130 Offset coverage; /* Offset to Coverage table--from
131 * beginning of Substitution table */
132 USHORT ligSetCount; /* Number of LigatureSet tables */
133 Offset ligatureSet[]; /* Array of offsets to LigatureSet
134 * tables--from beginning of
135 * Substitution table--ordered by
138 ASSERT_SIZE (LigatureSubstFormat1, 6);
144 USHORT ligatureCount; /* Number of Ligature tables */
145 Offset ligature[]; /* Array of offsets to Ligature
146 * tables--from beginning of
147 * LigatureSet table--ordered by
150 DEFINE_NULL_ASSERT_SIZE (LigatureSet, 2);
156 GlyphID ligGlyph; /* GlyphID of ligature to substitute */
157 USHORT compCount; /* Number of components in the ligature */
158 GlyphID component[]; /* Array of component GlyphIDs--start
159 * with the second component--ordered
160 * in writing direction */
162 DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
164 struct SubstLookupRecord {
168 USHORT sequenceIndex; /* Index into current glyph
169 * sequence--first glyph = 0 */
170 USHORT lookupListIndex; /* Lookup to apply to that
171 * position--zero--based */
173 DEFINE_NULL_ASSERT_SIZE (SubstLookupRecord, 4);
175 struct ContextSubstFormat1 {
179 USHORT substFormat; /* Format identifier--format = 1 */
180 Offset coverage; /* Offset to Coverage table--from
181 * beginning of Substitution table */
182 USHORT subRuleSetCount; /* Number of SubRuleSet tables--must
183 * equal GlyphCount in Coverage table */
184 Offset subRuleSet[]; /* Array of offsets to SubRuleSet
185 * tables--from beginning of
186 * Substitution table--ordered by
189 ASSERT_SIZE (ContextSubstFormat1, 6);
195 USHORT subRuleCount; /* Number of SubRule tables */
196 Offset subRule[]; /* Array of offsets to SubRule
197 * tables--from beginning of SubRuleSet
198 * table--ordered by preference */
200 DEFINE_NULL_ASSERT_SIZE (SubRuleSet, 2);
206 USHORT glyphCount; /* Total number of glyphs in input
207 * glyph sequence--includes the first
209 USHORT substCount; /* Number of SubstLookupRecords */
210 GlyphID input[]; /* Array of input GlyphIDs--start with
212 SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
215 DEFINE_NULL_ASSERT_SIZE (SubRule, 4);
217 struct ContextSubstFormat2 {
221 USHORT substFormat; /* Format identifier--format = 2 */
222 Offset coverage; /* Offset to Coverage table--from
223 * beginning of Substitution table */
224 Offset classDef; /* Offset to glyph ClassDef table--from
225 * beginning of Substitution table */
226 USHORT subClassSetCnt; /* Number of SubClassSet tables */
227 Offset subClassSet[]; /* Array of offsets to SubClassSet
228 * tables--from beginning of
229 * Substitution table--ordered by
230 * class--may be NULL */
232 ASSERT_SIZE (ContextSubstFormat2, 8);
238 USHORT subClassRuleCnt; /* Number of SubClassRule tables */
239 Offset subClassRule[]; /* Array of offsets to SubClassRule
240 * tables--from beginning of
241 * SubClassSet--ordered by preference */
243 DEFINE_NULL_ASSERT_SIZE (SubClassSet, 2);
245 struct SubClassRule {
249 USHORT glyphCount; /* Total number of classes
250 * specified for the context in the
251 * rule--includes the first class */
252 USHORT substCount; /* Number of SubstLookupRecords */
253 USHORT klass[]; /* Array of classes--beginning with the
254 * second class--to be matched to the
255 * input glyph class sequence */
256 SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
259 DEFINE_NULL_ASSERT_SIZE (SubClassRule, 4);
261 struct ContextSubstFormat3 {
265 USHORT substFormat; /* Format identifier--format = 3 */
266 USHORT glyphCount; /* Number of glyphs in the input glyph
268 USHORT substCount; /* Number of SubstLookupRecords */
269 Offset coverage[]; /* Array of offsets to Coverage
270 * table--from beginning of
271 * Substitution table--in glyph
273 SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
276 ASSERT_SIZE (ContextSubstFormat3, 6);
278 struct ChainContextSubstFormat1 {
282 USHORT substFormat; /* Format identifier--format = 1 */
283 Offset coverage; /* Offset to Coverage table--from
284 * beginning of Substitution table */
285 USHORT chainSubRuleSetCount; /* Number of ChainSubRuleSet
286 * tables--must equal GlyphCount in
288 Offset chainSubRuleSet[]; /* Array of offsets to ChainSubRuleSet
289 * tables--from beginning of
290 * Substitution table--ordered by
293 ASSERT_SIZE (ChainContextSubstFormat1, 6);
295 struct ChainSubRuleSet {
299 USHORT chainSubRuleCount; /* Number of ChainSubRule tables */
300 Offset chainSubRule[]; /* Array of offsets to ChainSubRule
301 * tables--from beginning of
302 * ChainSubRuleSet table--ordered
305 DEFINE_NULL_ASSERT_SIZE (ChainSubRuleSet, 2);
307 struct ChainSubRule {
311 USHORT backtrackGlyphCount; /* Total number of glyphs in the
312 * backtrack sequence (number of
313 * glyphs to be matched before the
315 GlyphID backtrack[]; /* Array of backtracking GlyphID's
316 * (to be matched before the input
318 USHORT inputGlyphCount; /* Total number of glyphs in the input
319 * sequence (includes the first glyph) */
320 GlyphID input[]; /* Array of input GlyphIDs (start with
322 USHORT lookaheadGlyphCount; /* Total number of glyphs in the look
323 * ahead sequence (number of glyphs to
324 * be matched after the input sequence) */
325 GlyphID lookAhead[]; /* Array of lookahead GlyphID's (to be
326 * matched after the input sequence) */
327 USHORT substCount; /* Number of SubstLookupRecords */
328 SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
331 DEFINE_NULL_ASSERT_SIZE (ChainSubRule, 8);
333 struct ChainContextSubstFormat2 {
337 USHORT substFormat; /* Format identifier--format = 2 */
338 Offset coverage; /* Offset to Coverage table--from
339 * beginning of Substitution table */
340 Offset backtrackClassDef; /* Offset to glyph ClassDef table
341 * containing backtrack sequence
342 * data--from beginning of Substitution
344 Offset inputClassDef; /* Offset to glyph ClassDef
345 * table containing input sequence
346 * data--from beginning of Substitution
348 Offset lookaheadClassDef; /* Offset to glyph ClassDef table
349 * containing lookahead sequence
350 * data--from beginning of Substitution
352 USHORT chainSubClassSetCnt; /* Number of ChainSubClassSet tables */
353 Offset chainSubClassSet[]; /* Array of offsets to ChainSubClassSet
354 * tables--from beginning of
355 * Substitution table--ordered by input
356 * class--may be NULL */
358 ASSERT_SIZE (ChainContextSubstFormat2, 12);
360 struct ChainSubClassSet {
364 USHORT chainSubClassRuleCnt; /* Number of ChainSubClassRule tables */
365 Offset chainSubClassRule[]; /* Array of offsets
366 * to ChainSubClassRule
367 * tables--from beginning of
368 * ChainSubClassSet--ordered by
371 DEFINE_NULL_ASSERT_SIZE (ChainSubClassSet, 2);
373 struct ChainSubClassRule {
377 USHORT backtrackGlyphCount; /* Total number of glyphs in the
378 * backtrack sequence (number of
379 * glyphs to be matched before the
381 USHORT backtrack[]; /* Array of backtracking classes(to be
382 * matched before the input sequence) */
383 USHORT inputGlyphCount; /* Total number of classes in the input
384 * sequence (includes the first class) */
385 USHORT input[]; /* Array of input classes(start with
386 * second class; to be matched with
387 * the input glyph sequence) */
388 USHORT lookaheadGlyphCount; /* Total number of classes in the
389 * look ahead sequence (number of
390 * classes to be matched after the
392 USHORT lookAhead[]; /* Array of lookahead classes(to be
393 * matched after the input sequence) */
394 USHORT substCount; /* Number of SubstLookupRecords */
395 SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
398 DEFINE_NULL_ASSERT_SIZE (ChainSubClassRule, 8);
400 struct ChainContextSubstFormat3 {
404 USHORT substFormat; /* Format identifier--format = 3 */
405 USHORT backtrackGlyphCount; /* Number of glyphs in the backtracking
407 Offset backtrackCoverage[]; /* Array of offsets to coverage tables
408 * in backtracking sequence, in glyph
410 USHORT inputGlyphCount; /* Number of glyphs in input sequence */
411 Offset inputCoverage[]; /* Array of offsets to coverage
412 * tables in input sequence, in glyph
414 USHORT lookaheadGlyphCount; /* Number of glyphs in lookahead
416 Offset lookaheadCoverage[]; /* Array of offsets to coverage tables
417 * in lookahead sequence, in glyph
419 USHORT substCount; /* Number of SubstLookupRecords */
420 SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
423 ASSERT_SIZE (ChainContextSubstFormat3, 10);
425 struct ExtensionSubstFormat1 {
429 USHORT substFormat; /* Format identifier. Set to 1. */
430 USHORT extensionLookupType; /* Lookup type of subtable referenced
431 * by ExtensionOffset (i.e. the
432 * extension subtable). */
433 ULONG extensionOffset; /* Offset to the extension subtable,
434 * of lookup type subtable. */
436 ASSERT_SIZE (ExtensionSubstFormat1, 8);
438 struct ReverseChainSingleSubstFormat1 {
442 USHORT substFormat; /* Format identifier--format = 1 */
443 Offset coverage; /* Offset to Coverage table -- from
444 * beginning of Substitution table */
445 USHORT backtrackGlyphCount; /* Number of glyphs in the backtracking
447 Offset backtrackCoverage[]; /* Array of offsets to coverage tables
448 * in backtracking sequence, in glyph
450 USHORT lookaheadGlyphCount; /* Number of glyphs in lookahead
452 Offset lookaheadCoverage[]; /* Array of offsets to coverage tables
453 * in lookahead sequence, in glyph
455 USHORT glyphCount; /* Number of GlyphIDs in the Substitute
457 GlyphID substitute[]; /* Array of substitute
458 * GlyphIDs--ordered by Coverage Index */
460 ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10);
466 struct SubstLookupSubTable {
467 DEFINE_NON_INSTANTIABLE(SubstLookupSubTable);
469 friend struct SubstLookup;
471 unsigned int get_size (unsigned int lookup_type) const {
472 switch (lookup_type) {
473 // case 1: return u.format1.get_size ();
474 // case 2: return u.format2.get_size ();
481 case ChainingContext:
483 case ReverseChainingContextSingle:
485 default:return sizeof (LookupSubTable);
489 inline bool substitute (hb_ot_layout_t *layout,
491 unsigned int context_length,
492 unsigned int nesting_level_left,
493 unsigned int lookup_type) const {
499 CoverageFormat1 format1;
500 CoverageFormat2 format2;
504 struct SubstLookup : Lookup {
506 DEFINE_NON_INSTANTIABLE(SubstLookup);
508 static const unsigned int Single = 1;
509 static const unsigned int Multiple = 2;
510 static const unsigned int Alternate = 3;
511 static const unsigned int Ligature = 4;
512 static const unsigned int Context = 5;
513 static const unsigned int ChainingContext = 6;
514 static const unsigned int Extension = 7;
515 static const unsigned int ReverseChainingContextSingle = 8;
517 inline const SubstLookupSubTable& get_subtable (unsigned int i) const {
518 return *(SubstLookupSubTable*)&(((Lookup *)this)->get_subtable (i));
521 /* Like get_type(), but looks through extension lookups.
522 * Never returns SubstLookup::Extension */
523 inline unsigned int get_effective_type (void) const {
524 unsigned int type = get_type ();
526 if (HB_UNLIKELY (type == Extension)) {
527 /* Return lookup type of first extension subtable.
528 * The spec says all of them should have the same type.
529 * XXX check for that somehow */
530 //XXX type = get_subtable(0).v.extension.get_type ();
536 inline bool is_reverse (void) const {
537 switch (get_effective_type ()) {
538 case ReverseChainingContextSingle: return true;
539 default: return false;
543 inline bool substitute (hb_ot_layout_t *layout,
545 unsigned int context_length,
546 unsigned int nesting_level_left) const {
547 unsigned int lookup_type = get_type ();
549 if (HB_UNLIKELY (nesting_level_left == 0))
551 nesting_level_left--;
553 for (unsigned int i = 0; i < get_subtable_count (); i++)
554 if (get_subtable (i).substitute (layout, buffer,
555 context_length, nesting_level_left,
562 DEFINE_NULL_ALIAS (SubstLookup, Lookup);
568 struct GSUB : GSUBGPOS {
569 static const hb_tag_t Tag = HB_TAG ('G','S','U','B');
571 STATIC_DEFINE_GET_FOR_DATA (GSUB);
572 /* XXX check version here? */
574 inline const SubstLookup& get_lookup (unsigned int i) const {
575 return *(SubstLookup*)&(((GSUBGPOS *)this)->get_lookup (i));
580 DEFINE_NULL_ALIAS (GSUB, GSUBGPOS);
583 #endif /* HB_OT_LAYOUT_GSUB_PRIVATE_H */