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++)
106 gstring->glyphs[from + i].c = otf->cmap->decode_table[ids[i]];
108 gstring->glyphs[from + i].c = 0;
109 gstring->glyphs[from + i].glyph_id = ids[i];
111 gstring->glyphs[from + i].GlyphClass
112 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
114 gstring->glyphs[from + i].GlyphClass = 0;
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 const char *features, int *lookup_indices)
210 OTF_Feature *feature;
211 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
213 for (i = 0; i < FeatureList->FeatureCount; i++)
214 feature_table[i] = 0;
222 if (*features == '*')
224 /* Consume all remaining features. */
225 for (i = 0; i < FeatureList->FeatureCount; i++)
226 if (! feature_table[i])
228 feature = FeatureList->Feature + i;
229 for (j = 0; j < feature->LookupCount; j++)
230 lookup_indices[n++] = feature->LookupListIndex[j];
235 if (*features == '~')
236 use_it = -1, features++;
237 for (i = 0; *features && *features != ','; i++, features++)
238 tagname[i] = *features;
244 tag = OTF_tag (tagname);
245 for (i = 0; i < FeatureList->FeatureCount; i++)
247 feature = FeatureList->Feature + i;
248 if (tag == feature->FeatureTag)
250 if (feature_table[i])
253 for (j = 0; j < feature->LookupCount; j++)
254 lookup_indices[n++] = feature->LookupListIndex[j];
255 feature_table[i] = use_it;
265 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
266 int count, OTF_GlyphID *ids)
268 OTF_Glyph *gbeg = gstring->glyphs + gidx;
269 OTF_Glyph *gend = gstring->glyphs + gstring->used;
273 for (g = gbeg, i = 0; g < gend && i < count; g++)
274 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
276 return (i < count ? -1 : g - gbeg);
280 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
283 int i = rule->BacktrackGlyphCount;
290 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
291 if (! IGNORED_GLYPH (g, flag) && --i == 0)
295 if (match_ids (gstring, j, flag,
296 rule->BacktrackGlyphCount, rule->Backtrack)
301 i = match_ids (gstring, gidx, flag,
302 rule->InputGlyphCount - 1, rule->Input);
306 i = match_ids (gstring, gidx, flag,
307 rule->LookaheadGlyphCount, rule->LookAhead);
314 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
315 int flag, int count, unsigned *classes)
317 OTF_Glyph *gbeg = gstring->glyphs + gidx;
318 OTF_Glyph *gend = gstring->glyphs + gstring->used;
322 for (g = gbeg, i = 0; g < gend && i < count; g++)
323 if (! IGNORED_GLYPH (g, flag)
324 && get_class_def (class_def, g->glyph_id) != classes[i++])
326 return (i < count ? -1 : g - gbeg);
330 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
331 OTF_ClassDef *BacktrackClassDef,
332 OTF_ClassDef *InputClassDef,
333 OTF_ClassDef *LookaheadClassDef,
334 OTF_ChainClassRule *rule)
336 int i = rule->BacktrackGlyphCount;
343 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
344 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
348 if (match_classes (BacktrackClassDef, gstring, j, flag,
349 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
353 i = match_classes (InputClassDef, gstring, gidx, flag,
354 rule->InputGlyphCount - 1, rule->Input);
358 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
359 rule->LookaheadGlyphCount, rule->LookAhead);
367 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
368 OTF_Coverage *coverages)
370 OTF_Glyph *gbeg = gstring->glyphs + gidx;
371 OTF_Glyph *gend = gstring->glyphs + gstring->used;
375 for (g = gbeg, i = 0; g < gend && i < count; g++)
376 if (! IGNORED_GLYPH (g, flag)
377 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
379 return (i < count ? -1 : g - gbeg);
383 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
384 OTF_GSUB_ChainContext3 *context3)
386 int i = context3->BacktrackGlyphCount;
393 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
394 if (! IGNORED_GLYPH (g, flag) && --i == 0)
398 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
399 context3->Backtrack) < 0)
403 if (context3->InputGlyphCount > 1)
405 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
406 context3->Input + 1);
411 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
412 context3->LookAhead) < 0)
418 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
419 OTF_GlyphString *gstring, int gidx, int alternate_subst)
421 char *errfmt = "GSUB Looking up%s";
423 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
424 unsigned int flag = (lookup->LookupFlag
425 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
426 int orig_gidx = gidx;
427 OTF_Glyph *g = gstring->glyphs + gidx;
430 if (IGNORED_GLYPH (g, flag))
433 /* Try all subtables until one of them handles the current glyph. */
434 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
436 unsigned lookup_type = lookup->LookupType;
437 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
440 if (lookup_type == 7)
442 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
444 lookup_type = extension1->ExtensionLookupType;
445 subtable = extension1->ExtensionSubtable;
449 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
450 : (lookup_type == 3))
453 if (subtable->Coverage.offset)
455 coverage_idx = get_coverage_index (&subtable->Coverage,
457 if (coverage_idx < 0)
464 if (subtable->Format == 1)
465 g->glyph_id += subtable->u.single1.DeltaGlyphID;
467 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
472 if (subtable->Format == 1)
474 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
475 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
477 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
478 seq->Substitute, seq->GlyphCount);
479 gidx += seq->GlyphCount;
482 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
486 if (subtable->Format == 1)
488 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
489 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
491 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
492 altset->Alternate, altset->GlyphCount);
493 gidx += altset->GlyphCount;;
496 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
500 if (subtable->Format == 1)
502 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
503 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
507 for (j = 0; j < ligset->LigatureCount; j++)
511 lig = ligset->Ligature + j;
512 n = match_ids (gstring, gidx + 1, flag,
513 lig->CompCount - 1, lig->Component);
516 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
523 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
527 if (subtable->Format == 1)
529 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
530 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
535 for (j = 0; j < set->RuleCount; j++)
537 rule = set->Rule + j;
538 if (match_ids (gstring, gidx + 1, flag,
539 rule->GlyphCount - 1, rule->Input) < 0)
541 orig_used = gstring->used;
542 for (k = 0; k < rule->LookupCount; k++)
543 lookup_gsub (otf, lookup_list,
544 rule->LookupRecord[k].LookupListIndex,
546 gidx + rule->LookupRecord[k].SequenceIndex,
548 gidx += rule->GlyphCount + (gstring->used - orig_used);
552 else if (subtable->Format == 2)
554 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
561 class = get_class_def (&context2->ClassDef, g->glyph_id);
562 set = context2->ClassSet + class;
564 for (j = 0; j < set->ClassRuleCnt; j++)
566 rule = set->ClassRule + j;
567 if (match_classes (&context2->ClassDef,
568 gstring, gidx + 1, flag,
569 rule->GlyphCount - 1, rule->Class)
572 orig_used = gstring->used;
573 for (k = 0; k < rule->LookupCount; k++)
574 lookup_gsub (otf, lookup_list,
575 rule->LookupRecord[k].LookupListIndex,
577 gidx + rule->LookupRecord[k].SequenceIndex,
579 gidx += rule->GlyphCount + (gstring->used - orig_used);
583 else /* subtable->Format == 3 */
585 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
589 if (match_coverages (gstring, gidx + 1, flag,
590 context3->GlyphCount - 1,
591 context3->Coverage + 1) < 0)
593 orig_used = gstring->used;
594 for (j = 0; j < context3->LookupCount; j++)
595 lookup_gsub (otf, lookup_list,
596 context3->LookupRecord[j].LookupListIndex,
598 gidx + context3->LookupRecord[j].SequenceIndex,
600 gidx += context3->GlyphCount + (gstring->used - orig_used);
605 if (subtable->Format == 1)
607 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
608 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
612 for (j = 0; j < set->ChainRuleCount; j++)
614 OTF_ChainRule *rule = set->ChainRule + j;
616 if (gidx < rule->BacktrackGlyphCount
617 || (gidx + rule->InputGlyphCount
618 + rule->LookaheadGlyphCount) > gstring->used)
620 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
622 orig_used = gstring->used;
623 for (k = 0; k < rule->LookupCount; k++)
624 lookup_gsub (otf, lookup_list,
625 rule->LookupRecord[k].LookupListIndex,
627 gidx + rule->LookupRecord[k].SequenceIndex,
629 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
633 else if (subtable->Format == 2)
635 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
636 OTF_ChainClassSet *set;
641 class = get_class_def (&context2->InputClassDef, g->glyph_id);
642 set = context2->ChainClassSet + class;
643 for (j = 0; j < set->ChainClassRuleCnt; j++)
645 OTF_ChainClassRule *rule = set->ChainClassRule + j;
648 if (gidx < rule->BacktrackGlyphCount
649 || (gidx + rule->InputGlyphCount
650 + rule->LookaheadGlyphCount) > gstring->used)
652 if (match_chain_classes (gstring, gidx, flag,
653 &context2->BacktrackClassDef,
654 &context2->InputClassDef,
655 &context2->LookaheadClassDef,
658 orig_used = gstring->used;
659 for (k = 0; k < rule->LookupCount; k++)
660 lookup_gsub (otf, lookup_list,
661 rule->LookupRecord[k].LookupListIndex,
663 gidx + rule->LookupRecord[k].SequenceIndex,
665 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
671 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
675 if (gidx < context3->BacktrackGlyphCount
676 || (gidx + context3->InputGlyphCount
677 + context3->LookaheadGlyphCount) > gstring->used)
679 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
681 orig_used = gstring->used;
682 for (j = 0; j < context3->LookupCount; j++)
683 lookup_gsub (otf, lookup_list,
684 context3->LookupRecord[j].LookupListIndex,
686 gidx + context3->LookupRecord[j].SequenceIndex,
688 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
694 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
695 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
696 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
699 if (back_gidx > gstring->used || ahead_gidx < 0)
702 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
703 if (get_coverage_index (reverse->Backtrack + j,
704 gstring->glyphs[gidx + 1 + j].glyph_id)
707 if (j < reverse->BacktrackGlyphCount)
709 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
710 if (get_coverage_index (reverse->LookAhead + j,
711 gstring->glyphs[gidx - 1 - j].glyph_id)
714 if (j < reverse->LookaheadGlyphCount)
716 g->glyph_id = reverse->Substitute[coverage_idx];
724 if (gidx == orig_gidx)
733 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
735 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
737 rec->XPlacement = anchor->XCoordinate;
738 rec->YPlacement = anchor->YCoordinate;
739 if (anchor->AnchorFormat == 1)
742 else if (anchor->AnchorFormat == 2)
743 /* Not yet implemented */
745 else if (anchor->AnchorFormat == 3)
746 /* Not yet implemented */
753 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
754 OTF_GlyphString *gstring, int gidx)
756 char *errfmt = "GPOS Looking up%s";
758 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
759 unsigned int flag = (lookup->LookupFlag
760 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
761 int orig_gidx = gidx;
762 OTF_Glyph *g = gstring->glyphs + gidx;
765 if (IGNORED_GLYPH (g, flag)
766 || g->positioning_type)
769 /* Try all subtables until one of them handles the current glyph. */
770 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
772 unsigned lookup_type = lookup->LookupType;
773 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
776 if (lookup_type == 9)
778 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
780 lookup_type = extension1->ExtensionLookupType;
781 subtable = extension1->ExtensionSubtable;
784 if (subtable->Coverage.offset)
786 coverage_idx = get_coverage_index (&subtable->Coverage,
788 if (coverage_idx < 0)
795 g->positioning_type = lookup_type;
796 if (subtable->Format == 1)
798 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
800 g->f.f1.format = single1->ValueFormat;
801 g->f.f1.value = &single1->Value;
803 else if (subtable->Format == 2)
805 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
807 g->f.f1.format = single2->ValueFormat;
808 g->f.f1.value = single2->Value + coverage_idx;
817 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
818 next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
819 next_gidx++, nextg++);
821 if (next_gidx >= gstring->used
822 || nextg->positioning_type)
824 if (subtable->Format == 1)
826 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
827 OTF_PairSet *set = pair1->PairSet + coverage_idx;
830 for (j = 0; j < set->PairValueCount; j++)
831 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
833 if (pair1->ValueFormat1)
835 g->positioning_type = lookup_type;
836 g->f.f2.format = pair1->ValueFormat1;
837 g->f.f2.value = &set->PairValueRecord[j].Value1;
840 if (pair1->ValueFormat2)
842 nextg->positioning_type = lookup_type;
843 nextg->f.f2.format = pair1->ValueFormat2;
844 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
850 else if (subtable->Format == 2)
852 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
853 unsigned class1, class2;
855 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
856 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
857 if (pair2->ValueFormat1)
859 g->positioning_type = lookup_type;
860 g->f.f2.format = pair2->ValueFormat1;
862 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
865 if (pair2->ValueFormat2)
867 nextg->positioning_type = lookup_type;
868 nextg->f.f2.format = pair2->ValueFormat2;
870 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
879 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
881 g->positioning_type = lookup_type;
883 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
885 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
892 if (subtable->Format == 1)
894 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
895 OTF_MarkRecord *mark_record;
896 OTF_AnchorRecord *base_record;
898 int coverage_idx_base;
899 unsigned int this_flag = flag | OTF_IgnoreMarks;
902 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
904 if (baseg < gstring->glyphs)
907 = get_coverage_index (&mark_base1->BaseCoverage,
909 if (coverage_idx_base < 0)
911 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
913 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
914 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
916 = &base_record->Anchor[mark_record->Class];
917 g->positioning_type = lookup_type;
924 if (subtable->Format == 1)
926 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
928 int coverage_idx_lig;
929 OTF_MarkRecord *mark_record;
930 OTF_LigatureAttach *attach;
931 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
934 for (j = 0; j < mark_lig1->ClassCount; j++)
938 (ligg >= gstring->glyphs
939 && (IGNORED_GLYPH (ligg, flag)
940 || ligg->GlyphClass > OTF_GlyphClassLigature));
942 if (ligg->positioning_type == 5
943 && ligg->MarkAttachClass < mark_lig1->ClassCount)
944 num_class[ligg->MarkAttachClass]++;
945 if (ligg < gstring->glyphs)
948 = get_coverage_index (&mark_lig1->LigatureCoverage,
950 if (coverage_idx_lig < 0)
952 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
953 g->MarkAttachClass = mark_record->Class;
954 attach = (mark_lig1->LigatureArray.LigatureAttach
956 for (j = 0; j < attach->ComponentCount; j++)
958 OTF_Anchor *lig_anchor
959 = attach->ComponentRecord[j].LigatureAnchor;
961 if (lig_anchor[mark_record->Class].AnchorFormat
962 && num_class[mark_record->Class]-- == 0)
964 g->positioning_type = lookup_type;
965 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
966 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
976 if (subtable->Format == 1)
978 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
979 OTF_MarkRecord *mark1_record;
980 OTF_AnchorRecord *mark2_record;
982 int coverage_idx_base;
985 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
987 if (prevg < gstring->glyphs)
990 = get_coverage_index (&mark_mark1->Mark2Coverage,
992 if (coverage_idx_base < 0)
994 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
996 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
997 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
999 = &mark2_record->Anchor[mark1_record->Class];
1000 g->positioning_type = lookup_type;
1006 if (subtable->Format == 1)
1008 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1009 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1014 for (j = 0; j < set->RuleCount; j++)
1016 rule = set->Rule + j;
1017 if (match_ids (gstring, gidx + 1, flag,
1018 rule->GlyphCount - 1, rule->Input) < 0)
1020 orig_used = gstring->used;
1021 for (k = 0; k < rule->LookupCount; k++)
1022 lookup_gpos (lookup_list,
1023 rule->LookupRecord[k].LookupListIndex,
1025 gidx + rule->LookupRecord[k].SequenceIndex);
1026 gidx += rule->GlyphCount + (gstring->used - orig_used);
1030 else if (subtable->Format == 2)
1032 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1034 OTF_ClassRule *rule;
1039 class = get_class_def (&context2->ClassDef, g->glyph_id);
1040 set = context2->ClassSet + class;
1042 for (j = 0; j < set->ClassRuleCnt; j++)
1044 rule = set->ClassRule + j;
1045 if (match_classes (&context2->ClassDef,
1046 gstring, gidx + 1, flag,
1047 rule->GlyphCount - 1, rule->Class)
1050 orig_used = gstring->used;
1051 for (k = 0; k < rule->LookupCount; k++)
1052 lookup_gpos (lookup_list,
1053 rule->LookupRecord[k].LookupListIndex,
1055 gidx + rule->LookupRecord[k].SequenceIndex);
1056 gidx += rule->GlyphCount + (gstring->used - orig_used);
1060 else /* subtable->Format == 3 */
1062 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1066 if (match_coverages (gstring, gidx + 1, flag,
1067 context3->GlyphCount - 1,
1068 context3->Coverage + 1) < 0)
1070 orig_used = gstring->used;
1071 for (j = 0; j < context3->LookupCount; j++)
1072 lookup_gpos (lookup_list,
1073 context3->LookupRecord[j].LookupListIndex,
1075 gidx + context3->LookupRecord[j].SequenceIndex);
1076 gidx += context3->GlyphCount + (gstring->used - orig_used);
1081 if (subtable->Format == 1)
1083 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1084 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1088 for (j = 0; j < set->ChainRuleCount; j++)
1090 OTF_ChainRule *rule = set->ChainRule + j;
1092 if (gidx < rule->BacktrackGlyphCount
1093 || (gidx + rule->InputGlyphCount
1094 + rule->LookaheadGlyphCount) > gstring->used)
1096 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1098 orig_used = gstring->used;
1099 for (k = 0; k < rule->LookupCount; k++)
1100 lookup_gpos (lookup_list,
1101 rule->LookupRecord[k].LookupListIndex,
1103 gidx + rule->LookupRecord[k].SequenceIndex);
1104 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1108 else if (subtable->Format == 2)
1110 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1111 OTF_ChainClassSet *set;
1116 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1117 set = context2->ChainClassSet + class;
1118 for (j = 0; j < set->ChainClassRuleCnt; j++)
1120 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1123 if (gidx < rule->BacktrackGlyphCount
1124 || (gidx + rule->InputGlyphCount
1125 + rule->LookaheadGlyphCount) > gstring->used)
1127 if (match_chain_classes (gstring, gidx, flag,
1128 &context2->BacktrackClassDef,
1129 &context2->InputClassDef,
1130 &context2->LookaheadClassDef,
1133 orig_used = gstring->used;
1134 for (k = 0; k < rule->LookupCount; k++)
1135 lookup_gpos (lookup_list,
1136 rule->LookupRecord[k].LookupListIndex,
1138 gidx + rule->LookupRecord[k].SequenceIndex);
1139 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1143 else if (subtable->Format == 3)
1145 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1149 if (gidx < context3->BacktrackGlyphCount
1150 || (gidx + context3->InputGlyphCount
1151 + context3->LookaheadGlyphCount) > gstring->used)
1153 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1155 orig_used = gstring->used;
1156 for (j = 0; j < context3->LookupCount; j++)
1157 lookup_gpos (lookup_list,
1158 context3->LookupRecord[j].LookupListIndex,
1160 gidx + context3->LookupRecord[j].SequenceIndex);
1161 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1164 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1171 if (gidx == orig_gidx)
1177 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1181 for (i = 0; i < gstring->used; i++)
1183 c = gstring->glyphs[i].c;
1184 if (c < 0 || c >= 256)
1185 gstring->glyphs[i].glyph_id = 0;
1187 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1193 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1199 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1202 int segCount = sub4->segCountX2 / 2;
1204 for (i = 0; i < gstring->used; i++)
1206 c = gstring->glyphs[i].c;
1208 gstring->glyphs[i].glyph_id = 0;
1209 for (j = 0; j < segCount; j++)
1211 OTF_cmapSegument *seg = sub4->segments + i;
1213 if (c >= seg->startCount && c <= seg->endCount)
1215 if (seg->idRangeOffset == 0xFFFF)
1216 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1218 gstring->glyphs[i].glyph_id
1219 = sub4->glyphIdArray[seg->idRangeOffset
1220 + (c - seg->startCount)];
1230 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1236 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1242 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1248 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1258 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1264 && OTF_get_table (otf, "cmap") < 0)
1268 for (i = 0; i < gstring->used; i++)
1269 if (! gstring->glyphs[i].glyph_id)
1271 int c = gstring->glyphs[i].c;
1272 if (c < 32 || ! cmap->unicode_table)
1273 gstring->glyphs[i].glyph_id = 0;
1275 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1282 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1283 int platform_id, int encoding_id)
1287 char *errfmt = "CMAP Looking up%s";
1289 OTF_EncodingRecord *enc;
1292 && OTF_get_table (otf, "cmap") < 0)
1296 for (i = 0; i < cmap->numTables; i++)
1297 if (cmap->EncodingRecord[i].platformID == platform_id
1298 && cmap->EncodingRecord[i].encodingID == encoding_id)
1300 if (i == cmap->numTables)
1301 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1302 enc = cmap->EncodingRecord + i;
1303 switch (enc->subtable.format)
1305 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1306 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1307 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1308 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1309 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1310 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1311 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1313 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1318 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1321 && OTF_get_table (otf, "cmap") < 0)
1324 || code > otf->cmap->max_glyph_id
1325 || ! otf->cmap->decode_table)
1327 return otf->cmap->decode_table[code];
1331 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1337 && OTF_get_table (otf, "GDEF") < 0)
1341 if (gdef->glyph_class_def.offset)
1342 for (i = 0; i < gstring->used; i++)
1343 gstring->glyphs[i].GlyphClass
1344 = get_class_def (&gdef->glyph_class_def,
1345 gstring->glyphs[i].glyph_id);
1347 if (gdef->mark_attach_class_def.offset)
1348 for (i = 0; i < gstring->used; i++)
1349 gstring->glyphs[i].MarkAttachClass
1350 = get_class_def (&gdef->mark_attach_class_def,
1351 gstring->glyphs[i].glyph_id);
1357 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1358 const char *script, const char *language,
1359 const char *features,
1360 int alternate_subst)
1362 char *errfmt = "GSUB driving%s";
1365 OTF_LangSys *LangSys;
1366 int *lookup_indices;
1369 for (i = 0; i < gstring->used; i++)
1371 gstring->glyphs[i].positioning_type = 0;
1372 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1375 if (OTF_get_table (otf, "GSUB") < 0)
1378 if (gsub->FeatureList.FeatureCount == 0
1379 || gsub->LookupList.LookupCount == 0)
1382 LangSys = get_langsys (&gsub->ScriptList, script, language);
1386 /* One lookup may be used by multiple features. */
1387 lookup_indices = alloca (sizeof (int)
1388 * gsub->LookupList.LookupCount
1389 * (gsub->FeatureList.FeatureCount + 1));
1390 if (! lookup_indices)
1391 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1392 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1393 features, lookup_indices);
1397 for (i = 0; i < n; i++)
1399 int index = lookup_indices[i];
1402 if (gsub->LookupList.Lookup[index].LookupType != 8)
1405 while (gidx < gstring->used)
1407 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1415 gidx = gstring->used - 1;
1418 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1430 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1431 const char *script, const char *language, const char *features)
1434 OTF_get_table (otf, "cmap");
1435 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1439 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1440 const char *script, const char *language, const char *features)
1442 char *errfmt = "GPOS driving%s";
1445 OTF_LangSys *LangSys;
1446 int *lookup_indices;
1449 for (i = 0; i < gstring->used; i++)
1450 gstring->glyphs[i].positioning_type = 0;
1452 if (OTF_get_table (otf, "GPOS") < 0)
1455 if (gpos->FeatureList.FeatureCount == 0
1456 || gpos->LookupList.LookupCount == 0)
1459 LangSys = get_langsys (&gpos->ScriptList, script, language);
1463 /* One lookup may be used by multiple features. */
1464 lookup_indices = alloca (sizeof (int)
1465 * gpos->LookupList.LookupCount
1466 * (gpos->FeatureList.FeatureCount + 1));
1467 if (! lookup_indices)
1468 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1469 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1470 features, lookup_indices);
1474 for (i = 0; i < n; i++)
1476 int index = lookup_indices[i];
1479 while (gidx < gstring->used)
1481 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1491 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1492 const char *script, const char *language,
1493 const char *gsub_features, const char *gpos_features)
1495 if (OTF_drive_cmap (otf, gstring) < 0)
1497 if (OTF_drive_gdef (otf, gstring) < 0)
1500 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1503 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1509 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1510 const char *script, const char *language,
1511 const char *features)
1513 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);