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 /* Return nonzero (-1 if ID is zero, 1 otherwise) if OTF_Glyph *G
33 should be ignored according to LookupFlag FLAG. */
34 #define IGNORED_GLYPH(g, flag) \
35 ((g)->glyph_id == 0 ? -1 \
36 : (((flag) & (1 << (g)->GlyphClass)) \
37 || (((flag) & OTF_MarkAttachmentType) \
38 && (g)->GlyphClass == OTF_GlyphClassMark \
39 && ((flag) >> 8) != (g)->MarkAttachClass)))
41 #define GSTRING_DELETE(gstring, from, len) \
43 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
44 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
45 gstring->used -= len; \
49 #define GSTRING_INSERT(gstring, pos, len) \
51 if (gstring->used + len > gstring->size) \
53 char *errfmt = "GSTRING%s"; \
55 gstring->size = gstring->used + len; \
57 = (OTF_Glyph *) realloc (gstring->glyphs, \
58 sizeof (OTF_Glyph) * gstring->size); \
59 if (! gstring->glyphs) \
60 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
62 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
63 sizeof (OTF_Glyph) * (gstring->used - pos)); \
64 gstring->used += len; \
68 static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID);
71 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
72 OTF_GlyphID *ids, int num)
77 int from_idx = gstring->glyphs[from].f.index.from;
78 int to_idx = gstring->glyphs[to - 1].f.index.to;
81 for (i = non_ignored_idx = to - 1; i >= from; i--)
83 OTF_Glyph *g = gstring->glyphs + i;
85 if (IGNORED_GLYPH (g, flag) == 1)
87 /* Move this glyph to the next of the current target of
91 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
92 temp.f.index.from = from_idx;
93 temp.f.index.to = to_idx;
94 gstring->glyphs[non_ignored_idx--] = temp;
100 GSTRING_INSERT (gstring, from, (num - len));
102 GSTRING_DELETE (gstring, from, (len - num));
103 for (i = 0; i < num; i++)
105 if (gstring->glyphs[from + i].glyph_id != ids[i])
107 gstring->glyphs[from + i].c = 0;
109 gstring->glyphs[from + i].GlyphClass
110 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
112 gstring->glyphs[from + i].GlyphClass = 0;
114 gstring->glyphs[from + i].glyph_id = ids[i];
115 gstring->glyphs[from + i].positioning_type = 0;
116 gstring->glyphs[from + i].f.index.from = from_idx;
117 gstring->glyphs[from + i].f.index.to = to_idx;
124 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
128 if (coverage->CoverageFormat == 1)
130 for (i = 0; i < coverage->Count; i++)
131 if (coverage->table.GlyphArray[i] == id)
136 for (i = 0; i < coverage->Count; i++)
137 if (coverage->table.RangeRecord[i].Start <= id
138 && coverage->table.RangeRecord[i].End >= id)
139 return (coverage->table.RangeRecord[i].StartCoverageIndex
140 + (id - coverage->table.RangeRecord[i].Start));
146 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
148 if (class_def->ClassFormat == 1)
150 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
152 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
153 return class_def->f.f1.ClassValueArray[idx];
159 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
160 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
161 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
162 return class_def->f.f2.ClassRangeRecord[i].Class;
168 get_langsys (OTF_ScriptList *script_list,
169 const char *script, const char *language)
172 OTF_Tag script_tag = OTF_tag (script);
173 OTF_Tag langsys_tag = OTF_tag (language);
175 OTF_Tag dflt_tag = OTF_tag ("DFLT");
176 OTF_Script *dflt = NULL;
178 for (i = 0; i < script_list->ScriptCount; i++)
180 OTF_Script *script = script_list->Script + i;
182 if (script_list->Script[i].ScriptTag == dflt_tag)
184 if (script_list->Script[i].ScriptTag == script_tag)
187 return &script->DefaultLangSys;
188 for (j = 0; j < script->LangSysCount; j++)
189 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
190 return script->LangSys + j;
191 return &script->DefaultLangSys;
196 dflt = script_list->Script;
198 return &dflt->DefaultLangSys;
199 for (j = 0; j < dflt->LangSysCount; j++)
200 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
201 return dflt->LangSys + j;
202 return &dflt->DefaultLangSys;
206 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
207 OTF_LangSys *LangSys,
208 const char *features, int *lookup_indices)
211 OTF_Feature *feature;
212 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
214 for (i = 0; i < FeatureList->FeatureCount; i++)
215 feature_table[i] = 0;
223 if (*features == '*')
225 /* Consume all remaining features. */
226 for (i = 0; i < LangSys->FeatureCount; i++)
228 int index = LangSys->FeatureIndex[i];
230 if (! feature_table[index])
232 feature = FeatureList->Feature + index;
233 for (j = 0; j < feature->LookupCount; j++)
234 lookup_indices[n++] = feature->LookupListIndex[j];
240 if (*features == '~')
241 use_it = -1, features++;
242 for (i = 0; *features && *features != ','; i++, features++)
243 tagname[i] = *features;
249 tag = OTF_tag (tagname);
250 for (i = 0; i < LangSys->FeatureCount; i++)
252 feature = FeatureList->Feature + LangSys->FeatureIndex[i];
253 if (tag == feature->FeatureTag)
255 if (feature_table[i])
258 for (j = 0; j < feature->LookupCount; j++)
259 lookup_indices[n++] = feature->LookupListIndex[j];
260 feature_table[i] = use_it;
270 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
271 int count, OTF_GlyphID *ids)
273 OTF_Glyph *gbeg = gstring->glyphs + gidx;
274 OTF_Glyph *gend = gstring->glyphs + gstring->used;
278 for (g = gbeg, i = 0; g < gend && i < count; g++)
279 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
281 return (i < count ? -1 : g - gbeg);
285 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
288 int i = rule->BacktrackGlyphCount;
295 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
296 if (! IGNORED_GLYPH (g, flag) && --i == 0)
300 if (match_ids (gstring, j, flag,
301 rule->BacktrackGlyphCount, rule->Backtrack)
306 i = match_ids (gstring, gidx, flag,
307 rule->InputGlyphCount - 1, rule->Input);
311 i = match_ids (gstring, gidx, flag,
312 rule->LookaheadGlyphCount, rule->LookAhead);
319 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
320 int flag, int count, unsigned *classes)
322 OTF_Glyph *gbeg = gstring->glyphs + gidx;
323 OTF_Glyph *gend = gstring->glyphs + gstring->used;
327 for (g = gbeg, i = 0; g < gend && i < count; g++)
328 if (! IGNORED_GLYPH (g, flag)
329 && get_class_def (class_def, g->glyph_id) != classes[i++])
331 return (i < count ? -1 : g - gbeg);
335 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
336 OTF_ClassDef *BacktrackClassDef,
337 OTF_ClassDef *InputClassDef,
338 OTF_ClassDef *LookaheadClassDef,
339 OTF_ChainClassRule *rule)
341 int i = rule->BacktrackGlyphCount;
348 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
349 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
353 if (match_classes (BacktrackClassDef, gstring, j, flag,
354 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
358 i = match_classes (InputClassDef, gstring, gidx, flag,
359 rule->InputGlyphCount - 1, rule->Input);
363 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
364 rule->LookaheadGlyphCount, rule->LookAhead);
372 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
373 OTF_Coverage *coverages)
375 OTF_Glyph *gbeg = gstring->glyphs + gidx;
376 OTF_Glyph *gend = gstring->glyphs + gstring->used;
380 for (g = gbeg, i = 0; g < gend && i < count; g++)
381 if (! IGNORED_GLYPH (g, flag)
382 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
384 return (i < count ? -1 : g - gbeg);
388 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
389 OTF_GSUB_ChainContext3 *context3)
391 int i = context3->BacktrackGlyphCount;
398 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
399 if (! IGNORED_GLYPH (g, flag) && --i == 0)
403 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
404 context3->Backtrack) < 0)
408 if (context3->InputGlyphCount > 1)
410 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
411 context3->Input + 1);
416 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
417 context3->LookAhead) < 0)
423 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
424 OTF_GlyphString *gstring, int gidx, int alternate_subst)
426 char *errfmt = "GSUB Looking up%s";
428 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
429 unsigned int flag = (lookup->LookupFlag
430 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
431 int orig_gidx = gidx;
432 OTF_Glyph *g = gstring->glyphs + gidx;
435 if (IGNORED_GLYPH (g, flag))
438 /* Try all subtables until one of them handles the current glyph. */
439 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
441 unsigned lookup_type = lookup->LookupType;
442 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
445 if (lookup_type == 7)
447 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
449 lookup_type = extension1->ExtensionLookupType;
450 subtable = extension1->ExtensionSubtable;
454 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
455 : (lookup_type == 3))
458 if (subtable->Coverage.offset)
460 coverage_idx = get_coverage_index (&subtable->Coverage,
462 if (coverage_idx < 0)
469 if (subtable->Format == 1)
470 g->glyph_id += subtable->u.single1.DeltaGlyphID;
472 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
477 if (subtable->Format == 1)
479 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
480 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
482 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
483 seq->Substitute, seq->GlyphCount);
484 gidx += seq->GlyphCount;
487 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
491 if (subtable->Format == 1)
493 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
494 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
496 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
497 altset->Alternate, altset->GlyphCount);
498 gidx += altset->GlyphCount;;
501 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
505 if (subtable->Format == 1)
507 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
508 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
512 for (j = 0; j < ligset->LigatureCount; j++)
516 lig = ligset->Ligature + j;
517 n = match_ids (gstring, gidx + 1, flag,
518 lig->CompCount - 1, lig->Component);
521 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
528 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
532 if (subtable->Format == 1)
534 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
535 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
540 for (j = 0; j < set->RuleCount; j++)
542 rule = set->Rule + j;
543 if (match_ids (gstring, gidx + 1, flag,
544 rule->GlyphCount - 1, rule->Input) < 0)
546 orig_used = gstring->used;
547 for (k = 0; k < rule->LookupCount; k++)
548 lookup_gsub (otf, lookup_list,
549 rule->LookupRecord[k].LookupListIndex,
551 gidx + rule->LookupRecord[k].SequenceIndex,
553 gidx += rule->GlyphCount + (gstring->used - orig_used);
557 else if (subtable->Format == 2)
559 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
566 class = get_class_def (&context2->ClassDef, g->glyph_id);
567 set = context2->ClassSet + class;
569 for (j = 0; j < set->ClassRuleCnt; j++)
571 rule = set->ClassRule + j;
572 if (match_classes (&context2->ClassDef,
573 gstring, gidx + 1, flag,
574 rule->GlyphCount - 1, rule->Class)
577 orig_used = gstring->used;
578 for (k = 0; k < rule->LookupCount; k++)
579 lookup_gsub (otf, lookup_list,
580 rule->LookupRecord[k].LookupListIndex,
582 gidx + rule->LookupRecord[k].SequenceIndex,
584 gidx += rule->GlyphCount + (gstring->used - orig_used);
588 else /* subtable->Format == 3 */
590 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
594 if (match_coverages (gstring, gidx + 1, flag,
595 context3->GlyphCount - 1,
596 context3->Coverage + 1) < 0)
598 orig_used = gstring->used;
599 for (j = 0; j < context3->LookupCount; j++)
600 lookup_gsub (otf, lookup_list,
601 context3->LookupRecord[j].LookupListIndex,
603 gidx + context3->LookupRecord[j].SequenceIndex,
605 gidx += context3->GlyphCount + (gstring->used - orig_used);
610 if (subtable->Format == 1)
612 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
613 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
617 for (j = 0; j < set->ChainRuleCount; j++)
619 OTF_ChainRule *rule = set->ChainRule + j;
621 if (gidx < rule->BacktrackGlyphCount
622 || (gidx + rule->InputGlyphCount
623 + rule->LookaheadGlyphCount) > gstring->used)
625 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
627 orig_used = gstring->used;
628 for (k = 0; k < rule->LookupCount; k++)
629 lookup_gsub (otf, lookup_list,
630 rule->LookupRecord[k].LookupListIndex,
632 gidx + rule->LookupRecord[k].SequenceIndex,
634 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
638 else if (subtable->Format == 2)
640 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
641 OTF_ChainClassSet *set;
646 class = get_class_def (&context2->InputClassDef, g->glyph_id);
647 set = context2->ChainClassSet + class;
648 for (j = 0; j < set->ChainClassRuleCnt; j++)
650 OTF_ChainClassRule *rule = set->ChainClassRule + j;
653 if (gidx < rule->BacktrackGlyphCount
654 || (gidx + rule->InputGlyphCount
655 + rule->LookaheadGlyphCount) > gstring->used)
657 if (match_chain_classes (gstring, gidx, flag,
658 &context2->BacktrackClassDef,
659 &context2->InputClassDef,
660 &context2->LookaheadClassDef,
663 orig_used = gstring->used;
664 for (k = 0; k < rule->LookupCount; k++)
665 lookup_gsub (otf, lookup_list,
666 rule->LookupRecord[k].LookupListIndex,
668 gidx + rule->LookupRecord[k].SequenceIndex,
670 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
676 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
680 if (gidx < context3->BacktrackGlyphCount
681 || (gidx + context3->InputGlyphCount
682 + context3->LookaheadGlyphCount) > gstring->used)
684 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
686 orig_used = gstring->used;
687 for (j = 0; j < context3->LookupCount; j++)
688 lookup_gsub (otf, lookup_list,
689 context3->LookupRecord[j].LookupListIndex,
691 gidx + context3->LookupRecord[j].SequenceIndex,
693 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
699 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
700 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
701 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
704 if (back_gidx > gstring->used || ahead_gidx < 0)
707 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
708 if (get_coverage_index (reverse->Backtrack + j,
709 gstring->glyphs[gidx + 1 + j].glyph_id)
712 if (j < reverse->BacktrackGlyphCount)
714 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
715 if (get_coverage_index (reverse->LookAhead + j,
716 gstring->glyphs[gidx - 1 - j].glyph_id)
719 if (j < reverse->LookaheadGlyphCount)
721 g->glyph_id = reverse->Substitute[coverage_idx];
729 if (gidx == orig_gidx)
738 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
740 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
742 rec->XPlacement = anchor->XCoordinate;
743 rec->YPlacement = anchor->YCoordinate;
744 if (anchor->AnchorFormat == 1)
747 else if (anchor->AnchorFormat == 2)
748 /* Not yet implemented */
750 else if (anchor->AnchorFormat == 3)
751 /* Not yet implemented */
758 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
759 OTF_GlyphString *gstring, int gidx)
761 char *errfmt = "GPOS Looking up%s";
763 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
764 unsigned int flag = (lookup->LookupFlag
765 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
766 int orig_gidx = gidx;
767 OTF_Glyph *g = gstring->glyphs + gidx;
770 if (IGNORED_GLYPH (g, flag)
771 || (0 & g->positioning_type))
774 /* Try all subtables until one of them handles the current glyph. */
775 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
777 unsigned lookup_type = lookup->LookupType;
778 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
781 if (lookup_type == 9)
783 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
785 lookup_type = extension1->ExtensionLookupType;
786 subtable = extension1->ExtensionSubtable;
789 if (subtable->Coverage.offset)
791 coverage_idx = get_coverage_index (&subtable->Coverage,
793 if (coverage_idx < 0)
800 g->positioning_type = lookup_type;
801 if (subtable->Format == 1)
803 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
805 g->f.f1.format = single1->ValueFormat;
806 g->f.f1.value = &single1->Value;
808 else if (subtable->Format == 2)
810 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
812 g->f.f1.format = single2->ValueFormat;
813 g->f.f1.value = single2->Value + coverage_idx;
822 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
823 next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
824 next_gidx++, nextg++);
826 if (next_gidx >= gstring->used
827 || nextg->positioning_type)
829 if (subtable->Format == 1)
831 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
832 OTF_PairSet *set = pair1->PairSet + coverage_idx;
835 for (j = 0; j < set->PairValueCount; j++)
836 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
838 if (pair1->ValueFormat1)
840 g->positioning_type = lookup_type;
841 g->f.f2.format = pair1->ValueFormat1;
842 g->f.f2.value = &set->PairValueRecord[j].Value1;
845 if (pair1->ValueFormat2)
847 nextg->positioning_type = lookup_type;
848 nextg->f.f2.format = pair1->ValueFormat2;
849 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
855 else if (subtable->Format == 2)
857 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
858 unsigned class1, class2;
860 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
861 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
862 if (pair2->ValueFormat1)
864 g->positioning_type = lookup_type;
865 g->f.f2.format = pair2->ValueFormat1;
867 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
870 if (pair2->ValueFormat2)
872 nextg->positioning_type = lookup_type;
873 nextg->f.f2.format = pair2->ValueFormat2;
875 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
884 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
886 g->positioning_type = lookup_type;
888 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
890 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
897 if (subtable->Format == 1)
899 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
900 OTF_MarkRecord *mark_record;
901 OTF_AnchorRecord *base_record;
903 int coverage_idx_base;
904 unsigned int this_flag = flag | OTF_IgnoreMarks;
907 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
909 if (baseg < gstring->glyphs)
912 = get_coverage_index (&mark_base1->BaseCoverage,
914 if (coverage_idx_base < 0)
916 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
918 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
919 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
921 = &base_record->Anchor[mark_record->Class];
922 g->positioning_type = lookup_type;
929 if (subtable->Format == 1)
931 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
933 int coverage_idx_lig;
934 OTF_MarkRecord *mark_record;
935 OTF_LigatureAttach *attach;
936 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
939 for (j = 0; j < mark_lig1->ClassCount; j++)
943 (ligg >= gstring->glyphs
944 && (IGNORED_GLYPH (ligg, flag)
945 || ligg->GlyphClass > OTF_GlyphClassLigature));
947 if (ligg->positioning_type == 5
948 && ligg->MarkAttachClass < mark_lig1->ClassCount)
949 num_class[ligg->MarkAttachClass]++;
950 if (ligg < gstring->glyphs)
953 = get_coverage_index (&mark_lig1->LigatureCoverage,
955 if (coverage_idx_lig < 0)
957 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
958 g->MarkAttachClass = mark_record->Class;
959 attach = (mark_lig1->LigatureArray.LigatureAttach
961 for (j = 0; j < attach->ComponentCount; j++)
963 OTF_Anchor *lig_anchor
964 = attach->ComponentRecord[j].LigatureAnchor;
966 if (lig_anchor[mark_record->Class].AnchorFormat
967 && num_class[mark_record->Class]-- == 0)
969 g->positioning_type = lookup_type;
970 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
971 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
981 if (subtable->Format == 1)
983 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
984 OTF_MarkRecord *mark1_record;
985 OTF_AnchorRecord *mark2_record;
987 int coverage_idx_base;
990 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
992 if (prevg < gstring->glyphs)
995 = get_coverage_index (&mark_mark1->Mark2Coverage,
997 if (coverage_idx_base < 0)
999 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
1001 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
1002 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
1003 g->f.f6.mark2_anchor
1004 = &mark2_record->Anchor[mark1_record->Class];
1005 g->positioning_type = lookup_type;
1011 if (subtable->Format == 1)
1013 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1014 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1019 for (j = 0; j < set->RuleCount; j++)
1021 rule = set->Rule + j;
1022 if (match_ids (gstring, gidx + 1, flag,
1023 rule->GlyphCount - 1, rule->Input) < 0)
1025 orig_used = gstring->used;
1026 for (k = 0; k < rule->LookupCount; k++)
1027 lookup_gpos (lookup_list,
1028 rule->LookupRecord[k].LookupListIndex,
1030 gidx + rule->LookupRecord[k].SequenceIndex);
1031 gidx += rule->GlyphCount + (gstring->used - orig_used);
1035 else if (subtable->Format == 2)
1037 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1039 OTF_ClassRule *rule;
1044 class = get_class_def (&context2->ClassDef, g->glyph_id);
1045 set = context2->ClassSet + class;
1047 for (j = 0; j < set->ClassRuleCnt; j++)
1049 rule = set->ClassRule + j;
1050 if (match_classes (&context2->ClassDef,
1051 gstring, gidx + 1, flag,
1052 rule->GlyphCount - 1, rule->Class)
1055 orig_used = gstring->used;
1056 for (k = 0; k < rule->LookupCount; k++)
1057 lookup_gpos (lookup_list,
1058 rule->LookupRecord[k].LookupListIndex,
1060 gidx + rule->LookupRecord[k].SequenceIndex);
1061 gidx += rule->GlyphCount + (gstring->used - orig_used);
1065 else /* subtable->Format == 3 */
1067 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1071 if (match_coverages (gstring, gidx + 1, flag,
1072 context3->GlyphCount - 1,
1073 context3->Coverage + 1) < 0)
1075 orig_used = gstring->used;
1076 for (j = 0; j < context3->LookupCount; j++)
1077 lookup_gpos (lookup_list,
1078 context3->LookupRecord[j].LookupListIndex,
1080 gidx + context3->LookupRecord[j].SequenceIndex);
1081 gidx += context3->GlyphCount + (gstring->used - orig_used);
1086 if (subtable->Format == 1)
1088 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1089 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1093 for (j = 0; j < set->ChainRuleCount; j++)
1095 OTF_ChainRule *rule = set->ChainRule + j;
1097 if (gidx < rule->BacktrackGlyphCount
1098 || (gidx + rule->InputGlyphCount
1099 + rule->LookaheadGlyphCount) > gstring->used)
1101 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1103 orig_used = gstring->used;
1104 for (k = 0; k < rule->LookupCount; k++)
1105 lookup_gpos (lookup_list,
1106 rule->LookupRecord[k].LookupListIndex,
1108 gidx + rule->LookupRecord[k].SequenceIndex);
1109 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1113 else if (subtable->Format == 2)
1115 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1116 OTF_ChainClassSet *set;
1121 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1122 set = context2->ChainClassSet + class;
1123 for (j = 0; j < set->ChainClassRuleCnt; j++)
1125 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1128 if (gidx < rule->BacktrackGlyphCount
1129 || (gidx + rule->InputGlyphCount
1130 + rule->LookaheadGlyphCount) > gstring->used)
1132 if (match_chain_classes (gstring, gidx, flag,
1133 &context2->BacktrackClassDef,
1134 &context2->InputClassDef,
1135 &context2->LookaheadClassDef,
1138 orig_used = gstring->used;
1139 for (k = 0; k < rule->LookupCount; k++)
1140 lookup_gpos (lookup_list,
1141 rule->LookupRecord[k].LookupListIndex,
1143 gidx + rule->LookupRecord[k].SequenceIndex);
1144 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1148 else if (subtable->Format == 3)
1150 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1154 if (gidx < context3->BacktrackGlyphCount
1155 || (gidx + context3->InputGlyphCount
1156 + context3->LookaheadGlyphCount) > gstring->used)
1158 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1160 orig_used = gstring->used;
1161 for (j = 0; j < context3->LookupCount; j++)
1162 lookup_gpos (lookup_list,
1163 context3->LookupRecord[j].LookupListIndex,
1165 gidx + context3->LookupRecord[j].SequenceIndex);
1166 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1169 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1176 if (gidx == orig_gidx)
1182 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1186 for (i = 0; i < gstring->used; i++)
1188 c = gstring->glyphs[i].c;
1189 if (c < 0 || c >= 256)
1190 gstring->glyphs[i].glyph_id = 0;
1192 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1198 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1204 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1207 int segCount = sub4->segCountX2 / 2;
1209 for (i = 0; i < gstring->used; i++)
1211 c = gstring->glyphs[i].c;
1213 gstring->glyphs[i].glyph_id = 0;
1214 for (j = 0; j < segCount; j++)
1216 OTF_cmapSegument *seg = sub4->segments + i;
1218 if (c >= seg->startCount && c <= seg->endCount)
1220 if (seg->idRangeOffset == 0xFFFF)
1221 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1223 gstring->glyphs[i].glyph_id
1224 = sub4->glyphIdArray[seg->idRangeOffset
1225 + (c - seg->startCount)];
1235 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1241 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1247 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1253 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1263 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1269 && OTF_get_table (otf, "cmap") < 0)
1273 for (i = 0; i < gstring->used; i++)
1274 if (! gstring->glyphs[i].glyph_id)
1276 int c = gstring->glyphs[i].c;
1277 if (c < 32 || ! cmap->unicode_table)
1278 gstring->glyphs[i].glyph_id = 0;
1280 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1287 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1288 int platform_id, int encoding_id)
1292 char *errfmt = "CMAP Looking up%s";
1294 OTF_EncodingRecord *enc;
1297 && OTF_get_table (otf, "cmap") < 0)
1301 for (i = 0; i < cmap->numTables; i++)
1302 if (cmap->EncodingRecord[i].platformID == platform_id
1303 && cmap->EncodingRecord[i].encodingID == encoding_id)
1305 if (i == cmap->numTables)
1306 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1307 enc = cmap->EncodingRecord + i;
1308 switch (enc->subtable.format)
1310 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1311 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1312 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1313 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1314 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1315 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1316 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1318 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1323 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1326 && OTF_get_table (otf, "cmap") < 0)
1329 || code > otf->cmap->max_glyph_id
1330 || ! otf->cmap->decode_table)
1332 return otf->cmap->decode_table[code];
1336 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1342 && OTF_get_table (otf, "GDEF") < 0)
1346 if (gdef->glyph_class_def.offset)
1347 for (i = 0; i < gstring->used; i++)
1348 gstring->glyphs[i].GlyphClass
1349 = get_class_def (&gdef->glyph_class_def,
1350 gstring->glyphs[i].glyph_id);
1352 if (gdef->mark_attach_class_def.offset)
1353 for (i = 0; i < gstring->used; i++)
1354 gstring->glyphs[i].MarkAttachClass
1355 = get_class_def (&gdef->mark_attach_class_def,
1356 gstring->glyphs[i].glyph_id);
1362 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1363 const char *script, const char *language,
1364 const char *features,
1365 int alternate_subst)
1367 char *errfmt = "GSUB driving%s";
1370 OTF_LangSys *LangSys;
1371 int *lookup_indices;
1374 for (i = 0; i < gstring->used; i++)
1376 gstring->glyphs[i].positioning_type = 0;
1377 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1380 if (OTF_get_table (otf, "GSUB") < 0)
1383 if (gsub->FeatureList.FeatureCount == 0
1384 || gsub->LookupList.LookupCount == 0)
1387 LangSys = get_langsys (&gsub->ScriptList, script, language);
1391 /* One lookup may be used by multiple features. */
1392 lookup_indices = alloca (sizeof (int)
1393 * gsub->LookupList.LookupCount
1394 * (gsub->FeatureList.FeatureCount + 1));
1395 if (! lookup_indices)
1396 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1397 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList, LangSys,
1398 features, lookup_indices);
1402 for (i = 0; i < n; i++)
1404 int index = lookup_indices[i];
1407 if (gsub->LookupList.Lookup[index].LookupType != 8)
1410 while (gidx < gstring->used)
1412 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1420 gidx = gstring->used - 1;
1423 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1435 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1436 const char *script, const char *language, const char *features)
1439 OTF_get_table (otf, "cmap");
1440 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1444 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1445 const char *script, const char *language, const char *features)
1447 char *errfmt = "GPOS driving%s";
1450 OTF_LangSys *LangSys;
1451 int *lookup_indices;
1454 for (i = 0; i < gstring->used; i++)
1455 gstring->glyphs[i].positioning_type = 0;
1457 if (OTF_get_table (otf, "GPOS") < 0)
1460 if (gpos->FeatureList.FeatureCount == 0
1461 || gpos->LookupList.LookupCount == 0)
1464 LangSys = get_langsys (&gpos->ScriptList, script, language);
1468 /* One lookup may be used by multiple features. */
1469 lookup_indices = alloca (sizeof (int)
1470 * gpos->LookupList.LookupCount
1471 * (gpos->FeatureList.FeatureCount + 1));
1472 if (! lookup_indices)
1473 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1474 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList, LangSys,
1475 features, lookup_indices);
1479 for (i = 0; i < n; i++)
1481 int index = lookup_indices[i];
1484 while (gidx < gstring->used)
1486 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1496 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1497 const char *script, const char *language,
1498 const char *gsub_features, const char *gpos_features)
1500 if (OTF_drive_cmap (otf, gstring) < 0)
1502 if (OTF_drive_gdef (otf, gstring) < 0)
1505 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1508 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1514 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1515 const char *script, const char *language,
1516 const char *features)
1518 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);