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;
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 for (i = 0; i < FeatureList->FeatureCount; i++)
164 if (! feature_table[i])
166 feature = FeatureList->Feature + i;
167 for (j = 0; j < feature->LookupCount; j++)
168 lookup_indices[n++] = feature->LookupListIndex[j];
173 if (*features == '~')
174 negate = 1, features++;
175 for (i = 0; *features && *features != ','; i++, features++)
176 tagname[i] = *features;
182 tag = OTF_tag (tagname);
183 for (i = 0; i < FeatureList->FeatureCount; i++)
185 feature = FeatureList->Feature + i;
186 if (tag == feature->FeatureTag)
189 for (j = 0; j < feature->LookupCount; j++)
190 lookup_indices[n++] = feature->LookupListIndex[j];
191 feature_table[i] = 1;
201 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
205 if (gstring->used - gidx < count)
207 for (i = j = 0; i < count; i++, j++)
209 if (! gstring->glyphs[gidx + j].glyph_id)
210 /* Skip this glyph. */
212 else if (ids[i] && gstring->glyphs[gidx + i].glyph_id != ids[i])
219 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
221 if (match_ids (gstring, gidx, rule->BacktrackGlyphCount, rule->Backtrack)
224 gidx += rule->BacktrackGlyphCount + 1;
225 if (match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input)
228 gidx += rule->InputGlyphCount;
229 if (match_ids (gstring, gidx, rule->LookaheadGlyphCount - 1, rule->LookAhead)
236 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
237 int count, unsigned *classes)
241 if (gstring->used - gidx < count)
243 for (i = 0; i < count; i++)
244 if (get_class_def (class_def, gstring->glyphs[gidx + i].glyph_id)
251 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
252 OTF_GlyphString *gstring, int gidx)
254 char *errfmt = "GSUB Looking up%s";
256 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
257 unsigned int flag = lookup->LookupFlag;
258 int orig_gidx = gidx;
259 OTF_Glyph *g = gstring->glyphs + gidx;
264 && (flag & (1 << g->GlyphClass))))
267 /* Try all subtables until one of them handles the current glyph. */
268 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
270 unsigned lookup_type = lookup->LookupType;
271 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
274 if (lookup_type == 7)
276 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
278 lookup_type = extension1->ExtensionLookupType;
279 subtable = extension1->ExtensionSubtable;
282 if (subtable->Coverage.offset)
284 coverage_idx = get_coverage_index (&subtable->Coverage,
286 if (coverage_idx < 0)
290 switch (lookup->LookupType)
293 if (subtable->Format == 1)
294 g->glyph_id += subtable->u.single1.DeltaGlyphID;
296 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
302 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
303 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
305 gstring_subst (gstring, gidx, gidx + 1,
306 seq->Substitute, seq->GlyphCount);
307 gidx += seq->GlyphCount;
312 if (subtable->Format == 1)
314 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
315 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
317 g->glyph_id = altset->Alternate[0];
321 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
325 if (subtable->Format == 1)
327 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
328 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
332 for (j = 0; j < ligset->LigatureCount; j++)
334 lig = ligset->Ligature + j;
335 if (match_ids (gstring, gidx + 1,
336 lig->CompCount - 1, lig->Component) < 0)
338 gstring_subst (gstring, gidx, gidx + lig->CompCount,
345 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
349 if (subtable->Format == 1)
351 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
352 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
357 for (j = 0; j < set->RuleCount; j++)
359 rule = set->Rule + j;
360 if (match_ids (gstring, gidx + 1,
361 rule->GlyphCount - 1, rule->Input) < 0)
363 orig_used = gstring->used;
364 for (k = 0; k < rule->LookupCount; k++)
365 lookup_gsub (lookup_list,
366 rule->LookupRecord[k].LookupListIndex,
368 gidx + rule->LookupRecord[k].SequenceIndex);
369 gidx += rule->GlyphCount + (gstring->used - orig_used);
373 else if (subtable->Format == 2)
375 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
382 class = get_class_def (&context2->ClassDef, g->glyph_id);
383 set = context2->ClassSet + class;
384 for (j = 0; j < set->ClassRuleCnt; j++)
386 rule = set->ClassRule + j;
387 if (match_classes (&context2->ClassDef,
389 rule->GlyphCount - 1, rule->Class)
392 orig_used = gstring->used;
393 for (k = 0; k < rule->LookupCount; k++)
394 lookup_gsub (lookup_list,
395 rule->LookupRecord[k].LookupListIndex,
397 gidx + rule->LookupRecord[k].SequenceIndex);
398 gidx += rule->GlyphCount + (gstring->used - orig_used);
402 else /* subtable->Format == 3 */
404 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
408 if (gstring->used - gidx < context3->GlyphCount)
410 /* Start from the secoding coverage_idx because the
411 first one is the same as subtable->Coverage and thus
413 for (j = 1; j < context3->GlyphCount; j++)
414 if (get_coverage_index (context3->Coverage + j,
415 gstring->glyphs[gidx + j].glyph_id)
418 if (j < context3->GlyphCount)
420 orig_used = gstring->used;
421 for (k = 0; k < context3->LookupCount; k++)
422 lookup_gsub (lookup_list,
423 context3->LookupRecord[k].LookupListIndex,
425 gidx + context3->LookupRecord[k].SequenceIndex);
426 gidx += context3->GlyphCount + (gstring->used - orig_used);
431 if (subtable->Format == 1)
433 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
434 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
438 for (j = 0; j < set->ChainRuleCount; j++)
440 OTF_ChainRule *rule = set->ChainRule + j;
441 int backs = rule->BacktrackGlyphCount;
442 int inputs = rule->InputGlyphCount;
443 int aheads = rule->LookaheadGlyphCount;
445 if (gidx < backs || gidx + inputs + aheads > gstring->used)
447 if (match_chain_ids (gstring, gidx - backs, rule) < 0)
449 orig_used = gstring->used;
450 for (k = 0; k < rule->LookupCount; k++)
451 lookup_gsub (lookup_list,
452 rule->LookupRecord[k].LookupListIndex,
454 gidx + rule->LookupRecord[k].SequenceIndex);
455 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
459 else if (subtable->Format == 2)
461 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
462 OTF_ChainClassSet *set;
467 // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
468 class = get_class_def (&context2->InputClassDef, g->glyph_id);
469 set = context2->ChainClassSet + class;
470 for (j = 0; j < set->ChainClassRuleCnt; j++)
472 OTF_ChainClassRule *rule = set->ChainClassRule + j;
473 int fore_idx = gidx + rule->InputGlyphCount;
476 if (gidx < rule->BacktrackGlyphCount
477 || (gidx + rule->InputGlyphCount
478 + rule->LookaheadGlyphCount) >= gstring->used)
480 for (k = 0; k < rule->BacktrackGlyphCount; k++)
481 if (get_class_def (&context2->BacktrackClassDef,
482 gstring->glyphs[gidx - 1 - k].glyph_id)
483 != rule->Backtrack[k])
485 if (k < rule->BacktrackGlyphCount)
487 for (k = 1; k < rule->InputGlyphCount; k++)
488 if (get_class_def (&context2->InputClassDef,
489 gstring->glyphs[gidx + k].glyph_id)
490 != rule->Input[k - 1])
492 if (k < rule->InputGlyphCount)
494 for (k = 0; k < rule->LookaheadGlyphCount; k++)
495 if (get_class_def (&context2->LookaheadClassDef,
496 gstring->glyphs[fore_idx + k].glyph_id)
497 != rule->LookAhead[k])
499 if (k < rule->LookaheadGlyphCount)
502 orig_used = gstring->used;
503 for (k = 0; k < rule->LookupCount; k++)
504 lookup_gsub (lookup_list,
505 rule->LookupRecord[k].LookupListIndex,
507 gidx + rule->LookupRecord[k].SequenceIndex);
508 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
514 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
515 int back_gidx = gidx - context3->BacktrackGlyphCount;
516 int fore_gidx = gidx + context3->InputGlyphCount;
521 || fore_gidx + context3->LookaheadGlyphCount > gstring->used)
524 for (j = 0; j < context3->BacktrackGlyphCount; j++)
525 if (get_coverage_index (context3->Backtrack + j,
526 gstring->glyphs[gidx - 1 - j].glyph_id)
529 if (j < context3->BacktrackGlyphCount)
532 /* Start from the second coverage_idx because the first
533 one is the same as subtable->Coverage and thus
535 for (j = 1; j < context3->InputGlyphCount; j++)
536 if (get_coverage_index (context3->Input + j,
537 gstring->glyphs[gidx + j].glyph_id)
540 if (j < context3->InputGlyphCount)
543 for (j = 0; j < context3->LookaheadGlyphCount; j++)
544 if (get_coverage_index (context3->LookAhead + j,
545 gstring->glyphs[fore_gidx + j].glyph_id)
548 if (j < context3->LookaheadGlyphCount)
551 orig_used = gstring->used;
552 for (j = 0; j < context3->LookupCount; j++)
553 lookup_gsub (lookup_list,
554 context3->LookupRecord[j].LookupListIndex,
556 gidx + context3->LookupRecord[j].SequenceIndex);
557 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
563 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
564 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
565 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
568 if (back_gidx > gstring->used || ahead_gidx < 0)
571 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
572 if (get_coverage_index (reverse->Backtrack + j,
573 gstring->glyphs[gidx + 1 + j].glyph_id)
576 if (j < reverse->BacktrackGlyphCount)
578 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
579 if (get_coverage_index (reverse->LookAhead + j,
580 gstring->glyphs[gidx - 1 - j].glyph_id)
583 if (j < reverse->LookaheadGlyphCount)
585 g->glyph_id = reverse->Substitute[coverage_idx];
593 if (gidx == orig_gidx)
595 //printf ("not applied\n");
600 // printf ("done\n");
609 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
611 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
613 rec->XPlacement = anchor->XCoordinate;
614 rec->YPlacement = anchor->YCoordinate;
615 if (anchor->AnchorFormat == 1)
618 else if (anchor->AnchorFormat == 2)
619 /* Not yet implemented */
621 else if (anchor->AnchorFormat == 3)
622 /* Not yet implemented */
629 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
630 OTF_GlyphString *gstring, int gidx)
632 char *errfmt = "GPOS Looking up%s";
634 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
635 unsigned int flag = lookup->LookupFlag;
636 int orig_gidx = gidx;
637 OTF_Glyph *g = gstring->glyphs + gidx;
642 && (flag & (1 << g->GlyphClass))))
645 /* Try all subtables until one of them handles the current glyph. */
646 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
648 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
651 // printf ("subtype:%d ", subtable->Format);
652 if (subtable->Coverage.offset)
654 coverage_idx = get_coverage_index (&subtable->Coverage,
656 if (coverage_idx < 0)
658 // printf ("not covererd ");
663 switch (lookup->LookupType)
666 g->positioning_type = lookup->LookupType;
667 if (subtable->Format == 1)
669 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
671 g->f.f1.format = single1->ValueFormat;
672 g->f.f1.value = &single1->Value;
674 else if (subtable->Format == 2)
676 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
678 g->f.f1.format = single2->ValueFormat;
679 g->f.f1.value = single2->Value + coverage_idx;
684 if (gidx + 1 >= gstring->used)
686 if (subtable->Format == 1)
688 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
689 OTF_PairSet *set = pair1->PairSet + coverage_idx;
692 for (j = 0; j < set->PairValueCount; j++)
694 if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
697 g->positioning_type = lookup->LookupType;
698 g->f.f2.format = pair1->ValueFormat1;
699 g->f.f2.value = &set->PairValueRecord[j].Value1;
700 if (pair1->ValueFormat2)
703 g->positioning_type = lookup->LookupType;
704 g->f.f2.format = pair1->ValueFormat2;
705 g->f.f2.value = &set->PairValueRecord[j].Value2;
709 else if (subtable->Format == 2)
711 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
712 unsigned class1, class2;
714 // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
716 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
717 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
718 g->positioning_type = lookup->LookupType;
719 g->f.f2.format = pair2->ValueFormat1;
721 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
722 if (pair2->ValueFormat2)
725 g->positioning_type = lookup->LookupType;
726 g->f.f2.format = pair2->ValueFormat2;
728 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
735 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
737 g->positioning_type = lookup->LookupType;
739 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
741 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
748 if (subtable->Format == 1)
750 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
751 OTF_MarkRecord *mark_record;
752 OTF_AnchorRecord *base_record;
753 int coverage_idx_base
754 = get_coverage_index (&mark_base1->BaseCoverage,
757 if (coverage_idx_base < 0)
759 // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
760 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
762 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
763 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
765 = &base_record->Anchor[mark_record->Class];
766 g->positioning_type = lookup->LookupType;
774 if (subtable->Format == 1)
776 /* As the document of this lookup type is quite
777 ambiguous, and we can't know the exact procedure to
779 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
786 if (subtable->Format == 1)
788 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
789 OTF_MarkRecord *mark1_record;
790 OTF_AnchorRecord *mark2_record;
791 int coverage_idx_base
792 = get_coverage_index (&mark_mark1->Mark2Coverage,
795 if (coverage_idx_base < 0)
797 // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
798 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
800 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
801 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
803 = &mark2_record->Anchor[mark1_record->Class];
804 g->positioning_type = lookup->LookupType;
810 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
814 if (subtable->Format == 1)
815 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
816 else if (subtable->Format == 2)
818 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
819 OTF_ChainClassSet *set;
824 // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
825 class = get_class_def (&context2->InputClassDef, g->glyph_id);
826 set = context2->ChainClassSet + class;
827 for (j = 0; j < set->ChainClassRuleCnt; j++)
829 OTF_ChainClassRule *rule = set->ChainClassRule + j;
830 int fore_idx = gidx + rule->InputGlyphCount;
833 if (gidx < rule->BacktrackGlyphCount
834 || (gidx + rule->InputGlyphCount
835 + rule->LookaheadGlyphCount) >= gstring->used)
837 for (k = 0; k < rule->BacktrackGlyphCount; k++)
838 if (get_class_def (&context2->BacktrackClassDef,
839 gstring->glyphs[gidx - 1 - k].glyph_id)
840 != rule->Backtrack[k])
842 if (k < rule->BacktrackGlyphCount)
844 for (k = 1; k < rule->InputGlyphCount; k++)
845 if (get_class_def (&context2->InputClassDef,
846 gstring->glyphs[gidx + k].glyph_id)
847 != rule->Input[k - 1])
849 if (k < rule->InputGlyphCount)
851 for (k = 0; k < rule->LookaheadGlyphCount; k++)
852 if (get_class_def (&context2->LookaheadClassDef,
853 gstring->glyphs[fore_idx + k].glyph_id)
854 != rule->LookAhead[k])
856 if (k < rule->LookaheadGlyphCount)
859 orig_used = gstring->used;
860 for (k = 0; k < rule->LookupCount; k++)
861 lookup_gpos (lookup_list,
862 rule->LookupRecord[k].LookupListIndex,
864 gidx + rule->LookupRecord[k].SequenceIndex);
865 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
869 else if (subtable->Format == 3)
870 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
872 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
876 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
883 if (gidx == orig_gidx)
885 // printf ("not applied\n");
890 // printf ("done\n");
900 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
906 && OTF_get_table (otf, "cmap") < 0)
910 for (i = 0; i < gstring->used; i++)
912 int c = gstring->glyphs[i].c;
913 if (c < 32 || ! cmap || ! cmap->unicode_table)
914 gstring->glyphs[i].glyph_id = 0;
916 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
917 if (gstring->glyphs[i].glyph_id < 0)
925 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
931 && OTF_get_table (otf, "GDEF") < 0)
935 if (gdef->glyph_class_def.offset)
936 for (i = 0; i < gstring->used; i++)
937 gstring->glyphs[i].GlyphClass
938 = get_class_def (&gdef->glyph_class_def,
939 gstring->glyphs[i].glyph_id);
941 if (gdef->mark_attach_class_def.offset)
942 for (i = 0; i < gstring->used; i++)
943 gstring->glyphs[i].MarkAttachClass
944 = get_class_def (&gdef->mark_attach_class_def,
945 gstring->glyphs[i].glyph_id);
952 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
953 char *script, char *language, char *features)
955 char *errfmt = "GSUB driving%s";
958 OTF_LangSys *LangSys;
963 && OTF_get_table (otf, "GSUB") < 0)
966 if (gsub->FeatureList.FeatureCount == 0
967 || gsub->LookupList.LookupCount == 0)
970 LangSys = get_langsys (&gsub->ScriptList, script, language);
974 /* One lookup may be used by multiple features. */
975 lookup_indices = alloca (sizeof (int)
976 * gsub->LookupList.LookupCount
977 * gsub->FeatureList.FeatureCount);
978 if (! lookup_indices)
979 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
980 n = setup_lookup_indices (LangSys, &gsub->FeatureList,
981 features, lookup_indices);
985 for (i = 0; i < n; i++)
987 int index = lookup_indices[i];
990 if (gsub->LookupList.Lookup[index].LookupType != 8)
993 while (gidx < gstring->used)
995 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1002 gidx = gstring->used - 1;
1005 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1016 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1017 char *script, char *language, char *features)
1019 char *errfmt = "GPOS driving%s";
1022 OTF_LangSys *LangSys;
1023 int *lookup_indices;
1027 && OTF_get_table (otf, "GPOS") < 0)
1030 if (gpos->FeatureList.FeatureCount == 0
1031 || gpos->LookupList.LookupCount == 0)
1034 LangSys = get_langsys (&gpos->ScriptList, script, language);
1038 /* One lookup may be used by multiple features. */
1039 lookup_indices = alloca (sizeof (int)
1040 * gpos->LookupList.LookupCount
1041 * gpos->FeatureList.FeatureCount);
1042 if (! lookup_indices)
1043 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1044 n = setup_lookup_indices (LangSys, &gpos->FeatureList,
1045 features, lookup_indices);
1049 for (i = 0; i < n; i++)
1051 int index = lookup_indices[i];
1054 while (gidx < gstring->used)
1056 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1066 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1067 char *script, char *language,
1068 char *gsub_features, char *gpos_features)
1070 if (OTF_drive_cmap (otf, gstring) < 0)
1072 if (OTF_drive_gdef (otf, gstring) < 0)
1075 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1078 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)