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 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)
659 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
661 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
663 rec->XPlacement = anchor->XCoordinate;
664 rec->YPlacement = anchor->YCoordinate;
665 if (anchor->AnchorFormat == 1)
668 else if (anchor->AnchorFormat == 2)
669 /* Not yet implemented */
671 else if (anchor->AnchorFormat == 3)
672 /* Not yet implemented */
679 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
680 OTF_GlyphString *gstring, int gidx)
682 char *errfmt = "GPOS Looking up%s";
684 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
685 unsigned int flag = lookup->LookupFlag;
686 int orig_gidx = gidx;
687 OTF_Glyph *g = gstring->glyphs + gidx;
692 && (flag & (1 << g->GlyphClass))))
695 /* Try all subtables until one of them handles the current glyph. */
696 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
698 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
701 if (subtable->Coverage.offset)
703 coverage_idx = get_coverage_index (&subtable->Coverage,
705 if (coverage_idx < 0)
709 switch (lookup->LookupType)
712 g->positioning_type = lookup->LookupType;
713 if (subtable->Format == 1)
715 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
717 g->f.f1.format = single1->ValueFormat;
718 g->f.f1.value = &single1->Value;
720 else if (subtable->Format == 2)
722 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
724 g->f.f1.format = single2->ValueFormat;
725 g->f.f1.value = single2->Value + coverage_idx;
730 if (gidx + 1 >= gstring->used)
732 if (subtable->Format == 1)
734 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
735 OTF_PairSet *set = pair1->PairSet + coverage_idx;
738 for (j = 0; j < set->PairValueCount; j++)
740 if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
743 g->positioning_type = lookup->LookupType;
744 g->f.f2.format = pair1->ValueFormat1;
745 g->f.f2.value = &set->PairValueRecord[j].Value1;
746 if (pair1->ValueFormat2)
749 g->positioning_type = lookup->LookupType;
750 g->f.f2.format = pair1->ValueFormat2;
751 g->f.f2.value = &set->PairValueRecord[j].Value2;
755 else if (subtable->Format == 2)
757 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
758 unsigned class1, class2;
761 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
762 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
763 g->positioning_type = lookup->LookupType;
764 g->f.f2.format = pair2->ValueFormat1;
766 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
767 if (pair2->ValueFormat2)
770 g->positioning_type = lookup->LookupType;
771 g->f.f2.format = pair2->ValueFormat2;
773 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
780 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
782 g->positioning_type = lookup->LookupType;
784 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
786 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
793 if (subtable->Format == 1)
795 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
796 OTF_MarkRecord *mark_record;
797 OTF_AnchorRecord *base_record;
798 int coverage_idx_base
799 = get_coverage_index (&mark_base1->BaseCoverage,
802 if (coverage_idx_base < 0)
804 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
806 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
807 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
809 = &base_record->Anchor[mark_record->Class];
810 g->positioning_type = lookup->LookupType;
818 if (subtable->Format == 1)
820 /* As the document of this lookup type is quite
821 ambiguous, and we can't know the exact procedure to
823 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
830 if (subtable->Format == 1)
832 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
833 OTF_MarkRecord *mark1_record;
834 OTF_AnchorRecord *mark2_record;
835 int coverage_idx_base
836 = get_coverage_index (&mark_mark1->Mark2Coverage,
839 if (coverage_idx_base < 0)
841 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
843 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
844 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
846 = &mark2_record->Anchor[mark1_record->Class];
847 g->positioning_type = lookup->LookupType;
853 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
857 if (subtable->Format == 1)
858 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
859 else if (subtable->Format == 2)
861 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
862 OTF_ChainClassSet *set;
867 class = get_class_def (&context2->InputClassDef, g->glyph_id);
868 set = context2->ChainClassSet + class;
869 for (j = 0; j < set->ChainClassRuleCnt; j++)
871 OTF_ChainClassRule *rule = set->ChainClassRule + j;
872 int fore_idx = gidx + rule->InputGlyphCount;
875 if (gidx < rule->BacktrackGlyphCount
876 || (gidx + rule->InputGlyphCount
877 + rule->LookaheadGlyphCount) > gstring->used)
879 for (k = 0; k < rule->BacktrackGlyphCount; k++)
880 if (get_class_def (&context2->BacktrackClassDef,
881 gstring->glyphs[gidx - 1 - k].glyph_id)
882 != rule->Backtrack[k])
884 if (k < rule->BacktrackGlyphCount)
886 for (k = 1; k < rule->InputGlyphCount; k++)
887 if (get_class_def (&context2->InputClassDef,
888 gstring->glyphs[gidx + k].glyph_id)
889 != rule->Input[k - 1])
891 if (k < rule->InputGlyphCount)
893 for (k = 0; k < rule->LookaheadGlyphCount; k++)
894 if (get_class_def (&context2->LookaheadClassDef,
895 gstring->glyphs[fore_idx + k].glyph_id)
896 != rule->LookAhead[k])
898 if (k < rule->LookaheadGlyphCount)
901 orig_used = gstring->used;
902 for (k = 0; k < rule->LookupCount; k++)
903 lookup_gpos (lookup_list,
904 rule->LookupRecord[k].LookupListIndex,
906 gidx + rule->LookupRecord[k].SequenceIndex);
907 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
911 else if (subtable->Format == 3)
912 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
914 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
918 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
925 if (gidx == orig_gidx)
931 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
935 for (i = 0; i < gstring->used; i++)
937 c = gstring->glyphs[i].c;
938 if (c < 0 || c >= 256)
939 gstring->glyphs[i].glyph_id = 0;
941 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
947 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
953 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
956 int segCount = sub4->segCountX2 / 2;
958 for (i = 0; i < gstring->used; i++)
960 c = gstring->glyphs[i].c;
962 gstring->glyphs[i].glyph_id = 0;
963 for (j = 0; j < segCount; j++)
965 OTF_cmapSegument *seg = sub4->segments + i;
967 if (c >= seg->startCount && c <= seg->endCount)
969 if (seg->idRangeOffset == 0xFFFF)
970 gstring->glyphs[i].glyph_id = c + seg->idDelta;
972 gstring->glyphs[i].glyph_id
973 = sub4->glyphIdArray[seg->idRangeOffset
974 + (c - seg->startCount)];
984 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
990 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
996 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1002 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1012 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1018 && OTF_get_table (otf, "cmap") < 0)
1022 for (i = 0; i < gstring->used; i++)
1023 if (! gstring->glyphs[i].glyph_id)
1025 int c = gstring->glyphs[i].c;
1026 if (c < 32 || ! cmap->unicode_table)
1027 gstring->glyphs[i].glyph_id = 0;
1029 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1036 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1037 int platform_id, int encoding_id)
1041 char *errfmt = "CMAP Looking up%s";
1043 OTF_EncodingRecord *enc;
1046 && OTF_get_table (otf, "cmap") < 0)
1050 for (i = 0; i < cmap->numTables; i++)
1051 if (cmap->EncodingRecord[i].platformID == platform_id
1052 && cmap->EncodingRecord[i].encodingID == encoding_id)
1054 if (i == cmap->numTables)
1055 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1056 enc = cmap->EncodingRecord + i;
1057 switch (enc->subtable.format)
1059 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1060 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1061 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1062 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1063 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1064 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1065 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1067 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1072 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1075 && OTF_get_table (otf, "cmap") < 0)
1078 || code > otf->cmap->max_glyph_id
1079 || ! otf->cmap->decode_table)
1081 return otf->cmap->decode_table[code];
1085 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1091 && OTF_get_table (otf, "GDEF") < 0)
1095 if (gdef->glyph_class_def.offset)
1096 for (i = 0; i < gstring->used; i++)
1097 gstring->glyphs[i].GlyphClass
1098 = get_class_def (&gdef->glyph_class_def,
1099 gstring->glyphs[i].glyph_id);
1101 if (gdef->mark_attach_class_def.offset)
1102 for (i = 0; i < gstring->used; i++)
1103 gstring->glyphs[i].MarkAttachClass
1104 = get_class_def (&gdef->mark_attach_class_def,
1105 gstring->glyphs[i].glyph_id);
1112 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1113 char *script, char *language, char *features)
1115 char *errfmt = "GSUB driving%s";
1118 OTF_LangSys *LangSys;
1119 int *lookup_indices;
1123 && OTF_get_table (otf, "GSUB") < 0)
1126 if (gsub->FeatureList.FeatureCount == 0
1127 || gsub->LookupList.LookupCount == 0)
1130 LangSys = get_langsys (&gsub->ScriptList, script, language);
1134 /* One lookup may be used by multiple features. */
1135 lookup_indices = alloca (sizeof (int)
1136 * gsub->LookupList.LookupCount
1137 * (gsub->FeatureList.FeatureCount + 1));
1138 if (! lookup_indices)
1139 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1140 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1141 features, lookup_indices);
1145 for (i = 0; i < n; i++)
1147 int index = lookup_indices[i];
1150 if (gsub->LookupList.Lookup[index].LookupType != 8)
1153 while (gidx < gstring->used)
1155 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1162 gidx = gstring->used - 1;
1165 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1176 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1177 char *script, char *language, char *features)
1179 char *errfmt = "GPOS driving%s";
1182 OTF_LangSys *LangSys;
1183 int *lookup_indices;
1187 && OTF_get_table (otf, "GPOS") < 0)
1190 if (gpos->FeatureList.FeatureCount == 0
1191 || gpos->LookupList.LookupCount == 0)
1194 LangSys = get_langsys (&gpos->ScriptList, script, language);
1198 /* One lookup may be used by multiple features. */
1199 lookup_indices = alloca (sizeof (int)
1200 * gpos->LookupList.LookupCount
1201 * (gpos->FeatureList.FeatureCount + 1));
1202 if (! lookup_indices)
1203 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1204 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1205 features, lookup_indices);
1209 for (i = 0; i < n; i++)
1211 int index = lookup_indices[i];
1214 while (gidx < gstring->used)
1216 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1226 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1227 char *script, char *language,
1228 char *gsub_features, char *gpos_features)
1230 if (OTF_drive_cmap (otf, gstring) < 0)
1232 if (OTF_drive_gdef (otf, gstring) < 0)
1235 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1238 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)