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 && IGNORED_GLYPH (ligg, flag);
910 if (ligg->positioning_type == 5
911 && ligg->MarkAttachClass < mark_lig1->ClassCount)
912 num_class[ligg->MarkAttachClass]++;
913 if (ligg < gstring->glyphs)
916 = get_coverage_index (&mark_lig1->LigatureCoverage,
918 if (coverage_idx_lig < 0)
920 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
921 g->MarkAttachClass = mark_record->Class;
922 attach = (mark_lig1->LigatureArray.LigatureAttach
924 for (j = 0; j < attach->ComponentCount; j++)
926 OTF_Anchor *lig_anchor
927 = attach->ComponentRecord[j].LigatureAnchor;
929 if (lig_anchor[mark_record->Class].AnchorFormat
930 && num_class[mark_record->Class]-- == 0)
932 g->positioning_type = lookup_type;
933 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
934 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
944 if (subtable->Format == 1)
946 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
947 OTF_MarkRecord *mark1_record;
948 OTF_AnchorRecord *mark2_record;
950 int coverage_idx_base;
953 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
955 if (prevg < gstring->glyphs)
958 = get_coverage_index (&mark_mark1->Mark2Coverage,
960 if (coverage_idx_base < 0)
962 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
964 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
965 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
967 = &mark2_record->Anchor[mark1_record->Class];
968 g->positioning_type = lookup_type;
974 if (subtable->Format == 1)
976 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
977 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
982 for (j = 0; j < set->RuleCount; j++)
984 rule = set->Rule + j;
985 if (match_ids (gstring, gidx + 1, flag,
986 rule->GlyphCount - 1, rule->Input) < 0)
988 orig_used = gstring->used;
989 for (k = 0; k < rule->LookupCount; k++)
990 lookup_gpos (lookup_list,
991 rule->LookupRecord[k].LookupListIndex,
993 gidx + rule->LookupRecord[k].SequenceIndex);
994 gidx += rule->GlyphCount + (gstring->used - orig_used);
998 else if (subtable->Format == 2)
1000 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1002 OTF_ClassRule *rule;
1007 class = get_class_def (&context2->ClassDef, g->glyph_id);
1008 set = context2->ClassSet + class;
1010 for (j = 0; j < set->ClassRuleCnt; j++)
1012 rule = set->ClassRule + j;
1013 if (match_classes (&context2->ClassDef,
1014 gstring, gidx + 1, flag,
1015 rule->GlyphCount - 1, rule->Class)
1018 orig_used = gstring->used;
1019 for (k = 0; k < rule->LookupCount; k++)
1020 lookup_gpos (lookup_list,
1021 rule->LookupRecord[k].LookupListIndex,
1023 gidx + rule->LookupRecord[k].SequenceIndex);
1024 gidx += rule->GlyphCount + (gstring->used - orig_used);
1028 else /* subtable->Format == 3 */
1030 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1034 if (match_coverages (gstring, gidx + 1, flag,
1035 context3->GlyphCount - 1,
1036 context3->Coverage + 1) < 0)
1038 orig_used = gstring->used;
1039 for (j = 0; j < context3->LookupCount; j++)
1040 lookup_gpos (lookup_list,
1041 context3->LookupRecord[j].LookupListIndex,
1043 gidx + context3->LookupRecord[j].SequenceIndex);
1044 gidx += context3->GlyphCount + (gstring->used - orig_used);
1049 if (subtable->Format == 1)
1051 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1052 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1056 for (j = 0; j < set->ChainRuleCount; j++)
1058 OTF_ChainRule *rule = set->ChainRule + j;
1060 if (gidx < rule->BacktrackGlyphCount
1061 || (gidx + rule->InputGlyphCount
1062 + rule->LookaheadGlyphCount) > gstring->used)
1064 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1066 orig_used = gstring->used;
1067 for (k = 0; k < rule->LookupCount; k++)
1068 lookup_gpos (lookup_list,
1069 rule->LookupRecord[k].LookupListIndex,
1071 gidx + rule->LookupRecord[k].SequenceIndex);
1072 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1076 else if (subtable->Format == 2)
1078 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1079 OTF_ChainClassSet *set;
1084 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1085 set = context2->ChainClassSet + class;
1086 for (j = 0; j < set->ChainClassRuleCnt; j++)
1088 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1091 if (gidx < rule->BacktrackGlyphCount
1092 || (gidx + rule->InputGlyphCount
1093 + rule->LookaheadGlyphCount) > gstring->used)
1095 if (match_chain_classes (gstring, gidx, flag,
1096 &context2->BacktrackClassDef,
1097 &context2->InputClassDef,
1098 &context2->LookaheadClassDef,
1101 orig_used = gstring->used;
1102 for (k = 0; k < rule->LookupCount; k++)
1103 lookup_gpos (lookup_list,
1104 rule->LookupRecord[k].LookupListIndex,
1106 gidx + rule->LookupRecord[k].SequenceIndex);
1107 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1111 else if (subtable->Format == 3)
1113 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1117 if (gidx < context3->BacktrackGlyphCount
1118 || (gidx + context3->InputGlyphCount
1119 + context3->LookaheadGlyphCount) > gstring->used)
1121 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1123 orig_used = gstring->used;
1124 for (j = 0; j < context3->LookupCount; j++)
1125 lookup_gpos (lookup_list,
1126 context3->LookupRecord[j].LookupListIndex,
1128 gidx + context3->LookupRecord[j].SequenceIndex);
1129 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1132 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1139 if (gidx == orig_gidx)
1145 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1149 for (i = 0; i < gstring->used; i++)
1151 c = gstring->glyphs[i].c;
1152 if (c < 0 || c >= 256)
1153 gstring->glyphs[i].glyph_id = 0;
1155 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1161 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1167 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1170 int segCount = sub4->segCountX2 / 2;
1172 for (i = 0; i < gstring->used; i++)
1174 c = gstring->glyphs[i].c;
1176 gstring->glyphs[i].glyph_id = 0;
1177 for (j = 0; j < segCount; j++)
1179 OTF_cmapSegument *seg = sub4->segments + i;
1181 if (c >= seg->startCount && c <= seg->endCount)
1183 if (seg->idRangeOffset == 0xFFFF)
1184 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1186 gstring->glyphs[i].glyph_id
1187 = sub4->glyphIdArray[seg->idRangeOffset
1188 + (c - seg->startCount)];
1198 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1204 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1210 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1216 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1226 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1232 && OTF_get_table (otf, "cmap") < 0)
1236 for (i = 0; i < gstring->used; i++)
1237 if (! gstring->glyphs[i].glyph_id)
1239 int c = gstring->glyphs[i].c;
1240 if (c < 32 || ! cmap->unicode_table)
1241 gstring->glyphs[i].glyph_id = 0;
1243 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1250 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1251 int platform_id, int encoding_id)
1255 char *errfmt = "CMAP Looking up%s";
1257 OTF_EncodingRecord *enc;
1260 && OTF_get_table (otf, "cmap") < 0)
1264 for (i = 0; i < cmap->numTables; i++)
1265 if (cmap->EncodingRecord[i].platformID == platform_id
1266 && cmap->EncodingRecord[i].encodingID == encoding_id)
1268 if (i == cmap->numTables)
1269 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1270 enc = cmap->EncodingRecord + i;
1271 switch (enc->subtable.format)
1273 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1274 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1275 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1276 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1277 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1278 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1279 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1281 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1286 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1289 && OTF_get_table (otf, "cmap") < 0)
1292 || code > otf->cmap->max_glyph_id
1293 || ! otf->cmap->decode_table)
1295 return otf->cmap->decode_table[code];
1299 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1305 && OTF_get_table (otf, "GDEF") < 0)
1309 if (gdef->glyph_class_def.offset)
1310 for (i = 0; i < gstring->used; i++)
1311 gstring->glyphs[i].GlyphClass
1312 = get_class_def (&gdef->glyph_class_def,
1313 gstring->glyphs[i].glyph_id);
1315 if (gdef->mark_attach_class_def.offset)
1316 for (i = 0; i < gstring->used; i++)
1317 gstring->glyphs[i].MarkAttachClass
1318 = get_class_def (&gdef->mark_attach_class_def,
1319 gstring->glyphs[i].glyph_id);
1326 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1327 char *script, char *language, char *features)
1329 char *errfmt = "GSUB driving%s";
1332 OTF_LangSys *LangSys;
1333 int *lookup_indices;
1336 for (i = 0; i < gstring->used; i++)
1337 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1340 && OTF_get_table (otf, "GSUB") < 0)
1343 if (gsub->FeatureList.FeatureCount == 0
1344 || gsub->LookupList.LookupCount == 0)
1347 LangSys = get_langsys (&gsub->ScriptList, script, language);
1351 /* One lookup may be used by multiple features. */
1352 lookup_indices = alloca (sizeof (int)
1353 * gsub->LookupList.LookupCount
1354 * (gsub->FeatureList.FeatureCount + 1));
1355 if (! lookup_indices)
1356 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1357 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1358 features, lookup_indices);
1362 for (i = 0; i < n; i++)
1364 int index = lookup_indices[i];
1367 if (gsub->LookupList.Lookup[index].LookupType != 8)
1370 while (gidx < gstring->used)
1372 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1379 gidx = gstring->used - 1;
1382 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1393 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1394 char *script, char *language, char *features)
1396 char *errfmt = "GPOS driving%s";
1399 OTF_LangSys *LangSys;
1400 int *lookup_indices;
1404 && OTF_get_table (otf, "GPOS") < 0)
1407 if (gpos->FeatureList.FeatureCount == 0
1408 || gpos->LookupList.LookupCount == 0)
1411 LangSys = get_langsys (&gpos->ScriptList, script, language);
1415 /* One lookup may be used by multiple features. */
1416 lookup_indices = alloca (sizeof (int)
1417 * gpos->LookupList.LookupCount
1418 * (gpos->FeatureList.FeatureCount + 1));
1419 if (! lookup_indices)
1420 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1421 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1422 features, lookup_indices);
1426 for (i = 0; i < gstring->used; i++)
1427 gstring->glyphs[i].positioning_type = 0;
1429 for (i = 0; i < n; i++)
1431 int index = lookup_indices[i];
1434 while (gidx < gstring->used)
1436 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1446 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1447 char *script, char *language,
1448 char *gsub_features, char *gpos_features)
1450 if (OTF_drive_cmap (otf, gstring) < 0)
1452 if (OTF_drive_gdef (otf, gstring) < 0)
1455 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1458 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)