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++)
130 || script_list->Script[i].ScriptTag == script_tag)
132 OTF_Script *script = script_list->Script + i;
135 return &script->DefaultLangSys;
136 for (j = 0; j < script->LangSysCount; j++)
137 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
138 return script->LangSys + j;
139 return &script->DefaultLangSys;
146 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
147 char *features, int *lookup_indices)
150 OTF_Feature *feature;
151 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
153 for (i = 0; i < FeatureList->FeatureCount; i++)
154 feature_table[i] = 0;
162 if (*features == '*')
164 /* Consume all remaining features. */
165 /* We are sure that the last LookupCount elements of
166 lookup_indices are free to be used for this work. */
167 int *free_table = (lookup_indices + (LookupList->LookupCount
168 * FeatureList->FeatureCount));
170 for (i = 0; i < LookupList->LookupCount; i++)
172 for (i = 0; i < FeatureList->FeatureCount; i++)
173 if (! feature_table[i])
175 feature = FeatureList->Feature + i;
176 for (j = 0; j < feature->LookupCount; j++)
177 free_table[feature->LookupListIndex[j]] = 1;
179 for (i = 0; i < LookupList->LookupCount; i++)
181 lookup_indices[n++] = i;
185 if (*features == '~')
186 negate = 1, features++;
187 for (i = 0; *features && *features != ','; i++, features++)
188 tagname[i] = *features;
194 tag = OTF_tag (tagname);
195 for (i = 0; i < FeatureList->FeatureCount; i++)
197 feature = FeatureList->Feature + i;
198 if (tag == feature->FeatureTag)
201 for (j = 0; j < feature->LookupCount; j++)
202 lookup_indices[n++] = feature->LookupListIndex[j];
203 feature_table[i] = 1;
213 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
215 OTF_Glyph *gbeg = gstring->glyphs + gidx;
216 OTF_Glyph *gend = gstring->glyphs + gstring->used;
220 for (g = gbeg, i = 0; g < gend && i < count; g++)
221 if (g->glyph_id && g->glyph_id != ids[i++])
223 return (i < count ? -1 : g - gbeg);
227 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
229 int i = rule->BacktrackGlyphCount;
235 for (j = gidx - 1; j >= 0; j--)
236 if (gstring->glyphs[j].glyph_id
241 if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
246 i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
250 i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
257 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
258 int count, unsigned *classes)
260 OTF_Glyph *gbeg = gstring->glyphs + gidx;
261 OTF_Glyph *gend = gstring->glyphs + gstring->used;
265 for (g = gbeg, i = 0; g < gend && i < count; g++)
267 && get_class_def (class_def, g->glyph_id) != classes[i++])
269 return (i < count ? -1 : g - gbeg);
273 match_chain_classes (OTF_GlyphString *gstring, int gidx,
274 OTF_ClassDef *BacktrackClassDef,
275 OTF_ClassDef *InputClassDef,
276 OTF_ClassDef *LookaheadClassDef,
277 OTF_ChainClassRule *rule)
279 int i = rule->BacktrackGlyphCount;
285 for (j = gidx - 1; j >= 0 && i > 0; j--)
286 if (gstring->glyphs[j].glyph_id
291 if (match_classes (BacktrackClassDef, gstring, j,
292 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
296 i = match_classes (InputClassDef, gstring, gidx,
297 rule->InputGlyphCount - 1, rule->Input);
301 i = match_classes (LookaheadClassDef, gstring, gidx,
302 rule->LookaheadGlyphCount, rule->LookAhead);
310 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
311 OTF_Coverage *coverages)
313 OTF_Glyph *gbeg = gstring->glyphs + gidx;
314 OTF_Glyph *gend = gstring->glyphs + gstring->used;
318 for (g = gbeg, i = 0; g < gend && i < count; g++)
320 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
322 return (i < count ? -1 : g - gbeg);
326 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
327 OTF_GSUB_ChainContext3 *context3)
329 int i = context3->BacktrackGlyphCount;
335 for (j = gidx - 1; j >= 0; j--)
336 if (gstring->glyphs[j].glyph_id
341 if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
342 context3->Backtrack) < 0)
346 if (context3->InputGlyphCount > 1)
348 i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
349 context3->Input + 1);
354 if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
355 context3->LookAhead) < 0)
361 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
362 OTF_GlyphString *gstring, int gidx)
364 char *errfmt = "GSUB Looking up%s";
366 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
367 unsigned int flag = lookup->LookupFlag;
368 int orig_gidx = gidx;
369 OTF_Glyph *g = gstring->glyphs + gidx;
374 && (flag & (1 << g->GlyphClass))))
377 /* Try all subtables until one of them handles the current glyph. */
378 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
380 unsigned lookup_type = lookup->LookupType;
381 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
384 if (lookup_type == 7)
386 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
388 lookup_type = extension1->ExtensionLookupType;
389 subtable = extension1->ExtensionSubtable;
392 if (subtable->Coverage.offset)
394 coverage_idx = get_coverage_index (&subtable->Coverage,
396 if (coverage_idx < 0)
400 switch (lookup->LookupType)
403 if (subtable->Format == 1)
404 g->glyph_id += subtable->u.single1.DeltaGlyphID;
406 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
412 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
413 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
415 gstring_subst (gstring, gidx, gidx + 1,
416 seq->Substitute, seq->GlyphCount);
417 gidx += seq->GlyphCount;
422 if (subtable->Format == 1)
424 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
425 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
427 g->glyph_id = altset->Alternate[0];
431 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
435 if (subtable->Format == 1)
437 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
438 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
442 for (j = 0; j < ligset->LigatureCount; j++)
446 lig = ligset->Ligature + j;
447 n = match_ids (gstring, gidx + 1,
448 lig->CompCount - 1, lig->Component);
451 gstring_subst (gstring, gidx, gidx + 1 + n,
458 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
462 if (subtable->Format == 1)
464 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
465 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
470 for (j = 0; j < set->RuleCount; j++)
472 rule = set->Rule + j;
473 if (match_ids (gstring, gidx + 1,
474 rule->GlyphCount - 1, rule->Input) < 0)
476 orig_used = gstring->used;
477 for (k = 0; k < rule->LookupCount; k++)
478 lookup_gsub (lookup_list,
479 rule->LookupRecord[k].LookupListIndex,
481 gidx + rule->LookupRecord[k].SequenceIndex);
482 gidx += rule->GlyphCount + (gstring->used - orig_used);
486 else if (subtable->Format == 2)
488 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
495 class = get_class_def (&context2->ClassDef, g->glyph_id);
496 set = context2->ClassSet + class;
498 for (j = 0; j < set->ClassRuleCnt; j++)
500 rule = set->ClassRule + j;
501 if (match_classes (&context2->ClassDef,
503 rule->GlyphCount - 1, rule->Class)
506 orig_used = gstring->used;
507 for (k = 0; k < rule->LookupCount; k++)
508 lookup_gsub (lookup_list,
509 rule->LookupRecord[k].LookupListIndex,
511 gidx + rule->LookupRecord[k].SequenceIndex);
512 gidx += rule->GlyphCount + (gstring->used - orig_used);
516 else /* subtable->Format == 3 */
518 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
522 if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
523 context3->Coverage + 1) < 0)
525 orig_used = gstring->used;
526 for (j = 0; j < context3->LookupCount; j++)
527 lookup_gsub (lookup_list,
528 context3->LookupRecord[j].LookupListIndex,
530 gidx + context3->LookupRecord[j].SequenceIndex);
531 gidx += context3->GlyphCount + (gstring->used - orig_used);
536 if (subtable->Format == 1)
538 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
539 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
543 for (j = 0; j < set->ChainRuleCount; j++)
545 OTF_ChainRule *rule = set->ChainRule + j;
547 if (gidx < rule->BacktrackGlyphCount
548 || (gidx + rule->InputGlyphCount
549 + rule->LookaheadGlyphCount) > gstring->used)
551 if (match_chain_ids (gstring, gidx, rule) < 0)
553 orig_used = gstring->used;
554 for (k = 0; k < rule->LookupCount; k++)
555 lookup_gsub (lookup_list,
556 rule->LookupRecord[k].LookupListIndex,
558 gidx + rule->LookupRecord[k].SequenceIndex);
559 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
563 else if (subtable->Format == 2)
565 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
566 OTF_ChainClassSet *set;
571 class = get_class_def (&context2->InputClassDef, g->glyph_id);
572 set = context2->ChainClassSet + class;
573 for (j = 0; j < set->ChainClassRuleCnt; j++)
575 OTF_ChainClassRule *rule = set->ChainClassRule + j;
578 if (gidx < rule->BacktrackGlyphCount
579 || (gidx + rule->InputGlyphCount
580 + rule->LookaheadGlyphCount) > gstring->used)
582 if (match_chain_classes (gstring, gidx,
583 &context2->BacktrackClassDef,
584 &context2->InputClassDef,
585 &context2->LookaheadClassDef,
588 orig_used = gstring->used;
589 for (k = 0; k < rule->LookupCount; k++)
590 lookup_gsub (lookup_list,
591 rule->LookupRecord[k].LookupListIndex,
593 gidx + rule->LookupRecord[k].SequenceIndex);
594 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
600 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
604 if (gidx < context3->BacktrackGlyphCount
605 || (gidx + context3->InputGlyphCount
606 + context3->LookaheadGlyphCount) > gstring->used)
608 if (match_chain_coverages (gstring, gidx, context3) < 0)
610 orig_used = gstring->used;
611 for (j = 0; j < context3->LookupCount; j++)
612 lookup_gsub (lookup_list,
613 context3->LookupRecord[j].LookupListIndex,
615 gidx + context3->LookupRecord[j].SequenceIndex);
616 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
622 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
623 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
624 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
627 if (back_gidx > gstring->used || ahead_gidx < 0)
630 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
631 if (get_coverage_index (reverse->Backtrack + j,
632 gstring->glyphs[gidx + 1 + j].glyph_id)
635 if (j < reverse->BacktrackGlyphCount)
637 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
638 if (get_coverage_index (reverse->LookAhead + j,
639 gstring->glyphs[gidx - 1 - j].glyph_id)
642 if (j < reverse->LookaheadGlyphCount)
644 g->glyph_id = reverse->Substitute[coverage_idx];
652 if (gidx == orig_gidx)
661 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
663 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
665 rec->XPlacement = anchor->XCoordinate;
666 rec->YPlacement = anchor->YCoordinate;
667 if (anchor->AnchorFormat == 1)
670 else if (anchor->AnchorFormat == 2)
671 /* Not yet implemented */
673 else if (anchor->AnchorFormat == 3)
674 /* Not yet implemented */
681 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
682 OTF_GlyphString *gstring, int gidx)
684 char *errfmt = "GPOS Looking up%s";
686 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
687 unsigned int flag = lookup->LookupFlag;
688 int orig_gidx = gidx;
689 OTF_Glyph *g = gstring->glyphs + gidx;
694 && (flag & (1 << g->GlyphClass))))
697 /* Try all subtables until one of them handles the current glyph. */
698 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
700 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
703 if (subtable->Coverage.offset)
705 coverage_idx = get_coverage_index (&subtable->Coverage,
707 if (coverage_idx < 0)
711 switch (lookup->LookupType)
714 g->positioning_type = lookup->LookupType;
715 if (subtable->Format == 1)
717 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
719 g->f.f1.format = single1->ValueFormat;
720 g->f.f1.value = &single1->Value;
722 else if (subtable->Format == 2)
724 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
726 g->f.f1.format = single2->ValueFormat;
727 g->f.f1.value = single2->Value + coverage_idx;
733 int next_gidx = gidx + 1;
736 while (next_gidx < gstring->used
737 && ! gstring->glyphs[next_gidx].glyph_id)
740 if (next_gidx >= gstring->used)
742 nextg = gstring->glyphs + next_gidx;
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++)
750 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
752 if (pair1->ValueFormat1)
754 g->positioning_type = lookup->LookupType;
755 g->f.f2.format = pair1->ValueFormat1;
756 g->f.f2.value = &set->PairValueRecord[j].Value1;
759 if (pair1->ValueFormat2)
761 nextg->positioning_type = lookup->LookupType;
762 nextg->f.f2.format = pair1->ValueFormat2;
763 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
769 else if (subtable->Format == 2)
771 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
772 unsigned class1, class2;
774 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
775 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
776 if (pair2->ValueFormat1)
778 g->positioning_type = lookup->LookupType;
779 g->f.f2.format = pair2->ValueFormat1;
781 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
784 if (pair2->ValueFormat2)
786 nextg->positioning_type = lookup->LookupType;
787 nextg->f.f2.format = pair2->ValueFormat2;
789 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
798 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
800 g->positioning_type = lookup->LookupType;
802 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
804 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
811 if (subtable->Format == 1)
813 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
814 OTF_MarkRecord *mark_record;
815 OTF_AnchorRecord *base_record;
816 int coverage_idx_base
817 = get_coverage_index (&mark_base1->BaseCoverage,
820 if (coverage_idx_base < 0)
822 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
824 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
825 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
827 = &base_record->Anchor[mark_record->Class];
828 g->positioning_type = lookup->LookupType;
836 if (subtable->Format == 1)
838 /* As the document of this lookup type is quite
839 ambiguous, and we can't know the exact procedure to
841 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
848 if (subtable->Format == 1)
850 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
851 OTF_MarkRecord *mark1_record;
852 OTF_AnchorRecord *mark2_record;
853 int coverage_idx_base
854 = get_coverage_index (&mark_mark1->Mark2Coverage,
857 if (coverage_idx_base < 0)
859 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
861 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
862 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
864 = &mark2_record->Anchor[mark1_record->Class];
865 g->positioning_type = lookup->LookupType;
871 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
875 if (subtable->Format == 1)
876 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
877 else if (subtable->Format == 2)
879 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
880 OTF_ChainClassSet *set;
885 class = get_class_def (&context2->InputClassDef, g->glyph_id);
886 set = context2->ChainClassSet + class;
887 for (j = 0; j < set->ChainClassRuleCnt; j++)
889 OTF_ChainClassRule *rule = set->ChainClassRule + j;
890 int fore_idx = gidx + rule->InputGlyphCount;
893 if (gidx < rule->BacktrackGlyphCount
894 || (gidx + rule->InputGlyphCount
895 + rule->LookaheadGlyphCount) > gstring->used)
897 for (k = 0; k < rule->BacktrackGlyphCount; k++)
898 if (get_class_def (&context2->BacktrackClassDef,
899 gstring->glyphs[gidx - 1 - k].glyph_id)
900 != rule->Backtrack[k])
902 if (k < rule->BacktrackGlyphCount)
904 for (k = 1; k < rule->InputGlyphCount; k++)
905 if (get_class_def (&context2->InputClassDef,
906 gstring->glyphs[gidx + k].glyph_id)
907 != rule->Input[k - 1])
909 if (k < rule->InputGlyphCount)
911 for (k = 0; k < rule->LookaheadGlyphCount; k++)
912 if (get_class_def (&context2->LookaheadClassDef,
913 gstring->glyphs[fore_idx + k].glyph_id)
914 != rule->LookAhead[k])
916 if (k < rule->LookaheadGlyphCount)
919 orig_used = gstring->used;
920 for (k = 0; k < rule->LookupCount; k++)
921 lookup_gpos (lookup_list,
922 rule->LookupRecord[k].LookupListIndex,
924 gidx + rule->LookupRecord[k].SequenceIndex);
925 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
929 else if (subtable->Format == 3)
930 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
932 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
936 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
943 if (gidx == orig_gidx)
949 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
953 for (i = 0; i < gstring->used; i++)
955 c = gstring->glyphs[i].c;
956 if (c < 0 || c >= 256)
957 gstring->glyphs[i].glyph_id = 0;
959 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
965 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
971 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
974 int segCount = sub4->segCountX2 / 2;
976 for (i = 0; i < gstring->used; i++)
978 c = gstring->glyphs[i].c;
980 gstring->glyphs[i].glyph_id = 0;
981 for (j = 0; j < segCount; j++)
983 OTF_cmapSegument *seg = sub4->segments + i;
985 if (c >= seg->startCount && c <= seg->endCount)
987 if (seg->idRangeOffset == 0xFFFF)
988 gstring->glyphs[i].glyph_id = c + seg->idDelta;
990 gstring->glyphs[i].glyph_id
991 = sub4->glyphIdArray[seg->idRangeOffset
992 + (c - seg->startCount)];
1002 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1008 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1014 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1020 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1030 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1036 && OTF_get_table (otf, "cmap") < 0)
1040 for (i = 0; i < gstring->used; i++)
1041 if (! gstring->glyphs[i].glyph_id)
1043 int c = gstring->glyphs[i].c;
1044 if (c < 32 || ! cmap->unicode_table)
1045 gstring->glyphs[i].glyph_id = 0;
1047 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1054 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1055 int platform_id, int encoding_id)
1059 char *errfmt = "CMAP Looking up%s";
1061 OTF_EncodingRecord *enc;
1064 && OTF_get_table (otf, "cmap") < 0)
1068 for (i = 0; i < cmap->numTables; i++)
1069 if (cmap->EncodingRecord[i].platformID == platform_id
1070 && cmap->EncodingRecord[i].encodingID == encoding_id)
1072 if (i == cmap->numTables)
1073 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1074 enc = cmap->EncodingRecord + i;
1075 switch (enc->subtable.format)
1077 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1078 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1079 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1080 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1081 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1082 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1083 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1085 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1090 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1093 && OTF_get_table (otf, "cmap") < 0)
1096 || code > otf->cmap->max_glyph_id
1097 || ! otf->cmap->decode_table)
1099 return otf->cmap->decode_table[code];
1103 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1109 && OTF_get_table (otf, "GDEF") < 0)
1113 if (gdef->glyph_class_def.offset)
1114 for (i = 0; i < gstring->used; i++)
1115 gstring->glyphs[i].GlyphClass
1116 = get_class_def (&gdef->glyph_class_def,
1117 gstring->glyphs[i].glyph_id);
1119 if (gdef->mark_attach_class_def.offset)
1120 for (i = 0; i < gstring->used; i++)
1121 gstring->glyphs[i].MarkAttachClass
1122 = get_class_def (&gdef->mark_attach_class_def,
1123 gstring->glyphs[i].glyph_id);
1130 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1131 char *script, char *language, char *features)
1133 char *errfmt = "GSUB driving%s";
1136 OTF_LangSys *LangSys;
1137 int *lookup_indices;
1141 && OTF_get_table (otf, "GSUB") < 0)
1144 if (gsub->FeatureList.FeatureCount == 0
1145 || gsub->LookupList.LookupCount == 0)
1148 LangSys = get_langsys (&gsub->ScriptList, script, language);
1152 /* One lookup may be used by multiple features. */
1153 lookup_indices = alloca (sizeof (int)
1154 * gsub->LookupList.LookupCount
1155 * (gsub->FeatureList.FeatureCount + 1));
1156 if (! lookup_indices)
1157 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1158 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1159 features, lookup_indices);
1163 for (i = 0; i < n; i++)
1165 int index = lookup_indices[i];
1168 if (gsub->LookupList.Lookup[index].LookupType != 8)
1171 while (gidx < gstring->used)
1173 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1180 gidx = gstring->used - 1;
1183 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1194 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1195 char *script, char *language, char *features)
1197 char *errfmt = "GPOS driving%s";
1200 OTF_LangSys *LangSys;
1201 int *lookup_indices;
1205 && OTF_get_table (otf, "GPOS") < 0)
1208 if (gpos->FeatureList.FeatureCount == 0
1209 || gpos->LookupList.LookupCount == 0)
1212 LangSys = get_langsys (&gpos->ScriptList, script, language);
1216 /* One lookup may be used by multiple features. */
1217 lookup_indices = alloca (sizeof (int)
1218 * gpos->LookupList.LookupCount
1219 * (gpos->FeatureList.FeatureCount + 1));
1220 if (! lookup_indices)
1221 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1222 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1223 features, lookup_indices);
1227 for (i = 0; i < n; i++)
1229 int index = lookup_indices[i];
1232 while (gidx < gstring->used)
1234 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1244 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1245 char *script, char *language,
1246 char *gsub_features, char *gpos_features)
1248 if (OTF_drive_cmap (otf, gstring) < 0)
1250 if (OTF_drive_gdef (otf, gstring) < 0)
1253 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1256 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)