1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
32 /* Return nonzero if OTF_Glyph *G should be ignored according to
34 #define IGNORED_GLYPH(g, flag) \
36 || ((flag) & (1 << (g)->GlyphClass)) \
37 || (((flag) & OTF_MarkAttachmentType) \
38 && (g)->GlyphClass == OTF_GlyphClassMark \
39 && ((flag) >> 8) != (g)->MarkAttachClass))
41 #define GSTRING_DELETE(gstring, from, len) \
43 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
44 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
45 gstring->used -= len; \
49 #define GSTRING_INSERT(gstring, pos, len) \
51 if (gstring->used + len > gstring->size) \
53 char *errfmt = "GSTRING%s"; \
55 gstring->size = gstring->used + len; \
57 = (OTF_Glyph *) realloc (gstring->glyphs, \
58 sizeof (OTF_Glyph) * gstring->size); \
59 if (! gstring->glyphs) \
60 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
62 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
63 sizeof (OTF_Glyph) * (gstring->used - pos)); \
64 gstring->used += len; \
69 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
70 OTF_GlyphID *ids, int num)
75 int from_idx = gstring->glyphs[from].f.index.from;
76 int to_idx = gstring->glyphs[to - 1].f.index.to;
79 for (i = non_ignored_idx = to - 1; i >= from; i--)
81 OTF_Glyph *g = gstring->glyphs + i;
82 if (IGNORED_GLYPH (g, flag))
86 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
87 temp.f.index.from = from_idx;
88 temp.f.index.to = to_idx;
89 gstring->glyphs[non_ignored_idx--] = temp;
95 GSTRING_INSERT (gstring, from, (num - len));
97 GSTRING_DELETE (gstring, from, (len - num));
98 for (i = 0; i < num; i++)
100 gstring->glyphs[from + i].c = otf->cmap->decode_table[ids[i]];
101 gstring->glyphs[from + i].glyph_id = ids[i];
102 gstring->glyphs[from + i].f.index.from = from_idx;
103 gstring->glyphs[from + i].f.index.to = to_idx;
110 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
114 if (coverage->CoverageFormat == 1)
116 for (i = 0; i < coverage->Count; i++)
117 if (coverage->table.GlyphArray[i] == id)
122 for (i = 0; i < coverage->Count; i++)
123 if (coverage->table.RangeRecord[i].Start <= id
124 && coverage->table.RangeRecord[i].End >= id)
125 return (coverage->table.RangeRecord[i].StartCoverageIndex
126 + (id - coverage->table.RangeRecord[i].Start));
132 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
134 if (class_def->ClassFormat == 1)
136 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
138 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
139 return class_def->f.f1.ClassValueArray[idx];
145 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
146 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
147 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
148 return class_def->f.f2.ClassRangeRecord[i].Class;
154 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
157 OTF_Tag script_tag = OTF_tag (script);
158 OTF_Tag langsys_tag = OTF_tag (language);
160 OTF_Tag dflt_tag = OTF_tag ("DFLT");
161 OTF_Script *dflt = NULL;
163 for (i = 0; i < script_list->ScriptCount; i++)
165 OTF_Script *script = script_list->Script + i;
167 if (script_list->Script[i].ScriptTag == dflt_tag)
169 if (script_list->Script[i].ScriptTag == script_tag)
172 return &script->DefaultLangSys;
173 for (j = 0; j < script->LangSysCount; j++)
174 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
175 return script->LangSys + j;
176 return &script->DefaultLangSys;
181 dflt = script_list->Script;
183 return &dflt->DefaultLangSys;
184 for (j = 0; j < dflt->LangSysCount; j++)
185 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
186 return dflt->LangSys + j;
187 return &dflt->DefaultLangSys;
191 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
192 char *features, int *lookup_indices)
195 OTF_Feature *feature;
196 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
198 for (i = 0; i < FeatureList->FeatureCount; i++)
199 feature_table[i] = 0;
207 if (*features == '*')
209 /* Consume all remaining features. */
210 for (i = 0; i < FeatureList->FeatureCount; i++)
211 if (! feature_table[i])
213 feature = FeatureList->Feature + i;
214 for (j = 0; j < feature->LookupCount; j++)
215 lookup_indices[n++] = feature->LookupListIndex[j];
220 if (*features == '~')
221 use_it = -1, features++;
222 for (i = 0; *features && *features != ','; i++, features++)
223 tagname[i] = *features;
229 tag = OTF_tag (tagname);
230 for (i = 0; i < FeatureList->FeatureCount; i++)
232 feature = FeatureList->Feature + i;
233 if (tag == feature->FeatureTag)
235 if (feature_table[i])
238 for (j = 0; j < feature->LookupCount; j++)
239 lookup_indices[n++] = feature->LookupListIndex[j];
240 feature_table[i] = use_it;
250 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
251 int count, OTF_GlyphID *ids)
253 OTF_Glyph *gbeg = gstring->glyphs + gidx;
254 OTF_Glyph *gend = gstring->glyphs + gstring->used;
258 for (g = gbeg, i = 0; g < gend && i < count; g++)
259 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
261 return (i < count ? -1 : g - gbeg);
265 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
268 int i = rule->BacktrackGlyphCount;
275 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
276 if (! IGNORED_GLYPH (g, flag) && --i == 0)
280 if (match_ids (gstring, j, flag,
281 rule->BacktrackGlyphCount, rule->Backtrack)
286 i = match_ids (gstring, gidx, flag,
287 rule->InputGlyphCount - 1, rule->Input);
291 i = match_ids (gstring, gidx, flag,
292 rule->LookaheadGlyphCount, rule->LookAhead);
299 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
300 int flag, int count, unsigned *classes)
302 OTF_Glyph *gbeg = gstring->glyphs + gidx;
303 OTF_Glyph *gend = gstring->glyphs + gstring->used;
307 for (g = gbeg, i = 0; g < gend && i < count; g++)
308 if (! IGNORED_GLYPH (g, flag)
309 && get_class_def (class_def, g->glyph_id) != classes[i++])
311 return (i < count ? -1 : g - gbeg);
315 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
316 OTF_ClassDef *BacktrackClassDef,
317 OTF_ClassDef *InputClassDef,
318 OTF_ClassDef *LookaheadClassDef,
319 OTF_ChainClassRule *rule)
321 int i = rule->BacktrackGlyphCount;
328 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
329 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
333 if (match_classes (BacktrackClassDef, gstring, j, flag,
334 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
338 i = match_classes (InputClassDef, gstring, gidx, flag,
339 rule->InputGlyphCount - 1, rule->Input);
343 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
344 rule->LookaheadGlyphCount, rule->LookAhead);
352 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
353 OTF_Coverage *coverages)
355 OTF_Glyph *gbeg = gstring->glyphs + gidx;
356 OTF_Glyph *gend = gstring->glyphs + gstring->used;
360 for (g = gbeg, i = 0; g < gend && i < count; g++)
361 if (! IGNORED_GLYPH (g, flag)
362 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
364 return (i < count ? -1 : g - gbeg);
368 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
369 OTF_GSUB_ChainContext3 *context3)
371 int i = context3->BacktrackGlyphCount;
378 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
379 if (! IGNORED_GLYPH (g, flag) && --i == 0)
383 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
384 context3->Backtrack) < 0)
388 if (context3->InputGlyphCount > 1)
390 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
391 context3->Input + 1);
396 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
397 context3->LookAhead) < 0)
403 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
404 OTF_GlyphString *gstring, int gidx, int alternate_subst)
406 char *errfmt = "GSUB Looking up%s";
408 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
409 unsigned int flag = (lookup->LookupFlag
410 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
411 int orig_gidx = gidx;
412 OTF_Glyph *g = gstring->glyphs + gidx;
415 if (IGNORED_GLYPH (g, flag))
418 /* Try all subtables until one of them handles the current glyph. */
419 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
421 unsigned lookup_type = lookup->LookupType;
422 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
425 if (lookup_type == 7)
427 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
429 lookup_type = extension1->ExtensionLookupType;
430 subtable = extension1->ExtensionSubtable;
434 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
435 : (lookup_type == 3))
438 if (subtable->Coverage.offset)
440 coverage_idx = get_coverage_index (&subtable->Coverage,
442 if (coverage_idx < 0)
449 if (subtable->Format == 1)
450 g->glyph_id += subtable->u.single1.DeltaGlyphID;
452 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
457 if (subtable->Format == 1)
459 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
460 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
462 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
463 seq->Substitute, seq->GlyphCount);
464 gidx += seq->GlyphCount;
467 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
471 if (subtable->Format == 1)
473 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
474 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
476 gstring_subst (otf, gstring, gidx + 1, gidx + 1, flag,
477 altset->Alternate, altset->GlyphCount);
478 gidx += altset->GlyphCount;;
481 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
485 if (subtable->Format == 1)
487 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
488 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
492 for (j = 0; j < ligset->LigatureCount; j++)
496 lig = ligset->Ligature + j;
497 n = match_ids (gstring, gidx + 1, flag,
498 lig->CompCount - 1, lig->Component);
501 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
503 gidx += lig->CompCount;
508 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
512 if (subtable->Format == 1)
514 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
515 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
520 for (j = 0; j < set->RuleCount; j++)
522 rule = set->Rule + j;
523 if (match_ids (gstring, gidx + 1, flag,
524 rule->GlyphCount - 1, rule->Input) < 0)
526 orig_used = gstring->used;
527 for (k = 0; k < rule->LookupCount; k++)
528 lookup_gsub (otf, lookup_list,
529 rule->LookupRecord[k].LookupListIndex,
531 gidx + rule->LookupRecord[k].SequenceIndex,
533 gidx += rule->GlyphCount + (gstring->used - orig_used);
537 else if (subtable->Format == 2)
539 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
546 class = get_class_def (&context2->ClassDef, g->glyph_id);
547 set = context2->ClassSet + class;
549 for (j = 0; j < set->ClassRuleCnt; j++)
551 rule = set->ClassRule + j;
552 if (match_classes (&context2->ClassDef,
553 gstring, gidx + 1, flag,
554 rule->GlyphCount - 1, rule->Class)
557 orig_used = gstring->used;
558 for (k = 0; k < rule->LookupCount; k++)
559 lookup_gsub (otf, lookup_list,
560 rule->LookupRecord[k].LookupListIndex,
562 gidx + rule->LookupRecord[k].SequenceIndex,
564 gidx += rule->GlyphCount + (gstring->used - orig_used);
568 else /* subtable->Format == 3 */
570 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
574 if (match_coverages (gstring, gidx + 1, flag,
575 context3->GlyphCount - 1,
576 context3->Coverage + 1) < 0)
578 orig_used = gstring->used;
579 for (j = 0; j < context3->LookupCount; j++)
580 lookup_gsub (otf, lookup_list,
581 context3->LookupRecord[j].LookupListIndex,
583 gidx + context3->LookupRecord[j].SequenceIndex,
585 gidx += context3->GlyphCount + (gstring->used - orig_used);
590 if (subtable->Format == 1)
592 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
593 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
597 for (j = 0; j < set->ChainRuleCount; j++)
599 OTF_ChainRule *rule = set->ChainRule + j;
601 if (gidx < rule->BacktrackGlyphCount
602 || (gidx + rule->InputGlyphCount
603 + rule->LookaheadGlyphCount) > gstring->used)
605 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
607 orig_used = gstring->used;
608 for (k = 0; k < rule->LookupCount; k++)
609 lookup_gsub (otf, lookup_list,
610 rule->LookupRecord[k].LookupListIndex,
612 gidx + rule->LookupRecord[k].SequenceIndex,
614 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
618 else if (subtable->Format == 2)
620 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
621 OTF_ChainClassSet *set;
626 class = get_class_def (&context2->InputClassDef, g->glyph_id);
627 set = context2->ChainClassSet + class;
628 for (j = 0; j < set->ChainClassRuleCnt; j++)
630 OTF_ChainClassRule *rule = set->ChainClassRule + j;
633 if (gidx < rule->BacktrackGlyphCount
634 || (gidx + rule->InputGlyphCount
635 + rule->LookaheadGlyphCount) > gstring->used)
637 if (match_chain_classes (gstring, gidx, flag,
638 &context2->BacktrackClassDef,
639 &context2->InputClassDef,
640 &context2->LookaheadClassDef,
643 orig_used = gstring->used;
644 for (k = 0; k < rule->LookupCount; k++)
645 lookup_gsub (otf, lookup_list,
646 rule->LookupRecord[k].LookupListIndex,
648 gidx + rule->LookupRecord[k].SequenceIndex,
650 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
656 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
660 if (gidx < context3->BacktrackGlyphCount
661 || (gidx + context3->InputGlyphCount
662 + context3->LookaheadGlyphCount) > gstring->used)
664 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
666 orig_used = gstring->used;
667 for (j = 0; j < context3->LookupCount; j++)
668 lookup_gsub (otf, lookup_list,
669 context3->LookupRecord[j].LookupListIndex,
671 gidx + context3->LookupRecord[j].SequenceIndex,
673 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
679 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
680 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
681 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
684 if (back_gidx > gstring->used || ahead_gidx < 0)
687 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
688 if (get_coverage_index (reverse->Backtrack + j,
689 gstring->glyphs[gidx + 1 + j].glyph_id)
692 if (j < reverse->BacktrackGlyphCount)
694 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
695 if (get_coverage_index (reverse->LookAhead + j,
696 gstring->glyphs[gidx - 1 - j].glyph_id)
699 if (j < reverse->LookaheadGlyphCount)
701 g->glyph_id = reverse->Substitute[coverage_idx];
709 if (gidx == orig_gidx)
718 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
720 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
722 rec->XPlacement = anchor->XCoordinate;
723 rec->YPlacement = anchor->YCoordinate;
724 if (anchor->AnchorFormat == 1)
727 else if (anchor->AnchorFormat == 2)
728 /* Not yet implemented */
730 else if (anchor->AnchorFormat == 3)
731 /* Not yet implemented */
738 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
739 OTF_GlyphString *gstring, int gidx)
741 char *errfmt = "GPOS Looking up%s";
743 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
744 unsigned int flag = (lookup->LookupFlag
745 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
746 int orig_gidx = gidx;
747 OTF_Glyph *g = gstring->glyphs + gidx;
750 if (IGNORED_GLYPH (g, flag)
751 || g->positioning_type)
754 /* Try all subtables until one of them handles the current glyph. */
755 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
757 unsigned lookup_type = lookup->LookupType;
758 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
761 if (lookup_type == 9)
763 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
765 lookup_type = extension1->ExtensionLookupType;
766 subtable = extension1->ExtensionSubtable;
769 if (subtable->Coverage.offset)
771 coverage_idx = get_coverage_index (&subtable->Coverage,
773 if (coverage_idx < 0)
780 g->positioning_type = lookup_type;
781 if (subtable->Format == 1)
783 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
785 g->f.f1.format = single1->ValueFormat;
786 g->f.f1.value = &single1->Value;
788 else if (subtable->Format == 2)
790 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
792 g->f.f1.format = single2->ValueFormat;
793 g->f.f1.value = single2->Value + coverage_idx;
802 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
803 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
804 next_gidx++, nextg++);
806 if (next_gidx >= gstring->used
807 || nextg->positioning_type)
809 if (subtable->Format == 1)
811 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
812 OTF_PairSet *set = pair1->PairSet + coverage_idx;
815 for (j = 0; j < set->PairValueCount; j++)
816 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
818 if (pair1->ValueFormat1)
820 g->positioning_type = lookup_type;
821 g->f.f2.format = pair1->ValueFormat1;
822 g->f.f2.value = &set->PairValueRecord[j].Value1;
825 if (pair1->ValueFormat2)
827 nextg->positioning_type = lookup_type;
828 nextg->f.f2.format = pair1->ValueFormat2;
829 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
835 else if (subtable->Format == 2)
837 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
838 unsigned class1, class2;
840 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
841 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
842 if (pair2->ValueFormat1)
844 g->positioning_type = lookup_type;
845 g->f.f2.format = pair2->ValueFormat1;
847 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
850 if (pair2->ValueFormat2)
852 nextg->positioning_type = lookup_type;
853 nextg->f.f2.format = pair2->ValueFormat2;
855 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
864 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
866 g->positioning_type = lookup_type;
868 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
870 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
877 if (subtable->Format == 1)
879 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
880 OTF_MarkRecord *mark_record;
881 OTF_AnchorRecord *base_record;
883 int coverage_idx_base;
886 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
888 if (baseg < gstring->glyphs)
891 = get_coverage_index (&mark_base1->BaseCoverage,
893 if (coverage_idx_base < 0)
895 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
897 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
898 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
900 = &base_record->Anchor[mark_record->Class];
901 g->positioning_type = lookup_type;
908 if (subtable->Format == 1)
910 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
912 int coverage_idx_lig;
913 OTF_MarkRecord *mark_record;
914 OTF_LigatureAttach *attach;
915 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
918 for (j = 0; j < mark_lig1->ClassCount; j++)
922 (ligg >= gstring->glyphs
923 && (IGNORED_GLYPH (ligg, flag)
924 || ligg->GlyphClass > OTF_GlyphClassLigature));
926 if (ligg->positioning_type == 5
927 && ligg->MarkAttachClass < mark_lig1->ClassCount)
928 num_class[ligg->MarkAttachClass]++;
929 if (ligg < gstring->glyphs)
932 = get_coverage_index (&mark_lig1->LigatureCoverage,
934 if (coverage_idx_lig < 0)
936 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
937 g->MarkAttachClass = mark_record->Class;
938 attach = (mark_lig1->LigatureArray.LigatureAttach
940 for (j = 0; j < attach->ComponentCount; j++)
942 OTF_Anchor *lig_anchor
943 = attach->ComponentRecord[j].LigatureAnchor;
945 if (lig_anchor[mark_record->Class].AnchorFormat
946 && num_class[mark_record->Class]-- == 0)
948 g->positioning_type = lookup_type;
949 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
950 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
960 if (subtable->Format == 1)
962 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
963 OTF_MarkRecord *mark1_record;
964 OTF_AnchorRecord *mark2_record;
966 int coverage_idx_base;
969 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
971 if (prevg < gstring->glyphs)
974 = get_coverage_index (&mark_mark1->Mark2Coverage,
976 if (coverage_idx_base < 0)
978 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
980 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
981 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
983 = &mark2_record->Anchor[mark1_record->Class];
984 g->positioning_type = lookup_type;
990 if (subtable->Format == 1)
992 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
993 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
998 for (j = 0; j < set->RuleCount; j++)
1000 rule = set->Rule + j;
1001 if (match_ids (gstring, gidx + 1, flag,
1002 rule->GlyphCount - 1, rule->Input) < 0)
1004 orig_used = gstring->used;
1005 for (k = 0; k < rule->LookupCount; k++)
1006 lookup_gpos (lookup_list,
1007 rule->LookupRecord[k].LookupListIndex,
1009 gidx + rule->LookupRecord[k].SequenceIndex);
1010 gidx += rule->GlyphCount + (gstring->used - orig_used);
1014 else if (subtable->Format == 2)
1016 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1018 OTF_ClassRule *rule;
1023 class = get_class_def (&context2->ClassDef, g->glyph_id);
1024 set = context2->ClassSet + class;
1026 for (j = 0; j < set->ClassRuleCnt; j++)
1028 rule = set->ClassRule + j;
1029 if (match_classes (&context2->ClassDef,
1030 gstring, gidx + 1, flag,
1031 rule->GlyphCount - 1, rule->Class)
1034 orig_used = gstring->used;
1035 for (k = 0; k < rule->LookupCount; k++)
1036 lookup_gpos (lookup_list,
1037 rule->LookupRecord[k].LookupListIndex,
1039 gidx + rule->LookupRecord[k].SequenceIndex);
1040 gidx += rule->GlyphCount + (gstring->used - orig_used);
1044 else /* subtable->Format == 3 */
1046 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1050 if (match_coverages (gstring, gidx + 1, flag,
1051 context3->GlyphCount - 1,
1052 context3->Coverage + 1) < 0)
1054 orig_used = gstring->used;
1055 for (j = 0; j < context3->LookupCount; j++)
1056 lookup_gpos (lookup_list,
1057 context3->LookupRecord[j].LookupListIndex,
1059 gidx + context3->LookupRecord[j].SequenceIndex);
1060 gidx += context3->GlyphCount + (gstring->used - orig_used);
1065 if (subtable->Format == 1)
1067 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1068 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1072 for (j = 0; j < set->ChainRuleCount; j++)
1074 OTF_ChainRule *rule = set->ChainRule + j;
1076 if (gidx < rule->BacktrackGlyphCount
1077 || (gidx + rule->InputGlyphCount
1078 + rule->LookaheadGlyphCount) > gstring->used)
1080 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1082 orig_used = gstring->used;
1083 for (k = 0; k < rule->LookupCount; k++)
1084 lookup_gpos (lookup_list,
1085 rule->LookupRecord[k].LookupListIndex,
1087 gidx + rule->LookupRecord[k].SequenceIndex);
1088 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1092 else if (subtable->Format == 2)
1094 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1095 OTF_ChainClassSet *set;
1100 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1101 set = context2->ChainClassSet + class;
1102 for (j = 0; j < set->ChainClassRuleCnt; j++)
1104 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1107 if (gidx < rule->BacktrackGlyphCount
1108 || (gidx + rule->InputGlyphCount
1109 + rule->LookaheadGlyphCount) > gstring->used)
1111 if (match_chain_classes (gstring, gidx, flag,
1112 &context2->BacktrackClassDef,
1113 &context2->InputClassDef,
1114 &context2->LookaheadClassDef,
1117 orig_used = gstring->used;
1118 for (k = 0; k < rule->LookupCount; k++)
1119 lookup_gpos (lookup_list,
1120 rule->LookupRecord[k].LookupListIndex,
1122 gidx + rule->LookupRecord[k].SequenceIndex);
1123 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1127 else if (subtable->Format == 3)
1129 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1133 if (gidx < context3->BacktrackGlyphCount
1134 || (gidx + context3->InputGlyphCount
1135 + context3->LookaheadGlyphCount) > gstring->used)
1137 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1139 orig_used = gstring->used;
1140 for (j = 0; j < context3->LookupCount; j++)
1141 lookup_gpos (lookup_list,
1142 context3->LookupRecord[j].LookupListIndex,
1144 gidx + context3->LookupRecord[j].SequenceIndex);
1145 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1148 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1155 if (gidx == orig_gidx)
1161 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1165 for (i = 0; i < gstring->used; i++)
1167 c = gstring->glyphs[i].c;
1168 if (c < 0 || c >= 256)
1169 gstring->glyphs[i].glyph_id = 0;
1171 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1177 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1183 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1186 int segCount = sub4->segCountX2 / 2;
1188 for (i = 0; i < gstring->used; i++)
1190 c = gstring->glyphs[i].c;
1192 gstring->glyphs[i].glyph_id = 0;
1193 for (j = 0; j < segCount; j++)
1195 OTF_cmapSegument *seg = sub4->segments + i;
1197 if (c >= seg->startCount && c <= seg->endCount)
1199 if (seg->idRangeOffset == 0xFFFF)
1200 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1202 gstring->glyphs[i].glyph_id
1203 = sub4->glyphIdArray[seg->idRangeOffset
1204 + (c - seg->startCount)];
1214 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1220 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1226 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1232 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1242 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1248 && OTF_get_table (otf, "cmap") < 0)
1252 for (i = 0; i < gstring->used; i++)
1253 if (! gstring->glyphs[i].glyph_id)
1255 int c = gstring->glyphs[i].c;
1256 if (c < 32 || ! cmap->unicode_table)
1257 gstring->glyphs[i].glyph_id = 0;
1259 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1266 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1267 int platform_id, int encoding_id)
1271 char *errfmt = "CMAP Looking up%s";
1273 OTF_EncodingRecord *enc;
1276 && OTF_get_table (otf, "cmap") < 0)
1280 for (i = 0; i < cmap->numTables; i++)
1281 if (cmap->EncodingRecord[i].platformID == platform_id
1282 && cmap->EncodingRecord[i].encodingID == encoding_id)
1284 if (i == cmap->numTables)
1285 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1286 enc = cmap->EncodingRecord + i;
1287 switch (enc->subtable.format)
1289 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1290 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1291 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1292 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1293 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1294 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1295 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1297 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1302 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1305 && OTF_get_table (otf, "cmap") < 0)
1308 || code > otf->cmap->max_glyph_id
1309 || ! otf->cmap->decode_table)
1311 return otf->cmap->decode_table[code];
1315 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1321 && OTF_get_table (otf, "GDEF") < 0)
1325 if (gdef->glyph_class_def.offset)
1326 for (i = 0; i < gstring->used; i++)
1327 gstring->glyphs[i].GlyphClass
1328 = get_class_def (&gdef->glyph_class_def,
1329 gstring->glyphs[i].glyph_id);
1331 if (gdef->mark_attach_class_def.offset)
1332 for (i = 0; i < gstring->used; i++)
1333 gstring->glyphs[i].MarkAttachClass
1334 = get_class_def (&gdef->mark_attach_class_def,
1335 gstring->glyphs[i].glyph_id);
1341 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1342 char *script, char *language, char *features,
1343 int alternate_subst)
1345 char *errfmt = "GSUB driving%s";
1348 OTF_LangSys *LangSys;
1349 int *lookup_indices;
1352 for (i = 0; i < gstring->used; i++)
1353 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1356 && OTF_get_table (otf, "GSUB") < 0)
1359 if (gsub->FeatureList.FeatureCount == 0
1360 || gsub->LookupList.LookupCount == 0)
1363 LangSys = get_langsys (&gsub->ScriptList, script, language);
1367 /* One lookup may be used by multiple features. */
1368 lookup_indices = alloca (sizeof (int)
1369 * gsub->LookupList.LookupCount
1370 * (gsub->FeatureList.FeatureCount + 1));
1371 if (! lookup_indices)
1372 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1373 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1374 features, lookup_indices);
1378 for (i = 0; i < n; i++)
1380 int index = lookup_indices[i];
1383 if (gsub->LookupList.Lookup[index].LookupType != 8)
1386 while (gidx < gstring->used)
1388 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1396 gidx = gstring->used - 1;
1399 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1411 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1412 char *script, char *language, char *features)
1414 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1418 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1419 char *script, char *language, char *features)
1421 char *errfmt = "GPOS driving%s";
1424 OTF_LangSys *LangSys;
1425 int *lookup_indices;
1429 && OTF_get_table (otf, "GPOS") < 0)
1432 if (gpos->FeatureList.FeatureCount == 0
1433 || gpos->LookupList.LookupCount == 0)
1436 LangSys = get_langsys (&gpos->ScriptList, script, language);
1440 /* One lookup may be used by multiple features. */
1441 lookup_indices = alloca (sizeof (int)
1442 * gpos->LookupList.LookupCount
1443 * (gpos->FeatureList.FeatureCount + 1));
1444 if (! lookup_indices)
1445 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1446 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1447 features, lookup_indices);
1451 for (i = 0; i < gstring->used; i++)
1452 gstring->glyphs[i].positioning_type = 0;
1454 for (i = 0; i < n; i++)
1456 int index = lookup_indices[i];
1459 while (gidx < gstring->used)
1461 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1471 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1472 char *script, char *language,
1473 char *gsub_features, char *gpos_features)
1475 if (OTF_drive_cmap (otf, gstring) < 0)
1477 if (OTF_drive_gdef (otf, gstring) < 0)
1480 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1483 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1489 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1490 char *script, char *language, char *features)
1492 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);