1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
32 /* Return nonzero if OTF_Glyph *G should be ignored according to
34 #define IGNORED_GLYPH(g, flag) \
36 || ((flag) & (1 << (g)->GlyphClass)) \
37 || (((flag) & OTF_MarkAttachmentType) \
38 && (g)->GlyphClass == OTF_GlyphClassMark \
39 && ((flag) >> 8) != (g)->MarkAttachClass))
41 #define GSTRING_DELETE(gstring, from, len) \
43 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
44 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
45 gstring->used -= len; \
49 #define GSTRING_INSERT(gstring, pos, len) \
51 if (gstring->used + len > gstring->size) \
53 char *errfmt = "GSTRING%s"; \
55 gstring->size = gstring->used + len; \
57 = (OTF_Glyph *) realloc (gstring->glyphs, \
58 sizeof (OTF_Glyph) * gstring->size); \
59 if (! gstring->glyphs) \
60 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
62 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
63 sizeof (OTF_Glyph) * (gstring->used - pos)); \
64 gstring->used += len; \
69 gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag,
70 OTF_GlyphID *ids, int num)
75 int c = gstring->glyphs[from].c;
76 int from_idx = gstring->glyphs[from].f.index.from;
77 int to_idx = gstring->glyphs[to - 1].f.index.to;
80 for (i = non_ignored_idx = to - 1; i >= from; i--)
82 OTF_Glyph *g = gstring->glyphs + i;
83 if (IGNORED_GLYPH (g, flag))
87 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
88 gstring->glyphs[non_ignored_idx--] = temp;
94 GSTRING_INSERT (gstring, from, (num - len));
96 GSTRING_DELETE (gstring, from, (len - num));
97 for (i = 0; i < num; i++)
99 gstring->glyphs[from + i].c = c;
100 gstring->glyphs[from + i].glyph_id = ids[i];
101 gstring->glyphs[from + i].f.index.from = from_idx;
102 gstring->glyphs[from + i].f.index.to = to_idx;
109 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
113 if (coverage->CoverageFormat == 1)
115 for (i = 0; i < coverage->Count; i++)
116 if (coverage->table.GlyphArray[i] == id)
121 for (i = 0; i < coverage->Count; i++)
122 if (coverage->table.RangeRecord[i].Start <= id
123 && coverage->table.RangeRecord[i].End >= id)
124 return (coverage->table.RangeRecord[i].StartCoverageIndex
125 + (id - coverage->table.RangeRecord[i].Start));
131 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
133 if (class_def->ClassFormat == 1)
135 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
137 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
138 return class_def->f.f1.ClassValueArray[idx];
144 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
145 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
146 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
147 return class_def->f.f2.ClassRangeRecord[i].Class;
153 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
156 OTF_Tag script_tag = OTF_tag (script);
157 OTF_Tag langsys_tag = OTF_tag (language);
159 OTF_Tag dflt_tag = OTF_tag ("DFLT");
160 OTF_Script *dflt = NULL;
162 for (i = 0; i < script_list->ScriptCount; i++)
164 OTF_Script *script = script_list->Script + i;
166 if (script_list->Script[i].ScriptTag == dflt_tag)
168 if (script_list->Script[i].ScriptTag == script_tag)
171 return &script->DefaultLangSys;
172 for (j = 0; j < script->LangSysCount; j++)
173 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
174 return script->LangSys + j;
175 return &script->DefaultLangSys;
180 dflt = script_list->Script;
182 return &dflt->DefaultLangSys;
183 for (j = 0; j < dflt->LangSysCount; j++)
184 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
185 return dflt->LangSys + j;
186 return &dflt->DefaultLangSys;
190 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
191 char *features, int *lookup_indices)
194 OTF_Feature *feature;
195 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
197 for (i = 0; i < FeatureList->FeatureCount; i++)
198 feature_table[i] = 0;
206 if (*features == '*')
208 /* Consume all remaining features. */
209 for (i = 0; i < FeatureList->FeatureCount; i++)
210 if (! feature_table[i])
212 feature = FeatureList->Feature + i;
213 for (j = 0; j < feature->LookupCount; j++)
214 lookup_indices[n++] = feature->LookupListIndex[j];
219 if (*features == '~')
220 use_it = -1, features++;
221 for (i = 0; *features && *features != ','; i++, features++)
222 tagname[i] = *features;
228 tag = OTF_tag (tagname);
229 for (i = 0; i < FeatureList->FeatureCount; i++)
231 feature = FeatureList->Feature + i;
232 if (tag == feature->FeatureTag)
234 if (feature_table[i])
237 for (j = 0; j < feature->LookupCount; j++)
238 lookup_indices[n++] = feature->LookupListIndex[j];
239 feature_table[i] = use_it;
249 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
250 int count, OTF_GlyphID *ids)
252 OTF_Glyph *gbeg = gstring->glyphs + gidx;
253 OTF_Glyph *gend = gstring->glyphs + gstring->used;
257 for (g = gbeg, i = 0; g < gend && i < count; g++)
258 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
260 return (i < count ? -1 : g - gbeg);
264 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
267 int i = rule->BacktrackGlyphCount;
274 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
275 if (! IGNORED_GLYPH (g, flag) && --i == 0)
279 if (match_ids (gstring, j, flag,
280 rule->BacktrackGlyphCount, rule->Backtrack)
285 i = match_ids (gstring, gidx, flag,
286 rule->InputGlyphCount - 1, rule->Input);
290 i = match_ids (gstring, gidx, flag,
291 rule->LookaheadGlyphCount, rule->LookAhead);
298 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
299 int flag, int count, unsigned *classes)
301 OTF_Glyph *gbeg = gstring->glyphs + gidx;
302 OTF_Glyph *gend = gstring->glyphs + gstring->used;
306 for (g = gbeg, i = 0; g < gend && i < count; g++)
307 if (! IGNORED_GLYPH (g, flag)
308 && get_class_def (class_def, g->glyph_id) != classes[i++])
310 return (i < count ? -1 : g - gbeg);
314 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
315 OTF_ClassDef *BacktrackClassDef,
316 OTF_ClassDef *InputClassDef,
317 OTF_ClassDef *LookaheadClassDef,
318 OTF_ChainClassRule *rule)
320 int i = rule->BacktrackGlyphCount;
327 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
328 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
332 if (match_classes (BacktrackClassDef, gstring, j, flag,
333 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
337 i = match_classes (InputClassDef, gstring, gidx, flag,
338 rule->InputGlyphCount - 1, rule->Input);
342 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
343 rule->LookaheadGlyphCount, rule->LookAhead);
351 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
352 OTF_Coverage *coverages)
354 OTF_Glyph *gbeg = gstring->glyphs + gidx;
355 OTF_Glyph *gend = gstring->glyphs + gstring->used;
359 for (g = gbeg, i = 0; g < gend && i < count; g++)
360 if (! IGNORED_GLYPH (g, flag)
361 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
363 return (i < count ? -1 : g - gbeg);
367 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
368 OTF_GSUB_ChainContext3 *context3)
370 int i = context3->BacktrackGlyphCount;
377 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
378 if (! IGNORED_GLYPH (g, flag) && --i == 0)
382 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
383 context3->Backtrack) < 0)
387 if (context3->InputGlyphCount > 1)
389 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
390 context3->Input + 1);
395 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
396 context3->LookAhead) < 0)
402 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
403 OTF_GlyphString *gstring, int gidx)
405 char *errfmt = "GSUB Looking up%s";
407 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
408 unsigned int flag = (lookup->LookupFlag
409 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
410 int orig_gidx = gidx;
411 OTF_Glyph *g = gstring->glyphs + gidx;
414 if (IGNORED_GLYPH (g, flag))
417 /* Try all subtables until one of them handles the current glyph. */
418 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
420 unsigned lookup_type = lookup->LookupType;
421 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
424 if (lookup_type == 7)
426 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
428 lookup_type = extension1->ExtensionLookupType;
429 subtable = extension1->ExtensionSubtable;
432 if (subtable->Coverage.offset)
434 coverage_idx = get_coverage_index (&subtable->Coverage,
436 if (coverage_idx < 0)
443 if (subtable->Format == 1)
444 g->glyph_id += subtable->u.single1.DeltaGlyphID;
446 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
452 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
453 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
455 gstring_subst (gstring, gidx, gidx + 1, flag,
456 seq->Substitute, seq->GlyphCount);
457 gidx += seq->GlyphCount;
462 if (subtable->Format == 1)
464 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
466 g->alternate_set = alt1->AlternateSet + coverage_idx;
470 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
474 if (subtable->Format == 1)
476 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
477 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
481 for (j = 0; j < ligset->LigatureCount; j++)
485 lig = ligset->Ligature + j;
486 n = match_ids (gstring, gidx + 1, flag,
487 lig->CompCount - 1, lig->Component);
490 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
497 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
501 if (subtable->Format == 1)
503 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
504 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
509 for (j = 0; j < set->RuleCount; j++)
511 rule = set->Rule + j;
512 if (match_ids (gstring, gidx + 1, flag,
513 rule->GlyphCount - 1, rule->Input) < 0)
515 orig_used = gstring->used;
516 for (k = 0; k < rule->LookupCount; k++)
517 lookup_gsub (lookup_list,
518 rule->LookupRecord[k].LookupListIndex,
520 gidx + rule->LookupRecord[k].SequenceIndex);
521 gidx += rule->GlyphCount + (gstring->used - orig_used);
525 else if (subtable->Format == 2)
527 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
534 class = get_class_def (&context2->ClassDef, g->glyph_id);
535 set = context2->ClassSet + class;
537 for (j = 0; j < set->ClassRuleCnt; j++)
539 rule = set->ClassRule + j;
540 if (match_classes (&context2->ClassDef,
541 gstring, gidx + 1, flag,
542 rule->GlyphCount - 1, rule->Class)
545 orig_used = gstring->used;
546 for (k = 0; k < rule->LookupCount; k++)
547 lookup_gsub (lookup_list,
548 rule->LookupRecord[k].LookupListIndex,
550 gidx + rule->LookupRecord[k].SequenceIndex);
551 gidx += rule->GlyphCount + (gstring->used - orig_used);
555 else /* subtable->Format == 3 */
557 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
561 if (match_coverages (gstring, gidx + 1, flag,
562 context3->GlyphCount - 1,
563 context3->Coverage + 1) < 0)
565 orig_used = gstring->used;
566 for (j = 0; j < context3->LookupCount; j++)
567 lookup_gsub (lookup_list,
568 context3->LookupRecord[j].LookupListIndex,
570 gidx + context3->LookupRecord[j].SequenceIndex);
571 gidx += context3->GlyphCount + (gstring->used - orig_used);
576 if (subtable->Format == 1)
578 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
579 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
583 for (j = 0; j < set->ChainRuleCount; j++)
585 OTF_ChainRule *rule = set->ChainRule + j;
587 if (gidx < rule->BacktrackGlyphCount
588 || (gidx + rule->InputGlyphCount
589 + rule->LookaheadGlyphCount) > gstring->used)
591 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
593 orig_used = gstring->used;
594 for (k = 0; k < rule->LookupCount; k++)
595 lookup_gsub (lookup_list,
596 rule->LookupRecord[k].LookupListIndex,
598 gidx + rule->LookupRecord[k].SequenceIndex);
599 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
603 else if (subtable->Format == 2)
605 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
606 OTF_ChainClassSet *set;
611 class = get_class_def (&context2->InputClassDef, g->glyph_id);
612 set = context2->ChainClassSet + class;
613 for (j = 0; j < set->ChainClassRuleCnt; j++)
615 OTF_ChainClassRule *rule = set->ChainClassRule + j;
618 if (gidx < rule->BacktrackGlyphCount
619 || (gidx + rule->InputGlyphCount
620 + rule->LookaheadGlyphCount) > gstring->used)
622 if (match_chain_classes (gstring, gidx, flag,
623 &context2->BacktrackClassDef,
624 &context2->InputClassDef,
625 &context2->LookaheadClassDef,
628 orig_used = gstring->used;
629 for (k = 0; k < rule->LookupCount; k++)
630 lookup_gsub (lookup_list,
631 rule->LookupRecord[k].LookupListIndex,
633 gidx + rule->LookupRecord[k].SequenceIndex);
634 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
640 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
644 if (gidx < context3->BacktrackGlyphCount
645 || (gidx + context3->InputGlyphCount
646 + context3->LookaheadGlyphCount) > gstring->used)
648 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
650 orig_used = gstring->used;
651 for (j = 0; j < context3->LookupCount; j++)
652 lookup_gsub (lookup_list,
653 context3->LookupRecord[j].LookupListIndex,
655 gidx + context3->LookupRecord[j].SequenceIndex);
656 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
662 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
663 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
664 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
667 if (back_gidx > gstring->used || ahead_gidx < 0)
670 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
671 if (get_coverage_index (reverse->Backtrack + j,
672 gstring->glyphs[gidx + 1 + j].glyph_id)
675 if (j < reverse->BacktrackGlyphCount)
677 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
678 if (get_coverage_index (reverse->LookAhead + j,
679 gstring->glyphs[gidx - 1 - j].glyph_id)
682 if (j < reverse->LookaheadGlyphCount)
684 g->glyph_id = reverse->Substitute[coverage_idx];
692 if (gidx == orig_gidx)
701 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
703 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
705 rec->XPlacement = anchor->XCoordinate;
706 rec->YPlacement = anchor->YCoordinate;
707 if (anchor->AnchorFormat == 1)
710 else if (anchor->AnchorFormat == 2)
711 /* Not yet implemented */
713 else if (anchor->AnchorFormat == 3)
714 /* Not yet implemented */
721 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
722 OTF_GlyphString *gstring, int gidx)
724 char *errfmt = "GPOS Looking up%s";
726 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
727 unsigned int flag = (lookup->LookupFlag
728 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
729 int orig_gidx = gidx;
730 OTF_Glyph *g = gstring->glyphs + gidx;
733 if (IGNORED_GLYPH (g, flag)
734 || g->positioning_type)
737 /* Try all subtables until one of them handles the current glyph. */
738 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
740 unsigned lookup_type = lookup->LookupType;
741 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
744 if (lookup_type == 9)
746 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
748 lookup_type = extension1->ExtensionLookupType;
749 subtable = extension1->ExtensionSubtable;
752 if (subtable->Coverage.offset)
754 coverage_idx = get_coverage_index (&subtable->Coverage,
756 if (coverage_idx < 0)
763 g->positioning_type = lookup_type;
764 if (subtable->Format == 1)
766 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
768 g->f.f1.format = single1->ValueFormat;
769 g->f.f1.value = &single1->Value;
771 else if (subtable->Format == 2)
773 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
775 g->f.f1.format = single2->ValueFormat;
776 g->f.f1.value = single2->Value + coverage_idx;
785 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
786 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
787 next_gidx++, nextg++);
789 if (next_gidx >= gstring->used
790 || nextg->positioning_type)
792 if (subtable->Format == 1)
794 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
795 OTF_PairSet *set = pair1->PairSet + coverage_idx;
798 for (j = 0; j < set->PairValueCount; j++)
799 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
801 if (pair1->ValueFormat1)
803 g->positioning_type = lookup_type;
804 g->f.f2.format = pair1->ValueFormat1;
805 g->f.f2.value = &set->PairValueRecord[j].Value1;
808 if (pair1->ValueFormat2)
810 nextg->positioning_type = lookup_type;
811 nextg->f.f2.format = pair1->ValueFormat2;
812 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
818 else if (subtable->Format == 2)
820 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
821 unsigned class1, class2;
823 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
824 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
825 if (pair2->ValueFormat1)
827 g->positioning_type = lookup_type;
828 g->f.f2.format = pair2->ValueFormat1;
830 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
833 if (pair2->ValueFormat2)
835 nextg->positioning_type = lookup_type;
836 nextg->f.f2.format = pair2->ValueFormat2;
838 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
847 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
849 g->positioning_type = lookup_type;
851 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
853 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
860 if (subtable->Format == 1)
862 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
863 OTF_MarkRecord *mark_record;
864 OTF_AnchorRecord *base_record;
866 int coverage_idx_base;
869 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
871 if (baseg < gstring->glyphs)
874 = get_coverage_index (&mark_base1->BaseCoverage,
876 if (coverage_idx_base < 0)
878 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
880 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
881 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
883 = &base_record->Anchor[mark_record->Class];
884 g->positioning_type = lookup_type;
891 if (subtable->Format == 1)
893 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
895 int coverage_idx_lig;
896 OTF_MarkRecord *mark_record;
897 OTF_LigatureAttach *attach;
898 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
901 for (j = 0; j < mark_lig1->ClassCount; j++)
905 (ligg >= gstring->glyphs
906 && (IGNORED_GLYPH (ligg, flag)
907 || ligg->GlyphClass > OTF_GlyphClassLigature));
909 if (ligg->positioning_type == 5
910 && ligg->MarkAttachClass < mark_lig1->ClassCount)
911 num_class[ligg->MarkAttachClass]++;
912 if (ligg < gstring->glyphs)
915 = get_coverage_index (&mark_lig1->LigatureCoverage,
917 if (coverage_idx_lig < 0)
919 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
920 g->MarkAttachClass = mark_record->Class;
921 attach = (mark_lig1->LigatureArray.LigatureAttach
923 for (j = 0; j < attach->ComponentCount; j++)
925 OTF_Anchor *lig_anchor
926 = attach->ComponentRecord[j].LigatureAnchor;
928 if (lig_anchor[mark_record->Class].AnchorFormat
929 && num_class[mark_record->Class]-- == 0)
931 g->positioning_type = lookup_type;
932 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
933 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
943 if (subtable->Format == 1)
945 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
946 OTF_MarkRecord *mark1_record;
947 OTF_AnchorRecord *mark2_record;
949 int coverage_idx_base;
952 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
954 if (prevg < gstring->glyphs)
957 = get_coverage_index (&mark_mark1->Mark2Coverage,
959 if (coverage_idx_base < 0)
961 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
963 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
964 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
966 = &mark2_record->Anchor[mark1_record->Class];
967 g->positioning_type = lookup_type;
973 if (subtable->Format == 1)
975 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
976 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
981 for (j = 0; j < set->RuleCount; j++)
983 rule = set->Rule + j;
984 if (match_ids (gstring, gidx + 1, flag,
985 rule->GlyphCount - 1, rule->Input) < 0)
987 orig_used = gstring->used;
988 for (k = 0; k < rule->LookupCount; k++)
989 lookup_gpos (lookup_list,
990 rule->LookupRecord[k].LookupListIndex,
992 gidx + rule->LookupRecord[k].SequenceIndex);
993 gidx += rule->GlyphCount + (gstring->used - orig_used);
997 else if (subtable->Format == 2)
999 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1001 OTF_ClassRule *rule;
1006 class = get_class_def (&context2->ClassDef, g->glyph_id);
1007 set = context2->ClassSet + class;
1009 for (j = 0; j < set->ClassRuleCnt; j++)
1011 rule = set->ClassRule + j;
1012 if (match_classes (&context2->ClassDef,
1013 gstring, gidx + 1, flag,
1014 rule->GlyphCount - 1, rule->Class)
1017 orig_used = gstring->used;
1018 for (k = 0; k < rule->LookupCount; k++)
1019 lookup_gpos (lookup_list,
1020 rule->LookupRecord[k].LookupListIndex,
1022 gidx + rule->LookupRecord[k].SequenceIndex);
1023 gidx += rule->GlyphCount + (gstring->used - orig_used);
1027 else /* subtable->Format == 3 */
1029 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1033 if (match_coverages (gstring, gidx + 1, flag,
1034 context3->GlyphCount - 1,
1035 context3->Coverage + 1) < 0)
1037 orig_used = gstring->used;
1038 for (j = 0; j < context3->LookupCount; j++)
1039 lookup_gpos (lookup_list,
1040 context3->LookupRecord[j].LookupListIndex,
1042 gidx + context3->LookupRecord[j].SequenceIndex);
1043 gidx += context3->GlyphCount + (gstring->used - orig_used);
1048 if (subtable->Format == 1)
1050 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1051 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1055 for (j = 0; j < set->ChainRuleCount; j++)
1057 OTF_ChainRule *rule = set->ChainRule + j;
1059 if (gidx < rule->BacktrackGlyphCount
1060 || (gidx + rule->InputGlyphCount
1061 + rule->LookaheadGlyphCount) > gstring->used)
1063 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1065 orig_used = gstring->used;
1066 for (k = 0; k < rule->LookupCount; k++)
1067 lookup_gpos (lookup_list,
1068 rule->LookupRecord[k].LookupListIndex,
1070 gidx + rule->LookupRecord[k].SequenceIndex);
1071 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1075 else if (subtable->Format == 2)
1077 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1078 OTF_ChainClassSet *set;
1083 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1084 set = context2->ChainClassSet + class;
1085 for (j = 0; j < set->ChainClassRuleCnt; j++)
1087 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1090 if (gidx < rule->BacktrackGlyphCount
1091 || (gidx + rule->InputGlyphCount
1092 + rule->LookaheadGlyphCount) > gstring->used)
1094 if (match_chain_classes (gstring, gidx, flag,
1095 &context2->BacktrackClassDef,
1096 &context2->InputClassDef,
1097 &context2->LookaheadClassDef,
1100 orig_used = gstring->used;
1101 for (k = 0; k < rule->LookupCount; k++)
1102 lookup_gpos (lookup_list,
1103 rule->LookupRecord[k].LookupListIndex,
1105 gidx + rule->LookupRecord[k].SequenceIndex);
1106 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1110 else if (subtable->Format == 3)
1112 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1116 if (gidx < context3->BacktrackGlyphCount
1117 || (gidx + context3->InputGlyphCount
1118 + context3->LookaheadGlyphCount) > gstring->used)
1120 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1122 orig_used = gstring->used;
1123 for (j = 0; j < context3->LookupCount; j++)
1124 lookup_gpos (lookup_list,
1125 context3->LookupRecord[j].LookupListIndex,
1127 gidx + context3->LookupRecord[j].SequenceIndex);
1128 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1131 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1138 if (gidx == orig_gidx)
1144 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1148 for (i = 0; i < gstring->used; i++)
1150 c = gstring->glyphs[i].c;
1151 if (c < 0 || c >= 256)
1152 gstring->glyphs[i].glyph_id = 0;
1154 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1160 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1166 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1169 int segCount = sub4->segCountX2 / 2;
1171 for (i = 0; i < gstring->used; i++)
1173 c = gstring->glyphs[i].c;
1175 gstring->glyphs[i].glyph_id = 0;
1176 for (j = 0; j < segCount; j++)
1178 OTF_cmapSegument *seg = sub4->segments + i;
1180 if (c >= seg->startCount && c <= seg->endCount)
1182 if (seg->idRangeOffset == 0xFFFF)
1183 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1185 gstring->glyphs[i].glyph_id
1186 = sub4->glyphIdArray[seg->idRangeOffset
1187 + (c - seg->startCount)];
1197 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1203 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1209 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1215 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1225 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1231 && OTF_get_table (otf, "cmap") < 0)
1235 for (i = 0; i < gstring->used; i++)
1236 if (! gstring->glyphs[i].glyph_id)
1238 int c = gstring->glyphs[i].c;
1239 if (c < 32 || ! cmap->unicode_table)
1240 gstring->glyphs[i].glyph_id = 0;
1242 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1249 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1250 int platform_id, int encoding_id)
1254 char *errfmt = "CMAP Looking up%s";
1256 OTF_EncodingRecord *enc;
1259 && OTF_get_table (otf, "cmap") < 0)
1263 for (i = 0; i < cmap->numTables; i++)
1264 if (cmap->EncodingRecord[i].platformID == platform_id
1265 && cmap->EncodingRecord[i].encodingID == encoding_id)
1267 if (i == cmap->numTables)
1268 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1269 enc = cmap->EncodingRecord + i;
1270 switch (enc->subtable.format)
1272 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1273 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1274 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1275 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1276 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1277 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1278 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1280 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1285 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1288 && OTF_get_table (otf, "cmap") < 0)
1291 || code > otf->cmap->max_glyph_id
1292 || ! otf->cmap->decode_table)
1294 return otf->cmap->decode_table[code];
1298 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1304 && OTF_get_table (otf, "GDEF") < 0)
1308 if (gdef->glyph_class_def.offset)
1309 for (i = 0; i < gstring->used; i++)
1310 gstring->glyphs[i].GlyphClass
1311 = get_class_def (&gdef->glyph_class_def,
1312 gstring->glyphs[i].glyph_id);
1314 if (gdef->mark_attach_class_def.offset)
1315 for (i = 0; i < gstring->used; i++)
1316 gstring->glyphs[i].MarkAttachClass
1317 = get_class_def (&gdef->mark_attach_class_def,
1318 gstring->glyphs[i].glyph_id);
1325 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1326 char *script, char *language, char *features)
1328 char *errfmt = "GSUB driving%s";
1331 OTF_LangSys *LangSys;
1332 int *lookup_indices;
1335 for (i = 0; i < gstring->used; i++)
1336 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1339 && OTF_get_table (otf, "GSUB") < 0)
1342 if (gsub->FeatureList.FeatureCount == 0
1343 || gsub->LookupList.LookupCount == 0)
1346 LangSys = get_langsys (&gsub->ScriptList, script, language);
1350 /* One lookup may be used by multiple features. */
1351 lookup_indices = alloca (sizeof (int)
1352 * gsub->LookupList.LookupCount
1353 * (gsub->FeatureList.FeatureCount + 1));
1354 if (! lookup_indices)
1355 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1356 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1357 features, lookup_indices);
1361 for (i = 0; i < n; i++)
1363 int index = lookup_indices[i];
1366 if (gsub->LookupList.Lookup[index].LookupType != 8)
1369 while (gidx < gstring->used)
1371 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1378 gidx = gstring->used - 1;
1381 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1392 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1393 char *script, char *language, char *features)
1395 char *errfmt = "GPOS driving%s";
1398 OTF_LangSys *LangSys;
1399 int *lookup_indices;
1403 && OTF_get_table (otf, "GPOS") < 0)
1406 if (gpos->FeatureList.FeatureCount == 0
1407 || gpos->LookupList.LookupCount == 0)
1410 LangSys = get_langsys (&gpos->ScriptList, script, language);
1414 /* One lookup may be used by multiple features. */
1415 lookup_indices = alloca (sizeof (int)
1416 * gpos->LookupList.LookupCount
1417 * (gpos->FeatureList.FeatureCount + 1));
1418 if (! lookup_indices)
1419 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1420 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1421 features, lookup_indices);
1425 for (i = 0; i < gstring->used; i++)
1426 gstring->glyphs[i].positioning_type = 0;
1428 for (i = 0; i < n; i++)
1430 int index = lookup_indices[i];
1433 while (gidx < gstring->used)
1435 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1445 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1446 char *script, char *language,
1447 char *gsub_features, char *gpos_features)
1449 if (OTF_drive_cmap (otf, gstring) < 0)
1451 if (OTF_drive_gdef (otf, gstring) < 0)
1454 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1457 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)