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; \
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;
84 if (IGNORED_GLYPH (g, flag))
88 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
89 temp.f.index.from = from_idx;
90 temp.f.index.to = to_idx;
91 gstring->glyphs[non_ignored_idx--] = temp;
97 GSTRING_INSERT (gstring, from, (num - len));
99 GSTRING_DELETE (gstring, from, (len - num));
100 for (i = 0; i < num; i++)
102 gstring->glyphs[from + i].c = otf->cmap->decode_table[ids[i]];
103 gstring->glyphs[from + i].glyph_id = ids[i];
105 gstring->glyphs[from + i].GlyphClass
106 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
108 gstring->glyphs[from + i].GlyphClass = 0;
109 gstring->glyphs[from + i].positioning_type = 0;
110 gstring->glyphs[from + i].f.index.from = from_idx;
111 gstring->glyphs[from + i].f.index.to = to_idx;
118 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
122 if (coverage->CoverageFormat == 1)
124 for (i = 0; i < coverage->Count; i++)
125 if (coverage->table.GlyphArray[i] == id)
130 for (i = 0; i < coverage->Count; i++)
131 if (coverage->table.RangeRecord[i].Start <= id
132 && coverage->table.RangeRecord[i].End >= id)
133 return (coverage->table.RangeRecord[i].StartCoverageIndex
134 + (id - coverage->table.RangeRecord[i].Start));
140 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
142 if (class_def->ClassFormat == 1)
144 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
146 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
147 return class_def->f.f1.ClassValueArray[idx];
153 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
154 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
155 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
156 return class_def->f.f2.ClassRangeRecord[i].Class;
162 get_langsys (OTF_ScriptList *script_list,
163 const char *script, const char *language)
166 OTF_Tag script_tag = OTF_tag (script);
167 OTF_Tag langsys_tag = OTF_tag (language);
169 OTF_Tag dflt_tag = OTF_tag ("DFLT");
170 OTF_Script *dflt = NULL;
172 for (i = 0; i < script_list->ScriptCount; i++)
174 OTF_Script *script = script_list->Script + i;
176 if (script_list->Script[i].ScriptTag == dflt_tag)
178 if (script_list->Script[i].ScriptTag == script_tag)
181 return &script->DefaultLangSys;
182 for (j = 0; j < script->LangSysCount; j++)
183 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
184 return script->LangSys + j;
185 return &script->DefaultLangSys;
190 dflt = script_list->Script;
192 return &dflt->DefaultLangSys;
193 for (j = 0; j < dflt->LangSysCount; j++)
194 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
195 return dflt->LangSys + j;
196 return &dflt->DefaultLangSys;
200 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
201 const char *features, int *lookup_indices)
204 OTF_Feature *feature;
205 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
207 for (i = 0; i < FeatureList->FeatureCount; i++)
208 feature_table[i] = 0;
216 if (*features == '*')
218 /* Consume all remaining features. */
219 for (i = 0; i < FeatureList->FeatureCount; i++)
220 if (! feature_table[i])
222 feature = FeatureList->Feature + i;
223 for (j = 0; j < feature->LookupCount; j++)
224 lookup_indices[n++] = feature->LookupListIndex[j];
229 if (*features == '~')
230 use_it = -1, features++;
231 for (i = 0; *features && *features != ','; i++, features++)
232 tagname[i] = *features;
238 tag = OTF_tag (tagname);
239 for (i = 0; i < FeatureList->FeatureCount; i++)
241 feature = FeatureList->Feature + i;
242 if (tag == feature->FeatureTag)
244 if (feature_table[i])
247 for (j = 0; j < feature->LookupCount; j++)
248 lookup_indices[n++] = feature->LookupListIndex[j];
249 feature_table[i] = use_it;
259 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
260 int count, OTF_GlyphID *ids)
262 OTF_Glyph *gbeg = gstring->glyphs + gidx;
263 OTF_Glyph *gend = gstring->glyphs + gstring->used;
267 for (g = gbeg, i = 0; g < gend && i < count; g++)
268 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
270 return (i < count ? -1 : g - gbeg);
274 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
277 int i = rule->BacktrackGlyphCount;
284 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
285 if (! IGNORED_GLYPH (g, flag) && --i == 0)
289 if (match_ids (gstring, j, flag,
290 rule->BacktrackGlyphCount, rule->Backtrack)
295 i = match_ids (gstring, gidx, flag,
296 rule->InputGlyphCount - 1, rule->Input);
300 i = match_ids (gstring, gidx, flag,
301 rule->LookaheadGlyphCount, rule->LookAhead);
308 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
309 int flag, int count, unsigned *classes)
311 OTF_Glyph *gbeg = gstring->glyphs + gidx;
312 OTF_Glyph *gend = gstring->glyphs + gstring->used;
316 for (g = gbeg, i = 0; g < gend && i < count; g++)
317 if (! IGNORED_GLYPH (g, flag)
318 && get_class_def (class_def, g->glyph_id) != classes[i++])
320 return (i < count ? -1 : g - gbeg);
324 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
325 OTF_ClassDef *BacktrackClassDef,
326 OTF_ClassDef *InputClassDef,
327 OTF_ClassDef *LookaheadClassDef,
328 OTF_ChainClassRule *rule)
330 int i = rule->BacktrackGlyphCount;
337 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
338 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
342 if (match_classes (BacktrackClassDef, gstring, j, flag,
343 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
347 i = match_classes (InputClassDef, gstring, gidx, flag,
348 rule->InputGlyphCount - 1, rule->Input);
352 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
353 rule->LookaheadGlyphCount, rule->LookAhead);
361 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
362 OTF_Coverage *coverages)
364 OTF_Glyph *gbeg = gstring->glyphs + gidx;
365 OTF_Glyph *gend = gstring->glyphs + gstring->used;
369 for (g = gbeg, i = 0; g < gend && i < count; g++)
370 if (! IGNORED_GLYPH (g, flag)
371 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
373 return (i < count ? -1 : g - gbeg);
377 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
378 OTF_GSUB_ChainContext3 *context3)
380 int i = context3->BacktrackGlyphCount;
387 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
388 if (! IGNORED_GLYPH (g, flag) && --i == 0)
392 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
393 context3->Backtrack) < 0)
397 if (context3->InputGlyphCount > 1)
399 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
400 context3->Input + 1);
405 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
406 context3->LookAhead) < 0)
412 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
413 OTF_GlyphString *gstring, int gidx, int alternate_subst)
415 char *errfmt = "GSUB Looking up%s";
417 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
418 unsigned int flag = (lookup->LookupFlag
419 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
420 int orig_gidx = gidx;
421 OTF_Glyph *g = gstring->glyphs + gidx;
424 if (IGNORED_GLYPH (g, flag))
427 /* Try all subtables until one of them handles the current glyph. */
428 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
430 unsigned lookup_type = lookup->LookupType;
431 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
434 if (lookup_type == 7)
436 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
438 lookup_type = extension1->ExtensionLookupType;
439 subtable = extension1->ExtensionSubtable;
443 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
444 : (lookup_type == 3))
447 if (subtable->Coverage.offset)
449 coverage_idx = get_coverage_index (&subtable->Coverage,
451 if (coverage_idx < 0)
458 if (subtable->Format == 1)
459 g->glyph_id += subtable->u.single1.DeltaGlyphID;
461 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
466 if (subtable->Format == 1)
468 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
469 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
471 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
472 seq->Substitute, seq->GlyphCount);
473 gidx += seq->GlyphCount;
476 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
480 if (subtable->Format == 1)
482 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
483 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
485 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
486 altset->Alternate, altset->GlyphCount);
487 gidx += altset->GlyphCount;;
490 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
494 if (subtable->Format == 1)
496 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
497 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
501 for (j = 0; j < ligset->LigatureCount; j++)
505 lig = ligset->Ligature + j;
506 n = match_ids (gstring, gidx + 1, flag,
507 lig->CompCount - 1, lig->Component);
510 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
517 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
521 if (subtable->Format == 1)
523 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
524 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
529 for (j = 0; j < set->RuleCount; j++)
531 rule = set->Rule + j;
532 if (match_ids (gstring, gidx + 1, flag,
533 rule->GlyphCount - 1, rule->Input) < 0)
535 orig_used = gstring->used;
536 for (k = 0; k < rule->LookupCount; k++)
537 lookup_gsub (otf, lookup_list,
538 rule->LookupRecord[k].LookupListIndex,
540 gidx + rule->LookupRecord[k].SequenceIndex,
542 gidx += rule->GlyphCount + (gstring->used - orig_used);
546 else if (subtable->Format == 2)
548 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
555 class = get_class_def (&context2->ClassDef, g->glyph_id);
556 set = context2->ClassSet + class;
558 for (j = 0; j < set->ClassRuleCnt; j++)
560 rule = set->ClassRule + j;
561 if (match_classes (&context2->ClassDef,
562 gstring, gidx + 1, flag,
563 rule->GlyphCount - 1, rule->Class)
566 orig_used = gstring->used;
567 for (k = 0; k < rule->LookupCount; k++)
568 lookup_gsub (otf, lookup_list,
569 rule->LookupRecord[k].LookupListIndex,
571 gidx + rule->LookupRecord[k].SequenceIndex,
573 gidx += rule->GlyphCount + (gstring->used - orig_used);
577 else /* subtable->Format == 3 */
579 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
583 if (match_coverages (gstring, gidx + 1, flag,
584 context3->GlyphCount - 1,
585 context3->Coverage + 1) < 0)
587 orig_used = gstring->used;
588 for (j = 0; j < context3->LookupCount; j++)
589 lookup_gsub (otf, lookup_list,
590 context3->LookupRecord[j].LookupListIndex,
592 gidx + context3->LookupRecord[j].SequenceIndex,
594 gidx += context3->GlyphCount + (gstring->used - orig_used);
599 if (subtable->Format == 1)
601 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
602 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
606 for (j = 0; j < set->ChainRuleCount; j++)
608 OTF_ChainRule *rule = set->ChainRule + j;
610 if (gidx < rule->BacktrackGlyphCount
611 || (gidx + rule->InputGlyphCount
612 + rule->LookaheadGlyphCount) > gstring->used)
614 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
616 orig_used = gstring->used;
617 for (k = 0; k < rule->LookupCount; k++)
618 lookup_gsub (otf, lookup_list,
619 rule->LookupRecord[k].LookupListIndex,
621 gidx + rule->LookupRecord[k].SequenceIndex,
623 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
627 else if (subtable->Format == 2)
629 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
630 OTF_ChainClassSet *set;
635 class = get_class_def (&context2->InputClassDef, g->glyph_id);
636 set = context2->ChainClassSet + class;
637 for (j = 0; j < set->ChainClassRuleCnt; j++)
639 OTF_ChainClassRule *rule = set->ChainClassRule + j;
642 if (gidx < rule->BacktrackGlyphCount
643 || (gidx + rule->InputGlyphCount
644 + rule->LookaheadGlyphCount) > gstring->used)
646 if (match_chain_classes (gstring, gidx, flag,
647 &context2->BacktrackClassDef,
648 &context2->InputClassDef,
649 &context2->LookaheadClassDef,
652 orig_used = gstring->used;
653 for (k = 0; k < rule->LookupCount; k++)
654 lookup_gsub (otf, lookup_list,
655 rule->LookupRecord[k].LookupListIndex,
657 gidx + rule->LookupRecord[k].SequenceIndex,
659 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
665 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
669 if (gidx < context3->BacktrackGlyphCount
670 || (gidx + context3->InputGlyphCount
671 + context3->LookaheadGlyphCount) > gstring->used)
673 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
675 orig_used = gstring->used;
676 for (j = 0; j < context3->LookupCount; j++)
677 lookup_gsub (otf, lookup_list,
678 context3->LookupRecord[j].LookupListIndex,
680 gidx + context3->LookupRecord[j].SequenceIndex,
682 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
688 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
689 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
690 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
693 if (back_gidx > gstring->used || ahead_gidx < 0)
696 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
697 if (get_coverage_index (reverse->Backtrack + j,
698 gstring->glyphs[gidx + 1 + j].glyph_id)
701 if (j < reverse->BacktrackGlyphCount)
703 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
704 if (get_coverage_index (reverse->LookAhead + j,
705 gstring->glyphs[gidx - 1 - j].glyph_id)
708 if (j < reverse->LookaheadGlyphCount)
710 g->glyph_id = reverse->Substitute[coverage_idx];
718 if (gidx == orig_gidx)
727 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
729 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
731 rec->XPlacement = anchor->XCoordinate;
732 rec->YPlacement = anchor->YCoordinate;
733 if (anchor->AnchorFormat == 1)
736 else if (anchor->AnchorFormat == 2)
737 /* Not yet implemented */
739 else if (anchor->AnchorFormat == 3)
740 /* Not yet implemented */
747 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
748 OTF_GlyphString *gstring, int gidx)
750 char *errfmt = "GPOS Looking up%s";
752 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
753 unsigned int flag = (lookup->LookupFlag
754 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
755 int orig_gidx = gidx;
756 OTF_Glyph *g = gstring->glyphs + gidx;
759 if (IGNORED_GLYPH (g, flag)
760 || g->positioning_type)
763 /* Try all subtables until one of them handles the current glyph. */
764 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
766 unsigned lookup_type = lookup->LookupType;
767 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
770 if (lookup_type == 9)
772 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
774 lookup_type = extension1->ExtensionLookupType;
775 subtable = extension1->ExtensionSubtable;
778 if (subtable->Coverage.offset)
780 coverage_idx = get_coverage_index (&subtable->Coverage,
782 if (coverage_idx < 0)
789 g->positioning_type = lookup_type;
790 if (subtable->Format == 1)
792 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
794 g->f.f1.format = single1->ValueFormat;
795 g->f.f1.value = &single1->Value;
797 else if (subtable->Format == 2)
799 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
801 g->f.f1.format = single2->ValueFormat;
802 g->f.f1.value = single2->Value + coverage_idx;
811 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
812 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
813 next_gidx++, nextg++);
815 if (next_gidx >= gstring->used
816 || nextg->positioning_type)
818 if (subtable->Format == 1)
820 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
821 OTF_PairSet *set = pair1->PairSet + coverage_idx;
824 for (j = 0; j < set->PairValueCount; j++)
825 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
827 if (pair1->ValueFormat1)
829 g->positioning_type = lookup_type;
830 g->f.f2.format = pair1->ValueFormat1;
831 g->f.f2.value = &set->PairValueRecord[j].Value1;
834 if (pair1->ValueFormat2)
836 nextg->positioning_type = lookup_type;
837 nextg->f.f2.format = pair1->ValueFormat2;
838 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
844 else if (subtable->Format == 2)
846 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
847 unsigned class1, class2;
849 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
850 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
851 if (pair2->ValueFormat1)
853 g->positioning_type = lookup_type;
854 g->f.f2.format = pair2->ValueFormat1;
856 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
859 if (pair2->ValueFormat2)
861 nextg->positioning_type = lookup_type;
862 nextg->f.f2.format = pair2->ValueFormat2;
864 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
873 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
875 g->positioning_type = lookup_type;
877 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
879 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
886 if (subtable->Format == 1)
888 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
889 OTF_MarkRecord *mark_record;
890 OTF_AnchorRecord *base_record;
892 int coverage_idx_base;
895 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
897 if (baseg < gstring->glyphs)
900 = get_coverage_index (&mark_base1->BaseCoverage,
902 if (coverage_idx_base < 0)
904 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
906 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
907 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
909 = &base_record->Anchor[mark_record->Class];
910 g->positioning_type = lookup_type;
917 if (subtable->Format == 1)
919 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
921 int coverage_idx_lig;
922 OTF_MarkRecord *mark_record;
923 OTF_LigatureAttach *attach;
924 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
927 for (j = 0; j < mark_lig1->ClassCount; j++)
931 (ligg >= gstring->glyphs
932 && (IGNORED_GLYPH (ligg, flag)
933 || ligg->GlyphClass > OTF_GlyphClassLigature));
935 if (ligg->positioning_type == 5
936 && ligg->MarkAttachClass < mark_lig1->ClassCount)
937 num_class[ligg->MarkAttachClass]++;
938 if (ligg < gstring->glyphs)
941 = get_coverage_index (&mark_lig1->LigatureCoverage,
943 if (coverage_idx_lig < 0)
945 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
946 g->MarkAttachClass = mark_record->Class;
947 attach = (mark_lig1->LigatureArray.LigatureAttach
949 for (j = 0; j < attach->ComponentCount; j++)
951 OTF_Anchor *lig_anchor
952 = attach->ComponentRecord[j].LigatureAnchor;
954 if (lig_anchor[mark_record->Class].AnchorFormat
955 && num_class[mark_record->Class]-- == 0)
957 g->positioning_type = lookup_type;
958 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
959 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
969 if (subtable->Format == 1)
971 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
972 OTF_MarkRecord *mark1_record;
973 OTF_AnchorRecord *mark2_record;
975 int coverage_idx_base;
978 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
980 if (prevg < gstring->glyphs)
983 = get_coverage_index (&mark_mark1->Mark2Coverage,
985 if (coverage_idx_base < 0)
987 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
989 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
990 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
992 = &mark2_record->Anchor[mark1_record->Class];
993 g->positioning_type = lookup_type;
999 if (subtable->Format == 1)
1001 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1002 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1007 for (j = 0; j < set->RuleCount; j++)
1009 rule = set->Rule + j;
1010 if (match_ids (gstring, gidx + 1, flag,
1011 rule->GlyphCount - 1, rule->Input) < 0)
1013 orig_used = gstring->used;
1014 for (k = 0; k < rule->LookupCount; k++)
1015 lookup_gpos (lookup_list,
1016 rule->LookupRecord[k].LookupListIndex,
1018 gidx + rule->LookupRecord[k].SequenceIndex);
1019 gidx += rule->GlyphCount + (gstring->used - orig_used);
1023 else if (subtable->Format == 2)
1025 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1027 OTF_ClassRule *rule;
1032 class = get_class_def (&context2->ClassDef, g->glyph_id);
1033 set = context2->ClassSet + class;
1035 for (j = 0; j < set->ClassRuleCnt; j++)
1037 rule = set->ClassRule + j;
1038 if (match_classes (&context2->ClassDef,
1039 gstring, gidx + 1, flag,
1040 rule->GlyphCount - 1, rule->Class)
1043 orig_used = gstring->used;
1044 for (k = 0; k < rule->LookupCount; k++)
1045 lookup_gpos (lookup_list,
1046 rule->LookupRecord[k].LookupListIndex,
1048 gidx + rule->LookupRecord[k].SequenceIndex);
1049 gidx += rule->GlyphCount + (gstring->used - orig_used);
1053 else /* subtable->Format == 3 */
1055 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1059 if (match_coverages (gstring, gidx + 1, flag,
1060 context3->GlyphCount - 1,
1061 context3->Coverage + 1) < 0)
1063 orig_used = gstring->used;
1064 for (j = 0; j < context3->LookupCount; j++)
1065 lookup_gpos (lookup_list,
1066 context3->LookupRecord[j].LookupListIndex,
1068 gidx + context3->LookupRecord[j].SequenceIndex);
1069 gidx += context3->GlyphCount + (gstring->used - orig_used);
1074 if (subtable->Format == 1)
1076 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1077 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1081 for (j = 0; j < set->ChainRuleCount; j++)
1083 OTF_ChainRule *rule = set->ChainRule + j;
1085 if (gidx < rule->BacktrackGlyphCount
1086 || (gidx + rule->InputGlyphCount
1087 + rule->LookaheadGlyphCount) > gstring->used)
1089 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1091 orig_used = gstring->used;
1092 for (k = 0; k < rule->LookupCount; k++)
1093 lookup_gpos (lookup_list,
1094 rule->LookupRecord[k].LookupListIndex,
1096 gidx + rule->LookupRecord[k].SequenceIndex);
1097 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1101 else if (subtable->Format == 2)
1103 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1104 OTF_ChainClassSet *set;
1109 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1110 set = context2->ChainClassSet + class;
1111 for (j = 0; j < set->ChainClassRuleCnt; j++)
1113 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1116 if (gidx < rule->BacktrackGlyphCount
1117 || (gidx + rule->InputGlyphCount
1118 + rule->LookaheadGlyphCount) > gstring->used)
1120 if (match_chain_classes (gstring, gidx, flag,
1121 &context2->BacktrackClassDef,
1122 &context2->InputClassDef,
1123 &context2->LookaheadClassDef,
1126 orig_used = gstring->used;
1127 for (k = 0; k < rule->LookupCount; k++)
1128 lookup_gpos (lookup_list,
1129 rule->LookupRecord[k].LookupListIndex,
1131 gidx + rule->LookupRecord[k].SequenceIndex);
1132 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1136 else if (subtable->Format == 3)
1138 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1142 if (gidx < context3->BacktrackGlyphCount
1143 || (gidx + context3->InputGlyphCount
1144 + context3->LookaheadGlyphCount) > gstring->used)
1146 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1148 orig_used = gstring->used;
1149 for (j = 0; j < context3->LookupCount; j++)
1150 lookup_gpos (lookup_list,
1151 context3->LookupRecord[j].LookupListIndex,
1153 gidx + context3->LookupRecord[j].SequenceIndex);
1154 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1157 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1164 if (gidx == orig_gidx)
1170 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1174 for (i = 0; i < gstring->used; i++)
1176 c = gstring->glyphs[i].c;
1177 if (c < 0 || c >= 256)
1178 gstring->glyphs[i].glyph_id = 0;
1180 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1186 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1192 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1195 int segCount = sub4->segCountX2 / 2;
1197 for (i = 0; i < gstring->used; i++)
1199 c = gstring->glyphs[i].c;
1201 gstring->glyphs[i].glyph_id = 0;
1202 for (j = 0; j < segCount; j++)
1204 OTF_cmapSegument *seg = sub4->segments + i;
1206 if (c >= seg->startCount && c <= seg->endCount)
1208 if (seg->idRangeOffset == 0xFFFF)
1209 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1211 gstring->glyphs[i].glyph_id
1212 = sub4->glyphIdArray[seg->idRangeOffset
1213 + (c - seg->startCount)];
1223 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1229 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1235 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1241 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1251 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1257 && OTF_get_table (otf, "cmap") < 0)
1261 for (i = 0; i < gstring->used; i++)
1262 if (! gstring->glyphs[i].glyph_id)
1264 int c = gstring->glyphs[i].c;
1265 if (c < 32 || ! cmap->unicode_table)
1266 gstring->glyphs[i].glyph_id = 0;
1268 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1275 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1276 int platform_id, int encoding_id)
1280 char *errfmt = "CMAP Looking up%s";
1282 OTF_EncodingRecord *enc;
1285 && OTF_get_table (otf, "cmap") < 0)
1289 for (i = 0; i < cmap->numTables; i++)
1290 if (cmap->EncodingRecord[i].platformID == platform_id
1291 && cmap->EncodingRecord[i].encodingID == encoding_id)
1293 if (i == cmap->numTables)
1294 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1295 enc = cmap->EncodingRecord + i;
1296 switch (enc->subtable.format)
1298 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1299 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1300 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1301 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1302 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1303 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1304 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1306 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1311 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1314 && OTF_get_table (otf, "cmap") < 0)
1317 || code > otf->cmap->max_glyph_id
1318 || ! otf->cmap->decode_table)
1320 return otf->cmap->decode_table[code];
1324 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1330 && OTF_get_table (otf, "GDEF") < 0)
1334 if (gdef->glyph_class_def.offset)
1335 for (i = 0; i < gstring->used; i++)
1336 gstring->glyphs[i].GlyphClass
1337 = get_class_def (&gdef->glyph_class_def,
1338 gstring->glyphs[i].glyph_id);
1340 if (gdef->mark_attach_class_def.offset)
1341 for (i = 0; i < gstring->used; i++)
1342 gstring->glyphs[i].MarkAttachClass
1343 = get_class_def (&gdef->mark_attach_class_def,
1344 gstring->glyphs[i].glyph_id);
1350 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1351 const char *script, const char *language,
1352 const char *features,
1353 int alternate_subst)
1355 char *errfmt = "GSUB driving%s";
1358 OTF_LangSys *LangSys;
1359 int *lookup_indices;
1362 for (i = 0; i < gstring->used; i++)
1364 gstring->glyphs[i].positioning_type = 0;
1365 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1368 if (OTF_get_table (otf, "GSUB") < 0)
1371 if (gsub->FeatureList.FeatureCount == 0
1372 || gsub->LookupList.LookupCount == 0)
1375 LangSys = get_langsys (&gsub->ScriptList, script, language);
1379 /* One lookup may be used by multiple features. */
1380 lookup_indices = alloca (sizeof (int)
1381 * gsub->LookupList.LookupCount
1382 * (gsub->FeatureList.FeatureCount + 1));
1383 if (! lookup_indices)
1384 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1385 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1386 features, lookup_indices);
1390 for (i = 0; i < n; i++)
1392 int index = lookup_indices[i];
1395 if (gsub->LookupList.Lookup[index].LookupType != 8)
1398 while (gidx < gstring->used)
1400 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1408 gidx = gstring->used - 1;
1411 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1423 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1424 const char *script, const char *language, const char *features)
1426 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1430 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1431 const char *script, const char *language, const char *features)
1433 char *errfmt = "GPOS driving%s";
1436 OTF_LangSys *LangSys;
1437 int *lookup_indices;
1440 for (i = 0; i < gstring->used; i++)
1441 gstring->glyphs[i].positioning_type = 0;
1443 if (OTF_get_table (otf, "GPOS") < 0)
1446 if (gpos->FeatureList.FeatureCount == 0
1447 || gpos->LookupList.LookupCount == 0)
1450 LangSys = get_langsys (&gpos->ScriptList, script, language);
1454 /* One lookup may be used by multiple features. */
1455 lookup_indices = alloca (sizeof (int)
1456 * gpos->LookupList.LookupCount
1457 * (gpos->FeatureList.FeatureCount + 1));
1458 if (! lookup_indices)
1459 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1460 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1461 features, lookup_indices);
1465 for (i = 0; i < n; i++)
1467 int index = lookup_indices[i];
1470 while (gidx < gstring->used)
1472 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1482 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1483 const char *script, const char *language,
1484 const char *gsub_features, const char *gpos_features)
1486 if (OTF_drive_cmap (otf, gstring) < 0)
1488 if (OTF_drive_gdef (otf, gstring) < 0)
1491 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1494 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1500 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1501 const char *script, const char *language,
1502 const char *features)
1504 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);