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 // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
570 class = get_class_def (&context2->InputClassDef, g->glyph_id);
571 set = context2->ChainClassSet + class;
572 for (j = 0; j < set->ChainClassRuleCnt; j++)
574 OTF_ChainClassRule *rule = set->ChainClassRule + j;
577 if (gidx < rule->BacktrackGlyphCount
578 || (gidx + rule->InputGlyphCount
579 + rule->LookaheadGlyphCount) > gstring->used)
581 if (match_chain_classes (gstring, gidx,
582 &context2->BacktrackClassDef,
583 &context2->InputClassDef,
584 &context2->LookaheadClassDef,
587 orig_used = gstring->used;
588 for (k = 0; k < rule->LookupCount; k++)
589 lookup_gsub (lookup_list,
590 rule->LookupRecord[k].LookupListIndex,
592 gidx + rule->LookupRecord[k].SequenceIndex);
593 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
599 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
603 if (gidx < context3->BacktrackGlyphCount
604 || (gidx + context3->InputGlyphCount
605 + context3->LookaheadGlyphCount) > gstring->used)
607 if (match_chain_coverages (gstring, gidx, context3) < 0)
609 orig_used = gstring->used;
610 for (j = 0; j < context3->LookupCount; j++)
611 lookup_gsub (lookup_list,
612 context3->LookupRecord[j].LookupListIndex,
614 gidx + context3->LookupRecord[j].SequenceIndex);
615 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
621 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
622 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
623 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
626 if (back_gidx > gstring->used || ahead_gidx < 0)
629 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
630 if (get_coverage_index (reverse->Backtrack + j,
631 gstring->glyphs[gidx + 1 + j].glyph_id)
634 if (j < reverse->BacktrackGlyphCount)
636 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
637 if (get_coverage_index (reverse->LookAhead + j,
638 gstring->glyphs[gidx - 1 - j].glyph_id)
641 if (j < reverse->LookaheadGlyphCount)
643 g->glyph_id = reverse->Substitute[coverage_idx];
651 if (gidx == orig_gidx)
653 //printf ("not applied\n");
658 // printf ("done\n");
667 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
669 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
671 rec->XPlacement = anchor->XCoordinate;
672 rec->YPlacement = anchor->YCoordinate;
673 if (anchor->AnchorFormat == 1)
676 else if (anchor->AnchorFormat == 2)
677 /* Not yet implemented */
679 else if (anchor->AnchorFormat == 3)
680 /* Not yet implemented */
687 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
688 OTF_GlyphString *gstring, int gidx)
690 char *errfmt = "GPOS Looking up%s";
692 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
693 unsigned int flag = lookup->LookupFlag;
694 int orig_gidx = gidx;
695 OTF_Glyph *g = gstring->glyphs + gidx;
700 && (flag & (1 << g->GlyphClass))))
703 /* Try all subtables until one of them handles the current glyph. */
704 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
706 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
709 // printf ("subtype:%d ", subtable->Format);
710 if (subtable->Coverage.offset)
712 coverage_idx = get_coverage_index (&subtable->Coverage,
714 if (coverage_idx < 0)
716 // printf ("not covererd ");
721 switch (lookup->LookupType)
724 g->positioning_type = lookup->LookupType;
725 if (subtable->Format == 1)
727 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
729 g->f.f1.format = single1->ValueFormat;
730 g->f.f1.value = &single1->Value;
732 else if (subtable->Format == 2)
734 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
736 g->f.f1.format = single2->ValueFormat;
737 g->f.f1.value = single2->Value + coverage_idx;
742 if (gidx + 1 >= gstring->used)
744 if (subtable->Format == 1)
746 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
747 OTF_PairSet *set = pair1->PairSet + coverage_idx;
750 for (j = 0; j < set->PairValueCount; j++)
752 if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
755 g->positioning_type = lookup->LookupType;
756 g->f.f2.format = pair1->ValueFormat1;
757 g->f.f2.value = &set->PairValueRecord[j].Value1;
758 if (pair1->ValueFormat2)
761 g->positioning_type = lookup->LookupType;
762 g->f.f2.format = pair1->ValueFormat2;
763 g->f.f2.value = &set->PairValueRecord[j].Value2;
767 else if (subtable->Format == 2)
769 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
770 unsigned class1, class2;
772 // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
774 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
775 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
776 g->positioning_type = lookup->LookupType;
777 g->f.f2.format = pair2->ValueFormat1;
779 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
780 if (pair2->ValueFormat2)
783 g->positioning_type = lookup->LookupType;
784 g->f.f2.format = pair2->ValueFormat2;
786 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
793 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
795 g->positioning_type = lookup->LookupType;
797 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
799 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
806 if (subtable->Format == 1)
808 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
809 OTF_MarkRecord *mark_record;
810 OTF_AnchorRecord *base_record;
811 int coverage_idx_base
812 = get_coverage_index (&mark_base1->BaseCoverage,
815 if (coverage_idx_base < 0)
817 // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
818 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
820 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
821 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
823 = &base_record->Anchor[mark_record->Class];
824 g->positioning_type = lookup->LookupType;
832 if (subtable->Format == 1)
834 /* As the document of this lookup type is quite
835 ambiguous, and we can't know the exact procedure to
837 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
844 if (subtable->Format == 1)
846 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
847 OTF_MarkRecord *mark1_record;
848 OTF_AnchorRecord *mark2_record;
849 int coverage_idx_base
850 = get_coverage_index (&mark_mark1->Mark2Coverage,
853 if (coverage_idx_base < 0)
855 // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
856 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
858 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
859 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
861 = &mark2_record->Anchor[mark1_record->Class];
862 g->positioning_type = lookup->LookupType;
868 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
872 if (subtable->Format == 1)
873 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
874 else if (subtable->Format == 2)
876 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
877 OTF_ChainClassSet *set;
882 // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
883 class = get_class_def (&context2->InputClassDef, g->glyph_id);
884 set = context2->ChainClassSet + class;
885 for (j = 0; j < set->ChainClassRuleCnt; j++)
887 OTF_ChainClassRule *rule = set->ChainClassRule + j;
888 int fore_idx = gidx + rule->InputGlyphCount;
891 if (gidx < rule->BacktrackGlyphCount
892 || (gidx + rule->InputGlyphCount
893 + rule->LookaheadGlyphCount) > gstring->used)
895 for (k = 0; k < rule->BacktrackGlyphCount; k++)
896 if (get_class_def (&context2->BacktrackClassDef,
897 gstring->glyphs[gidx - 1 - k].glyph_id)
898 != rule->Backtrack[k])
900 if (k < rule->BacktrackGlyphCount)
902 for (k = 1; k < rule->InputGlyphCount; k++)
903 if (get_class_def (&context2->InputClassDef,
904 gstring->glyphs[gidx + k].glyph_id)
905 != rule->Input[k - 1])
907 if (k < rule->InputGlyphCount)
909 for (k = 0; k < rule->LookaheadGlyphCount; k++)
910 if (get_class_def (&context2->LookaheadClassDef,
911 gstring->glyphs[fore_idx + k].glyph_id)
912 != rule->LookAhead[k])
914 if (k < rule->LookaheadGlyphCount)
917 orig_used = gstring->used;
918 for (k = 0; k < rule->LookupCount; k++)
919 lookup_gpos (lookup_list,
920 rule->LookupRecord[k].LookupListIndex,
922 gidx + rule->LookupRecord[k].SequenceIndex);
923 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
927 else if (subtable->Format == 3)
928 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
930 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
934 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
941 if (gidx == orig_gidx)
943 // printf ("not applied\n");
948 // printf ("done\n");
958 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
964 && OTF_get_table (otf, "cmap") < 0)
968 for (i = 0; i < gstring->used; i++)
969 if (! gstring->glyphs[i].glyph_id)
971 int c = gstring->glyphs[i].c;
972 if (c < 32 || ! cmap->unicode_table)
973 gstring->glyphs[i].glyph_id = 0;
975 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
981 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
984 && OTF_get_table (otf, "cmap") < 0)
987 || code > otf->cmap->max_glyph_id
988 || ! otf->cmap->decode_table)
990 return otf->cmap->decode_table[code];
994 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1000 && OTF_get_table (otf, "GDEF") < 0)
1004 if (gdef->glyph_class_def.offset)
1005 for (i = 0; i < gstring->used; i++)
1006 gstring->glyphs[i].GlyphClass
1007 = get_class_def (&gdef->glyph_class_def,
1008 gstring->glyphs[i].glyph_id);
1010 if (gdef->mark_attach_class_def.offset)
1011 for (i = 0; i < gstring->used; i++)
1012 gstring->glyphs[i].MarkAttachClass
1013 = get_class_def (&gdef->mark_attach_class_def,
1014 gstring->glyphs[i].glyph_id);
1021 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1022 char *script, char *language, char *features)
1024 char *errfmt = "GSUB driving%s";
1027 OTF_LangSys *LangSys;
1028 int *lookup_indices;
1032 && OTF_get_table (otf, "GSUB") < 0)
1035 if (gsub->FeatureList.FeatureCount == 0
1036 || gsub->LookupList.LookupCount == 0)
1039 LangSys = get_langsys (&gsub->ScriptList, script, language);
1043 /* One lookup may be used by multiple features. */
1044 lookup_indices = alloca (sizeof (int)
1045 * gsub->LookupList.LookupCount
1046 * (gsub->FeatureList.FeatureCount + 1));
1047 if (! lookup_indices)
1048 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1049 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1050 features, lookup_indices);
1054 for (i = 0; i < n; i++)
1056 int index = lookup_indices[i];
1059 if (gsub->LookupList.Lookup[index].LookupType != 8)
1062 while (gidx < gstring->used)
1064 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1071 gidx = gstring->used - 1;
1074 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1085 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1086 char *script, char *language, char *features)
1088 char *errfmt = "GPOS driving%s";
1091 OTF_LangSys *LangSys;
1092 int *lookup_indices;
1096 && OTF_get_table (otf, "GPOS") < 0)
1099 if (gpos->FeatureList.FeatureCount == 0
1100 || gpos->LookupList.LookupCount == 0)
1103 LangSys = get_langsys (&gpos->ScriptList, script, language);
1107 /* One lookup may be used by multiple features. */
1108 lookup_indices = alloca (sizeof (int)
1109 * gpos->LookupList.LookupCount
1110 * (gpos->FeatureList.FeatureCount + 1));
1111 if (! lookup_indices)
1112 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1113 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1114 features, lookup_indices);
1118 for (i = 0; i < n; i++)
1120 int index = lookup_indices[i];
1123 while (gidx < gstring->used)
1125 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1135 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1136 char *script, char *language,
1137 char *gsub_features, char *gpos_features)
1139 if (OTF_drive_cmap (otf, gstring) < 0)
1141 if (OTF_drive_gdef (otf, gstring) < 0)
1144 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1147 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)