1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
32 /* Return nonzero if OTF_Glyph *G should be ignored according to
34 #define IGNORED_GLYPH(g, flag) \
36 || ((flag) & (1 << (g)->GlyphClass)) \
37 || (((flag) & OTF_MarkAttachmentType) \
38 && (g)->GlyphClass == OTF_GlyphClassMark \
39 && ((flag) >> 8) != (g)->MarkAttachClass))
41 #define GSTRING_DELETE(gstring, from, len) \
43 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
44 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
45 gstring->used -= len; \
49 #define GSTRING_INSERT(gstring, pos, len) \
51 if (gstring->used + len > gstring->size) \
53 char *errfmt = "GSTRING%s"; \
55 gstring->size = gstring->used + len; \
57 = (OTF_Glyph *) realloc (gstring->glyphs, \
58 sizeof (OTF_Glyph) * gstring->size); \
59 if (! gstring->glyphs) \
60 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
62 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
63 sizeof (OTF_Glyph) * (gstring->used - pos)); \
64 gstring->used += len; \
69 gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag,
70 OTF_GlyphID *ids, int num)
75 int c = gstring->glyphs[from].c;
76 int from_idx = gstring->glyphs[from].f.index.from;
77 int to_idx = gstring->glyphs[to - 1].f.index.to;
80 for (i = non_ignored_idx = to - 1; i >= from; i--)
82 OTF_Glyph *g = gstring->glyphs + i;
83 if (IGNORED_GLYPH (g, flag))
87 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
88 gstring->glyphs[non_ignored_idx--] = temp;
94 GSTRING_INSERT (gstring, from, (num - len));
96 GSTRING_DELETE (gstring, from, (len - num));
97 for (i = 0; i < num; i++)
99 gstring->glyphs[from + i].c = c;
100 gstring->glyphs[from + i].glyph_id = ids[i];
101 gstring->glyphs[from + i].f.index.from = from_idx;
102 gstring->glyphs[from + i].f.index.to = to_idx;
109 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
113 if (coverage->CoverageFormat == 1)
115 for (i = 0; i < coverage->Count; i++)
116 if (coverage->table.GlyphArray[i] == id)
121 for (i = 0; i < coverage->Count; i++)
122 if (coverage->table.RangeRecord[i].Start <= id
123 && coverage->table.RangeRecord[i].End >= id)
124 return (coverage->table.RangeRecord[i].StartCoverageIndex
125 + (id - coverage->table.RangeRecord[i].Start));
131 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
133 if (class_def->ClassFormat == 1)
135 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
137 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
138 return class_def->f.f1.ClassValueArray[idx];
144 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
145 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
146 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
147 return class_def->f.f2.ClassRangeRecord[i].Class;
153 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
156 OTF_Tag script_tag = OTF_tag (script);
157 OTF_Tag langsys_tag = OTF_tag (language);
159 OTF_Tag dflt_tag = OTF_tag ("DFLT");
160 OTF_Script *dflt = NULL;
162 for (i = 0; i < script_list->ScriptCount; i++)
164 OTF_Script *script = script_list->Script + i;
166 if (script_list->Script[i].ScriptTag == dflt_tag)
168 if (script_list->Script[i].ScriptTag == script_tag)
171 return &script->DefaultLangSys;
172 for (j = 0; j < script->LangSysCount; j++)
173 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
174 return script->LangSys + j;
175 return &script->DefaultLangSys;
180 dflt = script_list->Script;
182 return &dflt->DefaultLangSys;
183 for (j = 0; j < dflt->LangSysCount; j++)
184 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
185 return dflt->LangSys + j;
186 return &dflt->DefaultLangSys;
190 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
191 char *features, int *lookup_indices)
194 OTF_Feature *feature;
195 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
197 for (i = 0; i < FeatureList->FeatureCount; i++)
198 feature_table[i] = 0;
206 if (*features == '*')
208 /* Consume all remaining features. */
209 for (i = 0; i < FeatureList->FeatureCount; i++)
210 if (! feature_table[i])
212 feature = FeatureList->Feature + i;
213 for (j = 0; j < feature->LookupCount; j++)
214 lookup_indices[n++] = feature->LookupListIndex[j];
219 if (*features == '~')
220 use_it = -1, features++;
221 for (i = 0; *features && *features != ','; i++, features++)
222 tagname[i] = *features;
228 tag = OTF_tag (tagname);
229 for (i = 0; i < FeatureList->FeatureCount; i++)
231 feature = FeatureList->Feature + i;
232 if (tag == feature->FeatureTag)
234 if (feature_table[i])
237 for (j = 0; j < feature->LookupCount; j++)
238 lookup_indices[n++] = feature->LookupListIndex[j];
239 feature_table[i] = use_it;
249 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
250 int count, OTF_GlyphID *ids)
252 OTF_Glyph *gbeg = gstring->glyphs + gidx;
253 OTF_Glyph *gend = gstring->glyphs + gstring->used;
257 for (g = gbeg, i = 0; g < gend && i < count; g++)
258 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
260 return (i < count ? -1 : g - gbeg);
264 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
267 int i = rule->BacktrackGlyphCount;
274 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
275 if (! IGNORED_GLYPH (g, flag) && --i == 0)
279 if (match_ids (gstring, j, flag,
280 rule->BacktrackGlyphCount, rule->Backtrack)
285 i = match_ids (gstring, gidx, flag,
286 rule->InputGlyphCount - 1, rule->Input);
290 i = match_ids (gstring, gidx, flag,
291 rule->LookaheadGlyphCount, rule->LookAhead);
298 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
299 int flag, int count, unsigned *classes)
301 OTF_Glyph *gbeg = gstring->glyphs + gidx;
302 OTF_Glyph *gend = gstring->glyphs + gstring->used;
306 for (g = gbeg, i = 0; g < gend && i < count; g++)
307 if (! IGNORED_GLYPH (g, flag)
308 && get_class_def (class_def, g->glyph_id) != classes[i++])
310 return (i < count ? -1 : g - gbeg);
314 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
315 OTF_ClassDef *BacktrackClassDef,
316 OTF_ClassDef *InputClassDef,
317 OTF_ClassDef *LookaheadClassDef,
318 OTF_ChainClassRule *rule)
320 int i = rule->BacktrackGlyphCount;
327 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
328 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
332 if (match_classes (BacktrackClassDef, gstring, j, flag,
333 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
337 i = match_classes (InputClassDef, gstring, gidx, flag,
338 rule->InputGlyphCount - 1, rule->Input);
342 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
343 rule->LookaheadGlyphCount, rule->LookAhead);
351 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
352 OTF_Coverage *coverages)
354 OTF_Glyph *gbeg = gstring->glyphs + gidx;
355 OTF_Glyph *gend = gstring->glyphs + gstring->used;
359 for (g = gbeg, i = 0; g < gend && i < count; g++)
360 if (! IGNORED_GLYPH (g, flag)
361 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
363 return (i < count ? -1 : g - gbeg);
367 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
368 OTF_GSUB_ChainContext3 *context3)
370 int i = context3->BacktrackGlyphCount;
377 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
378 if (! IGNORED_GLYPH (g, flag) && --i == 0)
382 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
383 context3->Backtrack) < 0)
387 if (context3->InputGlyphCount > 1)
389 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
390 context3->Input + 1);
395 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
396 context3->LookAhead) < 0)
402 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
403 OTF_GlyphString *gstring, int gidx)
405 char *errfmt = "GSUB Looking up%s";
407 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
408 unsigned int flag = (lookup->LookupFlag
409 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
410 int orig_gidx = gidx;
411 OTF_Glyph *g = gstring->glyphs + gidx;
414 if (IGNORED_GLYPH (g, flag))
417 /* Try all subtables until one of them handles the current glyph. */
418 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
420 unsigned lookup_type = lookup->LookupType;
421 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
424 if (lookup_type == 7)
426 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
428 lookup_type = extension1->ExtensionLookupType;
429 subtable = extension1->ExtensionSubtable;
432 if (subtable->Coverage.offset)
434 coverage_idx = get_coverage_index (&subtable->Coverage,
436 if (coverage_idx < 0)
443 if (subtable->Format == 1)
444 g->glyph_id += subtable->u.single1.DeltaGlyphID;
446 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
452 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
453 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
455 gstring_subst (gstring, gidx, gidx + 1, flag,
456 seq->Substitute, seq->GlyphCount);
457 gidx += seq->GlyphCount;
462 /* For the moment, we always ignore this feature. */
464 if (subtable->Format == 1)
466 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
467 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
469 g->glyph_id = altset->Alternate[0];
473 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
477 if (subtable->Format == 1)
479 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
480 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
484 for (j = 0; j < ligset->LigatureCount; j++)
488 lig = ligset->Ligature + j;
489 n = match_ids (gstring, gidx + 1, flag,
490 lig->CompCount - 1, lig->Component);
493 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
500 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
504 if (subtable->Format == 1)
506 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
507 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
512 for (j = 0; j < set->RuleCount; j++)
514 rule = set->Rule + j;
515 if (match_ids (gstring, gidx + 1, flag,
516 rule->GlyphCount - 1, rule->Input) < 0)
518 orig_used = gstring->used;
519 for (k = 0; k < rule->LookupCount; k++)
520 lookup_gsub (lookup_list,
521 rule->LookupRecord[k].LookupListIndex,
523 gidx + rule->LookupRecord[k].SequenceIndex);
524 gidx += rule->GlyphCount + (gstring->used - orig_used);
528 else if (subtable->Format == 2)
530 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
537 class = get_class_def (&context2->ClassDef, g->glyph_id);
538 set = context2->ClassSet + class;
540 for (j = 0; j < set->ClassRuleCnt; j++)
542 rule = set->ClassRule + j;
543 if (match_classes (&context2->ClassDef,
544 gstring, gidx + 1, flag,
545 rule->GlyphCount - 1, rule->Class)
548 orig_used = gstring->used;
549 for (k = 0; k < rule->LookupCount; k++)
550 lookup_gsub (lookup_list,
551 rule->LookupRecord[k].LookupListIndex,
553 gidx + rule->LookupRecord[k].SequenceIndex);
554 gidx += rule->GlyphCount + (gstring->used - orig_used);
558 else /* subtable->Format == 3 */
560 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
564 if (match_coverages (gstring, gidx + 1, flag,
565 context3->GlyphCount - 1,
566 context3->Coverage + 1) < 0)
568 orig_used = gstring->used;
569 for (j = 0; j < context3->LookupCount; j++)
570 lookup_gsub (lookup_list,
571 context3->LookupRecord[j].LookupListIndex,
573 gidx + context3->LookupRecord[j].SequenceIndex);
574 gidx += context3->GlyphCount + (gstring->used - orig_used);
579 if (subtable->Format == 1)
581 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
582 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
586 for (j = 0; j < set->ChainRuleCount; j++)
588 OTF_ChainRule *rule = set->ChainRule + j;
590 if (gidx < rule->BacktrackGlyphCount
591 || (gidx + rule->InputGlyphCount
592 + rule->LookaheadGlyphCount) > gstring->used)
594 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
596 orig_used = gstring->used;
597 for (k = 0; k < rule->LookupCount; k++)
598 lookup_gsub (lookup_list,
599 rule->LookupRecord[k].LookupListIndex,
601 gidx + rule->LookupRecord[k].SequenceIndex);
602 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
606 else if (subtable->Format == 2)
608 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
609 OTF_ChainClassSet *set;
614 class = get_class_def (&context2->InputClassDef, g->glyph_id);
615 set = context2->ChainClassSet + class;
616 for (j = 0; j < set->ChainClassRuleCnt; j++)
618 OTF_ChainClassRule *rule = set->ChainClassRule + j;
621 if (gidx < rule->BacktrackGlyphCount
622 || (gidx + rule->InputGlyphCount
623 + rule->LookaheadGlyphCount) > gstring->used)
625 if (match_chain_classes (gstring, gidx, flag,
626 &context2->BacktrackClassDef,
627 &context2->InputClassDef,
628 &context2->LookaheadClassDef,
631 orig_used = gstring->used;
632 for (k = 0; k < rule->LookupCount; k++)
633 lookup_gsub (lookup_list,
634 rule->LookupRecord[k].LookupListIndex,
636 gidx + rule->LookupRecord[k].SequenceIndex);
637 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
643 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
647 if (gidx < context3->BacktrackGlyphCount
648 || (gidx + context3->InputGlyphCount
649 + context3->LookaheadGlyphCount) > gstring->used)
651 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
653 orig_used = gstring->used;
654 for (j = 0; j < context3->LookupCount; j++)
655 lookup_gsub (lookup_list,
656 context3->LookupRecord[j].LookupListIndex,
658 gidx + context3->LookupRecord[j].SequenceIndex);
659 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
665 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
666 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
667 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
670 if (back_gidx > gstring->used || ahead_gidx < 0)
673 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
674 if (get_coverage_index (reverse->Backtrack + j,
675 gstring->glyphs[gidx + 1 + j].glyph_id)
678 if (j < reverse->BacktrackGlyphCount)
680 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
681 if (get_coverage_index (reverse->LookAhead + j,
682 gstring->glyphs[gidx - 1 - j].glyph_id)
685 if (j < reverse->LookaheadGlyphCount)
687 g->glyph_id = reverse->Substitute[coverage_idx];
695 if (gidx == orig_gidx)
704 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
706 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
708 rec->XPlacement = anchor->XCoordinate;
709 rec->YPlacement = anchor->YCoordinate;
710 if (anchor->AnchorFormat == 1)
713 else if (anchor->AnchorFormat == 2)
714 /* Not yet implemented */
716 else if (anchor->AnchorFormat == 3)
717 /* Not yet implemented */
724 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
725 OTF_GlyphString *gstring, int gidx)
727 char *errfmt = "GPOS Looking up%s";
729 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
730 unsigned int flag = (lookup->LookupFlag
731 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
732 int orig_gidx = gidx;
733 OTF_Glyph *g = gstring->glyphs + gidx;
736 if (IGNORED_GLYPH (g, flag)
737 || g->positioning_type)
740 /* Try all subtables until one of them handles the current glyph. */
741 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
743 unsigned lookup_type = lookup->LookupType;
744 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
747 if (lookup_type == 9)
749 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
751 lookup_type = extension1->ExtensionLookupType;
752 subtable = extension1->ExtensionSubtable;
755 if (subtable->Coverage.offset)
757 coverage_idx = get_coverage_index (&subtable->Coverage,
759 if (coverage_idx < 0)
766 g->positioning_type = lookup_type;
767 if (subtable->Format == 1)
769 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
771 g->f.f1.format = single1->ValueFormat;
772 g->f.f1.value = &single1->Value;
774 else if (subtable->Format == 2)
776 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
778 g->f.f1.format = single2->ValueFormat;
779 g->f.f1.value = single2->Value + coverage_idx;
788 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
789 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
790 next_gidx++, nextg++);
792 if (next_gidx >= gstring->used
793 || nextg->positioning_type)
795 if (subtable->Format == 1)
797 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
798 OTF_PairSet *set = pair1->PairSet + coverage_idx;
801 for (j = 0; j < set->PairValueCount; j++)
802 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
804 if (pair1->ValueFormat1)
806 g->positioning_type = lookup_type;
807 g->f.f2.format = pair1->ValueFormat1;
808 g->f.f2.value = &set->PairValueRecord[j].Value1;
811 if (pair1->ValueFormat2)
813 nextg->positioning_type = lookup_type;
814 nextg->f.f2.format = pair1->ValueFormat2;
815 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
821 else if (subtable->Format == 2)
823 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
824 unsigned class1, class2;
826 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
827 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
828 if (pair2->ValueFormat1)
830 g->positioning_type = lookup_type;
831 g->f.f2.format = pair2->ValueFormat1;
833 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
836 if (pair2->ValueFormat2)
838 nextg->positioning_type = lookup_type;
839 nextg->f.f2.format = pair2->ValueFormat2;
841 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
850 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
852 g->positioning_type = lookup_type;
854 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
856 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
863 if (subtable->Format == 1)
865 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
866 OTF_MarkRecord *mark_record;
867 OTF_AnchorRecord *base_record;
869 int coverage_idx_base;
872 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
874 if (baseg < gstring->glyphs)
877 = get_coverage_index (&mark_base1->BaseCoverage,
879 if (coverage_idx_base < 0)
881 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
883 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
884 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
886 = &base_record->Anchor[mark_record->Class];
887 g->positioning_type = lookup_type;
894 if (subtable->Format == 1)
896 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
898 int coverage_idx_lig;
899 OTF_MarkRecord *mark_record;
900 OTF_LigatureAttach *attach;
901 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
904 for (j = 0; j < mark_lig1->ClassCount; j++)
908 (ligg >= gstring->glyphs
909 && (IGNORED_GLYPH (ligg, flag)
910 || ligg->GlyphClass >= OTF_GlyphClassLigature));
912 if (ligg->positioning_type == 5
913 && ligg->MarkAttachClass < mark_lig1->ClassCount)
914 num_class[ligg->MarkAttachClass]++;
915 if (ligg < gstring->glyphs)
918 = get_coverage_index (&mark_lig1->LigatureCoverage,
920 if (coverage_idx_lig < 0)
922 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
923 g->MarkAttachClass = mark_record->Class;
924 attach = (mark_lig1->LigatureArray.LigatureAttach
926 for (j = 0; j < attach->ComponentCount; j++)
928 OTF_Anchor *lig_anchor
929 = attach->ComponentRecord[j].LigatureAnchor;
931 if (lig_anchor[mark_record->Class].AnchorFormat
932 && num_class[mark_record->Class]-- == 0)
934 g->positioning_type = lookup_type;
935 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
936 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
946 if (subtable->Format == 1)
948 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
949 OTF_MarkRecord *mark1_record;
950 OTF_AnchorRecord *mark2_record;
952 int coverage_idx_base;
955 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
957 if (prevg < gstring->glyphs)
960 = get_coverage_index (&mark_mark1->Mark2Coverage,
962 if (coverage_idx_base < 0)
964 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
966 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
967 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
969 = &mark2_record->Anchor[mark1_record->Class];
970 g->positioning_type = lookup_type;
976 if (subtable->Format == 1)
978 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
979 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
984 for (j = 0; j < set->RuleCount; j++)
986 rule = set->Rule + j;
987 if (match_ids (gstring, gidx + 1, flag,
988 rule->GlyphCount - 1, rule->Input) < 0)
990 orig_used = gstring->used;
991 for (k = 0; k < rule->LookupCount; k++)
992 lookup_gpos (lookup_list,
993 rule->LookupRecord[k].LookupListIndex,
995 gidx + rule->LookupRecord[k].SequenceIndex);
996 gidx += rule->GlyphCount + (gstring->used - orig_used);
1000 else if (subtable->Format == 2)
1002 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1004 OTF_ClassRule *rule;
1009 class = get_class_def (&context2->ClassDef, g->glyph_id);
1010 set = context2->ClassSet + class;
1012 for (j = 0; j < set->ClassRuleCnt; j++)
1014 rule = set->ClassRule + j;
1015 if (match_classes (&context2->ClassDef,
1016 gstring, gidx + 1, flag,
1017 rule->GlyphCount - 1, rule->Class)
1020 orig_used = gstring->used;
1021 for (k = 0; k < rule->LookupCount; k++)
1022 lookup_gpos (lookup_list,
1023 rule->LookupRecord[k].LookupListIndex,
1025 gidx + rule->LookupRecord[k].SequenceIndex);
1026 gidx += rule->GlyphCount + (gstring->used - orig_used);
1030 else /* subtable->Format == 3 */
1032 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1036 if (match_coverages (gstring, gidx + 1, flag,
1037 context3->GlyphCount - 1,
1038 context3->Coverage + 1) < 0)
1040 orig_used = gstring->used;
1041 for (j = 0; j < context3->LookupCount; j++)
1042 lookup_gpos (lookup_list,
1043 context3->LookupRecord[j].LookupListIndex,
1045 gidx + context3->LookupRecord[j].SequenceIndex);
1046 gidx += context3->GlyphCount + (gstring->used - orig_used);
1051 if (subtable->Format == 1)
1053 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1054 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1058 for (j = 0; j < set->ChainRuleCount; j++)
1060 OTF_ChainRule *rule = set->ChainRule + j;
1062 if (gidx < rule->BacktrackGlyphCount
1063 || (gidx + rule->InputGlyphCount
1064 + rule->LookaheadGlyphCount) > gstring->used)
1066 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1068 orig_used = gstring->used;
1069 for (k = 0; k < rule->LookupCount; k++)
1070 lookup_gpos (lookup_list,
1071 rule->LookupRecord[k].LookupListIndex,
1073 gidx + rule->LookupRecord[k].SequenceIndex);
1074 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1078 else if (subtable->Format == 2)
1080 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1081 OTF_ChainClassSet *set;
1086 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1087 set = context2->ChainClassSet + class;
1088 for (j = 0; j < set->ChainClassRuleCnt; j++)
1090 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1093 if (gidx < rule->BacktrackGlyphCount
1094 || (gidx + rule->InputGlyphCount
1095 + rule->LookaheadGlyphCount) > gstring->used)
1097 if (match_chain_classes (gstring, gidx, flag,
1098 &context2->BacktrackClassDef,
1099 &context2->InputClassDef,
1100 &context2->LookaheadClassDef,
1103 orig_used = gstring->used;
1104 for (k = 0; k < rule->LookupCount; k++)
1105 lookup_gpos (lookup_list,
1106 rule->LookupRecord[k].LookupListIndex,
1108 gidx + rule->LookupRecord[k].SequenceIndex);
1109 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1113 else if (subtable->Format == 3)
1115 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1119 if (gidx < context3->BacktrackGlyphCount
1120 || (gidx + context3->InputGlyphCount
1121 + context3->LookaheadGlyphCount) > gstring->used)
1123 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1125 orig_used = gstring->used;
1126 for (j = 0; j < context3->LookupCount; j++)
1127 lookup_gpos (lookup_list,
1128 context3->LookupRecord[j].LookupListIndex,
1130 gidx + context3->LookupRecord[j].SequenceIndex);
1131 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1134 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1141 if (gidx == orig_gidx)
1147 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1151 for (i = 0; i < gstring->used; i++)
1153 c = gstring->glyphs[i].c;
1154 if (c < 0 || c >= 256)
1155 gstring->glyphs[i].glyph_id = 0;
1157 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1163 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1169 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1172 int segCount = sub4->segCountX2 / 2;
1174 for (i = 0; i < gstring->used; i++)
1176 c = gstring->glyphs[i].c;
1178 gstring->glyphs[i].glyph_id = 0;
1179 for (j = 0; j < segCount; j++)
1181 OTF_cmapSegument *seg = sub4->segments + i;
1183 if (c >= seg->startCount && c <= seg->endCount)
1185 if (seg->idRangeOffset == 0xFFFF)
1186 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1188 gstring->glyphs[i].glyph_id
1189 = sub4->glyphIdArray[seg->idRangeOffset
1190 + (c - seg->startCount)];
1200 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1206 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1212 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1218 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1228 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1234 && OTF_get_table (otf, "cmap") < 0)
1238 for (i = 0; i < gstring->used; i++)
1239 if (! gstring->glyphs[i].glyph_id)
1241 int c = gstring->glyphs[i].c;
1242 if (c < 32 || ! cmap->unicode_table)
1243 gstring->glyphs[i].glyph_id = 0;
1245 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1252 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1253 int platform_id, int encoding_id)
1257 char *errfmt = "CMAP Looking up%s";
1259 OTF_EncodingRecord *enc;
1262 && OTF_get_table (otf, "cmap") < 0)
1266 for (i = 0; i < cmap->numTables; i++)
1267 if (cmap->EncodingRecord[i].platformID == platform_id
1268 && cmap->EncodingRecord[i].encodingID == encoding_id)
1270 if (i == cmap->numTables)
1271 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1272 enc = cmap->EncodingRecord + i;
1273 switch (enc->subtable.format)
1275 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1276 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1277 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1278 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1279 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1280 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1281 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1283 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1288 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1291 && OTF_get_table (otf, "cmap") < 0)
1294 || code > otf->cmap->max_glyph_id
1295 || ! otf->cmap->decode_table)
1297 return otf->cmap->decode_table[code];
1301 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1307 && OTF_get_table (otf, "GDEF") < 0)
1311 if (gdef->glyph_class_def.offset)
1312 for (i = 0; i < gstring->used; i++)
1313 gstring->glyphs[i].GlyphClass
1314 = get_class_def (&gdef->glyph_class_def,
1315 gstring->glyphs[i].glyph_id);
1317 if (gdef->mark_attach_class_def.offset)
1318 for (i = 0; i < gstring->used; i++)
1319 gstring->glyphs[i].MarkAttachClass
1320 = get_class_def (&gdef->mark_attach_class_def,
1321 gstring->glyphs[i].glyph_id);
1328 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1329 char *script, char *language, char *features)
1331 char *errfmt = "GSUB driving%s";
1334 OTF_LangSys *LangSys;
1335 int *lookup_indices;
1338 for (i = 0; i < gstring->used; i++)
1339 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1342 && OTF_get_table (otf, "GSUB") < 0)
1345 if (gsub->FeatureList.FeatureCount == 0
1346 || gsub->LookupList.LookupCount == 0)
1349 LangSys = get_langsys (&gsub->ScriptList, script, language);
1353 /* One lookup may be used by multiple features. */
1354 lookup_indices = alloca (sizeof (int)
1355 * gsub->LookupList.LookupCount
1356 * (gsub->FeatureList.FeatureCount + 1));
1357 if (! lookup_indices)
1358 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1359 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1360 features, lookup_indices);
1364 for (i = 0; i < n; i++)
1366 int index = lookup_indices[i];
1369 if (gsub->LookupList.Lookup[index].LookupType != 8)
1372 while (gidx < gstring->used)
1374 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1381 gidx = gstring->used - 1;
1384 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1395 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1396 char *script, char *language, char *features)
1398 char *errfmt = "GPOS driving%s";
1401 OTF_LangSys *LangSys;
1402 int *lookup_indices;
1406 && OTF_get_table (otf, "GPOS") < 0)
1409 if (gpos->FeatureList.FeatureCount == 0
1410 || gpos->LookupList.LookupCount == 0)
1413 LangSys = get_langsys (&gpos->ScriptList, script, language);
1417 /* One lookup may be used by multiple features. */
1418 lookup_indices = alloca (sizeof (int)
1419 * gpos->LookupList.LookupCount
1420 * (gpos->FeatureList.FeatureCount + 1));
1421 if (! lookup_indices)
1422 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1423 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1424 features, lookup_indices);
1428 for (i = 0; i < gstring->used; i++)
1429 gstring->glyphs[i].positioning_type = 0;
1431 for (i = 0; i < n; i++)
1433 int index = lookup_indices[i];
1436 while (gidx < gstring->used)
1438 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1448 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1449 char *script, char *language,
1450 char *gsub_features, char *gpos_features)
1452 if (OTF_drive_cmap (otf, gstring) < 0)
1454 if (OTF_drive_gdef (otf, gstring) < 0)
1457 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1460 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)