1 /* otfdrive.c -- OpenType font driver.
4 by AIST (National Institute of Advanced Industrial Science and Technology)
5 Registration Number H15PRO???
7 This file is part of the OTF library.
9 The OTF library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 The OTF library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with the OTF library; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
31 #define GSTRING_DELETE(gstring, from, len) \
33 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
34 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
35 gstring->used -= len; \
39 #define GSTRING_INSERT(gstring, pos, len) \
41 if (gstring->used + len > gstring->size) \
43 char *errfmt = "GSTRING%s"; \
45 gstring->size = gstring->used + len; \
46 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
48 if (! gstring->glyphs) \
49 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
51 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
52 sizeof (OTF_Glyph) * (gstring->used - pos)); \
53 gstring->used += len; \
58 gstring_subst (OTF_GlyphString *gstring, int from, int to,
59 OTF_GlyphID *ids, int num)
66 GSTRING_INSERT (gstring, from, (num - len));
68 GSTRING_DELETE (gstring, from, (len - num));
69 for (i = 0; i < num; i++)
70 gstring->glyphs[from + i].glyph_id = ids[i];
76 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
80 if (coverage->CoverageFormat == 1)
82 for (i = 0; i < coverage->Count; i++)
83 if (coverage->table.GlyphArray[i] == id)
88 for (i = 0; i < coverage->Count; i++)
89 if (coverage->table.RangeRecord[i].Start <= id
90 && coverage->table.RangeRecord[i].End >= id)
91 return (coverage->table.RangeRecord[i].StartCoverageIndex
92 + (id - coverage->table.RangeRecord[i].Start));
98 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
100 if (class_def->ClassFormat == 1)
102 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
104 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
105 return class_def->f.f1.ClassValueArray[idx];
111 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
112 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
113 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
114 return class_def->f.f2.ClassRangeRecord[i].Class;
120 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
123 OTF_Tag script_tag = OTF_tag (script);
124 OTF_Tag langsys_tag = OTF_tag (language);
127 for (i = 0; i < script_list->ScriptCount; i++)
128 if (script_list->Script[i].ScriptTag == script_tag)
130 OTF_Script *script = script_list->Script + i;
133 return &script->DefaultLangSys;
134 for (j = 0; j < script->LangSysCount; j++)
135 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
136 return script->LangSys + j;
137 return &script->DefaultLangSys;
144 setup_lookup_indices (OTF_LangSys *LangSys, OTF_FeatureList *FeatureList,
145 char *features, int *lookup_indices)
148 OTF_Feature *feature;
153 int len = strlen (features) + 1;
156 for (p1 = p0; *p1; p1++)
162 int this_len = strlen (p0) + 1;
163 OTF_Tag tag = OTF_tag (p0);
166 for (i = 0; i < FeatureList->FeatureCount; i++)
168 feature = FeatureList->Feature + i;
169 if (tag == feature->FeatureTag)
170 for (j = 0; j < feature->LookupCount; j++)
172 lookup_indices[feature->LookupListIndex[j]] = 1;
181 for (i = 0; i < LangSys->FeatureCount; i++)
183 feature = FeatureList->Feature + LangSys->FeatureIndex[i];
184 for (j = 0; j < feature->LookupCount; j++)
186 lookup_indices[feature->LookupListIndex[j]] = 1;
196 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
200 if (gstring->used - gidx < count)
202 for (i = 0; i < count; i++)
203 if (gstring->glyphs[gidx + i].glyph_id != ids[i])
209 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
210 int count, unsigned *classes)
214 if (gstring->used - gidx < count)
216 for (i = 0; i < count; i++)
217 if (get_class_def (class_def, gstring->glyphs[gidx + i].glyph_id)
224 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
225 OTF_GlyphString *gstring, int gidx)
227 char *errfmt = "GSUB Looking up%s";
229 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
230 unsigned int flag = lookup->LookupFlag;
231 int orig_gidx = gidx;
232 OTF_Glyph *g = gstring->glyphs + gidx;
237 && (flag & (1 << g->GlyphClass))))
240 /* Try all subtables until one of them handles the current glyph. */
241 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
243 unsigned lookup_type = lookup->LookupType;
244 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
247 if (lookup_type == 7)
249 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
251 lookup_type = extension1->ExtensionLookupType;
252 subtable = extension1->ExtensionSubtable;
255 if (subtable->Coverage.offset)
257 coverage_idx = get_coverage_index (&subtable->Coverage,
259 if (coverage_idx < 0)
263 switch (lookup->LookupType)
266 if (subtable->Format == 1)
267 g->glyph_id += subtable->u.single1.DeltaGlyphID;
269 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
275 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
276 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
278 gstring_subst (gstring, gidx, gidx + 1,
279 seq->Substitute, seq->GlyphCount);
280 gidx += seq->GlyphCount;
285 if (subtable->Format == 1)
287 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
288 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
290 g->glyph_id = altset->Alternate[0];
294 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
298 if (subtable->Format == 1)
300 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
301 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
305 for (j = 0; j < ligset->LigatureCount; j++)
307 lig = ligset->Ligature + j;
308 if (match_ids (gstring, gidx + 1,
309 lig->CompCount - 1, lig->Component) < 0)
311 gstring_subst (gstring, gidx, gidx + lig->CompCount,
318 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
322 if (subtable->Format == 1)
324 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
325 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
330 for (j = 0; j < set->RuleCount; j++)
332 rule = set->Rule + j;
333 if (match_ids (gstring, gidx + 1,
334 rule->GlyphCount - 1, rule->Input) < 0)
336 orig_used = gstring->used;
337 for (k = 0; k < rule->LookupCount; k++)
338 lookup_gsub (lookup_list,
339 rule->LookupRecord[k].LookupListIndex,
341 gidx + rule->LookupRecord[k].SequenceIndex);
342 gidx += rule->GlyphCount + (gstring->used - orig_used);
346 else if (subtable->Format == 2)
348 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
355 class = get_class_def (&context2->ClassDef, g->glyph_id);
356 set = context2->ClassSet + class;
357 for (j = 0; j < set->ClassRuleCnt; j++)
359 rule = set->ClassRule + j;
360 if (match_classes (&context2->ClassDef,
362 rule->GlyphCount - 1, rule->Class)
365 orig_used = gstring->used;
366 for (k = 0; k < rule->LookupCount; k++)
367 lookup_gsub (lookup_list,
368 rule->LookupRecord[k].LookupListIndex,
370 gidx + rule->LookupRecord[k].SequenceIndex);
371 gidx += rule->GlyphCount + (gstring->used - orig_used);
375 else /* subtable->Format == 3 */
377 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
381 if (gstring->used - gidx < context3->GlyphCount)
383 /* Start from the secoding coverage_idx because the
384 first one is the same as subtable->Coverage and thus
386 for (j = 1; j < context3->GlyphCount; j++)
387 if (get_coverage_index (context3->Coverage + j,
388 gstring->glyphs[gidx + j].glyph_id)
391 if (j < context3->GlyphCount)
393 orig_used = gstring->used;
394 for (k = 0; k < context3->LookupCount; k++)
395 lookup_gsub (lookup_list,
396 context3->LookupRecord[k].LookupListIndex,
398 gidx + context3->LookupRecord[k].SequenceIndex);
399 gidx += context3->GlyphCount + (gstring->used - orig_used);
404 if (subtable->Format == 1)
406 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
407 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
411 for (j = 0; j < set->ChainRuleCount; j++)
413 rule = set->ChainRule + j;
416 else if (subtable->Format == 2)
418 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
419 OTF_ChainClassSet *set;
424 // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
425 class = get_class_def (&context2->InputClassDef, g->glyph_id);
426 set = context2->ChainClassSet + class;
427 for (j = 0; j < set->ChainClassRuleCnt; j++)
429 OTF_ChainClassRule *rule = set->ChainClassRule + j;
430 int fore_idx = gidx + rule->InputGlyphCount;
433 if (gidx < rule->BacktrackGlyphCount
434 || (gidx + rule->InputGlyphCount
435 + rule->LookaheadGlyphCount) >= gstring->used)
437 for (k = 0; k < rule->BacktrackGlyphCount; k++)
438 if (get_class_def (&context2->BacktrackClassDef,
439 gstring->glyphs[gidx - 1 - k].glyph_id)
440 != rule->Backtrack[k])
442 if (k < rule->BacktrackGlyphCount)
444 for (k = 1; k < rule->InputGlyphCount; k++)
445 if (get_class_def (&context2->InputClassDef,
446 gstring->glyphs[gidx + k].glyph_id)
447 != rule->Input[k - 1])
449 if (k < rule->InputGlyphCount)
451 for (k = 0; k < rule->LookaheadGlyphCount; k++)
452 if (get_class_def (&context2->LookaheadClassDef,
453 gstring->glyphs[fore_idx + k].glyph_id)
454 != rule->LookAhead[k])
456 if (k < rule->LookaheadGlyphCount)
459 orig_used = gstring->used;
460 for (k = 0; k < rule->LookupCount; k++)
461 lookup_gsub (lookup_list,
462 rule->LookupRecord[k].LookupListIndex,
464 gidx + rule->LookupRecord[k].SequenceIndex);
465 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
471 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
472 int back_gidx = gidx - context3->BacktrackGlyphCount;
473 int fore_gidx = gidx + context3->InputGlyphCount;
478 || fore_gidx + context3->LookaheadGlyphCount > gstring->used)
481 for (j = 0; j < context3->BacktrackGlyphCount; j++)
482 if (get_coverage_index (context3->Backtrack + j,
483 gstring->glyphs[gidx - 1 - j].glyph_id)
486 if (j < context3->BacktrackGlyphCount)
489 /* Start from the secode coverage_idx because the first
490 one is the same as subtable->Coverage and thus
492 for (j = 1; j < context3->InputGlyphCount; j++)
493 if (get_coverage_index (context3->Input + j,
494 gstring->glyphs[gidx + j].glyph_id)
497 if (j < context3->InputGlyphCount)
500 for (j = 0; j < context3->LookaheadGlyphCount; j++)
501 if (get_coverage_index (context3->LookAhead + j,
502 gstring->glyphs[fore_gidx + j].glyph_id)
505 if (j < context3->LookaheadGlyphCount)
508 orig_used = gstring->used;
509 for (j = 0; j < context3->LookupCount; j++)
510 lookup_gsub (lookup_list,
511 context3->LookupRecord[j].LookupListIndex,
513 gidx + context3->LookupRecord[j].SequenceIndex);
514 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
520 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
521 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
522 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
525 if (back_gidx > gstring->used || ahead_gidx < 0)
528 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
529 if (get_coverage_index (reverse->Backtrack + j,
530 gstring->glyphs[gidx + 1 + j].glyph_id)
533 if (j < reverse->BacktrackGlyphCount)
535 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
536 if (get_coverage_index (reverse->LookAhead + j,
537 gstring->glyphs[gidx - 1 - j].glyph_id)
540 if (j < reverse->LookaheadGlyphCount)
542 g->glyph_id = reverse->Substitute[coverage_idx];
550 if (gidx == orig_gidx)
552 //printf ("not applied\n");
557 // printf ("done\n");
566 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
568 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
570 rec->XPlacement = anchor->XCoordinate;
571 rec->YPlacement = anchor->YCoordinate;
572 if (anchor->AnchorFormat == 1)
575 else if (anchor->AnchorFormat == 2)
576 /* Not yet implemented */
578 else if (anchor->AnchorFormat == 3)
579 /* Not yet implemented */
586 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
587 OTF_GlyphString *gstring, int gidx)
589 char *errfmt = "GPOS Looking up%s";
591 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
592 unsigned int flag = lookup->LookupFlag;
593 int orig_gidx = gidx;
594 OTF_Glyph *g = gstring->glyphs + gidx;
599 && (flag & (1 << g->GlyphClass))))
602 /* Try all subtables until one of them handles the current glyph. */
603 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
605 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
608 // printf ("subtype:%d ", subtable->Format);
609 if (subtable->Coverage.offset)
611 coverage_idx = get_coverage_index (&subtable->Coverage,
613 if (coverage_idx < 0)
615 // printf ("not covererd ");
620 switch (lookup->LookupType)
623 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
626 if (gidx + 1 >= gstring->used)
628 if (subtable->Format == 1)
629 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
630 else if (subtable->Format == 2)
632 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
633 unsigned class1, class2;
635 // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
637 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
638 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
639 g->positioning_type = lookup->LookupType;
640 g->f.f2.format = pair2->ValueFormat1;
642 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
643 if (pair2->ValueFormat2)
646 g->positioning_type = lookup->LookupType;
647 g->f.f2.format = pair2->ValueFormat2;
649 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
655 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
660 if (subtable->Format == 1)
662 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
663 OTF_MarkRecord *mark_record;
664 OTF_AnchorRecord *base_record;
665 int coverage_idx_base
666 = get_coverage_index (&mark_base1->BaseCoverage,
669 if (coverage_idx_base < 0)
671 // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
672 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
674 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
675 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
677 = &base_record->Anchor[mark_record->Class];
678 g->positioning_type = lookup->LookupType;
682 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
686 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
692 if (subtable->Format == 1)
694 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
695 OTF_MarkRecord *mark1_record;
696 OTF_AnchorRecord *mark2_record;
697 int coverage_idx_base
698 = get_coverage_index (&mark_mark1->Mark2Coverage,
701 if (coverage_idx_base < 0)
703 // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
704 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
706 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
707 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
709 = &mark2_record->Anchor[mark1_record->Class];
710 g->positioning_type = lookup->LookupType;
714 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
718 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
722 if (subtable->Format == 1)
723 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
724 else if (subtable->Format == 2)
726 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
727 OTF_ChainClassSet *set;
732 // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
733 class = get_class_def (&context2->InputClassDef, g->glyph_id);
734 set = context2->ChainClassSet + class;
735 for (j = 0; j < set->ChainClassRuleCnt; j++)
737 OTF_ChainClassRule *rule = set->ChainClassRule + j;
738 int fore_idx = gidx + rule->InputGlyphCount;
741 if (gidx < rule->BacktrackGlyphCount
742 || (gidx + rule->InputGlyphCount
743 + rule->LookaheadGlyphCount) >= gstring->used)
745 for (k = 0; k < rule->BacktrackGlyphCount; k++)
746 if (get_class_def (&context2->BacktrackClassDef,
747 gstring->glyphs[gidx - 1 - k].glyph_id)
748 != rule->Backtrack[k])
750 if (k < rule->BacktrackGlyphCount)
752 for (k = 1; k < rule->InputGlyphCount; k++)
753 if (get_class_def (&context2->InputClassDef,
754 gstring->glyphs[gidx + k].glyph_id)
755 != rule->Input[k - 1])
757 if (k < rule->InputGlyphCount)
759 for (k = 0; k < rule->LookaheadGlyphCount; k++)
760 if (get_class_def (&context2->LookaheadClassDef,
761 gstring->glyphs[fore_idx + k].glyph_id)
762 != rule->LookAhead[k])
764 if (k < rule->LookaheadGlyphCount)
767 orig_used = gstring->used;
768 for (k = 0; k < rule->LookupCount; k++)
769 lookup_gpos (lookup_list,
770 rule->LookupRecord[k].LookupListIndex,
772 gidx + rule->LookupRecord[k].SequenceIndex);
773 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
777 else if (subtable->Format == 3)
778 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
780 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
784 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
791 if (gidx == orig_gidx)
793 // printf ("not applied\n");
798 // printf ("done\n");
804 lookup_cmap (OTF_cmap *cmap, int c)
806 char *errfmt = "cmap driving%s";
810 if (! cmap || ! cmap->Unicode)
813 switch (cmap->Unicode->subtable.format)
817 OTF_EncodingSubtable4 *sub4 = cmap->Unicode->subtable.f.f4;
818 int segCount = sub4->segCountX2 / 2;
820 for (i = 0; i < segCount; i++)
821 if (c <= sub4->segments[i].endCount)
823 if (i == segCount || c < sub4->segments[i].startCount)
825 if (sub4->segments[i].idRangeOffset == 0xFFFF)
826 return c + sub4->segments[i].idDelta;
829 return sub4->glyphIdArray[sub4->segments[i].idRangeOffset
830 + (c - sub4->segments[i].startCount)];
835 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (not yet supported)");
847 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
853 && OTF_get_table (otf, "cmap") < 0)
857 for (i = 0; i < gstring->used; i++)
859 gstring->glyphs[i].glyph_id = lookup_cmap (cmap, gstring->glyphs[i].c);
860 if (gstring->glyphs[i].glyph_id < 0)
868 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
874 && OTF_get_table (otf, "GDEF") < 0)
878 if (gdef->glyph_class_def.offset)
879 for (i = 0; i < gstring->used; i++)
880 gstring->glyphs[i].GlyphClass
881 = get_class_def (&gdef->glyph_class_def,
882 gstring->glyphs[i].glyph_id);
884 if (gdef->mark_attach_class_def.offset)
885 for (i = 0; i < gstring->used; i++)
886 gstring->glyphs[i].MarkAttachClass
887 = get_class_def (&gdef->mark_attach_class_def,
888 gstring->glyphs[i].glyph_id);
895 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
896 char *script, char *language, char *features)
898 char *errfmt = "GSUB driving%s";
901 OTF_LangSys *LangSys;
906 && OTF_get_table (otf, "GSUB") < 0)
910 LangSys = get_langsys (&gsub->ScriptList, script, language);
914 i = gsub->LookupList.LookupCount;
915 lookup_indices = alloca (sizeof (int) * i);
916 if (! lookup_indices)
917 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
918 memset (lookup_indices, 0, sizeof (int) * i);
919 if (setup_lookup_indices (LangSys, &gsub->FeatureList,
920 features, lookup_indices) < 0)
921 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " no lookups");
923 for (i = 0; i < gsub->LookupList.LookupCount; i++)
924 if (lookup_indices[i])
928 if (gsub->LookupList.Lookup[i].LookupType != 8)
931 while (gidx < gstring->used)
933 gidx = lookup_gsub (&gsub->LookupList, i, gstring, gidx);
940 gidx = gstring->used - 1;
943 gidx = lookup_gsub (&gsub->LookupList, i, gstring, gidx);
954 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
955 char *script, char *language, char *features)
957 char *errfmt = "GPOS driving%s";
960 OTF_LangSys *LangSys;
965 && OTF_get_table (otf, "GPOS") < 0)
969 LangSys = get_langsys (&gpos->ScriptList, script, language);
973 i = gpos->LookupList.LookupCount;
974 lookup_indices = alloca (sizeof (int) * i);
975 if (! lookup_indices)
976 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
977 memset (lookup_indices, 0, sizeof (int) * i);
978 if (setup_lookup_indices (LangSys, &gpos->FeatureList,
979 features, lookup_indices) < 0)
980 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " no lookups");
982 for (i = 0; i < gpos->LookupList.LookupCount; i++)
983 if (lookup_indices[i])
987 while (gidx < gstring->used)
989 gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx);
999 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1000 char *script, char *language,
1001 char *gsub_features, char *gpos_features)
1003 if (OTF_drive_cmap (otf, gstring) < 0)
1005 if (OTF_drive_gdef (otf, gstring) < 0)
1007 if ((! gsub_features || gsub_features[0])
1008 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1010 if ((! gpos_features || gpos_features[0])
1011 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)