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, int alternate_subst)
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;
433 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
434 : (lookup_type == 3))
437 if (subtable->Coverage.offset)
439 coverage_idx = get_coverage_index (&subtable->Coverage,
441 if (coverage_idx < 0)
448 if (subtable->Format == 1)
449 g->glyph_id += subtable->u.single1.DeltaGlyphID;
451 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
456 if (subtable->Format == 1)
458 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
459 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
461 gstring_subst (gstring, gidx, gidx + 1, flag,
462 seq->Substitute, seq->GlyphCount);
463 gidx += seq->GlyphCount;
466 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
470 if (subtable->Format == 1)
472 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
473 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
475 gstring_subst (gstring, gidx + 1, gidx + 1, flag,
476 altset->Alternate, altset->GlyphCount);
477 gidx += altset->GlyphCount;;
480 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
484 if (subtable->Format == 1)
486 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
487 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
491 for (j = 0; j < ligset->LigatureCount; j++)
495 lig = ligset->Ligature + j;
496 n = match_ids (gstring, gidx + 1, flag,
497 lig->CompCount - 1, lig->Component);
500 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
507 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
511 if (subtable->Format == 1)
513 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
514 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
519 for (j = 0; j < set->RuleCount; j++)
521 rule = set->Rule + j;
522 if (match_ids (gstring, gidx + 1, flag,
523 rule->GlyphCount - 1, rule->Input) < 0)
525 orig_used = gstring->used;
526 for (k = 0; k < rule->LookupCount; k++)
527 lookup_gsub (lookup_list,
528 rule->LookupRecord[k].LookupListIndex,
530 gidx + rule->LookupRecord[k].SequenceIndex,
532 gidx += rule->GlyphCount + (gstring->used - orig_used);
536 else if (subtable->Format == 2)
538 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
545 class = get_class_def (&context2->ClassDef, g->glyph_id);
546 set = context2->ClassSet + class;
548 for (j = 0; j < set->ClassRuleCnt; j++)
550 rule = set->ClassRule + j;
551 if (match_classes (&context2->ClassDef,
552 gstring, gidx + 1, flag,
553 rule->GlyphCount - 1, rule->Class)
556 orig_used = gstring->used;
557 for (k = 0; k < rule->LookupCount; k++)
558 lookup_gsub (lookup_list,
559 rule->LookupRecord[k].LookupListIndex,
561 gidx + rule->LookupRecord[k].SequenceIndex,
563 gidx += rule->GlyphCount + (gstring->used - orig_used);
567 else /* subtable->Format == 3 */
569 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
573 if (match_coverages (gstring, gidx + 1, flag,
574 context3->GlyphCount - 1,
575 context3->Coverage + 1) < 0)
577 orig_used = gstring->used;
578 for (j = 0; j < context3->LookupCount; j++)
579 lookup_gsub (lookup_list,
580 context3->LookupRecord[j].LookupListIndex,
582 gidx + context3->LookupRecord[j].SequenceIndex,
584 gidx += context3->GlyphCount + (gstring->used - orig_used);
589 if (subtable->Format == 1)
591 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
592 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
596 for (j = 0; j < set->ChainRuleCount; j++)
598 OTF_ChainRule *rule = set->ChainRule + j;
600 if (gidx < rule->BacktrackGlyphCount
601 || (gidx + rule->InputGlyphCount
602 + rule->LookaheadGlyphCount) > gstring->used)
604 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
606 orig_used = gstring->used;
607 for (k = 0; k < rule->LookupCount; k++)
608 lookup_gsub (lookup_list,
609 rule->LookupRecord[k].LookupListIndex,
611 gidx + rule->LookupRecord[k].SequenceIndex,
613 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
617 else if (subtable->Format == 2)
619 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
620 OTF_ChainClassSet *set;
625 class = get_class_def (&context2->InputClassDef, g->glyph_id);
626 set = context2->ChainClassSet + class;
627 for (j = 0; j < set->ChainClassRuleCnt; j++)
629 OTF_ChainClassRule *rule = set->ChainClassRule + j;
632 if (gidx < rule->BacktrackGlyphCount
633 || (gidx + rule->InputGlyphCount
634 + rule->LookaheadGlyphCount) > gstring->used)
636 if (match_chain_classes (gstring, gidx, flag,
637 &context2->BacktrackClassDef,
638 &context2->InputClassDef,
639 &context2->LookaheadClassDef,
642 orig_used = gstring->used;
643 for (k = 0; k < rule->LookupCount; k++)
644 lookup_gsub (lookup_list,
645 rule->LookupRecord[k].LookupListIndex,
647 gidx + rule->LookupRecord[k].SequenceIndex,
649 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
655 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
659 if (gidx < context3->BacktrackGlyphCount
660 || (gidx + context3->InputGlyphCount
661 + context3->LookaheadGlyphCount) > gstring->used)
663 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
665 orig_used = gstring->used;
666 for (j = 0; j < context3->LookupCount; j++)
667 lookup_gsub (lookup_list,
668 context3->LookupRecord[j].LookupListIndex,
670 gidx + context3->LookupRecord[j].SequenceIndex,
672 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
678 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
679 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
680 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
683 if (back_gidx > gstring->used || ahead_gidx < 0)
686 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
687 if (get_coverage_index (reverse->Backtrack + j,
688 gstring->glyphs[gidx + 1 + j].glyph_id)
691 if (j < reverse->BacktrackGlyphCount)
693 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
694 if (get_coverage_index (reverse->LookAhead + j,
695 gstring->glyphs[gidx - 1 - j].glyph_id)
698 if (j < reverse->LookaheadGlyphCount)
700 g->glyph_id = reverse->Substitute[coverage_idx];
708 if (gidx == orig_gidx)
717 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
719 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
721 rec->XPlacement = anchor->XCoordinate;
722 rec->YPlacement = anchor->YCoordinate;
723 if (anchor->AnchorFormat == 1)
726 else if (anchor->AnchorFormat == 2)
727 /* Not yet implemented */
729 else if (anchor->AnchorFormat == 3)
730 /* Not yet implemented */
737 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
738 OTF_GlyphString *gstring, int gidx)
740 char *errfmt = "GPOS Looking up%s";
742 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
743 unsigned int flag = (lookup->LookupFlag
744 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
745 int orig_gidx = gidx;
746 OTF_Glyph *g = gstring->glyphs + gidx;
749 if (IGNORED_GLYPH (g, flag)
750 || g->positioning_type)
753 /* Try all subtables until one of them handles the current glyph. */
754 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
756 unsigned lookup_type = lookup->LookupType;
757 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
760 if (lookup_type == 9)
762 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
764 lookup_type = extension1->ExtensionLookupType;
765 subtable = extension1->ExtensionSubtable;
768 if (subtable->Coverage.offset)
770 coverage_idx = get_coverage_index (&subtable->Coverage,
772 if (coverage_idx < 0)
779 g->positioning_type = lookup_type;
780 if (subtable->Format == 1)
782 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
784 g->f.f1.format = single1->ValueFormat;
785 g->f.f1.value = &single1->Value;
787 else if (subtable->Format == 2)
789 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
791 g->f.f1.format = single2->ValueFormat;
792 g->f.f1.value = single2->Value + coverage_idx;
801 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
802 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
803 next_gidx++, nextg++);
805 if (next_gidx >= gstring->used
806 || nextg->positioning_type)
808 if (subtable->Format == 1)
810 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
811 OTF_PairSet *set = pair1->PairSet + coverage_idx;
814 for (j = 0; j < set->PairValueCount; j++)
815 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
817 if (pair1->ValueFormat1)
819 g->positioning_type = lookup_type;
820 g->f.f2.format = pair1->ValueFormat1;
821 g->f.f2.value = &set->PairValueRecord[j].Value1;
824 if (pair1->ValueFormat2)
826 nextg->positioning_type = lookup_type;
827 nextg->f.f2.format = pair1->ValueFormat2;
828 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
834 else if (subtable->Format == 2)
836 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
837 unsigned class1, class2;
839 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
840 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
841 if (pair2->ValueFormat1)
843 g->positioning_type = lookup_type;
844 g->f.f2.format = pair2->ValueFormat1;
846 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
849 if (pair2->ValueFormat2)
851 nextg->positioning_type = lookup_type;
852 nextg->f.f2.format = pair2->ValueFormat2;
854 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
863 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
865 g->positioning_type = lookup_type;
867 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
869 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
876 if (subtable->Format == 1)
878 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
879 OTF_MarkRecord *mark_record;
880 OTF_AnchorRecord *base_record;
882 int coverage_idx_base;
885 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
887 if (baseg < gstring->glyphs)
890 = get_coverage_index (&mark_base1->BaseCoverage,
892 if (coverage_idx_base < 0)
894 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
896 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
897 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
899 = &base_record->Anchor[mark_record->Class];
900 g->positioning_type = lookup_type;
907 if (subtable->Format == 1)
909 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
911 int coverage_idx_lig;
912 OTF_MarkRecord *mark_record;
913 OTF_LigatureAttach *attach;
914 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
917 for (j = 0; j < mark_lig1->ClassCount; j++)
921 (ligg >= gstring->glyphs
922 && (IGNORED_GLYPH (ligg, flag)
923 || ligg->GlyphClass > OTF_GlyphClassLigature));
925 if (ligg->positioning_type == 5
926 && ligg->MarkAttachClass < mark_lig1->ClassCount)
927 num_class[ligg->MarkAttachClass]++;
928 if (ligg < gstring->glyphs)
931 = get_coverage_index (&mark_lig1->LigatureCoverage,
933 if (coverage_idx_lig < 0)
935 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
936 g->MarkAttachClass = mark_record->Class;
937 attach = (mark_lig1->LigatureArray.LigatureAttach
939 for (j = 0; j < attach->ComponentCount; j++)
941 OTF_Anchor *lig_anchor
942 = attach->ComponentRecord[j].LigatureAnchor;
944 if (lig_anchor[mark_record->Class].AnchorFormat
945 && num_class[mark_record->Class]-- == 0)
947 g->positioning_type = lookup_type;
948 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
949 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
959 if (subtable->Format == 1)
961 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
962 OTF_MarkRecord *mark1_record;
963 OTF_AnchorRecord *mark2_record;
965 int coverage_idx_base;
968 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
970 if (prevg < gstring->glyphs)
973 = get_coverage_index (&mark_mark1->Mark2Coverage,
975 if (coverage_idx_base < 0)
977 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
979 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
980 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
982 = &mark2_record->Anchor[mark1_record->Class];
983 g->positioning_type = lookup_type;
989 if (subtable->Format == 1)
991 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
992 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
997 for (j = 0; j < set->RuleCount; j++)
999 rule = set->Rule + j;
1000 if (match_ids (gstring, gidx + 1, flag,
1001 rule->GlyphCount - 1, rule->Input) < 0)
1003 orig_used = gstring->used;
1004 for (k = 0; k < rule->LookupCount; k++)
1005 lookup_gpos (lookup_list,
1006 rule->LookupRecord[k].LookupListIndex,
1008 gidx + rule->LookupRecord[k].SequenceIndex);
1009 gidx += rule->GlyphCount + (gstring->used - orig_used);
1013 else if (subtable->Format == 2)
1015 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1017 OTF_ClassRule *rule;
1022 class = get_class_def (&context2->ClassDef, g->glyph_id);
1023 set = context2->ClassSet + class;
1025 for (j = 0; j < set->ClassRuleCnt; j++)
1027 rule = set->ClassRule + j;
1028 if (match_classes (&context2->ClassDef,
1029 gstring, gidx + 1, flag,
1030 rule->GlyphCount - 1, rule->Class)
1033 orig_used = gstring->used;
1034 for (k = 0; k < rule->LookupCount; k++)
1035 lookup_gpos (lookup_list,
1036 rule->LookupRecord[k].LookupListIndex,
1038 gidx + rule->LookupRecord[k].SequenceIndex);
1039 gidx += rule->GlyphCount + (gstring->used - orig_used);
1043 else /* subtable->Format == 3 */
1045 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1049 if (match_coverages (gstring, gidx + 1, flag,
1050 context3->GlyphCount - 1,
1051 context3->Coverage + 1) < 0)
1053 orig_used = gstring->used;
1054 for (j = 0; j < context3->LookupCount; j++)
1055 lookup_gpos (lookup_list,
1056 context3->LookupRecord[j].LookupListIndex,
1058 gidx + context3->LookupRecord[j].SequenceIndex);
1059 gidx += context3->GlyphCount + (gstring->used - orig_used);
1064 if (subtable->Format == 1)
1066 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1067 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1071 for (j = 0; j < set->ChainRuleCount; j++)
1073 OTF_ChainRule *rule = set->ChainRule + j;
1075 if (gidx < rule->BacktrackGlyphCount
1076 || (gidx + rule->InputGlyphCount
1077 + rule->LookaheadGlyphCount) > gstring->used)
1079 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1081 orig_used = gstring->used;
1082 for (k = 0; k < rule->LookupCount; k++)
1083 lookup_gpos (lookup_list,
1084 rule->LookupRecord[k].LookupListIndex,
1086 gidx + rule->LookupRecord[k].SequenceIndex);
1087 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1091 else if (subtable->Format == 2)
1093 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1094 OTF_ChainClassSet *set;
1099 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1100 set = context2->ChainClassSet + class;
1101 for (j = 0; j < set->ChainClassRuleCnt; j++)
1103 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1106 if (gidx < rule->BacktrackGlyphCount
1107 || (gidx + rule->InputGlyphCount
1108 + rule->LookaheadGlyphCount) > gstring->used)
1110 if (match_chain_classes (gstring, gidx, flag,
1111 &context2->BacktrackClassDef,
1112 &context2->InputClassDef,
1113 &context2->LookaheadClassDef,
1116 orig_used = gstring->used;
1117 for (k = 0; k < rule->LookupCount; k++)
1118 lookup_gpos (lookup_list,
1119 rule->LookupRecord[k].LookupListIndex,
1121 gidx + rule->LookupRecord[k].SequenceIndex);
1122 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1126 else if (subtable->Format == 3)
1128 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1132 if (gidx < context3->BacktrackGlyphCount
1133 || (gidx + context3->InputGlyphCount
1134 + context3->LookaheadGlyphCount) > gstring->used)
1136 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1138 orig_used = gstring->used;
1139 for (j = 0; j < context3->LookupCount; j++)
1140 lookup_gpos (lookup_list,
1141 context3->LookupRecord[j].LookupListIndex,
1143 gidx + context3->LookupRecord[j].SequenceIndex);
1144 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1147 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1154 if (gidx == orig_gidx)
1160 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1164 for (i = 0; i < gstring->used; i++)
1166 c = gstring->glyphs[i].c;
1167 if (c < 0 || c >= 256)
1168 gstring->glyphs[i].glyph_id = 0;
1170 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1176 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1182 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1185 int segCount = sub4->segCountX2 / 2;
1187 for (i = 0; i < gstring->used; i++)
1189 c = gstring->glyphs[i].c;
1191 gstring->glyphs[i].glyph_id = 0;
1192 for (j = 0; j < segCount; j++)
1194 OTF_cmapSegument *seg = sub4->segments + i;
1196 if (c >= seg->startCount && c <= seg->endCount)
1198 if (seg->idRangeOffset == 0xFFFF)
1199 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1201 gstring->glyphs[i].glyph_id
1202 = sub4->glyphIdArray[seg->idRangeOffset
1203 + (c - seg->startCount)];
1213 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1219 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1225 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1231 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1241 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1247 && OTF_get_table (otf, "cmap") < 0)
1251 for (i = 0; i < gstring->used; i++)
1252 if (! gstring->glyphs[i].glyph_id)
1254 int c = gstring->glyphs[i].c;
1255 if (c < 32 || ! cmap->unicode_table)
1256 gstring->glyphs[i].glyph_id = 0;
1258 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1265 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1266 int platform_id, int encoding_id)
1270 char *errfmt = "CMAP Looking up%s";
1272 OTF_EncodingRecord *enc;
1275 && OTF_get_table (otf, "cmap") < 0)
1279 for (i = 0; i < cmap->numTables; i++)
1280 if (cmap->EncodingRecord[i].platformID == platform_id
1281 && cmap->EncodingRecord[i].encodingID == encoding_id)
1283 if (i == cmap->numTables)
1284 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1285 enc = cmap->EncodingRecord + i;
1286 switch (enc->subtable.format)
1288 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1289 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1290 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1291 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1292 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1293 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1294 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1296 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1301 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1304 && OTF_get_table (otf, "cmap") < 0)
1307 || code > otf->cmap->max_glyph_id
1308 || ! otf->cmap->decode_table)
1310 return otf->cmap->decode_table[code];
1314 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1320 && OTF_get_table (otf, "GDEF") < 0)
1324 if (gdef->glyph_class_def.offset)
1325 for (i = 0; i < gstring->used; i++)
1326 gstring->glyphs[i].GlyphClass
1327 = get_class_def (&gdef->glyph_class_def,
1328 gstring->glyphs[i].glyph_id);
1330 if (gdef->mark_attach_class_def.offset)
1331 for (i = 0; i < gstring->used; i++)
1332 gstring->glyphs[i].MarkAttachClass
1333 = get_class_def (&gdef->mark_attach_class_def,
1334 gstring->glyphs[i].glyph_id);
1340 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1341 char *script, char *language, char *features,
1342 int alternate_subst)
1344 char *errfmt = "GSUB driving%s";
1347 OTF_LangSys *LangSys;
1348 int *lookup_indices;
1351 for (i = 0; i < gstring->used; i++)
1352 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1355 && OTF_get_table (otf, "GSUB") < 0)
1358 if (gsub->FeatureList.FeatureCount == 0
1359 || gsub->LookupList.LookupCount == 0)
1362 LangSys = get_langsys (&gsub->ScriptList, script, language);
1366 /* One lookup may be used by multiple features. */
1367 lookup_indices = alloca (sizeof (int)
1368 * gsub->LookupList.LookupCount
1369 * (gsub->FeatureList.FeatureCount + 1));
1370 if (! lookup_indices)
1371 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1372 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1373 features, lookup_indices);
1377 for (i = 0; i < n; i++)
1379 int index = lookup_indices[i];
1382 if (gsub->LookupList.Lookup[index].LookupType != 8)
1385 while (gidx < gstring->used)
1387 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx,
1395 gidx = gstring->used - 1;
1398 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx,
1410 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1411 char *script, char *language, char *features)
1413 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1417 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1418 char *script, char *language, char *features)
1420 char *errfmt = "GPOS driving%s";
1423 OTF_LangSys *LangSys;
1424 int *lookup_indices;
1428 && OTF_get_table (otf, "GPOS") < 0)
1431 if (gpos->FeatureList.FeatureCount == 0
1432 || gpos->LookupList.LookupCount == 0)
1435 LangSys = get_langsys (&gpos->ScriptList, script, language);
1439 /* One lookup may be used by multiple features. */
1440 lookup_indices = alloca (sizeof (int)
1441 * gpos->LookupList.LookupCount
1442 * (gpos->FeatureList.FeatureCount + 1));
1443 if (! lookup_indices)
1444 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1445 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1446 features, lookup_indices);
1450 for (i = 0; i < gstring->used; i++)
1451 gstring->glyphs[i].positioning_type = 0;
1453 for (i = 0; i < n; i++)
1455 int index = lookup_indices[i];
1458 while (gidx < gstring->used)
1460 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1470 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1471 char *script, char *language,
1472 char *gsub_features, char *gpos_features)
1474 if (OTF_drive_cmap (otf, gstring) < 0)
1476 if (OTF_drive_gdef (otf, gstring) < 0)
1479 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1482 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1488 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1489 char *script, char *language, char *features)
1491 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);