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_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)