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 if OTF_Glyph *G should be ignored according to
34 #define IGNORED_GLYPH(g, flag) \
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; \
69 gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag,
70 OTF_GlyphID *ids, int num)
75 int c = gstring->glyphs[from].c;
76 int from_idx = gstring->glyphs[from].f.index.from;
77 int to_idx = gstring->glyphs[to - 1].f.index.to;
80 for (i = non_ignored_idx = to - 1; i >= from; i--)
82 OTF_Glyph *g = gstring->glyphs + i;
83 if (IGNORED_GLYPH (g, flag))
87 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
88 temp.f.index.from = from_idx;
89 temp.f.index.to = to_idx;
90 gstring->glyphs[non_ignored_idx--] = temp;
96 GSTRING_INSERT (gstring, from, (num - len));
98 GSTRING_DELETE (gstring, from, (len - num));
99 for (i = 0; i < num; i++)
101 gstring->glyphs[from + i].c = c;
102 gstring->glyphs[from + i].glyph_id = ids[i];
103 gstring->glyphs[from + i].f.index.from = from_idx;
104 gstring->glyphs[from + i].f.index.to = to_idx;
111 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
115 if (coverage->CoverageFormat == 1)
117 for (i = 0; i < coverage->Count; i++)
118 if (coverage->table.GlyphArray[i] == id)
123 for (i = 0; i < coverage->Count; i++)
124 if (coverage->table.RangeRecord[i].Start <= id
125 && coverage->table.RangeRecord[i].End >= id)
126 return (coverage->table.RangeRecord[i].StartCoverageIndex
127 + (id - coverage->table.RangeRecord[i].Start));
133 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
135 if (class_def->ClassFormat == 1)
137 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
139 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
140 return class_def->f.f1.ClassValueArray[idx];
146 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
147 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
148 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
149 return class_def->f.f2.ClassRangeRecord[i].Class;
155 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
158 OTF_Tag script_tag = OTF_tag (script);
159 OTF_Tag langsys_tag = OTF_tag (language);
161 OTF_Tag dflt_tag = OTF_tag ("DFLT");
162 OTF_Script *dflt = NULL;
164 for (i = 0; i < script_list->ScriptCount; i++)
166 OTF_Script *script = script_list->Script + i;
168 if (script_list->Script[i].ScriptTag == dflt_tag)
170 if (script_list->Script[i].ScriptTag == script_tag)
173 return &script->DefaultLangSys;
174 for (j = 0; j < script->LangSysCount; j++)
175 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
176 return script->LangSys + j;
177 return &script->DefaultLangSys;
182 dflt = script_list->Script;
184 return &dflt->DefaultLangSys;
185 for (j = 0; j < dflt->LangSysCount; j++)
186 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
187 return dflt->LangSys + j;
188 return &dflt->DefaultLangSys;
192 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
193 char *features, int *lookup_indices)
196 OTF_Feature *feature;
197 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
199 for (i = 0; i < FeatureList->FeatureCount; i++)
200 feature_table[i] = 0;
208 if (*features == '*')
210 /* Consume all remaining features. */
211 for (i = 0; i < FeatureList->FeatureCount; i++)
212 if (! feature_table[i])
214 feature = FeatureList->Feature + i;
215 for (j = 0; j < feature->LookupCount; j++)
216 lookup_indices[n++] = feature->LookupListIndex[j];
221 if (*features == '~')
222 use_it = -1, features++;
223 for (i = 0; *features && *features != ','; i++, features++)
224 tagname[i] = *features;
230 tag = OTF_tag (tagname);
231 for (i = 0; i < FeatureList->FeatureCount; i++)
233 feature = FeatureList->Feature + i;
234 if (tag == feature->FeatureTag)
236 if (feature_table[i])
239 for (j = 0; j < feature->LookupCount; j++)
240 lookup_indices[n++] = feature->LookupListIndex[j];
241 feature_table[i] = use_it;
251 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
252 int count, OTF_GlyphID *ids)
254 OTF_Glyph *gbeg = gstring->glyphs + gidx;
255 OTF_Glyph *gend = gstring->glyphs + gstring->used;
259 for (g = gbeg, i = 0; g < gend && i < count; g++)
260 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
262 return (i < count ? -1 : g - gbeg);
266 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
269 int i = rule->BacktrackGlyphCount;
276 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
277 if (! IGNORED_GLYPH (g, flag) && --i == 0)
281 if (match_ids (gstring, j, flag,
282 rule->BacktrackGlyphCount, rule->Backtrack)
287 i = match_ids (gstring, gidx, flag,
288 rule->InputGlyphCount - 1, rule->Input);
292 i = match_ids (gstring, gidx, flag,
293 rule->LookaheadGlyphCount, rule->LookAhead);
300 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
301 int flag, int count, unsigned *classes)
303 OTF_Glyph *gbeg = gstring->glyphs + gidx;
304 OTF_Glyph *gend = gstring->glyphs + gstring->used;
308 for (g = gbeg, i = 0; g < gend && i < count; g++)
309 if (! IGNORED_GLYPH (g, flag)
310 && get_class_def (class_def, g->glyph_id) != classes[i++])
312 return (i < count ? -1 : g - gbeg);
316 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
317 OTF_ClassDef *BacktrackClassDef,
318 OTF_ClassDef *InputClassDef,
319 OTF_ClassDef *LookaheadClassDef,
320 OTF_ChainClassRule *rule)
322 int i = rule->BacktrackGlyphCount;
329 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
330 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
334 if (match_classes (BacktrackClassDef, gstring, j, flag,
335 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
339 i = match_classes (InputClassDef, gstring, gidx, flag,
340 rule->InputGlyphCount - 1, rule->Input);
344 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
345 rule->LookaheadGlyphCount, rule->LookAhead);
353 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
354 OTF_Coverage *coverages)
356 OTF_Glyph *gbeg = gstring->glyphs + gidx;
357 OTF_Glyph *gend = gstring->glyphs + gstring->used;
361 for (g = gbeg, i = 0; g < gend && i < count; g++)
362 if (! IGNORED_GLYPH (g, flag)
363 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
365 return (i < count ? -1 : g - gbeg);
369 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
370 OTF_GSUB_ChainContext3 *context3)
372 int i = context3->BacktrackGlyphCount;
379 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
380 if (! IGNORED_GLYPH (g, flag) && --i == 0)
384 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
385 context3->Backtrack) < 0)
389 if (context3->InputGlyphCount > 1)
391 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
392 context3->Input + 1);
397 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
398 context3->LookAhead) < 0)
404 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
405 OTF_GlyphString *gstring, int gidx, int alternate_subst)
407 char *errfmt = "GSUB Looking up%s";
409 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
410 unsigned int flag = (lookup->LookupFlag
411 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
412 int orig_gidx = gidx;
413 OTF_Glyph *g = gstring->glyphs + gidx;
416 if (IGNORED_GLYPH (g, flag))
419 /* Try all subtables until one of them handles the current glyph. */
420 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
422 unsigned lookup_type = lookup->LookupType;
423 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
426 if (lookup_type == 7)
428 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
430 lookup_type = extension1->ExtensionLookupType;
431 subtable = extension1->ExtensionSubtable;
435 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
436 : (lookup_type == 3))
439 if (subtable->Coverage.offset)
441 coverage_idx = get_coverage_index (&subtable->Coverage,
443 if (coverage_idx < 0)
450 if (subtable->Format == 1)
451 g->glyph_id += subtable->u.single1.DeltaGlyphID;
453 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
458 if (subtable->Format == 1)
460 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
461 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
463 gstring_subst (gstring, gidx, gidx + 1, flag,
464 seq->Substitute, seq->GlyphCount);
465 gidx += seq->GlyphCount;
468 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
472 if (subtable->Format == 1)
474 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
475 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
477 gstring_subst (gstring, gidx + 1, gidx + 1, flag,
478 altset->Alternate, altset->GlyphCount);
479 gidx += altset->GlyphCount;;
482 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
486 if (subtable->Format == 1)
488 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
489 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
493 for (j = 0; j < ligset->LigatureCount; j++)
497 lig = ligset->Ligature + j;
498 n = match_ids (gstring, gidx + 1, flag,
499 lig->CompCount - 1, lig->Component);
502 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
504 gidx += lig->CompCount;
509 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
513 if (subtable->Format == 1)
515 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
516 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
521 for (j = 0; j < set->RuleCount; j++)
523 rule = set->Rule + j;
524 if (match_ids (gstring, gidx + 1, flag,
525 rule->GlyphCount - 1, rule->Input) < 0)
527 orig_used = gstring->used;
528 for (k = 0; k < rule->LookupCount; k++)
529 lookup_gsub (lookup_list,
530 rule->LookupRecord[k].LookupListIndex,
532 gidx + rule->LookupRecord[k].SequenceIndex,
534 gidx += rule->GlyphCount + (gstring->used - orig_used);
538 else if (subtable->Format == 2)
540 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
547 class = get_class_def (&context2->ClassDef, g->glyph_id);
548 set = context2->ClassSet + class;
550 for (j = 0; j < set->ClassRuleCnt; j++)
552 rule = set->ClassRule + j;
553 if (match_classes (&context2->ClassDef,
554 gstring, gidx + 1, flag,
555 rule->GlyphCount - 1, rule->Class)
558 orig_used = gstring->used;
559 for (k = 0; k < rule->LookupCount; k++)
560 lookup_gsub (lookup_list,
561 rule->LookupRecord[k].LookupListIndex,
563 gidx + rule->LookupRecord[k].SequenceIndex,
565 gidx += rule->GlyphCount + (gstring->used - orig_used);
569 else /* subtable->Format == 3 */
571 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
575 if (match_coverages (gstring, gidx + 1, flag,
576 context3->GlyphCount - 1,
577 context3->Coverage + 1) < 0)
579 orig_used = gstring->used;
580 for (j = 0; j < context3->LookupCount; j++)
581 lookup_gsub (lookup_list,
582 context3->LookupRecord[j].LookupListIndex,
584 gidx + context3->LookupRecord[j].SequenceIndex,
586 gidx += context3->GlyphCount + (gstring->used - orig_used);
591 if (subtable->Format == 1)
593 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
594 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
598 for (j = 0; j < set->ChainRuleCount; j++)
600 OTF_ChainRule *rule = set->ChainRule + j;
602 if (gidx < rule->BacktrackGlyphCount
603 || (gidx + rule->InputGlyphCount
604 + rule->LookaheadGlyphCount) > gstring->used)
606 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
608 orig_used = gstring->used;
609 for (k = 0; k < rule->LookupCount; k++)
610 lookup_gsub (lookup_list,
611 rule->LookupRecord[k].LookupListIndex,
613 gidx + rule->LookupRecord[k].SequenceIndex,
615 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
619 else if (subtable->Format == 2)
621 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
622 OTF_ChainClassSet *set;
627 class = get_class_def (&context2->InputClassDef, g->glyph_id);
628 set = context2->ChainClassSet + class;
629 for (j = 0; j < set->ChainClassRuleCnt; j++)
631 OTF_ChainClassRule *rule = set->ChainClassRule + j;
634 if (gidx < rule->BacktrackGlyphCount
635 || (gidx + rule->InputGlyphCount
636 + rule->LookaheadGlyphCount) > gstring->used)
638 if (match_chain_classes (gstring, gidx, flag,
639 &context2->BacktrackClassDef,
640 &context2->InputClassDef,
641 &context2->LookaheadClassDef,
644 orig_used = gstring->used;
645 for (k = 0; k < rule->LookupCount; k++)
646 lookup_gsub (lookup_list,
647 rule->LookupRecord[k].LookupListIndex,
649 gidx + rule->LookupRecord[k].SequenceIndex,
651 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
657 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
661 if (gidx < context3->BacktrackGlyphCount
662 || (gidx + context3->InputGlyphCount
663 + context3->LookaheadGlyphCount) > gstring->used)
665 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
667 orig_used = gstring->used;
668 for (j = 0; j < context3->LookupCount; j++)
669 lookup_gsub (lookup_list,
670 context3->LookupRecord[j].LookupListIndex,
672 gidx + context3->LookupRecord[j].SequenceIndex,
674 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
680 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
681 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
682 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
685 if (back_gidx > gstring->used || ahead_gidx < 0)
688 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
689 if (get_coverage_index (reverse->Backtrack + j,
690 gstring->glyphs[gidx + 1 + j].glyph_id)
693 if (j < reverse->BacktrackGlyphCount)
695 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
696 if (get_coverage_index (reverse->LookAhead + j,
697 gstring->glyphs[gidx - 1 - j].glyph_id)
700 if (j < reverse->LookaheadGlyphCount)
702 g->glyph_id = reverse->Substitute[coverage_idx];
710 if (gidx == orig_gidx)
719 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
721 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
723 rec->XPlacement = anchor->XCoordinate;
724 rec->YPlacement = anchor->YCoordinate;
725 if (anchor->AnchorFormat == 1)
728 else if (anchor->AnchorFormat == 2)
729 /* Not yet implemented */
731 else if (anchor->AnchorFormat == 3)
732 /* Not yet implemented */
739 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
740 OTF_GlyphString *gstring, int gidx)
742 char *errfmt = "GPOS Looking up%s";
744 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
745 unsigned int flag = (lookup->LookupFlag
746 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
747 int orig_gidx = gidx;
748 OTF_Glyph *g = gstring->glyphs + gidx;
751 if (IGNORED_GLYPH (g, flag)
752 || g->positioning_type)
755 /* Try all subtables until one of them handles the current glyph. */
756 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
758 unsigned lookup_type = lookup->LookupType;
759 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
762 if (lookup_type == 9)
764 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
766 lookup_type = extension1->ExtensionLookupType;
767 subtable = extension1->ExtensionSubtable;
770 if (subtable->Coverage.offset)
772 coverage_idx = get_coverage_index (&subtable->Coverage,
774 if (coverage_idx < 0)
781 g->positioning_type = lookup_type;
782 if (subtable->Format == 1)
784 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
786 g->f.f1.format = single1->ValueFormat;
787 g->f.f1.value = &single1->Value;
789 else if (subtable->Format == 2)
791 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
793 g->f.f1.format = single2->ValueFormat;
794 g->f.f1.value = single2->Value + coverage_idx;
803 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
804 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
805 next_gidx++, nextg++);
807 if (next_gidx >= gstring->used
808 || nextg->positioning_type)
810 if (subtable->Format == 1)
812 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
813 OTF_PairSet *set = pair1->PairSet + coverage_idx;
816 for (j = 0; j < set->PairValueCount; j++)
817 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
819 if (pair1->ValueFormat1)
821 g->positioning_type = lookup_type;
822 g->f.f2.format = pair1->ValueFormat1;
823 g->f.f2.value = &set->PairValueRecord[j].Value1;
826 if (pair1->ValueFormat2)
828 nextg->positioning_type = lookup_type;
829 nextg->f.f2.format = pair1->ValueFormat2;
830 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
836 else if (subtable->Format == 2)
838 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
839 unsigned class1, class2;
841 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
842 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
843 if (pair2->ValueFormat1)
845 g->positioning_type = lookup_type;
846 g->f.f2.format = pair2->ValueFormat1;
848 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
851 if (pair2->ValueFormat2)
853 nextg->positioning_type = lookup_type;
854 nextg->f.f2.format = pair2->ValueFormat2;
856 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
865 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
867 g->positioning_type = lookup_type;
869 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
871 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
878 if (subtable->Format == 1)
880 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
881 OTF_MarkRecord *mark_record;
882 OTF_AnchorRecord *base_record;
884 int coverage_idx_base;
887 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
889 if (baseg < gstring->glyphs)
892 = get_coverage_index (&mark_base1->BaseCoverage,
894 if (coverage_idx_base < 0)
896 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
898 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
899 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
901 = &base_record->Anchor[mark_record->Class];
902 g->positioning_type = lookup_type;
909 if (subtable->Format == 1)
911 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
913 int coverage_idx_lig;
914 OTF_MarkRecord *mark_record;
915 OTF_LigatureAttach *attach;
916 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
919 for (j = 0; j < mark_lig1->ClassCount; j++)
923 (ligg >= gstring->glyphs
924 && (IGNORED_GLYPH (ligg, flag)
925 || ligg->GlyphClass > OTF_GlyphClassLigature));
927 if (ligg->positioning_type == 5
928 && ligg->MarkAttachClass < mark_lig1->ClassCount)
929 num_class[ligg->MarkAttachClass]++;
930 if (ligg < gstring->glyphs)
933 = get_coverage_index (&mark_lig1->LigatureCoverage,
935 if (coverage_idx_lig < 0)
937 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
938 g->MarkAttachClass = mark_record->Class;
939 attach = (mark_lig1->LigatureArray.LigatureAttach
941 for (j = 0; j < attach->ComponentCount; j++)
943 OTF_Anchor *lig_anchor
944 = attach->ComponentRecord[j].LigatureAnchor;
946 if (lig_anchor[mark_record->Class].AnchorFormat
947 && num_class[mark_record->Class]-- == 0)
949 g->positioning_type = lookup_type;
950 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
951 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
961 if (subtable->Format == 1)
963 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
964 OTF_MarkRecord *mark1_record;
965 OTF_AnchorRecord *mark2_record;
967 int coverage_idx_base;
970 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
972 if (prevg < gstring->glyphs)
975 = get_coverage_index (&mark_mark1->Mark2Coverage,
977 if (coverage_idx_base < 0)
979 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
981 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
982 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
984 = &mark2_record->Anchor[mark1_record->Class];
985 g->positioning_type = lookup_type;
991 if (subtable->Format == 1)
993 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
994 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
999 for (j = 0; j < set->RuleCount; j++)
1001 rule = set->Rule + j;
1002 if (match_ids (gstring, gidx + 1, flag,
1003 rule->GlyphCount - 1, rule->Input) < 0)
1005 orig_used = gstring->used;
1006 for (k = 0; k < rule->LookupCount; k++)
1007 lookup_gpos (lookup_list,
1008 rule->LookupRecord[k].LookupListIndex,
1010 gidx + rule->LookupRecord[k].SequenceIndex);
1011 gidx += rule->GlyphCount + (gstring->used - orig_used);
1015 else if (subtable->Format == 2)
1017 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1019 OTF_ClassRule *rule;
1024 class = get_class_def (&context2->ClassDef, g->glyph_id);
1025 set = context2->ClassSet + class;
1027 for (j = 0; j < set->ClassRuleCnt; j++)
1029 rule = set->ClassRule + j;
1030 if (match_classes (&context2->ClassDef,
1031 gstring, gidx + 1, flag,
1032 rule->GlyphCount - 1, rule->Class)
1035 orig_used = gstring->used;
1036 for (k = 0; k < rule->LookupCount; k++)
1037 lookup_gpos (lookup_list,
1038 rule->LookupRecord[k].LookupListIndex,
1040 gidx + rule->LookupRecord[k].SequenceIndex);
1041 gidx += rule->GlyphCount + (gstring->used - orig_used);
1045 else /* subtable->Format == 3 */
1047 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1051 if (match_coverages (gstring, gidx + 1, flag,
1052 context3->GlyphCount - 1,
1053 context3->Coverage + 1) < 0)
1055 orig_used = gstring->used;
1056 for (j = 0; j < context3->LookupCount; j++)
1057 lookup_gpos (lookup_list,
1058 context3->LookupRecord[j].LookupListIndex,
1060 gidx + context3->LookupRecord[j].SequenceIndex);
1061 gidx += context3->GlyphCount + (gstring->used - orig_used);
1066 if (subtable->Format == 1)
1068 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1069 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1073 for (j = 0; j < set->ChainRuleCount; j++)
1075 OTF_ChainRule *rule = set->ChainRule + j;
1077 if (gidx < rule->BacktrackGlyphCount
1078 || (gidx + rule->InputGlyphCount
1079 + rule->LookaheadGlyphCount) > gstring->used)
1081 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1083 orig_used = gstring->used;
1084 for (k = 0; k < rule->LookupCount; k++)
1085 lookup_gpos (lookup_list,
1086 rule->LookupRecord[k].LookupListIndex,
1088 gidx + rule->LookupRecord[k].SequenceIndex);
1089 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1093 else if (subtable->Format == 2)
1095 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1096 OTF_ChainClassSet *set;
1101 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1102 set = context2->ChainClassSet + class;
1103 for (j = 0; j < set->ChainClassRuleCnt; j++)
1105 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1108 if (gidx < rule->BacktrackGlyphCount
1109 || (gidx + rule->InputGlyphCount
1110 + rule->LookaheadGlyphCount) > gstring->used)
1112 if (match_chain_classes (gstring, gidx, flag,
1113 &context2->BacktrackClassDef,
1114 &context2->InputClassDef,
1115 &context2->LookaheadClassDef,
1118 orig_used = gstring->used;
1119 for (k = 0; k < rule->LookupCount; k++)
1120 lookup_gpos (lookup_list,
1121 rule->LookupRecord[k].LookupListIndex,
1123 gidx + rule->LookupRecord[k].SequenceIndex);
1124 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1128 else if (subtable->Format == 3)
1130 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1134 if (gidx < context3->BacktrackGlyphCount
1135 || (gidx + context3->InputGlyphCount
1136 + context3->LookaheadGlyphCount) > gstring->used)
1138 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1140 orig_used = gstring->used;
1141 for (j = 0; j < context3->LookupCount; j++)
1142 lookup_gpos (lookup_list,
1143 context3->LookupRecord[j].LookupListIndex,
1145 gidx + context3->LookupRecord[j].SequenceIndex);
1146 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1149 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1156 if (gidx == orig_gidx)
1162 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1166 for (i = 0; i < gstring->used; i++)
1168 c = gstring->glyphs[i].c;
1169 if (c < 0 || c >= 256)
1170 gstring->glyphs[i].glyph_id = 0;
1172 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1178 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1184 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1187 int segCount = sub4->segCountX2 / 2;
1189 for (i = 0; i < gstring->used; i++)
1191 c = gstring->glyphs[i].c;
1193 gstring->glyphs[i].glyph_id = 0;
1194 for (j = 0; j < segCount; j++)
1196 OTF_cmapSegument *seg = sub4->segments + i;
1198 if (c >= seg->startCount && c <= seg->endCount)
1200 if (seg->idRangeOffset == 0xFFFF)
1201 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1203 gstring->glyphs[i].glyph_id
1204 = sub4->glyphIdArray[seg->idRangeOffset
1205 + (c - seg->startCount)];
1215 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1221 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1227 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1233 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1243 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1249 && OTF_get_table (otf, "cmap") < 0)
1253 for (i = 0; i < gstring->used; i++)
1254 if (! gstring->glyphs[i].glyph_id)
1256 int c = gstring->glyphs[i].c;
1257 if (c < 32 || ! cmap->unicode_table)
1258 gstring->glyphs[i].glyph_id = 0;
1260 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1267 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1268 int platform_id, int encoding_id)
1272 char *errfmt = "CMAP Looking up%s";
1274 OTF_EncodingRecord *enc;
1277 && OTF_get_table (otf, "cmap") < 0)
1281 for (i = 0; i < cmap->numTables; i++)
1282 if (cmap->EncodingRecord[i].platformID == platform_id
1283 && cmap->EncodingRecord[i].encodingID == encoding_id)
1285 if (i == cmap->numTables)
1286 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1287 enc = cmap->EncodingRecord + i;
1288 switch (enc->subtable.format)
1290 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1291 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1292 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1293 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1294 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1295 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1296 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1298 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1303 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1306 && OTF_get_table (otf, "cmap") < 0)
1309 || code > otf->cmap->max_glyph_id
1310 || ! otf->cmap->decode_table)
1312 return otf->cmap->decode_table[code];
1316 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1322 && OTF_get_table (otf, "GDEF") < 0)
1326 if (gdef->glyph_class_def.offset)
1327 for (i = 0; i < gstring->used; i++)
1328 gstring->glyphs[i].GlyphClass
1329 = get_class_def (&gdef->glyph_class_def,
1330 gstring->glyphs[i].glyph_id);
1332 if (gdef->mark_attach_class_def.offset)
1333 for (i = 0; i < gstring->used; i++)
1334 gstring->glyphs[i].MarkAttachClass
1335 = get_class_def (&gdef->mark_attach_class_def,
1336 gstring->glyphs[i].glyph_id);
1342 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1343 char *script, char *language, char *features,
1344 int alternate_subst)
1346 char *errfmt = "GSUB driving%s";
1349 OTF_LangSys *LangSys;
1350 int *lookup_indices;
1353 for (i = 0; i < gstring->used; i++)
1354 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1357 && OTF_get_table (otf, "GSUB") < 0)
1360 if (gsub->FeatureList.FeatureCount == 0
1361 || gsub->LookupList.LookupCount == 0)
1364 LangSys = get_langsys (&gsub->ScriptList, script, language);
1368 /* One lookup may be used by multiple features. */
1369 lookup_indices = alloca (sizeof (int)
1370 * gsub->LookupList.LookupCount
1371 * (gsub->FeatureList.FeatureCount + 1));
1372 if (! lookup_indices)
1373 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1374 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1375 features, lookup_indices);
1379 for (i = 0; i < n; i++)
1381 int index = lookup_indices[i];
1384 if (gsub->LookupList.Lookup[index].LookupType != 8)
1387 while (gidx < gstring->used)
1389 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx,
1397 gidx = gstring->used - 1;
1400 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx,
1412 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1413 char *script, char *language, char *features)
1415 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1419 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1420 char *script, char *language, char *features)
1422 char *errfmt = "GPOS driving%s";
1425 OTF_LangSys *LangSys;
1426 int *lookup_indices;
1430 && OTF_get_table (otf, "GPOS") < 0)
1433 if (gpos->FeatureList.FeatureCount == 0
1434 || gpos->LookupList.LookupCount == 0)
1437 LangSys = get_langsys (&gpos->ScriptList, script, language);
1441 /* One lookup may be used by multiple features. */
1442 lookup_indices = alloca (sizeof (int)
1443 * gpos->LookupList.LookupCount
1444 * (gpos->FeatureList.FeatureCount + 1));
1445 if (! lookup_indices)
1446 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1447 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1448 features, lookup_indices);
1452 for (i = 0; i < gstring->used; i++)
1453 gstring->glyphs[i].positioning_type = 0;
1455 for (i = 0; i < n; i++)
1457 int index = lookup_indices[i];
1460 while (gidx < gstring->used)
1462 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1472 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1473 char *script, char *language,
1474 char *gsub_features, char *gpos_features)
1476 if (OTF_drive_cmap (otf, gstring) < 0)
1478 if (OTF_drive_gdef (otf, gstring) < 0)
1481 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1484 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1490 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1491 char *script, char *language, char *features)
1493 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);