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)
67 GSTRING_INSERT (gstring, from, (num - len));
69 GSTRING_DELETE (gstring, from, (len - num));
70 for (i = 0; i < num; i++)
71 gstring->glyphs[from + i].glyph_id = ids[i];
77 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
81 if (coverage->CoverageFormat == 1)
83 for (i = 0; i < coverage->Count; i++)
84 if (coverage->table.GlyphArray[i] == id)
89 for (i = 0; i < coverage->Count; i++)
90 if (coverage->table.RangeRecord[i].Start <= id
91 && coverage->table.RangeRecord[i].End >= id)
92 return (coverage->table.RangeRecord[i].StartCoverageIndex
93 + (id - coverage->table.RangeRecord[i].Start));
99 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
101 if (class_def->ClassFormat == 1)
103 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
105 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
106 return class_def->f.f1.ClassValueArray[idx];
112 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
113 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
114 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
115 return class_def->f.f2.ClassRangeRecord[i].Class;
121 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
124 OTF_Tag script_tag = OTF_tag (script);
125 OTF_Tag langsys_tag = OTF_tag (language);
128 for (i = 0; i < script_list->ScriptCount; i++)
129 if (script_list->Script[i].ScriptTag == script_tag)
131 OTF_Script *script = script_list->Script + i;
134 return &script->DefaultLangSys;
135 for (j = 0; j < script->LangSysCount; j++)
136 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
137 return script->LangSys + j;
138 return &script->DefaultLangSys;
145 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
146 char *features, int *lookup_indices)
149 OTF_Feature *feature;
150 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
152 for (i = 0; i < FeatureList->FeatureCount; i++)
153 feature_table[i] = 0;
161 if (*features == '*')
163 /* Consume all remaining features. */
164 /* We are sure that the last LookupCount elements of
165 lookup_indices are free to be used for this work. */
166 int *free_table = (lookup_indices + (LookupList->LookupCount
167 * FeatureList->FeatureCount));
169 for (i = 0; i < LookupList->LookupCount; i++)
171 for (i = 0; i < FeatureList->FeatureCount; i++)
172 if (! feature_table[i])
174 feature = FeatureList->Feature + i;
175 for (j = 0; j < feature->LookupCount; j++)
176 free_table[feature->LookupListIndex[j]] = 1;
178 for (i = 0; i < LookupList->LookupCount; i++)
180 lookup_indices[n++] = i;
184 if (*features == '~')
185 negate = 1, features++;
186 for (i = 0; *features && *features != ','; i++, features++)
187 tagname[i] = *features;
193 tag = OTF_tag (tagname);
194 for (i = 0; i < FeatureList->FeatureCount; i++)
196 feature = FeatureList->Feature + i;
197 if (tag == feature->FeatureTag)
200 for (j = 0; j < feature->LookupCount; j++)
201 lookup_indices[n++] = feature->LookupListIndex[j];
202 feature_table[i] = 1;
212 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
214 OTF_Glyph *gbeg = gstring->glyphs + gidx;
215 OTF_Glyph *gend = gstring->glyphs + gstring->used;
219 for (g = gbeg, i = 0; g < gend && i < count; g++)
220 if (g->glyph_id && g->glyph_id != ids[i++])
222 return (i < count ? -1 : g - gbeg);
226 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
228 int i = rule->BacktrackGlyphCount;
234 for (j = gidx - 1; j >= 0; j--)
235 if (gstring->glyphs[j].glyph_id
240 if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
245 i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
249 i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
256 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
257 int count, unsigned *classes)
259 OTF_Glyph *gbeg = gstring->glyphs + gidx;
260 OTF_Glyph *gend = gstring->glyphs + gstring->used;
264 for (g = gbeg, i = 0; g < gend && i < count; g++)
266 && get_class_def (class_def, g->glyph_id) != classes[i++])
268 return (i < count ? -1 : g - gbeg);
272 match_chain_classes (OTF_GlyphString *gstring, int gidx,
273 OTF_ClassDef *BacktrackClassDef,
274 OTF_ClassDef *InputClassDef,
275 OTF_ClassDef *LookaheadClassDef,
276 OTF_ChainClassRule *rule)
278 int i = rule->BacktrackGlyphCount;
284 for (j = gidx - 1; j >= 0 && i > 0; j--)
285 if (gstring->glyphs[j].glyph_id
290 if (match_classes (BacktrackClassDef, gstring, j,
291 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
295 i = match_classes (InputClassDef, gstring, gidx,
296 rule->InputGlyphCount - 1, rule->Input);
300 i = match_classes (LookaheadClassDef, gstring, gidx,
301 rule->LookaheadGlyphCount, rule->LookAhead);
309 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
310 OTF_Coverage *coverages)
312 OTF_Glyph *gbeg = gstring->glyphs + gidx;
313 OTF_Glyph *gend = gstring->glyphs + gstring->used;
317 for (g = gbeg, i = 0; g < gend && i < count; g++)
319 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
321 return (i < count ? -1 : g - gbeg);
325 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
326 OTF_GSUB_ChainContext3 *context3)
328 int i = context3->BacktrackGlyphCount;
334 for (j = gidx - 1; j >= 0; j--)
335 if (gstring->glyphs[j].glyph_id
340 if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
341 context3->Backtrack) < 0)
345 if (context3->InputGlyphCount > 1)
347 i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
348 context3->Input + 1);
353 if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
354 context3->LookAhead) < 0)
360 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
361 OTF_GlyphString *gstring, int gidx)
363 char *errfmt = "GSUB Looking up%s";
365 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
366 unsigned int flag = lookup->LookupFlag;
367 int orig_gidx = gidx;
368 OTF_Glyph *g = gstring->glyphs + gidx;
373 && (flag & (1 << g->GlyphClass))))
376 /* Try all subtables until one of them handles the current glyph. */
377 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
379 unsigned lookup_type = lookup->LookupType;
380 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
383 if (lookup_type == 7)
385 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
387 lookup_type = extension1->ExtensionLookupType;
388 subtable = extension1->ExtensionSubtable;
391 if (subtable->Coverage.offset)
393 coverage_idx = get_coverage_index (&subtable->Coverage,
395 if (coverage_idx < 0)
399 switch (lookup->LookupType)
402 if (subtable->Format == 1)
403 g->glyph_id += subtable->u.single1.DeltaGlyphID;
405 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
411 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
412 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
414 gstring_subst (gstring, gidx, gidx + 1,
415 seq->Substitute, seq->GlyphCount);
416 gidx += seq->GlyphCount;
421 if (subtable->Format == 1)
423 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
424 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
426 g->glyph_id = altset->Alternate[0];
430 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
434 if (subtable->Format == 1)
436 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
437 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
441 for (j = 0; j < ligset->LigatureCount; j++)
445 lig = ligset->Ligature + j;
446 n = match_ids (gstring, gidx + 1,
447 lig->CompCount - 1, lig->Component);
450 gstring_subst (gstring, gidx, gidx + 1 + n,
457 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
461 if (subtable->Format == 1)
463 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
464 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
469 for (j = 0; j < set->RuleCount; j++)
471 rule = set->Rule + j;
472 if (match_ids (gstring, gidx + 1,
473 rule->GlyphCount - 1, rule->Input) < 0)
475 orig_used = gstring->used;
476 for (k = 0; k < rule->LookupCount; k++)
477 lookup_gsub (lookup_list,
478 rule->LookupRecord[k].LookupListIndex,
480 gidx + rule->LookupRecord[k].SequenceIndex);
481 gidx += rule->GlyphCount + (gstring->used - orig_used);
485 else if (subtable->Format == 2)
487 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
494 class = get_class_def (&context2->ClassDef, g->glyph_id);
495 set = context2->ClassSet + class;
496 for (j = 0; j < set->ClassRuleCnt; j++)
498 rule = set->ClassRule + j;
499 if (match_classes (&context2->ClassDef,
501 rule->GlyphCount - 1, rule->Class)
504 orig_used = gstring->used;
505 for (k = 0; k < rule->LookupCount; k++)
506 lookup_gsub (lookup_list,
507 rule->LookupRecord[k].LookupListIndex,
509 gidx + rule->LookupRecord[k].SequenceIndex);
510 gidx += rule->GlyphCount + (gstring->used - orig_used);
514 else /* subtable->Format == 3 */
516 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
520 if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
521 context3->Coverage + 1) < 0)
523 orig_used = gstring->used;
524 for (j = 0; j < context3->LookupCount; j++)
525 lookup_gsub (lookup_list,
526 context3->LookupRecord[j].LookupListIndex,
528 gidx + context3->LookupRecord[j].SequenceIndex);
529 gidx += context3->GlyphCount + (gstring->used - orig_used);
534 if (subtable->Format == 1)
536 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
537 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
541 for (j = 0; j < set->ChainRuleCount; j++)
543 OTF_ChainRule *rule = set->ChainRule + j;
545 if (gidx < rule->BacktrackGlyphCount
546 || (gidx + rule->InputGlyphCount
547 + rule->LookaheadGlyphCount) > gstring->used)
549 if (match_chain_ids (gstring, gidx, rule) < 0)
551 orig_used = gstring->used;
552 for (k = 0; k < rule->LookupCount; k++)
553 lookup_gsub (lookup_list,
554 rule->LookupRecord[k].LookupListIndex,
556 gidx + rule->LookupRecord[k].SequenceIndex);
557 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
561 else if (subtable->Format == 2)
563 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
564 OTF_ChainClassSet *set;
569 class = get_class_def (&context2->InputClassDef, g->glyph_id);
570 set = context2->ChainClassSet + class;
571 for (j = 0; j < set->ChainClassRuleCnt; j++)
573 OTF_ChainClassRule *rule = set->ChainClassRule + j;
576 if (gidx < rule->BacktrackGlyphCount
577 || (gidx + rule->InputGlyphCount
578 + rule->LookaheadGlyphCount) > gstring->used)
580 if (match_chain_classes (gstring, gidx,
581 &context2->BacktrackClassDef,
582 &context2->InputClassDef,
583 &context2->LookaheadClassDef,
586 orig_used = gstring->used;
587 for (k = 0; k < rule->LookupCount; k++)
588 lookup_gsub (lookup_list,
589 rule->LookupRecord[k].LookupListIndex,
591 gidx + rule->LookupRecord[k].SequenceIndex);
592 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
598 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
602 if (gidx < context3->BacktrackGlyphCount
603 || (gidx + context3->InputGlyphCount
604 + context3->LookaheadGlyphCount) > gstring->used)
606 if (match_chain_coverages (gstring, gidx, context3) < 0)
608 orig_used = gstring->used;
609 for (j = 0; j < context3->LookupCount; j++)
610 lookup_gsub (lookup_list,
611 context3->LookupRecord[j].LookupListIndex,
613 gidx + context3->LookupRecord[j].SequenceIndex);
614 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
620 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
621 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
622 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
625 if (back_gidx > gstring->used || ahead_gidx < 0)
628 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
629 if (get_coverage_index (reverse->Backtrack + j,
630 gstring->glyphs[gidx + 1 + j].glyph_id)
633 if (j < reverse->BacktrackGlyphCount)
635 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
636 if (get_coverage_index (reverse->LookAhead + j,
637 gstring->glyphs[gidx - 1 - j].glyph_id)
640 if (j < reverse->LookaheadGlyphCount)
642 g->glyph_id = reverse->Substitute[coverage_idx];
650 if (gidx == orig_gidx)
659 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
661 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
663 rec->XPlacement = anchor->XCoordinate;
664 rec->YPlacement = anchor->YCoordinate;
665 if (anchor->AnchorFormat == 1)
668 else if (anchor->AnchorFormat == 2)
669 /* Not yet implemented */
671 else if (anchor->AnchorFormat == 3)
672 /* Not yet implemented */
679 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
680 OTF_GlyphString *gstring, int gidx)
682 char *errfmt = "GPOS Looking up%s";
684 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
685 unsigned int flag = lookup->LookupFlag;
686 int orig_gidx = gidx;
687 OTF_Glyph *g = gstring->glyphs + gidx;
692 && (flag & (1 << g->GlyphClass))))
695 /* Try all subtables until one of them handles the current glyph. */
696 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
698 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
701 if (subtable->Coverage.offset)
703 coverage_idx = get_coverage_index (&subtable->Coverage,
705 if (coverage_idx < 0)
709 switch (lookup->LookupType)
712 g->positioning_type = lookup->LookupType;
713 if (subtable->Format == 1)
715 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
717 g->f.f1.format = single1->ValueFormat;
718 g->f.f1.value = &single1->Value;
720 else if (subtable->Format == 2)
722 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
724 g->f.f1.format = single2->ValueFormat;
725 g->f.f1.value = single2->Value + coverage_idx;
730 if (gidx + 1 >= gstring->used)
732 if (subtable->Format == 1)
734 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
735 OTF_PairSet *set = pair1->PairSet + coverage_idx;
738 for (j = 0; j < set->PairValueCount; j++)
740 if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
743 g->positioning_type = lookup->LookupType;
744 g->f.f2.format = pair1->ValueFormat1;
745 g->f.f2.value = &set->PairValueRecord[j].Value1;
746 if (pair1->ValueFormat2)
749 g->positioning_type = lookup->LookupType;
750 g->f.f2.format = pair1->ValueFormat2;
751 g->f.f2.value = &set->PairValueRecord[j].Value2;
755 else if (subtable->Format == 2)
757 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
758 unsigned class1, class2;
761 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
762 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
763 g->positioning_type = lookup->LookupType;
764 g->f.f2.format = pair2->ValueFormat1;
766 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
767 if (pair2->ValueFormat2)
770 g->positioning_type = lookup->LookupType;
771 g->f.f2.format = pair2->ValueFormat2;
773 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
780 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
782 g->positioning_type = lookup->LookupType;
784 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
786 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
793 if (subtable->Format == 1)
795 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
796 OTF_MarkRecord *mark_record;
797 OTF_AnchorRecord *base_record;
798 int coverage_idx_base
799 = get_coverage_index (&mark_base1->BaseCoverage,
802 if (coverage_idx_base < 0)
804 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
806 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
807 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
809 = &base_record->Anchor[mark_record->Class];
810 g->positioning_type = lookup->LookupType;
818 if (subtable->Format == 1)
820 /* As the document of this lookup type is quite
821 ambiguous, and we can't know the exact procedure to
823 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
830 if (subtable->Format == 1)
832 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
833 OTF_MarkRecord *mark1_record;
834 OTF_AnchorRecord *mark2_record;
835 int coverage_idx_base
836 = get_coverage_index (&mark_mark1->Mark2Coverage,
839 if (coverage_idx_base < 0)
841 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
843 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
844 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
846 = &mark2_record->Anchor[mark1_record->Class];
847 g->positioning_type = lookup->LookupType;
853 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
857 if (subtable->Format == 1)
858 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
859 else if (subtable->Format == 2)
861 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
862 OTF_ChainClassSet *set;
867 class = get_class_def (&context2->InputClassDef, g->glyph_id);
868 set = context2->ChainClassSet + class;
869 for (j = 0; j < set->ChainClassRuleCnt; j++)
871 OTF_ChainClassRule *rule = set->ChainClassRule + j;
872 int fore_idx = gidx + rule->InputGlyphCount;
875 if (gidx < rule->BacktrackGlyphCount
876 || (gidx + rule->InputGlyphCount
877 + rule->LookaheadGlyphCount) > gstring->used)
879 for (k = 0; k < rule->BacktrackGlyphCount; k++)
880 if (get_class_def (&context2->BacktrackClassDef,
881 gstring->glyphs[gidx - 1 - k].glyph_id)
882 != rule->Backtrack[k])
884 if (k < rule->BacktrackGlyphCount)
886 for (k = 1; k < rule->InputGlyphCount; k++)
887 if (get_class_def (&context2->InputClassDef,
888 gstring->glyphs[gidx + k].glyph_id)
889 != rule->Input[k - 1])
891 if (k < rule->InputGlyphCount)
893 for (k = 0; k < rule->LookaheadGlyphCount; k++)
894 if (get_class_def (&context2->LookaheadClassDef,
895 gstring->glyphs[fore_idx + k].glyph_id)
896 != rule->LookAhead[k])
898 if (k < rule->LookaheadGlyphCount)
901 orig_used = gstring->used;
902 for (k = 0; k < rule->LookupCount; k++)
903 lookup_gpos (lookup_list,
904 rule->LookupRecord[k].LookupListIndex,
906 gidx + rule->LookupRecord[k].SequenceIndex);
907 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
911 else if (subtable->Format == 3)
912 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
914 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
918 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
925 if (gidx == orig_gidx)
935 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
941 && OTF_get_table (otf, "cmap") < 0)
945 for (i = 0; i < gstring->used; i++)
946 if (! gstring->glyphs[i].glyph_id)
948 int c = gstring->glyphs[i].c;
949 if (c < 32 || ! cmap->unicode_table)
950 gstring->glyphs[i].glyph_id = 0;
952 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
958 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
961 && OTF_get_table (otf, "cmap") < 0)
964 || code > otf->cmap->max_glyph_id
965 || ! otf->cmap->decode_table)
967 return otf->cmap->decode_table[code];
971 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
977 && OTF_get_table (otf, "GDEF") < 0)
981 if (gdef->glyph_class_def.offset)
982 for (i = 0; i < gstring->used; i++)
983 gstring->glyphs[i].GlyphClass
984 = get_class_def (&gdef->glyph_class_def,
985 gstring->glyphs[i].glyph_id);
987 if (gdef->mark_attach_class_def.offset)
988 for (i = 0; i < gstring->used; i++)
989 gstring->glyphs[i].MarkAttachClass
990 = get_class_def (&gdef->mark_attach_class_def,
991 gstring->glyphs[i].glyph_id);
998 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
999 char *script, char *language, char *features)
1001 char *errfmt = "GSUB driving%s";
1004 OTF_LangSys *LangSys;
1005 int *lookup_indices;
1009 && OTF_get_table (otf, "GSUB") < 0)
1012 if (gsub->FeatureList.FeatureCount == 0
1013 || gsub->LookupList.LookupCount == 0)
1016 LangSys = get_langsys (&gsub->ScriptList, script, language);
1020 /* One lookup may be used by multiple features. */
1021 lookup_indices = alloca (sizeof (int)
1022 * gsub->LookupList.LookupCount
1023 * (gsub->FeatureList.FeatureCount + 1));
1024 if (! lookup_indices)
1025 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1026 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1027 features, lookup_indices);
1031 for (i = 0; i < n; i++)
1033 int index = lookup_indices[i];
1036 if (gsub->LookupList.Lookup[index].LookupType != 8)
1039 while (gidx < gstring->used)
1041 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1048 gidx = gstring->used - 1;
1051 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1062 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1063 char *script, char *language, char *features)
1065 char *errfmt = "GPOS driving%s";
1068 OTF_LangSys *LangSys;
1069 int *lookup_indices;
1073 && OTF_get_table (otf, "GPOS") < 0)
1076 if (gpos->FeatureList.FeatureCount == 0
1077 || gpos->LookupList.LookupCount == 0)
1080 LangSys = get_langsys (&gpos->ScriptList, script, language);
1084 /* One lookup may be used by multiple features. */
1085 lookup_indices = alloca (sizeof (int)
1086 * gpos->LookupList.LookupCount
1087 * (gpos->FeatureList.FeatureCount + 1));
1088 if (! lookup_indices)
1089 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1090 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1091 features, lookup_indices);
1095 for (i = 0; i < n; i++)
1097 int index = lookup_indices[i];
1100 while (gidx < gstring->used)
1102 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1112 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1113 char *script, char *language,
1114 char *gsub_features, char *gpos_features)
1116 if (OTF_drive_cmap (otf, gstring) < 0)
1118 if (OTF_drive_gdef (otf, gstring) < 0)
1121 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1124 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)