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. */
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_LookupList *LookupList, OTF_FeatureList *FeatureList,
145 char *features, int *lookup_indices)
148 OTF_Feature *feature;
149 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
151 for (i = 0; i < FeatureList->FeatureCount; i++)
152 feature_table[i] = 0;
160 if (*features == '*')
162 /* Consume all remaining features. */
163 /* We are sure that the last LookupCount elements of
164 lookup_indices are free to be used for this work. */
165 int *free_table = (lookup_indices + (LookupList->LookupCount
166 * FeatureList->FeatureCount));
168 for (i = 0; i < LookupList->LookupCount; i++)
170 for (i = 0; i < FeatureList->FeatureCount; i++)
171 if (! feature_table[i])
173 feature = FeatureList->Feature + i;
174 for (j = 0; j < feature->LookupCount; j++)
175 free_table[feature->LookupListIndex[j]] = 1;
177 for (i = 0; i < LookupList->LookupCount; i++)
179 lookup_indices[n++] = i;
183 if (*features == '~')
184 negate = 1, features++;
185 for (i = 0; *features && *features != ','; i++, features++)
186 tagname[i] = *features;
192 tag = OTF_tag (tagname);
193 for (i = 0; i < FeatureList->FeatureCount; i++)
195 feature = FeatureList->Feature + i;
196 if (tag == feature->FeatureTag)
199 for (j = 0; j < feature->LookupCount; j++)
200 lookup_indices[n++] = feature->LookupListIndex[j];
201 feature_table[i] = 1;
211 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
213 OTF_Glyph *gbeg = gstring->glyphs + gidx;
214 OTF_Glyph *gend = gstring->glyphs + gstring->used;
218 for (g = gbeg, i = 0; g < gend && i < count; g++)
219 if (g->glyph_id && g->glyph_id != ids[i++])
221 return (i < count ? -1 : g - gbeg);
225 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
227 int i = rule->BacktrackGlyphCount;
233 for (j = gidx - 1; j >= 0; j--)
234 if (gstring->glyphs[j].glyph_id
239 if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
244 i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
248 i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
255 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
256 int count, unsigned *classes)
258 OTF_Glyph *gbeg = gstring->glyphs + gidx;
259 OTF_Glyph *gend = gstring->glyphs + gstring->used;
263 for (g = gbeg, i = 0; g < gend && i < count; g++)
265 && get_class_def (class_def, g->glyph_id) != classes[i++])
267 return (i < count ? -1 : g - gbeg);
271 match_chain_classes (OTF_GlyphString *gstring, int gidx,
272 OTF_ClassDef *BacktrackClassDef,
273 OTF_ClassDef *InputClassDef,
274 OTF_ClassDef *LookaheadClassDef,
275 OTF_ChainClassRule *rule)
277 int i = rule->BacktrackGlyphCount;
283 for (j = gidx - 1; j >= 0 && i > 0; j--)
284 if (gstring->glyphs[j].glyph_id
289 if (match_classes (BacktrackClassDef, gstring, j,
290 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
294 i = match_classes (InputClassDef, gstring, gidx,
295 rule->InputGlyphCount - 1, rule->Input);
299 i = match_classes (LookaheadClassDef, gstring, gidx,
300 rule->LookaheadGlyphCount, rule->LookAhead);
308 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
309 OTF_Coverage *coverages)
311 OTF_Glyph *gbeg = gstring->glyphs + gidx;
312 OTF_Glyph *gend = gstring->glyphs + gstring->used;
316 for (g = gbeg, i = 0; g < gend && i < count; g++)
318 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
320 return (i < count ? -1 : g - gbeg);
324 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
325 OTF_GSUB_ChainContext3 *context3)
327 int i = context3->BacktrackGlyphCount;
333 for (j = gidx - 1; j >= 0; j--)
334 if (gstring->glyphs[j].glyph_id
339 if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
340 context3->Backtrack) < 0)
344 if (context3->InputGlyphCount > 1)
346 i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
347 context3->Input + 1);
352 if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
353 context3->LookAhead) < 0)
359 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
360 OTF_GlyphString *gstring, int gidx)
362 char *errfmt = "GSUB Looking up%s";
364 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
365 unsigned int flag = lookup->LookupFlag;
366 int orig_gidx = gidx;
367 OTF_Glyph *g = gstring->glyphs + gidx;
372 && (flag & (1 << g->GlyphClass))))
375 /* Try all subtables until one of them handles the current glyph. */
376 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
378 unsigned lookup_type = lookup->LookupType;
379 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
382 if (lookup_type == 7)
384 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
386 lookup_type = extension1->ExtensionLookupType;
387 subtable = extension1->ExtensionSubtable;
390 if (subtable->Coverage.offset)
392 coverage_idx = get_coverage_index (&subtable->Coverage,
394 if (coverage_idx < 0)
398 switch (lookup->LookupType)
401 if (subtable->Format == 1)
402 g->glyph_id += subtable->u.single1.DeltaGlyphID;
404 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
410 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
411 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
413 gstring_subst (gstring, gidx, gidx + 1,
414 seq->Substitute, seq->GlyphCount);
415 gidx += seq->GlyphCount;
420 if (subtable->Format == 1)
422 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
423 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
425 g->glyph_id = altset->Alternate[0];
429 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
433 if (subtable->Format == 1)
435 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
436 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
440 for (j = 0; j < ligset->LigatureCount; j++)
444 lig = ligset->Ligature + j;
445 n = match_ids (gstring, gidx + 1,
446 lig->CompCount - 1, lig->Component);
449 gstring_subst (gstring, gidx, gidx + 1 + n,
456 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
460 if (subtable->Format == 1)
462 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
463 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
468 for (j = 0; j < set->RuleCount; j++)
470 rule = set->Rule + j;
471 if (match_ids (gstring, gidx + 1,
472 rule->GlyphCount - 1, rule->Input) < 0)
474 orig_used = gstring->used;
475 for (k = 0; k < rule->LookupCount; k++)
476 lookup_gsub (lookup_list,
477 rule->LookupRecord[k].LookupListIndex,
479 gidx + rule->LookupRecord[k].SequenceIndex);
480 gidx += rule->GlyphCount + (gstring->used - orig_used);
484 else if (subtable->Format == 2)
486 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
493 class = get_class_def (&context2->ClassDef, g->glyph_id);
494 set = context2->ClassSet + class;
495 for (j = 0; j < set->ClassRuleCnt; j++)
497 rule = set->ClassRule + j;
498 if (match_classes (&context2->ClassDef,
500 rule->GlyphCount - 1, rule->Class)
503 orig_used = gstring->used;
504 for (k = 0; k < rule->LookupCount; k++)
505 lookup_gsub (lookup_list,
506 rule->LookupRecord[k].LookupListIndex,
508 gidx + rule->LookupRecord[k].SequenceIndex);
509 gidx += rule->GlyphCount + (gstring->used - orig_used);
513 else /* subtable->Format == 3 */
515 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
519 if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
520 context3->Coverage + 1) < 0)
522 orig_used = gstring->used;
523 for (j = 0; j < context3->LookupCount; j++)
524 lookup_gsub (lookup_list,
525 context3->LookupRecord[j].LookupListIndex,
527 gidx + context3->LookupRecord[j].SequenceIndex);
528 gidx += context3->GlyphCount + (gstring->used - orig_used);
533 if (subtable->Format == 1)
535 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
536 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
540 for (j = 0; j < set->ChainRuleCount; j++)
542 OTF_ChainRule *rule = set->ChainRule + j;
544 if (gidx < rule->BacktrackGlyphCount
545 || (gidx + rule->InputGlyphCount
546 + rule->LookaheadGlyphCount) > gstring->used)
548 if (match_chain_ids (gstring, gidx, rule) < 0)
550 orig_used = gstring->used;
551 for (k = 0; k < rule->LookupCount; k++)
552 lookup_gsub (lookup_list,
553 rule->LookupRecord[k].LookupListIndex,
555 gidx + rule->LookupRecord[k].SequenceIndex);
556 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
560 else if (subtable->Format == 2)
562 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
563 OTF_ChainClassSet *set;
568 // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
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)
652 //printf ("not applied\n");
657 // printf ("done\n");
666 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
668 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
670 rec->XPlacement = anchor->XCoordinate;
671 rec->YPlacement = anchor->YCoordinate;
672 if (anchor->AnchorFormat == 1)
675 else if (anchor->AnchorFormat == 2)
676 /* Not yet implemented */
678 else if (anchor->AnchorFormat == 3)
679 /* Not yet implemented */
686 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
687 OTF_GlyphString *gstring, int gidx)
689 char *errfmt = "GPOS Looking up%s";
691 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
692 unsigned int flag = lookup->LookupFlag;
693 int orig_gidx = gidx;
694 OTF_Glyph *g = gstring->glyphs + gidx;
699 && (flag & (1 << g->GlyphClass))))
702 /* Try all subtables until one of them handles the current glyph. */
703 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
705 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
708 // printf ("subtype:%d ", subtable->Format);
709 if (subtable->Coverage.offset)
711 coverage_idx = get_coverage_index (&subtable->Coverage,
713 if (coverage_idx < 0)
715 // printf ("not covererd ");
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;
741 if (gidx + 1 >= gstring->used)
743 if (subtable->Format == 1)
745 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
746 OTF_PairSet *set = pair1->PairSet + coverage_idx;
749 for (j = 0; j < set->PairValueCount; j++)
751 if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
754 g->positioning_type = lookup->LookupType;
755 g->f.f2.format = pair1->ValueFormat1;
756 g->f.f2.value = &set->PairValueRecord[j].Value1;
757 if (pair1->ValueFormat2)
760 g->positioning_type = lookup->LookupType;
761 g->f.f2.format = pair1->ValueFormat2;
762 g->f.f2.value = &set->PairValueRecord[j].Value2;
766 else if (subtable->Format == 2)
768 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
769 unsigned class1, class2;
771 // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
773 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
774 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
775 g->positioning_type = lookup->LookupType;
776 g->f.f2.format = pair2->ValueFormat1;
778 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
779 if (pair2->ValueFormat2)
782 g->positioning_type = lookup->LookupType;
783 g->f.f2.format = pair2->ValueFormat2;
785 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
792 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
794 g->positioning_type = lookup->LookupType;
796 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
798 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
805 if (subtable->Format == 1)
807 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
808 OTF_MarkRecord *mark_record;
809 OTF_AnchorRecord *base_record;
810 int coverage_idx_base
811 = get_coverage_index (&mark_base1->BaseCoverage,
814 if (coverage_idx_base < 0)
816 // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
817 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
819 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
820 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
822 = &base_record->Anchor[mark_record->Class];
823 g->positioning_type = lookup->LookupType;
831 if (subtable->Format == 1)
833 /* As the document of this lookup type is quite
834 ambiguous, and we can't know the exact procedure to
836 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
843 if (subtable->Format == 1)
845 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
846 OTF_MarkRecord *mark1_record;
847 OTF_AnchorRecord *mark2_record;
848 int coverage_idx_base
849 = get_coverage_index (&mark_mark1->Mark2Coverage,
852 if (coverage_idx_base < 0)
854 // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
855 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
857 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
858 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
860 = &mark2_record->Anchor[mark1_record->Class];
861 g->positioning_type = lookup->LookupType;
867 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
871 if (subtable->Format == 1)
872 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
873 else if (subtable->Format == 2)
875 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
876 OTF_ChainClassSet *set;
881 // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
882 class = get_class_def (&context2->InputClassDef, g->glyph_id);
883 set = context2->ChainClassSet + class;
884 for (j = 0; j < set->ChainClassRuleCnt; j++)
886 OTF_ChainClassRule *rule = set->ChainClassRule + j;
887 int fore_idx = gidx + rule->InputGlyphCount;
890 if (gidx < rule->BacktrackGlyphCount
891 || (gidx + rule->InputGlyphCount
892 + rule->LookaheadGlyphCount) > gstring->used)
894 for (k = 0; k < rule->BacktrackGlyphCount; k++)
895 if (get_class_def (&context2->BacktrackClassDef,
896 gstring->glyphs[gidx - 1 - k].glyph_id)
897 != rule->Backtrack[k])
899 if (k < rule->BacktrackGlyphCount)
901 for (k = 1; k < rule->InputGlyphCount; k++)
902 if (get_class_def (&context2->InputClassDef,
903 gstring->glyphs[gidx + k].glyph_id)
904 != rule->Input[k - 1])
906 if (k < rule->InputGlyphCount)
908 for (k = 0; k < rule->LookaheadGlyphCount; k++)
909 if (get_class_def (&context2->LookaheadClassDef,
910 gstring->glyphs[fore_idx + k].glyph_id)
911 != rule->LookAhead[k])
913 if (k < rule->LookaheadGlyphCount)
916 orig_used = gstring->used;
917 for (k = 0; k < rule->LookupCount; k++)
918 lookup_gpos (lookup_list,
919 rule->LookupRecord[k].LookupListIndex,
921 gidx + rule->LookupRecord[k].SequenceIndex);
922 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
926 else if (subtable->Format == 3)
927 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
929 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
933 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
940 if (gidx == orig_gidx)
942 // printf ("not applied\n");
947 // printf ("done\n");
957 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
963 && OTF_get_table (otf, "cmap") < 0)
967 for (i = 0; i < gstring->used; i++)
968 if (! gstring->glyphs[i].glyph_id)
970 int c = gstring->glyphs[i].c;
971 if (c < 32 || ! cmap->unicode_table)
972 gstring->glyphs[i].glyph_id = 0;
974 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
980 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
983 && OTF_get_table (otf, "cmap") < 0)
986 || code > otf->cmap->max_glyph_id
987 || ! otf->cmap->decode_table)
989 return otf->cmap->decode_table[code];
993 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
999 && OTF_get_table (otf, "GDEF") < 0)
1003 if (gdef->glyph_class_def.offset)
1004 for (i = 0; i < gstring->used; i++)
1005 gstring->glyphs[i].GlyphClass
1006 = get_class_def (&gdef->glyph_class_def,
1007 gstring->glyphs[i].glyph_id);
1009 if (gdef->mark_attach_class_def.offset)
1010 for (i = 0; i < gstring->used; i++)
1011 gstring->glyphs[i].MarkAttachClass
1012 = get_class_def (&gdef->mark_attach_class_def,
1013 gstring->glyphs[i].glyph_id);
1020 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1021 char *script, char *language, char *features)
1023 char *errfmt = "GSUB driving%s";
1026 OTF_LangSys *LangSys;
1027 int *lookup_indices;
1031 && OTF_get_table (otf, "GSUB") < 0)
1034 if (gsub->FeatureList.FeatureCount == 0
1035 || gsub->LookupList.LookupCount == 0)
1038 LangSys = get_langsys (&gsub->ScriptList, script, language);
1042 /* One lookup may be used by multiple features. */
1043 lookup_indices = alloca (sizeof (int)
1044 * gsub->LookupList.LookupCount
1045 * (gsub->FeatureList.FeatureCount + 1));
1046 if (! lookup_indices)
1047 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1048 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1049 features, lookup_indices);
1053 for (i = 0; i < n; i++)
1055 int index = lookup_indices[i];
1058 if (gsub->LookupList.Lookup[index].LookupType != 8)
1061 while (gidx < gstring->used)
1063 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1070 gidx = gstring->used - 1;
1073 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1084 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1085 char *script, char *language, char *features)
1087 char *errfmt = "GPOS driving%s";
1090 OTF_LangSys *LangSys;
1091 int *lookup_indices;
1095 && OTF_get_table (otf, "GPOS") < 0)
1098 if (gpos->FeatureList.FeatureCount == 0
1099 || gpos->LookupList.LookupCount == 0)
1102 LangSys = get_langsys (&gpos->ScriptList, script, language);
1106 /* One lookup may be used by multiple features. */
1107 lookup_indices = alloca (sizeof (int)
1108 * gpos->LookupList.LookupCount
1109 * (gpos->FeatureList.FeatureCount + 1));
1110 if (! lookup_indices)
1111 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1112 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1113 features, lookup_indices);
1117 for (i = 0; i < n; i++)
1119 int index = lookup_indices[i];
1122 while (gidx < gstring->used)
1124 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1134 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1135 char *script, char *language,
1136 char *gsub_features, char *gpos_features)
1138 if (OTF_drive_cmap (otf, gstring) < 0)
1140 if (OTF_drive_gdef (otf, gstring) < 0)
1143 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1146 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)