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)
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 unsigned lookup_type = lookup->LookupType;
743 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
746 if (lookup_type == 9)
748 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
750 lookup_type = extension1->ExtensionLookupType;
751 subtable = extension1->ExtensionSubtable;
754 if (subtable->Coverage.offset)
756 coverage_idx = get_coverage_index (&subtable->Coverage,
758 if (coverage_idx < 0)
765 g->positioning_type = lookup_type;
766 if (subtable->Format == 1)
768 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
770 g->f.f1.format = single1->ValueFormat;
771 g->f.f1.value = &single1->Value;
773 else if (subtable->Format == 2)
775 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
777 g->f.f1.format = single2->ValueFormat;
778 g->f.f1.value = single2->Value + coverage_idx;
784 int next_gidx = gidx + 1;
787 while (next_gidx < gstring->used
788 && (! gstring->glyphs[next_gidx].glyph_id
790 & (1 << gstring->glyphs[next_gidx].GlyphClass))))
793 if (next_gidx >= gstring->used)
795 nextg = gstring->glyphs + next_gidx;
796 if (nextg->positioning_type)
798 if (subtable->Format == 1)
800 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
801 OTF_PairSet *set = pair1->PairSet + coverage_idx;
804 for (j = 0; j < set->PairValueCount; j++)
805 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
807 if (pair1->ValueFormat1)
809 g->positioning_type = lookup_type;
810 g->f.f2.format = pair1->ValueFormat1;
811 g->f.f2.value = &set->PairValueRecord[j].Value1;
814 if (pair1->ValueFormat2)
816 nextg->positioning_type = lookup_type;
817 nextg->f.f2.format = pair1->ValueFormat2;
818 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
824 else if (subtable->Format == 2)
826 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
827 unsigned class1, class2;
829 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
830 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
831 if (pair2->ValueFormat1)
833 g->positioning_type = lookup_type;
834 g->f.f2.format = pair2->ValueFormat1;
836 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
839 if (pair2->ValueFormat2)
841 nextg->positioning_type = lookup_type;
842 nextg->f.f2.format = pair2->ValueFormat2;
844 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
853 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
855 g->positioning_type = lookup_type;
857 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
859 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
866 if (subtable->Format == 1)
868 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
869 OTF_MarkRecord *mark_record;
870 OTF_AnchorRecord *base_record;
871 OTF_Glyph *baseg = g - 1;
872 int coverage_idx_base;
874 while (baseg >= gstring->glyphs
875 && (! baseg->glyph_id
876 || (baseg->GlyphClass
877 && (flag & (1 << baseg->GlyphClass)))))
880 = get_coverage_index (&mark_base1->BaseCoverage,
883 if (coverage_idx_base < 0)
885 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
887 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
888 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
890 = &base_record->Anchor[mark_record->Class];
891 g->positioning_type = lookup_type;
898 if (subtable->Format == 1)
900 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
901 unsigned class = g->MarkAttachClass;
902 OTF_Glyph *ligg = g - 1;
903 int coverage_idx_lig;
904 OTF_MarkRecord *mark_record;
905 OTF_ComponentRecord *cmp_record;
906 OTF_LigatureAttach *attach;
907 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
910 for (j = 0; j < mark_lig1->ClassCount; j++)
913 while (ligg >= gstring->glyphs
916 && (flag & (1 << ligg->GlyphClass)))))
918 if (ligg->positioning_type == 5
919 && ligg->MarkAttachClass < mark_lig1->ClassCount)
920 num_class[ligg->MarkAttachClass]++;
924 = get_coverage_index (&mark_lig1->LigatureCoverage,
926 if (coverage_idx_lig < 0)
928 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
929 g->MarkAttachClass = mark_record->Class;
930 attach = (mark_lig1->LigatureArray.LigatureAttach
932 for (j = 0; j < attach->ComponentCount; j++)
934 OTF_Anchor *lig_anchor
935 = attach->ComponentRecord[j].LigatureAnchor;
937 if (lig_anchor[mark_record->Class].AnchorFormat
938 && num_class[mark_record->Class]-- == 0)
940 g->positioning_type = lookup_type;
941 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
942 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
952 if (subtable->Format == 1)
954 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
955 OTF_MarkRecord *mark1_record;
956 OTF_AnchorRecord *mark2_record;
957 OTF_Glyph *prevg = g - 1;
958 int coverage_idx_base;
960 while (prevg >= gstring->glyphs
961 && (! prevg->glyph_id
962 || (prevg->GlyphClass
963 && (flag & (1 << prevg->GlyphClass)))))
965 if (prevg < gstring->glyphs)
968 = get_coverage_index (&mark_mark1->Mark2Coverage,
970 if (coverage_idx_base < 0)
972 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
974 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
975 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
977 = &mark2_record->Anchor[mark1_record->Class];
978 g->positioning_type = lookup_type;
984 if (subtable->Format == 1)
986 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
987 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
992 for (j = 0; j < set->RuleCount; j++)
994 rule = set->Rule + j;
995 if (match_ids (gstring, gidx + 1, flag,
996 rule->GlyphCount - 1, rule->Input) < 0)
998 orig_used = gstring->used;
999 for (k = 0; k < rule->LookupCount; k++)
1000 lookup_gpos (lookup_list,
1001 rule->LookupRecord[k].LookupListIndex,
1003 gidx + rule->LookupRecord[k].SequenceIndex);
1004 gidx += rule->GlyphCount + (gstring->used - orig_used);
1008 else if (subtable->Format == 2)
1010 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1012 OTF_ClassRule *rule;
1017 class = get_class_def (&context2->ClassDef, g->glyph_id);
1018 set = context2->ClassSet + class;
1020 for (j = 0; j < set->ClassRuleCnt; j++)
1022 rule = set->ClassRule + j;
1023 if (match_classes (&context2->ClassDef,
1024 gstring, gidx + 1, flag,
1025 rule->GlyphCount - 1, rule->Class)
1028 orig_used = gstring->used;
1029 for (k = 0; k < rule->LookupCount; k++)
1030 lookup_gpos (lookup_list,
1031 rule->LookupRecord[k].LookupListIndex,
1033 gidx + rule->LookupRecord[k].SequenceIndex);
1034 gidx += rule->GlyphCount + (gstring->used - orig_used);
1038 else /* subtable->Format == 3 */
1040 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1044 if (match_coverages (gstring, gidx + 1, flag,
1045 context3->GlyphCount - 1,
1046 context3->Coverage + 1) < 0)
1048 orig_used = gstring->used;
1049 for (j = 0; j < context3->LookupCount; j++)
1050 lookup_gpos (lookup_list,
1051 context3->LookupRecord[j].LookupListIndex,
1053 gidx + context3->LookupRecord[j].SequenceIndex);
1054 gidx += context3->GlyphCount + (gstring->used - orig_used);
1059 if (subtable->Format == 1)
1061 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1062 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1066 for (j = 0; j < set->ChainRuleCount; j++)
1068 OTF_ChainRule *rule = set->ChainRule + j;
1070 if (gidx < rule->BacktrackGlyphCount
1071 || (gidx + rule->InputGlyphCount
1072 + rule->LookaheadGlyphCount) > gstring->used)
1074 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1076 orig_used = gstring->used;
1077 for (k = 0; k < rule->LookupCount; k++)
1078 lookup_gpos (lookup_list,
1079 rule->LookupRecord[k].LookupListIndex,
1081 gidx + rule->LookupRecord[k].SequenceIndex);
1082 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1086 else if (subtable->Format == 2)
1088 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1089 OTF_ChainClassSet *set;
1094 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1095 set = context2->ChainClassSet + class;
1096 for (j = 0; j < set->ChainClassRuleCnt; j++)
1098 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1101 if (gidx < rule->BacktrackGlyphCount
1102 || (gidx + rule->InputGlyphCount
1103 + rule->LookaheadGlyphCount) > gstring->used)
1105 if (match_chain_classes (gstring, gidx, flag,
1106 &context2->BacktrackClassDef,
1107 &context2->InputClassDef,
1108 &context2->LookaheadClassDef,
1111 orig_used = gstring->used;
1112 for (k = 0; k < rule->LookupCount; k++)
1113 lookup_gpos (lookup_list,
1114 rule->LookupRecord[k].LookupListIndex,
1116 gidx + rule->LookupRecord[k].SequenceIndex);
1117 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1121 else if (subtable->Format == 3)
1123 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1127 if (gidx < context3->BacktrackGlyphCount
1128 || (gidx + context3->InputGlyphCount
1129 + context3->LookaheadGlyphCount) > gstring->used)
1131 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1133 orig_used = gstring->used;
1134 for (j = 0; j < context3->LookupCount; j++)
1135 lookup_gpos (lookup_list,
1136 context3->LookupRecord[j].LookupListIndex,
1138 gidx + context3->LookupRecord[j].SequenceIndex);
1139 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1142 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1149 if (gidx == orig_gidx)
1155 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1159 for (i = 0; i < gstring->used; i++)
1161 c = gstring->glyphs[i].c;
1162 if (c < 0 || c >= 256)
1163 gstring->glyphs[i].glyph_id = 0;
1165 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1171 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1177 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1180 int segCount = sub4->segCountX2 / 2;
1182 for (i = 0; i < gstring->used; i++)
1184 c = gstring->glyphs[i].c;
1186 gstring->glyphs[i].glyph_id = 0;
1187 for (j = 0; j < segCount; j++)
1189 OTF_cmapSegument *seg = sub4->segments + i;
1191 if (c >= seg->startCount && c <= seg->endCount)
1193 if (seg->idRangeOffset == 0xFFFF)
1194 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1196 gstring->glyphs[i].glyph_id
1197 = sub4->glyphIdArray[seg->idRangeOffset
1198 + (c - seg->startCount)];
1208 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1214 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1220 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1226 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1236 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1242 && OTF_get_table (otf, "cmap") < 0)
1246 for (i = 0; i < gstring->used; i++)
1247 if (! gstring->glyphs[i].glyph_id)
1249 int c = gstring->glyphs[i].c;
1250 if (c < 32 || ! cmap->unicode_table)
1251 gstring->glyphs[i].glyph_id = 0;
1253 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1260 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1261 int platform_id, int encoding_id)
1265 char *errfmt = "CMAP Looking up%s";
1267 OTF_EncodingRecord *enc;
1270 && OTF_get_table (otf, "cmap") < 0)
1274 for (i = 0; i < cmap->numTables; i++)
1275 if (cmap->EncodingRecord[i].platformID == platform_id
1276 && cmap->EncodingRecord[i].encodingID == encoding_id)
1278 if (i == cmap->numTables)
1279 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1280 enc = cmap->EncodingRecord + i;
1281 switch (enc->subtable.format)
1283 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1284 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1285 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1286 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1287 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1288 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1289 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1291 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1296 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1299 && OTF_get_table (otf, "cmap") < 0)
1302 || code > otf->cmap->max_glyph_id
1303 || ! otf->cmap->decode_table)
1305 return otf->cmap->decode_table[code];
1309 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1315 && OTF_get_table (otf, "GDEF") < 0)
1319 if (gdef->glyph_class_def.offset)
1320 for (i = 0; i < gstring->used; i++)
1321 gstring->glyphs[i].GlyphClass
1322 = get_class_def (&gdef->glyph_class_def,
1323 gstring->glyphs[i].glyph_id);
1325 if (gdef->mark_attach_class_def.offset)
1326 for (i = 0; i < gstring->used; i++)
1327 gstring->glyphs[i].MarkAttachClass
1328 = get_class_def (&gdef->mark_attach_class_def,
1329 gstring->glyphs[i].glyph_id);
1336 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1337 char *script, char *language, char *features)
1339 char *errfmt = "GSUB driving%s";
1342 OTF_LangSys *LangSys;
1343 int *lookup_indices;
1346 for (i = 0; i < gstring->used; i++)
1347 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1350 && OTF_get_table (otf, "GSUB") < 0)
1353 if (gsub->FeatureList.FeatureCount == 0
1354 || gsub->LookupList.LookupCount == 0)
1357 LangSys = get_langsys (&gsub->ScriptList, script, language);
1361 /* One lookup may be used by multiple features. */
1362 lookup_indices = alloca (sizeof (int)
1363 * gsub->LookupList.LookupCount
1364 * (gsub->FeatureList.FeatureCount + 1));
1365 if (! lookup_indices)
1366 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1367 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1368 features, lookup_indices);
1372 for (i = 0; i < n; i++)
1374 int index = lookup_indices[i];
1377 if (gsub->LookupList.Lookup[index].LookupType != 8)
1380 while (gidx < gstring->used)
1382 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1389 gidx = gstring->used - 1;
1392 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1403 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1404 char *script, char *language, char *features)
1406 char *errfmt = "GPOS driving%s";
1409 OTF_LangSys *LangSys;
1410 int *lookup_indices;
1414 && OTF_get_table (otf, "GPOS") < 0)
1417 if (gpos->FeatureList.FeatureCount == 0
1418 || gpos->LookupList.LookupCount == 0)
1421 LangSys = get_langsys (&gpos->ScriptList, script, language);
1425 /* One lookup may be used by multiple features. */
1426 lookup_indices = alloca (sizeof (int)
1427 * gpos->LookupList.LookupCount
1428 * (gpos->FeatureList.FeatureCount + 1));
1429 if (! lookup_indices)
1430 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1431 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1432 features, lookup_indices);
1436 for (i = 0; i < gstring->used; i++)
1437 gstring->glyphs[i].positioning_type = 0;
1439 for (i = 0; i < n; i++)
1441 int index = lookup_indices[i];
1444 while (gidx < gstring->used)
1446 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1456 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1457 char *script, char *language,
1458 char *gsub_features, char *gpos_features)
1460 if (OTF_drive_cmap (otf, gstring) < 0)
1462 if (OTF_drive_gdef (otf, gstring) < 0)
1465 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1468 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)