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 #define GSTRING_DELETE(gstring, from, len) \
34 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
35 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
36 gstring->used -= len; \
40 #define GSTRING_INSERT(gstring, pos, len) \
42 if (gstring->used + len > gstring->size) \
44 char *errfmt = "GSTRING%s"; \
46 gstring->size = gstring->used + len; \
47 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
49 if (! gstring->glyphs) \
50 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
52 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
53 sizeof (OTF_Glyph) * (gstring->used - pos)); \
54 gstring->used += len; \
59 gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag,
60 OTF_GlyphID *ids, int num)
65 int c = gstring->glyphs[from].c;
66 int from_idx = gstring->glyphs[from].f.index.from;
67 int to_idx = gstring->glyphs[to - 1].f.index.to;
70 for (i = non_ignored_idx = to - 1; i >= from; i--)
71 if (flag & (1 << gstring->glyphs[i].GlyphClass))
73 OTF_Glyph temp = gstring->glyphs[i];
75 memmove (gstring->glyphs + i, gstring->glyphs + i + 1,
76 sizeof (OTF_Glyph) * (non_ignored_idx - i));
77 gstring->glyphs[non_ignored_idx--] = temp;
82 GSTRING_INSERT (gstring, from, (num - len));
84 GSTRING_DELETE (gstring, from, (len - num));
85 for (i = 0; i < num; i++)
87 gstring->glyphs[from + i].c = c;
88 gstring->glyphs[from + i].glyph_id = ids[i];
89 gstring->glyphs[from + i].f.index.from = from_idx;
90 gstring->glyphs[from + i].f.index.to = to_idx;
97 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
101 if (coverage->CoverageFormat == 1)
103 for (i = 0; i < coverage->Count; i++)
104 if (coverage->table.GlyphArray[i] == id)
109 for (i = 0; i < coverage->Count; i++)
110 if (coverage->table.RangeRecord[i].Start <= id
111 && coverage->table.RangeRecord[i].End >= id)
112 return (coverage->table.RangeRecord[i].StartCoverageIndex
113 + (id - coverage->table.RangeRecord[i].Start));
119 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
121 if (class_def->ClassFormat == 1)
123 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
125 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
126 return class_def->f.f1.ClassValueArray[idx];
132 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
133 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
134 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
135 return class_def->f.f2.ClassRangeRecord[i].Class;
141 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
144 OTF_Tag script_tag = OTF_tag (script);
145 OTF_Tag langsys_tag = OTF_tag (language);
147 OTF_Tag dflt_tag = OTF_tag ("DFLT");
148 OTF_Script *dflt = NULL;
150 for (i = 0; i < script_list->ScriptCount; i++)
152 OTF_Script *script = script_list->Script + i;
154 if (script_list->Script[i].ScriptTag == dflt_tag)
156 if (script_list->Script[i].ScriptTag == script_tag)
159 return &script->DefaultLangSys;
160 for (j = 0; j < script->LangSysCount; j++)
161 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
162 return script->LangSys + j;
163 return &script->DefaultLangSys;
168 dflt = script_list->Script;
170 return &dflt->DefaultLangSys;
171 for (j = 0; j < dflt->LangSysCount; j++)
172 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
173 return dflt->LangSys + j;
174 return &dflt->DefaultLangSys;
178 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
179 char *features, int *lookup_indices)
182 OTF_Feature *feature;
183 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
185 for (i = 0; i < FeatureList->FeatureCount; i++)
186 feature_table[i] = 0;
194 if (*features == '*')
196 /* Consume all remaining features. */
197 /* We are sure that the last LookupCount elements of
198 lookup_indices are free to be used for this work. */
199 int *free_table = (lookup_indices + (LookupList->LookupCount
200 * FeatureList->FeatureCount));
202 for (i = 0; i < LookupList->LookupCount; i++)
204 for (i = 0; i < FeatureList->FeatureCount; i++)
205 if (! feature_table[i])
207 feature = FeatureList->Feature + i;
208 for (j = 0; j < feature->LookupCount; j++)
209 free_table[feature->LookupListIndex[j]] = 1;
211 for (i = 0; i < LookupList->LookupCount; i++)
213 lookup_indices[n++] = i;
217 if (*features == '~')
218 negate = 1, features++;
219 for (i = 0; *features && *features != ','; i++, features++)
220 tagname[i] = *features;
226 tag = OTF_tag (tagname);
227 for (i = 0; i < FeatureList->FeatureCount; i++)
229 feature = FeatureList->Feature + i;
230 if (tag == feature->FeatureTag)
233 for (j = 0; j < feature->LookupCount; j++)
234 lookup_indices[n++] = feature->LookupListIndex[j];
235 feature_table[i] = 1;
245 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
246 int count, OTF_GlyphID *ids)
248 OTF_Glyph *gbeg = gstring->glyphs + gidx;
249 OTF_Glyph *gend = gstring->glyphs + gstring->used;
253 for (g = gbeg, i = 0; g < gend && i < count; g++)
254 if (g->glyph_id && ! (flag & (1 << g->GlyphClass))
255 && g->glyph_id != ids[i++])
257 return (i < count ? -1 : g - gbeg);
261 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
264 int i = rule->BacktrackGlyphCount;
270 for (j = gidx - 1; j >= 0; j--)
271 if (gstring->glyphs[j].glyph_id
276 if (match_ids (gstring, j, flag,
277 rule->BacktrackGlyphCount, rule->Backtrack)
282 i = match_ids (gstring, gidx, flag,
283 rule->InputGlyphCount - 1, rule->Input);
287 i = match_ids (gstring, gidx, flag,
288 rule->LookaheadGlyphCount, rule->LookAhead);
295 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
296 int flag, int count, unsigned *classes)
298 OTF_Glyph *gbeg = gstring->glyphs + gidx;
299 OTF_Glyph *gend = gstring->glyphs + gstring->used;
303 for (g = gbeg, i = 0; g < gend && i < count; g++)
304 if (g->glyph_id && ! (flag & (1 << g->GlyphClass))
305 && get_class_def (class_def, g->glyph_id) != classes[i++])
307 return (i < count ? -1 : g - gbeg);
311 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
312 OTF_ClassDef *BacktrackClassDef,
313 OTF_ClassDef *InputClassDef,
314 OTF_ClassDef *LookaheadClassDef,
315 OTF_ChainClassRule *rule)
317 int i = rule->BacktrackGlyphCount;
323 for (j = gidx - 1; j >= 0 && i > 0; j--)
324 if (gstring->glyphs[j].glyph_id
329 if (match_classes (BacktrackClassDef, gstring, j, flag,
330 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
334 i = match_classes (InputClassDef, gstring, gidx, flag,
335 rule->InputGlyphCount - 1, rule->Input);
339 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
340 rule->LookaheadGlyphCount, rule->LookAhead);
348 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
349 OTF_Coverage *coverages)
351 OTF_Glyph *gbeg = gstring->glyphs + gidx;
352 OTF_Glyph *gend = gstring->glyphs + gstring->used;
356 for (g = gbeg, i = 0; g < gend && i < count; g++)
357 if (g->glyph_id && ! (flag & (1 << g->GlyphClass))
358 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
360 return (i < count ? -1 : g - gbeg);
364 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
365 OTF_GSUB_ChainContext3 *context3)
367 int i = context3->BacktrackGlyphCount;
373 for (j = gidx - 1; j >= 0; j--)
374 if (gstring->glyphs[j].glyph_id
379 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
380 context3->Backtrack) < 0)
384 if (context3->InputGlyphCount > 1)
386 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
387 context3->Input + 1);
392 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
393 context3->LookAhead) < 0)
399 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
400 OTF_GlyphString *gstring, int gidx)
402 char *errfmt = "GSUB Looking up%s";
404 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
405 unsigned int flag = lookup->LookupFlag & OTF_LookupFlagIgnoreMask;
406 int orig_gidx = gidx;
407 OTF_Glyph *g = gstring->glyphs + gidx;
412 && (flag & (1 << g->GlyphClass))))
415 /* Try all subtables until one of them handles the current glyph. */
416 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
418 unsigned lookup_type = lookup->LookupType;
419 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
422 if (lookup_type == 7)
424 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
426 lookup_type = extension1->ExtensionLookupType;
427 subtable = extension1->ExtensionSubtable;
430 if (subtable->Coverage.offset)
432 coverage_idx = get_coverage_index (&subtable->Coverage,
434 if (coverage_idx < 0)
438 switch (lookup->LookupType)
441 if (subtable->Format == 1)
442 g->glyph_id += subtable->u.single1.DeltaGlyphID;
444 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
450 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
451 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
453 gstring_subst (gstring, gidx, gidx + 1, flag,
454 seq->Substitute, seq->GlyphCount);
455 gidx += seq->GlyphCount;
460 /* For the moment, we always ignore this feature. */
462 if (subtable->Format == 1)
464 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
465 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
467 g->glyph_id = altset->Alternate[0];
471 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
475 if (subtable->Format == 1)
477 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
478 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
482 for (j = 0; j < ligset->LigatureCount; j++)
486 lig = ligset->Ligature + j;
487 n = match_ids (gstring, gidx + 1, flag,
488 lig->CompCount - 1, lig->Component);
491 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
498 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
502 if (subtable->Format == 1)
504 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
505 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
510 for (j = 0; j < set->RuleCount; j++)
512 rule = set->Rule + j;
513 if (match_ids (gstring, gidx + 1, flag,
514 rule->GlyphCount - 1, rule->Input) < 0)
516 orig_used = gstring->used;
517 for (k = 0; k < rule->LookupCount; k++)
518 lookup_gsub (lookup_list,
519 rule->LookupRecord[k].LookupListIndex,
521 gidx + rule->LookupRecord[k].SequenceIndex);
522 gidx += rule->GlyphCount + (gstring->used - orig_used);
526 else if (subtable->Format == 2)
528 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
535 class = get_class_def (&context2->ClassDef, g->glyph_id);
536 set = context2->ClassSet + class;
538 for (j = 0; j < set->ClassRuleCnt; j++)
540 rule = set->ClassRule + j;
541 if (match_classes (&context2->ClassDef,
542 gstring, gidx + 1, flag,
543 rule->GlyphCount - 1, rule->Class)
546 orig_used = gstring->used;
547 for (k = 0; k < rule->LookupCount; k++)
548 lookup_gsub (lookup_list,
549 rule->LookupRecord[k].LookupListIndex,
551 gidx + rule->LookupRecord[k].SequenceIndex);
552 gidx += rule->GlyphCount + (gstring->used - orig_used);
556 else /* subtable->Format == 3 */
558 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
562 if (match_coverages (gstring, gidx + 1, flag,
563 context3->GlyphCount - 1,
564 context3->Coverage + 1) < 0)
566 orig_used = gstring->used;
567 for (j = 0; j < context3->LookupCount; j++)
568 lookup_gsub (lookup_list,
569 context3->LookupRecord[j].LookupListIndex,
571 gidx + context3->LookupRecord[j].SequenceIndex);
572 gidx += context3->GlyphCount + (gstring->used - orig_used);
577 if (subtable->Format == 1)
579 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
580 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
584 for (j = 0; j < set->ChainRuleCount; j++)
586 OTF_ChainRule *rule = set->ChainRule + j;
588 if (gidx < rule->BacktrackGlyphCount
589 || (gidx + rule->InputGlyphCount
590 + rule->LookaheadGlyphCount) > gstring->used)
592 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
594 orig_used = gstring->used;
595 for (k = 0; k < rule->LookupCount; k++)
596 lookup_gsub (lookup_list,
597 rule->LookupRecord[k].LookupListIndex,
599 gidx + rule->LookupRecord[k].SequenceIndex);
600 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
604 else if (subtable->Format == 2)
606 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
607 OTF_ChainClassSet *set;
612 class = get_class_def (&context2->InputClassDef, g->glyph_id);
613 set = context2->ChainClassSet + class;
614 for (j = 0; j < set->ChainClassRuleCnt; j++)
616 OTF_ChainClassRule *rule = set->ChainClassRule + j;
619 if (gidx < rule->BacktrackGlyphCount
620 || (gidx + rule->InputGlyphCount
621 + rule->LookaheadGlyphCount) > gstring->used)
623 if (match_chain_classes (gstring, gidx, flag,
624 &context2->BacktrackClassDef,
625 &context2->InputClassDef,
626 &context2->LookaheadClassDef,
629 orig_used = gstring->used;
630 for (k = 0; k < rule->LookupCount; k++)
631 lookup_gsub (lookup_list,
632 rule->LookupRecord[k].LookupListIndex,
634 gidx + rule->LookupRecord[k].SequenceIndex);
635 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
641 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
645 if (gidx < context3->BacktrackGlyphCount
646 || (gidx + context3->InputGlyphCount
647 + context3->LookaheadGlyphCount) > gstring->used)
649 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
651 orig_used = gstring->used;
652 for (j = 0; j < context3->LookupCount; j++)
653 lookup_gsub (lookup_list,
654 context3->LookupRecord[j].LookupListIndex,
656 gidx + context3->LookupRecord[j].SequenceIndex);
657 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
663 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
664 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
665 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
668 if (back_gidx > gstring->used || ahead_gidx < 0)
671 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
672 if (get_coverage_index (reverse->Backtrack + j,
673 gstring->glyphs[gidx + 1 + j].glyph_id)
676 if (j < reverse->BacktrackGlyphCount)
678 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
679 if (get_coverage_index (reverse->LookAhead + j,
680 gstring->glyphs[gidx - 1 - j].glyph_id)
683 if (j < reverse->LookaheadGlyphCount)
685 g->glyph_id = reverse->Substitute[coverage_idx];
693 if (gidx == orig_gidx)
702 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
704 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
706 rec->XPlacement = anchor->XCoordinate;
707 rec->YPlacement = anchor->YCoordinate;
708 if (anchor->AnchorFormat == 1)
711 else if (anchor->AnchorFormat == 2)
712 /* Not yet implemented */
714 else if (anchor->AnchorFormat == 3)
715 /* Not yet implemented */
722 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
723 OTF_GlyphString *gstring, int gidx)
725 char *errfmt = "GPOS Looking up%s";
727 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
728 unsigned int flag = lookup->LookupFlag & OTF_LookupFlagIgnoreMask;
729 int orig_gidx = gidx;
730 OTF_Glyph *g = gstring->glyphs + gidx;
734 || g->positioning_type
736 && (flag & (1 << g->GlyphClass))))
739 /* Try all subtables until one of them handles the current glyph. */
740 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
742 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
745 if (subtable->Coverage.offset)
747 coverage_idx = get_coverage_index (&subtable->Coverage,
749 if (coverage_idx < 0)
753 switch (lookup->LookupType)
756 g->positioning_type = lookup->LookupType;
757 if (subtable->Format == 1)
759 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
761 g->f.f1.format = single1->ValueFormat;
762 g->f.f1.value = &single1->Value;
764 else if (subtable->Format == 2)
766 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
768 g->f.f1.format = single2->ValueFormat;
769 g->f.f1.value = single2->Value + coverage_idx;
775 int next_gidx = gidx + 1;
778 while (next_gidx < gstring->used
779 && (! gstring->glyphs[next_gidx].glyph_id
781 & (1 << gstring->glyphs[next_gidx].GlyphClass))))
784 if (next_gidx >= gstring->used)
786 nextg = gstring->glyphs + next_gidx;
787 if (nextg->positioning_type)
789 if (subtable->Format == 1)
791 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
792 OTF_PairSet *set = pair1->PairSet + coverage_idx;
795 for (j = 0; j < set->PairValueCount; j++)
796 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
798 if (pair1->ValueFormat1)
800 g->positioning_type = lookup->LookupType;
801 g->f.f2.format = pair1->ValueFormat1;
802 g->f.f2.value = &set->PairValueRecord[j].Value1;
805 if (pair1->ValueFormat2)
807 nextg->positioning_type = lookup->LookupType;
808 nextg->f.f2.format = pair1->ValueFormat2;
809 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
815 else if (subtable->Format == 2)
817 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
818 unsigned class1, class2;
820 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
821 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
822 if (pair2->ValueFormat1)
824 g->positioning_type = lookup->LookupType;
825 g->f.f2.format = pair2->ValueFormat1;
827 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
830 if (pair2->ValueFormat2)
832 nextg->positioning_type = lookup->LookupType;
833 nextg->f.f2.format = pair2->ValueFormat2;
835 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
844 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
846 g->positioning_type = lookup->LookupType;
848 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
850 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
857 if (subtable->Format == 1)
859 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
860 OTF_MarkRecord *mark_record;
861 OTF_AnchorRecord *base_record;
862 OTF_Glyph *baseg = g - 1;
863 int coverage_idx_base;
865 while (baseg >= gstring->glyphs
866 && (! baseg->glyph_id
867 || (baseg->GlyphClass
868 && (flag & (1 << baseg->GlyphClass)))))
871 = get_coverage_index (&mark_base1->BaseCoverage,
874 if (coverage_idx_base < 0)
876 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
878 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
879 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
881 = &base_record->Anchor[mark_record->Class];
882 g->positioning_type = lookup->LookupType;
889 if (subtable->Format == 1)
891 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
892 unsigned class = g->MarkAttachClass;
893 OTF_Glyph *ligg = g - 1;
894 int coverage_idx_lig;
895 OTF_MarkRecord *mark_record;
896 OTF_ComponentRecord *cmp_record;
897 OTF_LigatureAttach *attach;
898 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
901 for (j = 0; j < mark_lig1->ClassCount; j++)
904 while (ligg >= gstring->glyphs
907 && (flag & (1 << ligg->GlyphClass)))))
909 if (ligg->positioning_type == 5
910 && ligg->MarkAttachClass < mark_lig1->ClassCount)
911 num_class[ligg->MarkAttachClass]++;
915 = get_coverage_index (&mark_lig1->LigatureCoverage,
917 if (coverage_idx_lig < 0)
919 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
920 g->MarkAttachClass = mark_record->Class;
921 attach = (mark_lig1->LigatureArray.LigatureAttach
923 for (j = 0; j < attach->ComponentCount; j++)
925 OTF_Anchor *lig_anchor
926 = attach->ComponentRecord[j].LigatureAnchor;
928 if (lig_anchor[mark_record->Class].AnchorFormat
929 && num_class[mark_record->Class]-- == 0)
931 g->positioning_type = lookup->LookupType;
932 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
933 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
943 if (subtable->Format == 1)
945 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
946 OTF_MarkRecord *mark1_record;
947 OTF_AnchorRecord *mark2_record;
948 OTF_Glyph *prevg = g - 1;
949 int coverage_idx_base;
951 while (prevg >= gstring->glyphs
952 && (! prevg->glyph_id
953 || (prevg->GlyphClass
954 && (flag & (1 << prevg->GlyphClass)))))
956 if (prevg < gstring->glyphs)
959 = get_coverage_index (&mark_mark1->Mark2Coverage,
961 if (coverage_idx_base < 0)
963 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
965 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
966 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
968 = &mark2_record->Anchor[mark1_record->Class];
969 g->positioning_type = lookup->LookupType;
975 if (subtable->Format == 1)
977 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
978 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
983 for (j = 0; j < set->RuleCount; j++)
985 rule = set->Rule + j;
986 if (match_ids (gstring, gidx + 1, flag,
987 rule->GlyphCount - 1, rule->Input) < 0)
989 orig_used = gstring->used;
990 for (k = 0; k < rule->LookupCount; k++)
991 lookup_gpos (lookup_list,
992 rule->LookupRecord[k].LookupListIndex,
994 gidx + rule->LookupRecord[k].SequenceIndex);
995 gidx += rule->GlyphCount + (gstring->used - orig_used);
999 else if (subtable->Format == 2)
1001 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1003 OTF_ClassRule *rule;
1008 class = get_class_def (&context2->ClassDef, g->glyph_id);
1009 set = context2->ClassSet + class;
1011 for (j = 0; j < set->ClassRuleCnt; j++)
1013 rule = set->ClassRule + j;
1014 if (match_classes (&context2->ClassDef,
1015 gstring, gidx + 1, flag,
1016 rule->GlyphCount - 1, rule->Class)
1019 orig_used = gstring->used;
1020 for (k = 0; k < rule->LookupCount; k++)
1021 lookup_gpos (lookup_list,
1022 rule->LookupRecord[k].LookupListIndex,
1024 gidx + rule->LookupRecord[k].SequenceIndex);
1025 gidx += rule->GlyphCount + (gstring->used - orig_used);
1029 else /* subtable->Format == 3 */
1031 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1035 if (match_coverages (gstring, gidx + 1, flag,
1036 context3->GlyphCount - 1,
1037 context3->Coverage + 1) < 0)
1039 orig_used = gstring->used;
1040 for (j = 0; j < context3->LookupCount; j++)
1041 lookup_gpos (lookup_list,
1042 context3->LookupRecord[j].LookupListIndex,
1044 gidx + context3->LookupRecord[j].SequenceIndex);
1045 gidx += context3->GlyphCount + (gstring->used - orig_used);
1050 if (subtable->Format == 1)
1052 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1053 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1057 for (j = 0; j < set->ChainRuleCount; j++)
1059 OTF_ChainRule *rule = set->ChainRule + j;
1061 if (gidx < rule->BacktrackGlyphCount
1062 || (gidx + rule->InputGlyphCount
1063 + rule->LookaheadGlyphCount) > gstring->used)
1065 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1067 orig_used = gstring->used;
1068 for (k = 0; k < rule->LookupCount; k++)
1069 lookup_gpos (lookup_list,
1070 rule->LookupRecord[k].LookupListIndex,
1072 gidx + rule->LookupRecord[k].SequenceIndex);
1073 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1077 else if (subtable->Format == 2)
1079 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1080 OTF_ChainClassSet *set;
1085 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1086 set = context2->ChainClassSet + class;
1087 for (j = 0; j < set->ChainClassRuleCnt; j++)
1089 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1092 if (gidx < rule->BacktrackGlyphCount
1093 || (gidx + rule->InputGlyphCount
1094 + rule->LookaheadGlyphCount) > gstring->used)
1096 if (match_chain_classes (gstring, gidx, flag,
1097 &context2->BacktrackClassDef,
1098 &context2->InputClassDef,
1099 &context2->LookaheadClassDef,
1102 orig_used = gstring->used;
1103 for (k = 0; k < rule->LookupCount; k++)
1104 lookup_gpos (lookup_list,
1105 rule->LookupRecord[k].LookupListIndex,
1107 gidx + rule->LookupRecord[k].SequenceIndex);
1108 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1112 else if (subtable->Format == 3)
1114 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1118 if (gidx < context3->BacktrackGlyphCount
1119 || (gidx + context3->InputGlyphCount
1120 + context3->LookaheadGlyphCount) > gstring->used)
1122 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1124 orig_used = gstring->used;
1125 for (j = 0; j < context3->LookupCount; j++)
1126 lookup_gpos (lookup_list,
1127 context3->LookupRecord[j].LookupListIndex,
1129 gidx + context3->LookupRecord[j].SequenceIndex);
1130 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1133 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1137 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
1144 if (gidx == orig_gidx)
1150 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1154 for (i = 0; i < gstring->used; i++)
1156 c = gstring->glyphs[i].c;
1157 if (c < 0 || c >= 256)
1158 gstring->glyphs[i].glyph_id = 0;
1160 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1166 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1172 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1175 int segCount = sub4->segCountX2 / 2;
1177 for (i = 0; i < gstring->used; i++)
1179 c = gstring->glyphs[i].c;
1181 gstring->glyphs[i].glyph_id = 0;
1182 for (j = 0; j < segCount; j++)
1184 OTF_cmapSegument *seg = sub4->segments + i;
1186 if (c >= seg->startCount && c <= seg->endCount)
1188 if (seg->idRangeOffset == 0xFFFF)
1189 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1191 gstring->glyphs[i].glyph_id
1192 = sub4->glyphIdArray[seg->idRangeOffset
1193 + (c - seg->startCount)];
1203 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1209 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1215 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1221 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1231 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1237 && OTF_get_table (otf, "cmap") < 0)
1241 for (i = 0; i < gstring->used; i++)
1242 if (! gstring->glyphs[i].glyph_id)
1244 int c = gstring->glyphs[i].c;
1245 if (c < 32 || ! cmap->unicode_table)
1246 gstring->glyphs[i].glyph_id = 0;
1248 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1255 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1256 int platform_id, int encoding_id)
1260 char *errfmt = "CMAP Looking up%s";
1262 OTF_EncodingRecord *enc;
1265 && OTF_get_table (otf, "cmap") < 0)
1269 for (i = 0; i < cmap->numTables; i++)
1270 if (cmap->EncodingRecord[i].platformID == platform_id
1271 && cmap->EncodingRecord[i].encodingID == encoding_id)
1273 if (i == cmap->numTables)
1274 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1275 enc = cmap->EncodingRecord + i;
1276 switch (enc->subtable.format)
1278 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1279 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1280 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1281 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1282 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1283 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1284 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1286 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1291 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1294 && OTF_get_table (otf, "cmap") < 0)
1297 || code > otf->cmap->max_glyph_id
1298 || ! otf->cmap->decode_table)
1300 return otf->cmap->decode_table[code];
1304 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1310 && OTF_get_table (otf, "GDEF") < 0)
1314 if (gdef->glyph_class_def.offset)
1315 for (i = 0; i < gstring->used; i++)
1316 gstring->glyphs[i].GlyphClass
1317 = get_class_def (&gdef->glyph_class_def,
1318 gstring->glyphs[i].glyph_id);
1320 if (gdef->mark_attach_class_def.offset)
1321 for (i = 0; i < gstring->used; i++)
1322 gstring->glyphs[i].MarkAttachClass
1323 = get_class_def (&gdef->mark_attach_class_def,
1324 gstring->glyphs[i].glyph_id);
1331 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1332 char *script, char *language, char *features)
1334 char *errfmt = "GSUB driving%s";
1337 OTF_LangSys *LangSys;
1338 int *lookup_indices;
1341 for (i = 0; i < gstring->used; i++)
1342 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1345 && OTF_get_table (otf, "GSUB") < 0)
1348 if (gsub->FeatureList.FeatureCount == 0
1349 || gsub->LookupList.LookupCount == 0)
1352 LangSys = get_langsys (&gsub->ScriptList, script, language);
1356 /* One lookup may be used by multiple features. */
1357 lookup_indices = alloca (sizeof (int)
1358 * gsub->LookupList.LookupCount
1359 * (gsub->FeatureList.FeatureCount + 1));
1360 if (! lookup_indices)
1361 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1362 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1363 features, lookup_indices);
1367 for (i = 0; i < n; i++)
1369 int index = lookup_indices[i];
1372 if (gsub->LookupList.Lookup[index].LookupType != 8)
1375 while (gidx < gstring->used)
1377 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1384 gidx = gstring->used - 1;
1387 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1398 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1399 char *script, char *language, char *features)
1401 char *errfmt = "GPOS driving%s";
1404 OTF_LangSys *LangSys;
1405 int *lookup_indices;
1409 && OTF_get_table (otf, "GPOS") < 0)
1412 if (gpos->FeatureList.FeatureCount == 0
1413 || gpos->LookupList.LookupCount == 0)
1416 LangSys = get_langsys (&gpos->ScriptList, script, language);
1420 /* One lookup may be used by multiple features. */
1421 lookup_indices = alloca (sizeof (int)
1422 * gpos->LookupList.LookupCount
1423 * (gpos->FeatureList.FeatureCount + 1));
1424 if (! lookup_indices)
1425 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1426 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1427 features, lookup_indices);
1431 for (i = 0; i < gstring->used; i++)
1432 gstring->glyphs[i].positioning_type = 0;
1434 for (i = 0; i < n; i++)
1436 int index = lookup_indices[i];
1439 while (gidx < gstring->used)
1441 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1451 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1452 char *script, char *language,
1453 char *gsub_features, char *gpos_features)
1455 if (OTF_drive_cmap (otf, gstring) < 0)
1457 if (OTF_drive_gdef (otf, gstring) < 0)
1460 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1463 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)