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,
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 GSTRING_INSERT (gstring, from, (num - len));
72 GSTRING_DELETE (gstring, from, (len - num));
73 for (i = 0; i < num; i++)
75 gstring->glyphs[from + i].c = c;
76 gstring->glyphs[from + i].glyph_id = ids[i];
77 gstring->glyphs[from + i].f.index.from = from_idx;
78 gstring->glyphs[from + i].f.index.to = to_idx;
85 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
89 if (coverage->CoverageFormat == 1)
91 for (i = 0; i < coverage->Count; i++)
92 if (coverage->table.GlyphArray[i] == id)
97 for (i = 0; i < coverage->Count; i++)
98 if (coverage->table.RangeRecord[i].Start <= id
99 && coverage->table.RangeRecord[i].End >= id)
100 return (coverage->table.RangeRecord[i].StartCoverageIndex
101 + (id - coverage->table.RangeRecord[i].Start));
107 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
109 if (class_def->ClassFormat == 1)
111 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
113 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
114 return class_def->f.f1.ClassValueArray[idx];
120 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
121 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
122 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
123 return class_def->f.f2.ClassRangeRecord[i].Class;
129 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
132 OTF_Tag script_tag = OTF_tag (script);
133 OTF_Tag langsys_tag = OTF_tag (language);
136 for (i = 0; i < script_list->ScriptCount; i++)
138 || script_list->Script[i].ScriptTag == script_tag)
140 OTF_Script *script = script_list->Script + i;
143 return &script->DefaultLangSys;
144 for (j = 0; j < script->LangSysCount; j++)
145 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
146 return script->LangSys + j;
147 return &script->DefaultLangSys;
154 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
155 char *features, int *lookup_indices)
158 OTF_Feature *feature;
159 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
161 for (i = 0; i < FeatureList->FeatureCount; i++)
162 feature_table[i] = 0;
170 if (*features == '*')
172 /* Consume all remaining features. */
173 /* We are sure that the last LookupCount elements of
174 lookup_indices are free to be used for this work. */
175 int *free_table = (lookup_indices + (LookupList->LookupCount
176 * FeatureList->FeatureCount));
178 for (i = 0; i < LookupList->LookupCount; i++)
180 for (i = 0; i < FeatureList->FeatureCount; i++)
181 if (! feature_table[i])
183 feature = FeatureList->Feature + i;
184 for (j = 0; j < feature->LookupCount; j++)
185 free_table[feature->LookupListIndex[j]] = 1;
187 for (i = 0; i < LookupList->LookupCount; i++)
189 lookup_indices[n++] = i;
193 if (*features == '~')
194 negate = 1, features++;
195 for (i = 0; *features && *features != ','; i++, features++)
196 tagname[i] = *features;
202 tag = OTF_tag (tagname);
203 for (i = 0; i < FeatureList->FeatureCount; i++)
205 feature = FeatureList->Feature + i;
206 if (tag == feature->FeatureTag)
209 for (j = 0; j < feature->LookupCount; j++)
210 lookup_indices[n++] = feature->LookupListIndex[j];
211 feature_table[i] = 1;
221 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
223 OTF_Glyph *gbeg = gstring->glyphs + gidx;
224 OTF_Glyph *gend = gstring->glyphs + gstring->used;
228 for (g = gbeg, i = 0; g < gend && i < count; g++)
229 if (g->glyph_id && g->glyph_id != ids[i++])
231 return (i < count ? -1 : g - gbeg);
235 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
237 int i = rule->BacktrackGlyphCount;
243 for (j = gidx - 1; j >= 0; j--)
244 if (gstring->glyphs[j].glyph_id
249 if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
254 i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
258 i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
265 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
266 int count, unsigned *classes)
268 OTF_Glyph *gbeg = gstring->glyphs + gidx;
269 OTF_Glyph *gend = gstring->glyphs + gstring->used;
273 for (g = gbeg, i = 0; g < gend && i < count; g++)
275 && get_class_def (class_def, g->glyph_id) != classes[i++])
277 return (i < count ? -1 : g - gbeg);
281 match_chain_classes (OTF_GlyphString *gstring, int gidx,
282 OTF_ClassDef *BacktrackClassDef,
283 OTF_ClassDef *InputClassDef,
284 OTF_ClassDef *LookaheadClassDef,
285 OTF_ChainClassRule *rule)
287 int i = rule->BacktrackGlyphCount;
293 for (j = gidx - 1; j >= 0 && i > 0; j--)
294 if (gstring->glyphs[j].glyph_id
299 if (match_classes (BacktrackClassDef, gstring, j,
300 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
304 i = match_classes (InputClassDef, gstring, gidx,
305 rule->InputGlyphCount - 1, rule->Input);
309 i = match_classes (LookaheadClassDef, gstring, gidx,
310 rule->LookaheadGlyphCount, rule->LookAhead);
318 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
319 OTF_Coverage *coverages)
321 OTF_Glyph *gbeg = gstring->glyphs + gidx;
322 OTF_Glyph *gend = gstring->glyphs + gstring->used;
326 for (g = gbeg, i = 0; g < gend && i < count; g++)
328 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
330 return (i < count ? -1 : g - gbeg);
334 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
335 OTF_GSUB_ChainContext3 *context3)
337 int i = context3->BacktrackGlyphCount;
343 for (j = gidx - 1; j >= 0; j--)
344 if (gstring->glyphs[j].glyph_id
349 if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
350 context3->Backtrack) < 0)
354 if (context3->InputGlyphCount > 1)
356 i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
357 context3->Input + 1);
362 if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
363 context3->LookAhead) < 0)
369 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
370 OTF_GlyphString *gstring, int gidx)
372 char *errfmt = "GSUB Looking up%s";
374 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
375 unsigned int flag = lookup->LookupFlag;
376 int orig_gidx = gidx;
377 OTF_Glyph *g = gstring->glyphs + gidx;
382 && (flag & (1 << g->GlyphClass))))
385 /* Try all subtables until one of them handles the current glyph. */
386 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
388 unsigned lookup_type = lookup->LookupType;
389 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
392 if (lookup_type == 7)
394 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
396 lookup_type = extension1->ExtensionLookupType;
397 subtable = extension1->ExtensionSubtable;
400 if (subtable->Coverage.offset)
402 coverage_idx = get_coverage_index (&subtable->Coverage,
404 if (coverage_idx < 0)
408 switch (lookup->LookupType)
411 if (subtable->Format == 1)
412 g->glyph_id += subtable->u.single1.DeltaGlyphID;
414 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
420 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
421 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
423 gstring_subst (gstring, gidx, gidx + 1,
424 seq->Substitute, seq->GlyphCount);
425 gidx += seq->GlyphCount;
430 if (subtable->Format == 1)
432 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
433 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
435 g->glyph_id = altset->Alternate[0];
439 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
443 if (subtable->Format == 1)
445 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
446 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
450 for (j = 0; j < ligset->LigatureCount; j++)
454 lig = ligset->Ligature + j;
455 n = match_ids (gstring, gidx + 1,
456 lig->CompCount - 1, lig->Component);
459 gstring_subst (gstring, gidx, gidx + 1 + n,
466 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
470 if (subtable->Format == 1)
472 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
473 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
478 for (j = 0; j < set->RuleCount; j++)
480 rule = set->Rule + j;
481 if (match_ids (gstring, gidx + 1,
482 rule->GlyphCount - 1, rule->Input) < 0)
484 orig_used = gstring->used;
485 for (k = 0; k < rule->LookupCount; k++)
486 lookup_gsub (lookup_list,
487 rule->LookupRecord[k].LookupListIndex,
489 gidx + rule->LookupRecord[k].SequenceIndex);
490 gidx += rule->GlyphCount + (gstring->used - orig_used);
494 else if (subtable->Format == 2)
496 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
503 class = get_class_def (&context2->ClassDef, g->glyph_id);
504 set = context2->ClassSet + class;
506 for (j = 0; j < set->ClassRuleCnt; j++)
508 rule = set->ClassRule + j;
509 if (match_classes (&context2->ClassDef,
511 rule->GlyphCount - 1, rule->Class)
514 orig_used = gstring->used;
515 for (k = 0; k < rule->LookupCount; k++)
516 lookup_gsub (lookup_list,
517 rule->LookupRecord[k].LookupListIndex,
519 gidx + rule->LookupRecord[k].SequenceIndex);
520 gidx += rule->GlyphCount + (gstring->used - orig_used);
524 else /* subtable->Format == 3 */
526 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
530 if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
531 context3->Coverage + 1) < 0)
533 orig_used = gstring->used;
534 for (j = 0; j < context3->LookupCount; j++)
535 lookup_gsub (lookup_list,
536 context3->LookupRecord[j].LookupListIndex,
538 gidx + context3->LookupRecord[j].SequenceIndex);
539 gidx += context3->GlyphCount + (gstring->used - orig_used);
544 if (subtable->Format == 1)
546 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
547 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
551 for (j = 0; j < set->ChainRuleCount; j++)
553 OTF_ChainRule *rule = set->ChainRule + j;
555 if (gidx < rule->BacktrackGlyphCount
556 || (gidx + rule->InputGlyphCount
557 + rule->LookaheadGlyphCount) > gstring->used)
559 if (match_chain_ids (gstring, gidx, rule) < 0)
561 orig_used = gstring->used;
562 for (k = 0; k < rule->LookupCount; k++)
563 lookup_gsub (lookup_list,
564 rule->LookupRecord[k].LookupListIndex,
566 gidx + rule->LookupRecord[k].SequenceIndex);
567 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
571 else if (subtable->Format == 2)
573 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
574 OTF_ChainClassSet *set;
579 class = get_class_def (&context2->InputClassDef, g->glyph_id);
580 set = context2->ChainClassSet + class;
581 for (j = 0; j < set->ChainClassRuleCnt; j++)
583 OTF_ChainClassRule *rule = set->ChainClassRule + j;
586 if (gidx < rule->BacktrackGlyphCount
587 || (gidx + rule->InputGlyphCount
588 + rule->LookaheadGlyphCount) > gstring->used)
590 if (match_chain_classes (gstring, gidx,
591 &context2->BacktrackClassDef,
592 &context2->InputClassDef,
593 &context2->LookaheadClassDef,
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);
608 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
612 if (gidx < context3->BacktrackGlyphCount
613 || (gidx + context3->InputGlyphCount
614 + context3->LookaheadGlyphCount) > gstring->used)
616 if (match_chain_coverages (gstring, gidx, context3) < 0)
618 orig_used = gstring->used;
619 for (j = 0; j < context3->LookupCount; j++)
620 lookup_gsub (lookup_list,
621 context3->LookupRecord[j].LookupListIndex,
623 gidx + context3->LookupRecord[j].SequenceIndex);
624 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
630 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
631 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
632 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
635 if (back_gidx > gstring->used || ahead_gidx < 0)
638 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
639 if (get_coverage_index (reverse->Backtrack + j,
640 gstring->glyphs[gidx + 1 + j].glyph_id)
643 if (j < reverse->BacktrackGlyphCount)
645 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
646 if (get_coverage_index (reverse->LookAhead + j,
647 gstring->glyphs[gidx - 1 - j].glyph_id)
650 if (j < reverse->LookaheadGlyphCount)
652 g->glyph_id = reverse->Substitute[coverage_idx];
660 if (gidx == orig_gidx)
669 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
671 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
673 rec->XPlacement = anchor->XCoordinate;
674 rec->YPlacement = anchor->YCoordinate;
675 if (anchor->AnchorFormat == 1)
678 else if (anchor->AnchorFormat == 2)
679 /* Not yet implemented */
681 else if (anchor->AnchorFormat == 3)
682 /* Not yet implemented */
689 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
690 OTF_GlyphString *gstring, int gidx)
692 char *errfmt = "GPOS Looking up%s";
694 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
695 unsigned int flag = lookup->LookupFlag;
696 int orig_gidx = gidx;
697 OTF_Glyph *g = gstring->glyphs + gidx;
701 || g->positioning_type
703 && (flag & (1 << g->GlyphClass))))
706 /* Try all subtables until one of them handles the current glyph. */
707 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
709 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
712 if (subtable->Coverage.offset)
714 coverage_idx = get_coverage_index (&subtable->Coverage,
716 if (coverage_idx < 0)
720 switch (lookup->LookupType)
723 g->positioning_type = lookup->LookupType;
724 if (subtable->Format == 1)
726 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
728 g->f.f1.format = single1->ValueFormat;
729 g->f.f1.value = &single1->Value;
731 else if (subtable->Format == 2)
733 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
735 g->f.f1.format = single2->ValueFormat;
736 g->f.f1.value = single2->Value + coverage_idx;
742 int next_gidx = gidx + 1;
745 while (next_gidx < gstring->used
746 && ! gstring->glyphs[next_gidx].glyph_id)
749 if (next_gidx >= gstring->used)
751 nextg = gstring->glyphs + next_gidx;
752 if (nextg->positioning_type)
754 if (subtable->Format == 1)
756 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
757 OTF_PairSet *set = pair1->PairSet + coverage_idx;
760 for (j = 0; j < set->PairValueCount; j++)
761 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
763 if (pair1->ValueFormat1)
765 g->positioning_type = lookup->LookupType;
766 g->f.f2.format = pair1->ValueFormat1;
767 g->f.f2.value = &set->PairValueRecord[j].Value1;
770 if (pair1->ValueFormat2)
772 nextg->positioning_type = lookup->LookupType;
773 nextg->f.f2.format = pair1->ValueFormat2;
774 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
780 else if (subtable->Format == 2)
782 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
783 unsigned class1, class2;
785 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
786 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
787 if (pair2->ValueFormat1)
789 g->positioning_type = lookup->LookupType;
790 g->f.f2.format = pair2->ValueFormat1;
792 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
795 if (pair2->ValueFormat2)
797 nextg->positioning_type = lookup->LookupType;
798 nextg->f.f2.format = pair2->ValueFormat2;
800 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
809 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
811 g->positioning_type = lookup->LookupType;
813 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
815 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
822 if (subtable->Format == 1)
824 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
825 OTF_MarkRecord *mark_record;
826 OTF_AnchorRecord *base_record;
827 int coverage_idx_base
828 = get_coverage_index (&mark_base1->BaseCoverage,
831 if (coverage_idx_base < 0)
833 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
835 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
836 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
838 = &base_record->Anchor[mark_record->Class];
839 g->positioning_type = lookup->LookupType;
847 if (subtable->Format == 1)
849 /* As the document of this lookup type is quite
850 ambiguous, and we can't know the exact procedure to
852 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
859 if (subtable->Format == 1)
861 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
862 OTF_MarkRecord *mark1_record;
863 OTF_AnchorRecord *mark2_record;
864 int coverage_idx_base
865 = get_coverage_index (&mark_mark1->Mark2Coverage,
868 if (coverage_idx_base < 0)
870 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
872 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
873 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
875 = &mark2_record->Anchor[mark1_record->Class];
876 g->positioning_type = lookup->LookupType;
882 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
886 if (subtable->Format == 1)
887 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
888 else if (subtable->Format == 2)
890 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
891 OTF_ChainClassSet *set;
896 class = get_class_def (&context2->InputClassDef, g->glyph_id);
897 set = context2->ChainClassSet + class;
898 for (j = 0; j < set->ChainClassRuleCnt; j++)
900 OTF_ChainClassRule *rule = set->ChainClassRule + j;
901 int fore_idx = gidx + rule->InputGlyphCount;
904 if (gidx < rule->BacktrackGlyphCount
905 || (gidx + rule->InputGlyphCount
906 + rule->LookaheadGlyphCount) > gstring->used)
908 for (k = 0; k < rule->BacktrackGlyphCount; k++)
909 if (get_class_def (&context2->BacktrackClassDef,
910 gstring->glyphs[gidx - 1 - k].glyph_id)
911 != rule->Backtrack[k])
913 if (k < rule->BacktrackGlyphCount)
915 for (k = 1; k < rule->InputGlyphCount; k++)
916 if (get_class_def (&context2->InputClassDef,
917 gstring->glyphs[gidx + k].glyph_id)
918 != rule->Input[k - 1])
920 if (k < rule->InputGlyphCount)
922 for (k = 0; k < rule->LookaheadGlyphCount; k++)
923 if (get_class_def (&context2->LookaheadClassDef,
924 gstring->glyphs[fore_idx + k].glyph_id)
925 != rule->LookAhead[k])
927 if (k < rule->LookaheadGlyphCount)
930 orig_used = gstring->used;
931 for (k = 0; k < rule->LookupCount; k++)
932 lookup_gpos (lookup_list,
933 rule->LookupRecord[k].LookupListIndex,
935 gidx + rule->LookupRecord[k].SequenceIndex);
936 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
940 else if (subtable->Format == 3)
941 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
943 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
947 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
954 if (gidx == orig_gidx)
960 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
964 for (i = 0; i < gstring->used; i++)
966 c = gstring->glyphs[i].c;
967 if (c < 0 || c >= 256)
968 gstring->glyphs[i].glyph_id = 0;
970 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
976 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
982 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
985 int segCount = sub4->segCountX2 / 2;
987 for (i = 0; i < gstring->used; i++)
989 c = gstring->glyphs[i].c;
991 gstring->glyphs[i].glyph_id = 0;
992 for (j = 0; j < segCount; j++)
994 OTF_cmapSegument *seg = sub4->segments + i;
996 if (c >= seg->startCount && c <= seg->endCount)
998 if (seg->idRangeOffset == 0xFFFF)
999 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1001 gstring->glyphs[i].glyph_id
1002 = sub4->glyphIdArray[seg->idRangeOffset
1003 + (c - seg->startCount)];
1013 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1019 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1025 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1031 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1041 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1047 && OTF_get_table (otf, "cmap") < 0)
1051 for (i = 0; i < gstring->used; i++)
1052 if (! gstring->glyphs[i].glyph_id)
1054 int c = gstring->glyphs[i].c;
1055 if (c < 32 || ! cmap->unicode_table)
1056 gstring->glyphs[i].glyph_id = 0;
1058 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1065 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1066 int platform_id, int encoding_id)
1070 char *errfmt = "CMAP Looking up%s";
1072 OTF_EncodingRecord *enc;
1075 && OTF_get_table (otf, "cmap") < 0)
1079 for (i = 0; i < cmap->numTables; i++)
1080 if (cmap->EncodingRecord[i].platformID == platform_id
1081 && cmap->EncodingRecord[i].encodingID == encoding_id)
1083 if (i == cmap->numTables)
1084 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1085 enc = cmap->EncodingRecord + i;
1086 switch (enc->subtable.format)
1088 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1089 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1090 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1091 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1092 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1093 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1094 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1096 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1101 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1104 && OTF_get_table (otf, "cmap") < 0)
1107 || code > otf->cmap->max_glyph_id
1108 || ! otf->cmap->decode_table)
1110 return otf->cmap->decode_table[code];
1114 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1120 && OTF_get_table (otf, "GDEF") < 0)
1124 if (gdef->glyph_class_def.offset)
1125 for (i = 0; i < gstring->used; i++)
1126 gstring->glyphs[i].GlyphClass
1127 = get_class_def (&gdef->glyph_class_def,
1128 gstring->glyphs[i].glyph_id);
1130 if (gdef->mark_attach_class_def.offset)
1131 for (i = 0; i < gstring->used; i++)
1132 gstring->glyphs[i].MarkAttachClass
1133 = get_class_def (&gdef->mark_attach_class_def,
1134 gstring->glyphs[i].glyph_id);
1141 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1142 char *script, char *language, char *features)
1144 char *errfmt = "GSUB driving%s";
1147 OTF_LangSys *LangSys;
1148 int *lookup_indices;
1152 && OTF_get_table (otf, "GSUB") < 0)
1155 if (gsub->FeatureList.FeatureCount == 0
1156 || gsub->LookupList.LookupCount == 0)
1159 LangSys = get_langsys (&gsub->ScriptList, script, language);
1163 /* One lookup may be used by multiple features. */
1164 lookup_indices = alloca (sizeof (int)
1165 * gsub->LookupList.LookupCount
1166 * (gsub->FeatureList.FeatureCount + 1));
1167 if (! lookup_indices)
1168 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1169 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1170 features, lookup_indices);
1174 for (i = 0; i < gstring->used; i++)
1175 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1177 for (i = 0; i < n; i++)
1179 int index = lookup_indices[i];
1182 if (gsub->LookupList.Lookup[index].LookupType != 8)
1185 while (gidx < gstring->used)
1187 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1194 gidx = gstring->used - 1;
1197 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1208 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1209 char *script, char *language, char *features)
1211 char *errfmt = "GPOS driving%s";
1214 OTF_LangSys *LangSys;
1215 int *lookup_indices;
1219 && OTF_get_table (otf, "GPOS") < 0)
1222 if (gpos->FeatureList.FeatureCount == 0
1223 || gpos->LookupList.LookupCount == 0)
1226 LangSys = get_langsys (&gpos->ScriptList, script, language);
1230 /* One lookup may be used by multiple features. */
1231 lookup_indices = alloca (sizeof (int)
1232 * gpos->LookupList.LookupCount
1233 * (gpos->FeatureList.FeatureCount + 1));
1234 if (! lookup_indices)
1235 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1236 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1237 features, lookup_indices);
1241 for (i = 0; i < gstring->used; i++)
1242 gstring->glyphs[i].positioning_type = 0;
1244 for (i = 0; i < n; i++)
1246 int index = lookup_indices[i];
1249 while (gidx < gstring->used)
1251 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1261 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1262 char *script, char *language,
1263 char *gsub_features, char *gpos_features)
1265 if (OTF_drive_cmap (otf, gstring) < 0)
1267 if (OTF_drive_gdef (otf, gstring) < 0)
1270 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1273 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)