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;
901 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
903 if (baseg < gstring->glyphs)
906 = get_coverage_index (&mark_base1->BaseCoverage,
908 if (coverage_idx_base < 0)
910 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
912 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
913 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
915 = &base_record->Anchor[mark_record->Class];
916 g->positioning_type = lookup_type;
923 if (subtable->Format == 1)
925 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
927 int coverage_idx_lig;
928 OTF_MarkRecord *mark_record;
929 OTF_LigatureAttach *attach;
930 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
933 for (j = 0; j < mark_lig1->ClassCount; j++)
937 (ligg >= gstring->glyphs
938 && (IGNORED_GLYPH (ligg, flag)
939 || ligg->GlyphClass > OTF_GlyphClassLigature));
941 if (ligg->positioning_type == 5
942 && ligg->MarkAttachClass < mark_lig1->ClassCount)
943 num_class[ligg->MarkAttachClass]++;
944 if (ligg < gstring->glyphs)
947 = get_coverage_index (&mark_lig1->LigatureCoverage,
949 if (coverage_idx_lig < 0)
951 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
952 g->MarkAttachClass = mark_record->Class;
953 attach = (mark_lig1->LigatureArray.LigatureAttach
955 for (j = 0; j < attach->ComponentCount; j++)
957 OTF_Anchor *lig_anchor
958 = attach->ComponentRecord[j].LigatureAnchor;
960 if (lig_anchor[mark_record->Class].AnchorFormat
961 && num_class[mark_record->Class]-- == 0)
963 g->positioning_type = lookup_type;
964 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
965 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
975 if (subtable->Format == 1)
977 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
978 OTF_MarkRecord *mark1_record;
979 OTF_AnchorRecord *mark2_record;
981 int coverage_idx_base;
984 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
986 if (prevg < gstring->glyphs)
989 = get_coverage_index (&mark_mark1->Mark2Coverage,
991 if (coverage_idx_base < 0)
993 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
995 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
996 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
998 = &mark2_record->Anchor[mark1_record->Class];
999 g->positioning_type = lookup_type;
1005 if (subtable->Format == 1)
1007 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1008 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1013 for (j = 0; j < set->RuleCount; j++)
1015 rule = set->Rule + j;
1016 if (match_ids (gstring, gidx + 1, flag,
1017 rule->GlyphCount - 1, rule->Input) < 0)
1019 orig_used = gstring->used;
1020 for (k = 0; k < rule->LookupCount; k++)
1021 lookup_gpos (lookup_list,
1022 rule->LookupRecord[k].LookupListIndex,
1024 gidx + rule->LookupRecord[k].SequenceIndex);
1025 gidx += rule->GlyphCount + (gstring->used - orig_used);
1029 else if (subtable->Format == 2)
1031 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1033 OTF_ClassRule *rule;
1038 class = get_class_def (&context2->ClassDef, g->glyph_id);
1039 set = context2->ClassSet + class;
1041 for (j = 0; j < set->ClassRuleCnt; j++)
1043 rule = set->ClassRule + j;
1044 if (match_classes (&context2->ClassDef,
1045 gstring, gidx + 1, flag,
1046 rule->GlyphCount - 1, rule->Class)
1049 orig_used = gstring->used;
1050 for (k = 0; k < rule->LookupCount; k++)
1051 lookup_gpos (lookup_list,
1052 rule->LookupRecord[k].LookupListIndex,
1054 gidx + rule->LookupRecord[k].SequenceIndex);
1055 gidx += rule->GlyphCount + (gstring->used - orig_used);
1059 else /* subtable->Format == 3 */
1061 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1065 if (match_coverages (gstring, gidx + 1, flag,
1066 context3->GlyphCount - 1,
1067 context3->Coverage + 1) < 0)
1069 orig_used = gstring->used;
1070 for (j = 0; j < context3->LookupCount; j++)
1071 lookup_gpos (lookup_list,
1072 context3->LookupRecord[j].LookupListIndex,
1074 gidx + context3->LookupRecord[j].SequenceIndex);
1075 gidx += context3->GlyphCount + (gstring->used - orig_used);
1080 if (subtable->Format == 1)
1082 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1083 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1087 for (j = 0; j < set->ChainRuleCount; j++)
1089 OTF_ChainRule *rule = set->ChainRule + j;
1091 if (gidx < rule->BacktrackGlyphCount
1092 || (gidx + rule->InputGlyphCount
1093 + rule->LookaheadGlyphCount) > gstring->used)
1095 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1097 orig_used = gstring->used;
1098 for (k = 0; k < rule->LookupCount; k++)
1099 lookup_gpos (lookup_list,
1100 rule->LookupRecord[k].LookupListIndex,
1102 gidx + rule->LookupRecord[k].SequenceIndex);
1103 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1107 else if (subtable->Format == 2)
1109 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1110 OTF_ChainClassSet *set;
1115 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1116 set = context2->ChainClassSet + class;
1117 for (j = 0; j < set->ChainClassRuleCnt; j++)
1119 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1122 if (gidx < rule->BacktrackGlyphCount
1123 || (gidx + rule->InputGlyphCount
1124 + rule->LookaheadGlyphCount) > gstring->used)
1126 if (match_chain_classes (gstring, gidx, flag,
1127 &context2->BacktrackClassDef,
1128 &context2->InputClassDef,
1129 &context2->LookaheadClassDef,
1132 orig_used = gstring->used;
1133 for (k = 0; k < rule->LookupCount; k++)
1134 lookup_gpos (lookup_list,
1135 rule->LookupRecord[k].LookupListIndex,
1137 gidx + rule->LookupRecord[k].SequenceIndex);
1138 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1142 else if (subtable->Format == 3)
1144 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1148 if (gidx < context3->BacktrackGlyphCount
1149 || (gidx + context3->InputGlyphCount
1150 + context3->LookaheadGlyphCount) > gstring->used)
1152 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1154 orig_used = gstring->used;
1155 for (j = 0; j < context3->LookupCount; j++)
1156 lookup_gpos (lookup_list,
1157 context3->LookupRecord[j].LookupListIndex,
1159 gidx + context3->LookupRecord[j].SequenceIndex);
1160 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1163 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1170 if (gidx == orig_gidx)
1176 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1180 for (i = 0; i < gstring->used; i++)
1182 c = gstring->glyphs[i].c;
1183 if (c < 0 || c >= 256)
1184 gstring->glyphs[i].glyph_id = 0;
1186 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1192 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1198 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1201 int segCount = sub4->segCountX2 / 2;
1203 for (i = 0; i < gstring->used; i++)
1205 c = gstring->glyphs[i].c;
1207 gstring->glyphs[i].glyph_id = 0;
1208 for (j = 0; j < segCount; j++)
1210 OTF_cmapSegument *seg = sub4->segments + i;
1212 if (c >= seg->startCount && c <= seg->endCount)
1214 if (seg->idRangeOffset == 0xFFFF)
1215 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1217 gstring->glyphs[i].glyph_id
1218 = sub4->glyphIdArray[seg->idRangeOffset
1219 + (c - seg->startCount)];
1229 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1235 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1241 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1247 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1257 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1263 && OTF_get_table (otf, "cmap") < 0)
1267 for (i = 0; i < gstring->used; i++)
1268 if (! gstring->glyphs[i].glyph_id)
1270 int c = gstring->glyphs[i].c;
1271 if (c < 32 || ! cmap->unicode_table)
1272 gstring->glyphs[i].glyph_id = 0;
1274 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1281 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1282 int platform_id, int encoding_id)
1286 char *errfmt = "CMAP Looking up%s";
1288 OTF_EncodingRecord *enc;
1291 && OTF_get_table (otf, "cmap") < 0)
1295 for (i = 0; i < cmap->numTables; i++)
1296 if (cmap->EncodingRecord[i].platformID == platform_id
1297 && cmap->EncodingRecord[i].encodingID == encoding_id)
1299 if (i == cmap->numTables)
1300 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1301 enc = cmap->EncodingRecord + i;
1302 switch (enc->subtable.format)
1304 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1305 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1306 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1307 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1308 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1309 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1310 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1312 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1317 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1320 && OTF_get_table (otf, "cmap") < 0)
1323 || code > otf->cmap->max_glyph_id
1324 || ! otf->cmap->decode_table)
1326 return otf->cmap->decode_table[code];
1330 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1336 && OTF_get_table (otf, "GDEF") < 0)
1340 if (gdef->glyph_class_def.offset)
1341 for (i = 0; i < gstring->used; i++)
1342 gstring->glyphs[i].GlyphClass
1343 = get_class_def (&gdef->glyph_class_def,
1344 gstring->glyphs[i].glyph_id);
1346 if (gdef->mark_attach_class_def.offset)
1347 for (i = 0; i < gstring->used; i++)
1348 gstring->glyphs[i].MarkAttachClass
1349 = get_class_def (&gdef->mark_attach_class_def,
1350 gstring->glyphs[i].glyph_id);
1356 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1357 const char *script, const char *language,
1358 const char *features,
1359 int alternate_subst)
1361 char *errfmt = "GSUB driving%s";
1364 OTF_LangSys *LangSys;
1365 int *lookup_indices;
1368 for (i = 0; i < gstring->used; i++)
1370 gstring->glyphs[i].positioning_type = 0;
1371 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1374 if (OTF_get_table (otf, "GSUB") < 0)
1377 if (gsub->FeatureList.FeatureCount == 0
1378 || gsub->LookupList.LookupCount == 0)
1381 LangSys = get_langsys (&gsub->ScriptList, script, language);
1385 /* One lookup may be used by multiple features. */
1386 lookup_indices = alloca (sizeof (int)
1387 * gsub->LookupList.LookupCount
1388 * (gsub->FeatureList.FeatureCount + 1));
1389 if (! lookup_indices)
1390 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1391 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1392 features, lookup_indices);
1396 for (i = 0; i < n; i++)
1398 int index = lookup_indices[i];
1401 if (gsub->LookupList.Lookup[index].LookupType != 8)
1404 while (gidx < gstring->used)
1406 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1414 gidx = gstring->used - 1;
1417 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1429 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1430 const char *script, const char *language, const char *features)
1433 OTF_get_table (otf, "cmap");
1434 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1438 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1439 const char *script, const char *language, const char *features)
1441 char *errfmt = "GPOS driving%s";
1444 OTF_LangSys *LangSys;
1445 int *lookup_indices;
1448 for (i = 0; i < gstring->used; i++)
1449 gstring->glyphs[i].positioning_type = 0;
1451 if (OTF_get_table (otf, "GPOS") < 0)
1454 if (gpos->FeatureList.FeatureCount == 0
1455 || gpos->LookupList.LookupCount == 0)
1458 LangSys = get_langsys (&gpos->ScriptList, script, language);
1462 /* One lookup may be used by multiple features. */
1463 lookup_indices = alloca (sizeof (int)
1464 * gpos->LookupList.LookupCount
1465 * (gpos->FeatureList.FeatureCount + 1));
1466 if (! lookup_indices)
1467 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1468 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1469 features, lookup_indices);
1473 for (i = 0; i < n; i++)
1475 int index = lookup_indices[i];
1478 while (gidx < gstring->used)
1480 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1490 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1491 const char *script, const char *language,
1492 const char *gsub_features, const char *gpos_features)
1494 if (OTF_drive_cmap (otf, gstring) < 0)
1496 if (OTF_drive_gdef (otf, gstring) < 0)
1499 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1502 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1508 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1509 const char *script, const char *language,
1510 const char *features)
1512 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);