1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
32 /* Return nonzero if OTF_Glyph *G should be ignored according to
34 #define IGNORED_GLYPH(g, flag) \
36 || ((flag) & (1 << (g)->GlyphClass)) \
37 || (((flag) & OTF_MarkAttachmentType) \
38 && (g)->GlyphClass == OTF_GlyphClassMark \
39 && ((flag) >> 8) != (g)->MarkAttachClass))
41 #define GSTRING_DELETE(gstring, from, len) \
43 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
44 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
45 gstring->used -= len; \
49 #define GSTRING_INSERT(gstring, pos, len) \
51 if (gstring->used + len > gstring->size) \
53 char *errfmt = "GSTRING%s"; \
55 gstring->size = gstring->used + len; \
57 = (OTF_Glyph *) realloc (gstring->glyphs, \
58 sizeof (OTF_Glyph) * gstring->size); \
59 if (! gstring->glyphs) \
60 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
62 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
63 sizeof (OTF_Glyph) * (gstring->used - pos)); \
64 gstring->used += len; \
68 static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID);
71 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
72 OTF_GlyphID *ids, int num)
77 int from_idx = gstring->glyphs[from].f.index.from;
78 int to_idx = gstring->glyphs[to - 1].f.index.to;
81 for (i = non_ignored_idx = to - 1; i >= from; i--)
83 OTF_Glyph *g = gstring->glyphs + i;
84 if (IGNORED_GLYPH (g, flag))
88 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
89 temp.f.index.from = from_idx;
90 temp.f.index.to = to_idx;
91 gstring->glyphs[non_ignored_idx--] = temp;
97 GSTRING_INSERT (gstring, from, (num - len));
99 GSTRING_DELETE (gstring, from, (len - num));
100 for (i = 0; i < num; i++)
102 gstring->glyphs[from + i].c = otf->cmap->decode_table[ids[i]];
103 gstring->glyphs[from + i].glyph_id = ids[i];
105 gstring->glyphs[from + i].GlyphClass
106 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
108 gstring->glyphs[from + i].GlyphClass = 0;
109 gstring->glyphs[from + i].positioning_type = 0;
110 gstring->glyphs[from + i].f.index.from = from_idx;
111 gstring->glyphs[from + i].f.index.to = to_idx;
118 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
122 if (coverage->CoverageFormat == 1)
124 for (i = 0; i < coverage->Count; i++)
125 if (coverage->table.GlyphArray[i] == id)
130 for (i = 0; i < coverage->Count; i++)
131 if (coverage->table.RangeRecord[i].Start <= id
132 && coverage->table.RangeRecord[i].End >= id)
133 return (coverage->table.RangeRecord[i].StartCoverageIndex
134 + (id - coverage->table.RangeRecord[i].Start));
140 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
142 if (class_def->ClassFormat == 1)
144 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
146 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
147 return class_def->f.f1.ClassValueArray[idx];
153 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
154 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
155 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
156 return class_def->f.f2.ClassRangeRecord[i].Class;
162 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
165 OTF_Tag script_tag = OTF_tag (script);
166 OTF_Tag langsys_tag = OTF_tag (language);
168 OTF_Tag dflt_tag = OTF_tag ("DFLT");
169 OTF_Script *dflt = NULL;
171 for (i = 0; i < script_list->ScriptCount; i++)
173 OTF_Script *script = script_list->Script + i;
175 if (script_list->Script[i].ScriptTag == dflt_tag)
177 if (script_list->Script[i].ScriptTag == script_tag)
180 return &script->DefaultLangSys;
181 for (j = 0; j < script->LangSysCount; j++)
182 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
183 return script->LangSys + j;
184 return &script->DefaultLangSys;
189 dflt = script_list->Script;
191 return &dflt->DefaultLangSys;
192 for (j = 0; j < dflt->LangSysCount; j++)
193 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
194 return dflt->LangSys + j;
195 return &dflt->DefaultLangSys;
199 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
200 char *features, int *lookup_indices)
203 OTF_Feature *feature;
204 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
206 for (i = 0; i < FeatureList->FeatureCount; i++)
207 feature_table[i] = 0;
215 if (*features == '*')
217 /* Consume all remaining features. */
218 for (i = 0; i < FeatureList->FeatureCount; i++)
219 if (! feature_table[i])
221 feature = FeatureList->Feature + i;
222 for (j = 0; j < feature->LookupCount; j++)
223 lookup_indices[n++] = feature->LookupListIndex[j];
228 if (*features == '~')
229 use_it = -1, features++;
230 for (i = 0; *features && *features != ','; i++, features++)
231 tagname[i] = *features;
237 tag = OTF_tag (tagname);
238 for (i = 0; i < FeatureList->FeatureCount; i++)
240 feature = FeatureList->Feature + i;
241 if (tag == feature->FeatureTag)
243 if (feature_table[i])
246 for (j = 0; j < feature->LookupCount; j++)
247 lookup_indices[n++] = feature->LookupListIndex[j];
248 feature_table[i] = use_it;
258 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
259 int count, OTF_GlyphID *ids)
261 OTF_Glyph *gbeg = gstring->glyphs + gidx;
262 OTF_Glyph *gend = gstring->glyphs + gstring->used;
266 for (g = gbeg, i = 0; g < gend && i < count; g++)
267 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
269 return (i < count ? -1 : g - gbeg);
273 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
276 int i = rule->BacktrackGlyphCount;
283 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
284 if (! IGNORED_GLYPH (g, flag) && --i == 0)
288 if (match_ids (gstring, j, flag,
289 rule->BacktrackGlyphCount, rule->Backtrack)
294 i = match_ids (gstring, gidx, flag,
295 rule->InputGlyphCount - 1, rule->Input);
299 i = match_ids (gstring, gidx, flag,
300 rule->LookaheadGlyphCount, rule->LookAhead);
307 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
308 int flag, int count, unsigned *classes)
310 OTF_Glyph *gbeg = gstring->glyphs + gidx;
311 OTF_Glyph *gend = gstring->glyphs + gstring->used;
315 for (g = gbeg, i = 0; g < gend && i < count; g++)
316 if (! IGNORED_GLYPH (g, flag)
317 && get_class_def (class_def, g->glyph_id) != classes[i++])
319 return (i < count ? -1 : g - gbeg);
323 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
324 OTF_ClassDef *BacktrackClassDef,
325 OTF_ClassDef *InputClassDef,
326 OTF_ClassDef *LookaheadClassDef,
327 OTF_ChainClassRule *rule)
329 int i = rule->BacktrackGlyphCount;
336 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
337 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
341 if (match_classes (BacktrackClassDef, gstring, j, flag,
342 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
346 i = match_classes (InputClassDef, gstring, gidx, flag,
347 rule->InputGlyphCount - 1, rule->Input);
351 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
352 rule->LookaheadGlyphCount, rule->LookAhead);
360 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
361 OTF_Coverage *coverages)
363 OTF_Glyph *gbeg = gstring->glyphs + gidx;
364 OTF_Glyph *gend = gstring->glyphs + gstring->used;
368 for (g = gbeg, i = 0; g < gend && i < count; g++)
369 if (! IGNORED_GLYPH (g, flag)
370 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
372 return (i < count ? -1 : g - gbeg);
376 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
377 OTF_GSUB_ChainContext3 *context3)
379 int i = context3->BacktrackGlyphCount;
386 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
387 if (! IGNORED_GLYPH (g, flag) && --i == 0)
391 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
392 context3->Backtrack) < 0)
396 if (context3->InputGlyphCount > 1)
398 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
399 context3->Input + 1);
404 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
405 context3->LookAhead) < 0)
411 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
412 OTF_GlyphString *gstring, int gidx, int alternate_subst)
414 char *errfmt = "GSUB Looking up%s";
416 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
417 unsigned int flag = (lookup->LookupFlag
418 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
419 int orig_gidx = gidx;
420 OTF_Glyph *g = gstring->glyphs + gidx;
423 if (IGNORED_GLYPH (g, flag))
426 /* Try all subtables until one of them handles the current glyph. */
427 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
429 unsigned lookup_type = lookup->LookupType;
430 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
433 if (lookup_type == 7)
435 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
437 lookup_type = extension1->ExtensionLookupType;
438 subtable = extension1->ExtensionSubtable;
442 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
443 : (lookup_type == 3))
446 if (subtable->Coverage.offset)
448 coverage_idx = get_coverage_index (&subtable->Coverage,
450 if (coverage_idx < 0)
457 if (subtable->Format == 1)
458 g->glyph_id += subtable->u.single1.DeltaGlyphID;
460 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
465 if (subtable->Format == 1)
467 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
468 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
470 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
471 seq->Substitute, seq->GlyphCount);
472 gidx += seq->GlyphCount;
475 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
479 if (subtable->Format == 1)
481 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
482 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
484 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
485 altset->Alternate, altset->GlyphCount);
486 gidx += altset->GlyphCount;;
489 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
493 if (subtable->Format == 1)
495 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
496 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
500 for (j = 0; j < ligset->LigatureCount; j++)
504 lig = ligset->Ligature + j;
505 n = match_ids (gstring, gidx + 1, flag,
506 lig->CompCount - 1, lig->Component);
509 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
516 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
520 if (subtable->Format == 1)
522 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
523 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
528 for (j = 0; j < set->RuleCount; j++)
530 rule = set->Rule + j;
531 if (match_ids (gstring, gidx + 1, flag,
532 rule->GlyphCount - 1, rule->Input) < 0)
534 orig_used = gstring->used;
535 for (k = 0; k < rule->LookupCount; k++)
536 lookup_gsub (otf, lookup_list,
537 rule->LookupRecord[k].LookupListIndex,
539 gidx + rule->LookupRecord[k].SequenceIndex,
541 gidx += rule->GlyphCount + (gstring->used - orig_used);
545 else if (subtable->Format == 2)
547 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
554 class = get_class_def (&context2->ClassDef, g->glyph_id);
555 set = context2->ClassSet + class;
557 for (j = 0; j < set->ClassRuleCnt; j++)
559 rule = set->ClassRule + j;
560 if (match_classes (&context2->ClassDef,
561 gstring, gidx + 1, flag,
562 rule->GlyphCount - 1, rule->Class)
565 orig_used = gstring->used;
566 for (k = 0; k < rule->LookupCount; k++)
567 lookup_gsub (otf, lookup_list,
568 rule->LookupRecord[k].LookupListIndex,
570 gidx + rule->LookupRecord[k].SequenceIndex,
572 gidx += rule->GlyphCount + (gstring->used - orig_used);
576 else /* subtable->Format == 3 */
578 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
582 if (match_coverages (gstring, gidx + 1, flag,
583 context3->GlyphCount - 1,
584 context3->Coverage + 1) < 0)
586 orig_used = gstring->used;
587 for (j = 0; j < context3->LookupCount; j++)
588 lookup_gsub (otf, lookup_list,
589 context3->LookupRecord[j].LookupListIndex,
591 gidx + context3->LookupRecord[j].SequenceIndex,
593 gidx += context3->GlyphCount + (gstring->used - orig_used);
598 if (subtable->Format == 1)
600 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
601 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
605 for (j = 0; j < set->ChainRuleCount; j++)
607 OTF_ChainRule *rule = set->ChainRule + j;
609 if (gidx < rule->BacktrackGlyphCount
610 || (gidx + rule->InputGlyphCount
611 + rule->LookaheadGlyphCount) > gstring->used)
613 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
615 orig_used = gstring->used;
616 for (k = 0; k < rule->LookupCount; k++)
617 lookup_gsub (otf, lookup_list,
618 rule->LookupRecord[k].LookupListIndex,
620 gidx + rule->LookupRecord[k].SequenceIndex,
622 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
626 else if (subtable->Format == 2)
628 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
629 OTF_ChainClassSet *set;
634 class = get_class_def (&context2->InputClassDef, g->glyph_id);
635 set = context2->ChainClassSet + class;
636 for (j = 0; j < set->ChainClassRuleCnt; j++)
638 OTF_ChainClassRule *rule = set->ChainClassRule + j;
641 if (gidx < rule->BacktrackGlyphCount
642 || (gidx + rule->InputGlyphCount
643 + rule->LookaheadGlyphCount) > gstring->used)
645 if (match_chain_classes (gstring, gidx, flag,
646 &context2->BacktrackClassDef,
647 &context2->InputClassDef,
648 &context2->LookaheadClassDef,
651 orig_used = gstring->used;
652 for (k = 0; k < rule->LookupCount; k++)
653 lookup_gsub (otf, lookup_list,
654 rule->LookupRecord[k].LookupListIndex,
656 gidx + rule->LookupRecord[k].SequenceIndex,
658 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
664 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
668 if (gidx < context3->BacktrackGlyphCount
669 || (gidx + context3->InputGlyphCount
670 + context3->LookaheadGlyphCount) > gstring->used)
672 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
674 orig_used = gstring->used;
675 for (j = 0; j < context3->LookupCount; j++)
676 lookup_gsub (otf, lookup_list,
677 context3->LookupRecord[j].LookupListIndex,
679 gidx + context3->LookupRecord[j].SequenceIndex,
681 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
687 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
688 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
689 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
692 if (back_gidx > gstring->used || ahead_gidx < 0)
695 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
696 if (get_coverage_index (reverse->Backtrack + j,
697 gstring->glyphs[gidx + 1 + j].glyph_id)
700 if (j < reverse->BacktrackGlyphCount)
702 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
703 if (get_coverage_index (reverse->LookAhead + j,
704 gstring->glyphs[gidx - 1 - j].glyph_id)
707 if (j < reverse->LookaheadGlyphCount)
709 g->glyph_id = reverse->Substitute[coverage_idx];
717 if (gidx == orig_gidx)
726 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
728 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
730 rec->XPlacement = anchor->XCoordinate;
731 rec->YPlacement = anchor->YCoordinate;
732 if (anchor->AnchorFormat == 1)
735 else if (anchor->AnchorFormat == 2)
736 /* Not yet implemented */
738 else if (anchor->AnchorFormat == 3)
739 /* Not yet implemented */
746 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
747 OTF_GlyphString *gstring, int gidx)
749 char *errfmt = "GPOS Looking up%s";
751 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
752 unsigned int flag = (lookup->LookupFlag
753 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
754 int orig_gidx = gidx;
755 OTF_Glyph *g = gstring->glyphs + gidx;
758 if (IGNORED_GLYPH (g, flag)
759 || g->positioning_type)
762 /* Try all subtables until one of them handles the current glyph. */
763 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
765 unsigned lookup_type = lookup->LookupType;
766 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
769 if (lookup_type == 9)
771 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
773 lookup_type = extension1->ExtensionLookupType;
774 subtable = extension1->ExtensionSubtable;
777 if (subtable->Coverage.offset)
779 coverage_idx = get_coverage_index (&subtable->Coverage,
781 if (coverage_idx < 0)
788 g->positioning_type = lookup_type;
789 if (subtable->Format == 1)
791 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
793 g->f.f1.format = single1->ValueFormat;
794 g->f.f1.value = &single1->Value;
796 else if (subtable->Format == 2)
798 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
800 g->f.f1.format = single2->ValueFormat;
801 g->f.f1.value = single2->Value + coverage_idx;
810 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
811 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
812 next_gidx++, nextg++);
814 if (next_gidx >= gstring->used
815 || nextg->positioning_type)
817 if (subtable->Format == 1)
819 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
820 OTF_PairSet *set = pair1->PairSet + coverage_idx;
823 for (j = 0; j < set->PairValueCount; j++)
824 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
826 if (pair1->ValueFormat1)
828 g->positioning_type = lookup_type;
829 g->f.f2.format = pair1->ValueFormat1;
830 g->f.f2.value = &set->PairValueRecord[j].Value1;
833 if (pair1->ValueFormat2)
835 nextg->positioning_type = lookup_type;
836 nextg->f.f2.format = pair1->ValueFormat2;
837 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
843 else if (subtable->Format == 2)
845 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
846 unsigned class1, class2;
848 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
849 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
850 if (pair2->ValueFormat1)
852 g->positioning_type = lookup_type;
853 g->f.f2.format = pair2->ValueFormat1;
855 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
858 if (pair2->ValueFormat2)
860 nextg->positioning_type = lookup_type;
861 nextg->f.f2.format = pair2->ValueFormat2;
863 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
872 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
874 g->positioning_type = lookup_type;
876 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
878 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
885 if (subtable->Format == 1)
887 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
888 OTF_MarkRecord *mark_record;
889 OTF_AnchorRecord *base_record;
891 int coverage_idx_base;
894 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
896 if (baseg < gstring->glyphs)
899 = get_coverage_index (&mark_base1->BaseCoverage,
901 if (coverage_idx_base < 0)
903 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
905 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
906 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
908 = &base_record->Anchor[mark_record->Class];
909 g->positioning_type = lookup_type;
916 if (subtable->Format == 1)
918 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
920 int coverage_idx_lig;
921 OTF_MarkRecord *mark_record;
922 OTF_LigatureAttach *attach;
923 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
926 for (j = 0; j < mark_lig1->ClassCount; j++)
930 (ligg >= gstring->glyphs
931 && (IGNORED_GLYPH (ligg, flag)
932 || ligg->GlyphClass > OTF_GlyphClassLigature));
934 if (ligg->positioning_type == 5
935 && ligg->MarkAttachClass < mark_lig1->ClassCount)
936 num_class[ligg->MarkAttachClass]++;
937 if (ligg < gstring->glyphs)
940 = get_coverage_index (&mark_lig1->LigatureCoverage,
942 if (coverage_idx_lig < 0)
944 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
945 g->MarkAttachClass = mark_record->Class;
946 attach = (mark_lig1->LigatureArray.LigatureAttach
948 for (j = 0; j < attach->ComponentCount; j++)
950 OTF_Anchor *lig_anchor
951 = attach->ComponentRecord[j].LigatureAnchor;
953 if (lig_anchor[mark_record->Class].AnchorFormat
954 && num_class[mark_record->Class]-- == 0)
956 g->positioning_type = lookup_type;
957 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
958 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
968 if (subtable->Format == 1)
970 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
971 OTF_MarkRecord *mark1_record;
972 OTF_AnchorRecord *mark2_record;
974 int coverage_idx_base;
977 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
979 if (prevg < gstring->glyphs)
982 = get_coverage_index (&mark_mark1->Mark2Coverage,
984 if (coverage_idx_base < 0)
986 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
988 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
989 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
991 = &mark2_record->Anchor[mark1_record->Class];
992 g->positioning_type = lookup_type;
998 if (subtable->Format == 1)
1000 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1001 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1006 for (j = 0; j < set->RuleCount; j++)
1008 rule = set->Rule + j;
1009 if (match_ids (gstring, gidx + 1, flag,
1010 rule->GlyphCount - 1, rule->Input) < 0)
1012 orig_used = gstring->used;
1013 for (k = 0; k < rule->LookupCount; k++)
1014 lookup_gpos (lookup_list,
1015 rule->LookupRecord[k].LookupListIndex,
1017 gidx + rule->LookupRecord[k].SequenceIndex);
1018 gidx += rule->GlyphCount + (gstring->used - orig_used);
1022 else if (subtable->Format == 2)
1024 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1026 OTF_ClassRule *rule;
1031 class = get_class_def (&context2->ClassDef, g->glyph_id);
1032 set = context2->ClassSet + class;
1034 for (j = 0; j < set->ClassRuleCnt; j++)
1036 rule = set->ClassRule + j;
1037 if (match_classes (&context2->ClassDef,
1038 gstring, gidx + 1, flag,
1039 rule->GlyphCount - 1, rule->Class)
1042 orig_used = gstring->used;
1043 for (k = 0; k < rule->LookupCount; k++)
1044 lookup_gpos (lookup_list,
1045 rule->LookupRecord[k].LookupListIndex,
1047 gidx + rule->LookupRecord[k].SequenceIndex);
1048 gidx += rule->GlyphCount + (gstring->used - orig_used);
1052 else /* subtable->Format == 3 */
1054 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1058 if (match_coverages (gstring, gidx + 1, flag,
1059 context3->GlyphCount - 1,
1060 context3->Coverage + 1) < 0)
1062 orig_used = gstring->used;
1063 for (j = 0; j < context3->LookupCount; j++)
1064 lookup_gpos (lookup_list,
1065 context3->LookupRecord[j].LookupListIndex,
1067 gidx + context3->LookupRecord[j].SequenceIndex);
1068 gidx += context3->GlyphCount + (gstring->used - orig_used);
1073 if (subtable->Format == 1)
1075 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1076 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1080 for (j = 0; j < set->ChainRuleCount; j++)
1082 OTF_ChainRule *rule = set->ChainRule + j;
1084 if (gidx < rule->BacktrackGlyphCount
1085 || (gidx + rule->InputGlyphCount
1086 + rule->LookaheadGlyphCount) > gstring->used)
1088 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1090 orig_used = gstring->used;
1091 for (k = 0; k < rule->LookupCount; k++)
1092 lookup_gpos (lookup_list,
1093 rule->LookupRecord[k].LookupListIndex,
1095 gidx + rule->LookupRecord[k].SequenceIndex);
1096 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1100 else if (subtable->Format == 2)
1102 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1103 OTF_ChainClassSet *set;
1108 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1109 set = context2->ChainClassSet + class;
1110 for (j = 0; j < set->ChainClassRuleCnt; j++)
1112 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1115 if (gidx < rule->BacktrackGlyphCount
1116 || (gidx + rule->InputGlyphCount
1117 + rule->LookaheadGlyphCount) > gstring->used)
1119 if (match_chain_classes (gstring, gidx, flag,
1120 &context2->BacktrackClassDef,
1121 &context2->InputClassDef,
1122 &context2->LookaheadClassDef,
1125 orig_used = gstring->used;
1126 for (k = 0; k < rule->LookupCount; k++)
1127 lookup_gpos (lookup_list,
1128 rule->LookupRecord[k].LookupListIndex,
1130 gidx + rule->LookupRecord[k].SequenceIndex);
1131 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1135 else if (subtable->Format == 3)
1137 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1141 if (gidx < context3->BacktrackGlyphCount
1142 || (gidx + context3->InputGlyphCount
1143 + context3->LookaheadGlyphCount) > gstring->used)
1145 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1147 orig_used = gstring->used;
1148 for (j = 0; j < context3->LookupCount; j++)
1149 lookup_gpos (lookup_list,
1150 context3->LookupRecord[j].LookupListIndex,
1152 gidx + context3->LookupRecord[j].SequenceIndex);
1153 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1156 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1163 if (gidx == orig_gidx)
1169 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1173 for (i = 0; i < gstring->used; i++)
1175 c = gstring->glyphs[i].c;
1176 if (c < 0 || c >= 256)
1177 gstring->glyphs[i].glyph_id = 0;
1179 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1185 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1191 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1194 int segCount = sub4->segCountX2 / 2;
1196 for (i = 0; i < gstring->used; i++)
1198 c = gstring->glyphs[i].c;
1200 gstring->glyphs[i].glyph_id = 0;
1201 for (j = 0; j < segCount; j++)
1203 OTF_cmapSegument *seg = sub4->segments + i;
1205 if (c >= seg->startCount && c <= seg->endCount)
1207 if (seg->idRangeOffset == 0xFFFF)
1208 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1210 gstring->glyphs[i].glyph_id
1211 = sub4->glyphIdArray[seg->idRangeOffset
1212 + (c - seg->startCount)];
1222 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1228 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1234 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1240 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1250 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1256 && OTF_get_table (otf, "cmap") < 0)
1260 for (i = 0; i < gstring->used; i++)
1261 if (! gstring->glyphs[i].glyph_id)
1263 int c = gstring->glyphs[i].c;
1264 if (c < 32 || ! cmap->unicode_table)
1265 gstring->glyphs[i].glyph_id = 0;
1267 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1274 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1275 int platform_id, int encoding_id)
1279 char *errfmt = "CMAP Looking up%s";
1281 OTF_EncodingRecord *enc;
1284 && OTF_get_table (otf, "cmap") < 0)
1288 for (i = 0; i < cmap->numTables; i++)
1289 if (cmap->EncodingRecord[i].platformID == platform_id
1290 && cmap->EncodingRecord[i].encodingID == encoding_id)
1292 if (i == cmap->numTables)
1293 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1294 enc = cmap->EncodingRecord + i;
1295 switch (enc->subtable.format)
1297 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1298 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1299 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1300 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1301 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1302 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1303 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1305 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1310 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1313 && OTF_get_table (otf, "cmap") < 0)
1316 || code > otf->cmap->max_glyph_id
1317 || ! otf->cmap->decode_table)
1319 return otf->cmap->decode_table[code];
1323 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1329 && OTF_get_table (otf, "GDEF") < 0)
1333 if (gdef->glyph_class_def.offset)
1334 for (i = 0; i < gstring->used; i++)
1335 gstring->glyphs[i].GlyphClass
1336 = get_class_def (&gdef->glyph_class_def,
1337 gstring->glyphs[i].glyph_id);
1339 if (gdef->mark_attach_class_def.offset)
1340 for (i = 0; i < gstring->used; i++)
1341 gstring->glyphs[i].MarkAttachClass
1342 = get_class_def (&gdef->mark_attach_class_def,
1343 gstring->glyphs[i].glyph_id);
1349 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1350 char *script, char *language, char *features,
1351 int alternate_subst)
1353 char *errfmt = "GSUB driving%s";
1356 OTF_LangSys *LangSys;
1357 int *lookup_indices;
1360 for (i = 0; i < gstring->used; i++)
1362 gstring->glyphs[i].positioning_type = 0;
1363 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1366 if (OTF_get_table (otf, "GSUB") < 0)
1369 if (gsub->FeatureList.FeatureCount == 0
1370 || gsub->LookupList.LookupCount == 0)
1373 LangSys = get_langsys (&gsub->ScriptList, script, language);
1377 /* One lookup may be used by multiple features. */
1378 lookup_indices = alloca (sizeof (int)
1379 * gsub->LookupList.LookupCount
1380 * (gsub->FeatureList.FeatureCount + 1));
1381 if (! lookup_indices)
1382 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1383 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1384 features, lookup_indices);
1388 for (i = 0; i < n; i++)
1390 int index = lookup_indices[i];
1393 if (gsub->LookupList.Lookup[index].LookupType != 8)
1396 while (gidx < gstring->used)
1398 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1406 gidx = gstring->used - 1;
1409 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1421 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1422 char *script, char *language, char *features)
1424 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1428 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1429 char *script, char *language, char *features)
1431 char *errfmt = "GPOS driving%s";
1434 OTF_LangSys *LangSys;
1435 int *lookup_indices;
1438 for (i = 0; i < gstring->used; i++)
1439 gstring->glyphs[i].positioning_type = 0;
1441 if (OTF_get_table (otf, "GPOS") < 0)
1444 if (gpos->FeatureList.FeatureCount == 0
1445 || gpos->LookupList.LookupCount == 0)
1448 LangSys = get_langsys (&gpos->ScriptList, script, language);
1452 /* One lookup may be used by multiple features. */
1453 lookup_indices = alloca (sizeof (int)
1454 * gpos->LookupList.LookupCount
1455 * (gpos->FeatureList.FeatureCount + 1));
1456 if (! lookup_indices)
1457 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1458 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1459 features, lookup_indices);
1463 for (i = 0; i < n; i++)
1465 int index = lookup_indices[i];
1468 while (gidx < gstring->used)
1470 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1480 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1481 char *script, char *language,
1482 char *gsub_features, char *gpos_features)
1484 if (OTF_drive_cmap (otf, gstring) < 0)
1486 if (OTF_drive_gdef (otf, gstring) < 0)
1489 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1492 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1498 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1499 char *script, char *language, char *features)
1501 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);