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);
135 OTF_Tag dflt_tag = OTF_tag ("DFLT");
136 OTF_Script *dflt = NULL;
138 for (i = 0; i < script_list->ScriptCount; i++)
140 OTF_Script *script = script_list->Script + i;
142 if (script_list->Script[i].ScriptTag == dflt_tag)
144 if (script_list->Script[i].ScriptTag == script_tag)
147 return &script->DefaultLangSys;
148 for (j = 0; j < script->LangSysCount; j++)
149 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
150 return script->LangSys + j;
151 return &script->DefaultLangSys;
156 dflt = script_list->Script;
158 return &dflt->DefaultLangSys;
159 for (j = 0; j < dflt->LangSysCount; j++)
160 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
161 return dflt->LangSys + j;
162 return &dflt->DefaultLangSys;
166 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
167 char *features, int *lookup_indices)
170 OTF_Feature *feature;
171 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
173 for (i = 0; i < FeatureList->FeatureCount; i++)
174 feature_table[i] = 0;
182 if (*features == '*')
184 /* Consume all remaining features. */
185 /* We are sure that the last LookupCount elements of
186 lookup_indices are free to be used for this work. */
187 int *free_table = (lookup_indices + (LookupList->LookupCount
188 * FeatureList->FeatureCount));
190 for (i = 0; i < LookupList->LookupCount; i++)
192 for (i = 0; i < FeatureList->FeatureCount; i++)
193 if (! feature_table[i])
195 feature = FeatureList->Feature + i;
196 for (j = 0; j < feature->LookupCount; j++)
197 free_table[feature->LookupListIndex[j]] = 1;
199 for (i = 0; i < LookupList->LookupCount; i++)
201 lookup_indices[n++] = i;
205 if (*features == '~')
206 negate = 1, features++;
207 for (i = 0; *features && *features != ','; i++, features++)
208 tagname[i] = *features;
214 tag = OTF_tag (tagname);
215 for (i = 0; i < FeatureList->FeatureCount; i++)
217 feature = FeatureList->Feature + i;
218 if (tag == feature->FeatureTag)
221 for (j = 0; j < feature->LookupCount; j++)
222 lookup_indices[n++] = feature->LookupListIndex[j];
223 feature_table[i] = 1;
233 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
235 OTF_Glyph *gbeg = gstring->glyphs + gidx;
236 OTF_Glyph *gend = gstring->glyphs + gstring->used;
240 for (g = gbeg, i = 0; g < gend && i < count; g++)
241 if (g->glyph_id && g->glyph_id != ids[i++])
243 return (i < count ? -1 : g - gbeg);
247 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
249 int i = rule->BacktrackGlyphCount;
255 for (j = gidx - 1; j >= 0; j--)
256 if (gstring->glyphs[j].glyph_id
261 if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
266 i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
270 i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
277 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
278 int count, unsigned *classes)
280 OTF_Glyph *gbeg = gstring->glyphs + gidx;
281 OTF_Glyph *gend = gstring->glyphs + gstring->used;
285 for (g = gbeg, i = 0; g < gend && i < count; g++)
287 && get_class_def (class_def, g->glyph_id) != classes[i++])
289 return (i < count ? -1 : g - gbeg);
293 match_chain_classes (OTF_GlyphString *gstring, int gidx,
294 OTF_ClassDef *BacktrackClassDef,
295 OTF_ClassDef *InputClassDef,
296 OTF_ClassDef *LookaheadClassDef,
297 OTF_ChainClassRule *rule)
299 int i = rule->BacktrackGlyphCount;
305 for (j = gidx - 1; j >= 0 && i > 0; j--)
306 if (gstring->glyphs[j].glyph_id
311 if (match_classes (BacktrackClassDef, gstring, j,
312 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
316 i = match_classes (InputClassDef, gstring, gidx,
317 rule->InputGlyphCount - 1, rule->Input);
321 i = match_classes (LookaheadClassDef, gstring, gidx,
322 rule->LookaheadGlyphCount, rule->LookAhead);
330 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
331 OTF_Coverage *coverages)
333 OTF_Glyph *gbeg = gstring->glyphs + gidx;
334 OTF_Glyph *gend = gstring->glyphs + gstring->used;
338 for (g = gbeg, i = 0; g < gend && i < count; g++)
340 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
342 return (i < count ? -1 : g - gbeg);
346 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
347 OTF_GSUB_ChainContext3 *context3)
349 int i = context3->BacktrackGlyphCount;
355 for (j = gidx - 1; j >= 0; j--)
356 if (gstring->glyphs[j].glyph_id
361 if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
362 context3->Backtrack) < 0)
366 if (context3->InputGlyphCount > 1)
368 i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
369 context3->Input + 1);
374 if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
375 context3->LookAhead) < 0)
381 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
382 OTF_GlyphString *gstring, int gidx)
384 char *errfmt = "GSUB Looking up%s";
386 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
387 unsigned int flag = lookup->LookupFlag;
388 int orig_gidx = gidx;
389 OTF_Glyph *g = gstring->glyphs + gidx;
394 && (flag & (1 << g->GlyphClass))))
397 /* Try all subtables until one of them handles the current glyph. */
398 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
400 unsigned lookup_type = lookup->LookupType;
401 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
404 if (lookup_type == 7)
406 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
408 lookup_type = extension1->ExtensionLookupType;
409 subtable = extension1->ExtensionSubtable;
412 if (subtable->Coverage.offset)
414 coverage_idx = get_coverage_index (&subtable->Coverage,
416 if (coverage_idx < 0)
420 switch (lookup->LookupType)
423 if (subtable->Format == 1)
424 g->glyph_id += subtable->u.single1.DeltaGlyphID;
426 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
432 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
433 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
435 gstring_subst (gstring, gidx, gidx + 1,
436 seq->Substitute, seq->GlyphCount);
437 gidx += seq->GlyphCount;
442 if (subtable->Format == 1)
444 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
445 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
447 g->glyph_id = altset->Alternate[0];
451 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
455 if (subtable->Format == 1)
457 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
458 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
462 for (j = 0; j < ligset->LigatureCount; j++)
466 lig = ligset->Ligature + j;
467 n = match_ids (gstring, gidx + 1,
468 lig->CompCount - 1, lig->Component);
471 gstring_subst (gstring, gidx, gidx + 1 + n,
478 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
482 if (subtable->Format == 1)
484 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
485 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
490 for (j = 0; j < set->RuleCount; j++)
492 rule = set->Rule + j;
493 if (match_ids (gstring, gidx + 1,
494 rule->GlyphCount - 1, rule->Input) < 0)
496 orig_used = gstring->used;
497 for (k = 0; k < rule->LookupCount; k++)
498 lookup_gsub (lookup_list,
499 rule->LookupRecord[k].LookupListIndex,
501 gidx + rule->LookupRecord[k].SequenceIndex);
502 gidx += rule->GlyphCount + (gstring->used - orig_used);
506 else if (subtable->Format == 2)
508 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
515 class = get_class_def (&context2->ClassDef, g->glyph_id);
516 set = context2->ClassSet + class;
518 for (j = 0; j < set->ClassRuleCnt; j++)
520 rule = set->ClassRule + j;
521 if (match_classes (&context2->ClassDef,
523 rule->GlyphCount - 1, rule->Class)
526 orig_used = gstring->used;
527 for (k = 0; k < rule->LookupCount; k++)
528 lookup_gsub (lookup_list,
529 rule->LookupRecord[k].LookupListIndex,
531 gidx + rule->LookupRecord[k].SequenceIndex);
532 gidx += rule->GlyphCount + (gstring->used - orig_used);
536 else /* subtable->Format == 3 */
538 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
542 if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
543 context3->Coverage + 1) < 0)
545 orig_used = gstring->used;
546 for (j = 0; j < context3->LookupCount; j++)
547 lookup_gsub (lookup_list,
548 context3->LookupRecord[j].LookupListIndex,
550 gidx + context3->LookupRecord[j].SequenceIndex);
551 gidx += context3->GlyphCount + (gstring->used - orig_used);
556 if (subtable->Format == 1)
558 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
559 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
563 for (j = 0; j < set->ChainRuleCount; j++)
565 OTF_ChainRule *rule = set->ChainRule + j;
567 if (gidx < rule->BacktrackGlyphCount
568 || (gidx + rule->InputGlyphCount
569 + rule->LookaheadGlyphCount) > gstring->used)
571 if (match_chain_ids (gstring, gidx, rule) < 0)
573 orig_used = gstring->used;
574 for (k = 0; k < rule->LookupCount; k++)
575 lookup_gsub (lookup_list,
576 rule->LookupRecord[k].LookupListIndex,
578 gidx + rule->LookupRecord[k].SequenceIndex);
579 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
583 else if (subtable->Format == 2)
585 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
586 OTF_ChainClassSet *set;
591 class = get_class_def (&context2->InputClassDef, g->glyph_id);
592 set = context2->ChainClassSet + class;
593 for (j = 0; j < set->ChainClassRuleCnt; j++)
595 OTF_ChainClassRule *rule = set->ChainClassRule + j;
598 if (gidx < rule->BacktrackGlyphCount
599 || (gidx + rule->InputGlyphCount
600 + rule->LookaheadGlyphCount) > gstring->used)
602 if (match_chain_classes (gstring, gidx,
603 &context2->BacktrackClassDef,
604 &context2->InputClassDef,
605 &context2->LookaheadClassDef,
608 orig_used = gstring->used;
609 for (k = 0; k < rule->LookupCount; k++)
610 lookup_gsub (lookup_list,
611 rule->LookupRecord[k].LookupListIndex,
613 gidx + rule->LookupRecord[k].SequenceIndex);
614 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
620 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
624 if (gidx < context3->BacktrackGlyphCount
625 || (gidx + context3->InputGlyphCount
626 + context3->LookaheadGlyphCount) > gstring->used)
628 if (match_chain_coverages (gstring, gidx, context3) < 0)
630 orig_used = gstring->used;
631 for (j = 0; j < context3->LookupCount; j++)
632 lookup_gsub (lookup_list,
633 context3->LookupRecord[j].LookupListIndex,
635 gidx + context3->LookupRecord[j].SequenceIndex);
636 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
642 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
643 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
644 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
647 if (back_gidx > gstring->used || ahead_gidx < 0)
650 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
651 if (get_coverage_index (reverse->Backtrack + j,
652 gstring->glyphs[gidx + 1 + j].glyph_id)
655 if (j < reverse->BacktrackGlyphCount)
657 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
658 if (get_coverage_index (reverse->LookAhead + j,
659 gstring->glyphs[gidx - 1 - j].glyph_id)
662 if (j < reverse->LookaheadGlyphCount)
664 g->glyph_id = reverse->Substitute[coverage_idx];
672 if (gidx == orig_gidx)
681 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
683 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
685 rec->XPlacement = anchor->XCoordinate;
686 rec->YPlacement = anchor->YCoordinate;
687 if (anchor->AnchorFormat == 1)
690 else if (anchor->AnchorFormat == 2)
691 /* Not yet implemented */
693 else if (anchor->AnchorFormat == 3)
694 /* Not yet implemented */
701 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
702 OTF_GlyphString *gstring, int gidx)
704 char *errfmt = "GPOS Looking up%s";
706 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
707 unsigned int flag = lookup->LookupFlag;
708 int orig_gidx = gidx;
709 OTF_Glyph *g = gstring->glyphs + gidx;
713 || g->positioning_type
715 && (flag & (1 << g->GlyphClass))))
718 /* Try all subtables until one of them handles the current glyph. */
719 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
721 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
724 if (subtable->Coverage.offset)
726 coverage_idx = get_coverage_index (&subtable->Coverage,
728 if (coverage_idx < 0)
732 switch (lookup->LookupType)
735 g->positioning_type = lookup->LookupType;
736 if (subtable->Format == 1)
738 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
740 g->f.f1.format = single1->ValueFormat;
741 g->f.f1.value = &single1->Value;
743 else if (subtable->Format == 2)
745 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
747 g->f.f1.format = single2->ValueFormat;
748 g->f.f1.value = single2->Value + coverage_idx;
754 int next_gidx = gidx + 1;
757 while (next_gidx < gstring->used
758 && ! gstring->glyphs[next_gidx].glyph_id)
761 if (next_gidx >= gstring->used)
763 nextg = gstring->glyphs + next_gidx;
764 if (nextg->positioning_type)
766 if (subtable->Format == 1)
768 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
769 OTF_PairSet *set = pair1->PairSet + coverage_idx;
772 for (j = 0; j < set->PairValueCount; j++)
773 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
775 if (pair1->ValueFormat1)
777 g->positioning_type = lookup->LookupType;
778 g->f.f2.format = pair1->ValueFormat1;
779 g->f.f2.value = &set->PairValueRecord[j].Value1;
782 if (pair1->ValueFormat2)
784 nextg->positioning_type = lookup->LookupType;
785 nextg->f.f2.format = pair1->ValueFormat2;
786 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
792 else if (subtable->Format == 2)
794 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
795 unsigned class1, class2;
797 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
798 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
799 if (pair2->ValueFormat1)
801 g->positioning_type = lookup->LookupType;
802 g->f.f2.format = pair2->ValueFormat1;
804 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
807 if (pair2->ValueFormat2)
809 nextg->positioning_type = lookup->LookupType;
810 nextg->f.f2.format = pair2->ValueFormat2;
812 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
821 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
823 g->positioning_type = lookup->LookupType;
825 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
827 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
834 if (subtable->Format == 1)
836 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
837 OTF_MarkRecord *mark_record;
838 OTF_AnchorRecord *base_record;
839 int coverage_idx_base
840 = get_coverage_index (&mark_base1->BaseCoverage,
843 if (coverage_idx_base < 0)
845 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
847 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
848 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
850 = &base_record->Anchor[mark_record->Class];
851 g->positioning_type = lookup->LookupType;
859 if (subtable->Format == 1)
861 /* As the document of this lookup type is quite
862 ambiguous, and we can't know the exact procedure to
864 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
871 if (subtable->Format == 1)
873 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
874 OTF_MarkRecord *mark1_record;
875 OTF_AnchorRecord *mark2_record;
876 int coverage_idx_base
877 = get_coverage_index (&mark_mark1->Mark2Coverage,
880 if (coverage_idx_base < 0)
882 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
884 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
885 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
887 = &mark2_record->Anchor[mark1_record->Class];
888 g->positioning_type = lookup->LookupType;
894 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
898 if (subtable->Format == 1)
899 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
900 else if (subtable->Format == 2)
902 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
903 OTF_ChainClassSet *set;
908 class = get_class_def (&context2->InputClassDef, g->glyph_id);
909 set = context2->ChainClassSet + class;
910 for (j = 0; j < set->ChainClassRuleCnt; j++)
912 OTF_ChainClassRule *rule = set->ChainClassRule + j;
913 int fore_idx = gidx + rule->InputGlyphCount;
916 if (gidx < rule->BacktrackGlyphCount
917 || (gidx + rule->InputGlyphCount
918 + rule->LookaheadGlyphCount) > gstring->used)
920 for (k = 0; k < rule->BacktrackGlyphCount; k++)
921 if (get_class_def (&context2->BacktrackClassDef,
922 gstring->glyphs[gidx - 1 - k].glyph_id)
923 != rule->Backtrack[k])
925 if (k < rule->BacktrackGlyphCount)
927 for (k = 1; k < rule->InputGlyphCount; k++)
928 if (get_class_def (&context2->InputClassDef,
929 gstring->glyphs[gidx + k].glyph_id)
930 != rule->Input[k - 1])
932 if (k < rule->InputGlyphCount)
934 for (k = 0; k < rule->LookaheadGlyphCount; k++)
935 if (get_class_def (&context2->LookaheadClassDef,
936 gstring->glyphs[fore_idx + k].glyph_id)
937 != rule->LookAhead[k])
939 if (k < rule->LookaheadGlyphCount)
942 orig_used = gstring->used;
943 for (k = 0; k < rule->LookupCount; k++)
944 lookup_gpos (lookup_list,
945 rule->LookupRecord[k].LookupListIndex,
947 gidx + rule->LookupRecord[k].SequenceIndex);
948 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
952 else if (subtable->Format == 3)
953 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
955 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
959 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
966 if (gidx == orig_gidx)
972 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
976 for (i = 0; i < gstring->used; i++)
978 c = gstring->glyphs[i].c;
979 if (c < 0 || c >= 256)
980 gstring->glyphs[i].glyph_id = 0;
982 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
988 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
994 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
997 int segCount = sub4->segCountX2 / 2;
999 for (i = 0; i < gstring->used; i++)
1001 c = gstring->glyphs[i].c;
1003 gstring->glyphs[i].glyph_id = 0;
1004 for (j = 0; j < segCount; j++)
1006 OTF_cmapSegument *seg = sub4->segments + i;
1008 if (c >= seg->startCount && c <= seg->endCount)
1010 if (seg->idRangeOffset == 0xFFFF)
1011 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1013 gstring->glyphs[i].glyph_id
1014 = sub4->glyphIdArray[seg->idRangeOffset
1015 + (c - seg->startCount)];
1025 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1031 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1037 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1043 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1053 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1059 && OTF_get_table (otf, "cmap") < 0)
1063 for (i = 0; i < gstring->used; i++)
1064 if (! gstring->glyphs[i].glyph_id)
1066 int c = gstring->glyphs[i].c;
1067 if (c < 32 || ! cmap->unicode_table)
1068 gstring->glyphs[i].glyph_id = 0;
1070 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1077 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1078 int platform_id, int encoding_id)
1082 char *errfmt = "CMAP Looking up%s";
1084 OTF_EncodingRecord *enc;
1087 && OTF_get_table (otf, "cmap") < 0)
1091 for (i = 0; i < cmap->numTables; i++)
1092 if (cmap->EncodingRecord[i].platformID == platform_id
1093 && cmap->EncodingRecord[i].encodingID == encoding_id)
1095 if (i == cmap->numTables)
1096 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1097 enc = cmap->EncodingRecord + i;
1098 switch (enc->subtable.format)
1100 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1101 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1102 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1103 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1104 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1105 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1106 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1108 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1113 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1116 && OTF_get_table (otf, "cmap") < 0)
1119 || code > otf->cmap->max_glyph_id
1120 || ! otf->cmap->decode_table)
1122 return otf->cmap->decode_table[code];
1126 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1132 && OTF_get_table (otf, "GDEF") < 0)
1136 if (gdef->glyph_class_def.offset)
1137 for (i = 0; i < gstring->used; i++)
1138 gstring->glyphs[i].GlyphClass
1139 = get_class_def (&gdef->glyph_class_def,
1140 gstring->glyphs[i].glyph_id);
1142 if (gdef->mark_attach_class_def.offset)
1143 for (i = 0; i < gstring->used; i++)
1144 gstring->glyphs[i].MarkAttachClass
1145 = get_class_def (&gdef->mark_attach_class_def,
1146 gstring->glyphs[i].glyph_id);
1153 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1154 char *script, char *language, char *features)
1156 char *errfmt = "GSUB driving%s";
1159 OTF_LangSys *LangSys;
1160 int *lookup_indices;
1163 for (i = 0; i < gstring->used; i++)
1164 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1167 && OTF_get_table (otf, "GSUB") < 0)
1170 if (gsub->FeatureList.FeatureCount == 0
1171 || gsub->LookupList.LookupCount == 0)
1174 LangSys = get_langsys (&gsub->ScriptList, script, language);
1178 /* One lookup may be used by multiple features. */
1179 lookup_indices = alloca (sizeof (int)
1180 * gsub->LookupList.LookupCount
1181 * (gsub->FeatureList.FeatureCount + 1));
1182 if (! lookup_indices)
1183 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1184 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1185 features, lookup_indices);
1189 for (i = 0; i < n; i++)
1191 int index = lookup_indices[i];
1194 if (gsub->LookupList.Lookup[index].LookupType != 8)
1197 while (gidx < gstring->used)
1199 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1206 gidx = gstring->used - 1;
1209 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1220 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1221 char *script, char *language, char *features)
1223 char *errfmt = "GPOS driving%s";
1226 OTF_LangSys *LangSys;
1227 int *lookup_indices;
1231 && OTF_get_table (otf, "GPOS") < 0)
1234 if (gpos->FeatureList.FeatureCount == 0
1235 || gpos->LookupList.LookupCount == 0)
1238 LangSys = get_langsys (&gpos->ScriptList, script, language);
1242 /* One lookup may be used by multiple features. */
1243 lookup_indices = alloca (sizeof (int)
1244 * gpos->LookupList.LookupCount
1245 * (gpos->FeatureList.FeatureCount + 1));
1246 if (! lookup_indices)
1247 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1248 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1249 features, lookup_indices);
1253 for (i = 0; i < gstring->used; i++)
1254 gstring->glyphs[i].positioning_type = 0;
1256 for (i = 0; i < n; i++)
1258 int index = lookup_indices[i];
1261 while (gidx < gstring->used)
1263 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1273 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1274 char *script, char *language,
1275 char *gsub_features, char *gpos_features)
1277 if (OTF_drive_cmap (otf, gstring) < 0)
1279 if (OTF_drive_gdef (otf, gstring) < 0)
1282 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1285 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)