1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
32 /* Return nonzero (-1 if ID is zero, 1 otherwise) if OTF_Glyph *G
33 should be ignored according to LookupFlag FLAG. */
34 #define IGNORED_GLYPH(g, flag) \
35 ((g)->glyph_id == 0 ? -1 \
36 : (((flag) & (1 << (g)->GlyphClass)) \
37 || (((flag) & OTF_MarkAttachmentType) \
38 && (g)->GlyphClass == OTF_GlyphClassMark \
39 && ((flag) >> 8) != (g)->MarkAttachClass)))
41 #define GSTRING_DELETE(gstring, from, len) \
43 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
44 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
45 gstring->used -= len; \
49 #define GSTRING_INSERT(gstring, pos, len) \
51 if (gstring->used + len > gstring->size) \
53 char *errfmt = "GSTRING%s"; \
55 gstring->size = gstring->used + len; \
57 = (OTF_Glyph *) realloc (gstring->glyphs, \
58 sizeof (OTF_Glyph) * gstring->size); \
59 if (! gstring->glyphs) \
60 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
62 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
63 sizeof (OTF_Glyph) * (gstring->used - pos)); \
64 gstring->used += len; \
68 static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID);
71 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
72 OTF_GlyphID *ids, int num)
77 int from_idx = gstring->glyphs[from].f.index.from;
78 int to_idx = gstring->glyphs[to - 1].f.index.to;
81 for (i = non_ignored_idx = to - 1; i >= from; i--)
83 OTF_Glyph *g = gstring->glyphs + i;
85 if (IGNORED_GLYPH (g, flag) == 1)
87 /* Move this glyph to the next of the current target of
91 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
92 temp.f.index.from = from_idx;
93 temp.f.index.to = to_idx;
94 gstring->glyphs[non_ignored_idx--] = temp;
100 GSTRING_INSERT (gstring, from, (num - len));
102 GSTRING_DELETE (gstring, from, (len - num));
103 for (i = 0; i < num; i++)
105 gstring->glyphs[from + i].c = otf->cmap->decode_table[ids[i]];
106 gstring->glyphs[from + i].glyph_id = ids[i];
108 gstring->glyphs[from + i].GlyphClass
109 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
111 gstring->glyphs[from + i].GlyphClass = 0;
112 gstring->glyphs[from + i].positioning_type = 0;
113 gstring->glyphs[from + i].f.index.from = from_idx;
114 gstring->glyphs[from + i].f.index.to = to_idx;
121 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
125 if (coverage->CoverageFormat == 1)
127 for (i = 0; i < coverage->Count; i++)
128 if (coverage->table.GlyphArray[i] == id)
133 for (i = 0; i < coverage->Count; i++)
134 if (coverage->table.RangeRecord[i].Start <= id
135 && coverage->table.RangeRecord[i].End >= id)
136 return (coverage->table.RangeRecord[i].StartCoverageIndex
137 + (id - coverage->table.RangeRecord[i].Start));
143 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
145 if (class_def->ClassFormat == 1)
147 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
149 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
150 return class_def->f.f1.ClassValueArray[idx];
156 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
157 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
158 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
159 return class_def->f.f2.ClassRangeRecord[i].Class;
165 get_langsys (OTF_ScriptList *script_list,
166 const char *script, const char *language)
169 OTF_Tag script_tag = OTF_tag (script);
170 OTF_Tag langsys_tag = OTF_tag (language);
172 OTF_Tag dflt_tag = OTF_tag ("DFLT");
173 OTF_Script *dflt = NULL;
175 for (i = 0; i < script_list->ScriptCount; i++)
177 OTF_Script *script = script_list->Script + i;
179 if (script_list->Script[i].ScriptTag == dflt_tag)
181 if (script_list->Script[i].ScriptTag == script_tag)
184 return &script->DefaultLangSys;
185 for (j = 0; j < script->LangSysCount; j++)
186 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
187 return script->LangSys + j;
188 return &script->DefaultLangSys;
193 dflt = script_list->Script;
195 return &dflt->DefaultLangSys;
196 for (j = 0; j < dflt->LangSysCount; j++)
197 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
198 return dflt->LangSys + j;
199 return &dflt->DefaultLangSys;
203 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
204 const char *features, int *lookup_indices)
207 OTF_Feature *feature;
208 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
210 for (i = 0; i < FeatureList->FeatureCount; i++)
211 feature_table[i] = 0;
219 if (*features == '*')
221 /* Consume all remaining features. */
222 for (i = 0; i < FeatureList->FeatureCount; i++)
223 if (! feature_table[i])
225 feature = FeatureList->Feature + i;
226 for (j = 0; j < feature->LookupCount; j++)
227 lookup_indices[n++] = feature->LookupListIndex[j];
232 if (*features == '~')
233 use_it = -1, features++;
234 for (i = 0; *features && *features != ','; i++, features++)
235 tagname[i] = *features;
241 tag = OTF_tag (tagname);
242 for (i = 0; i < FeatureList->FeatureCount; i++)
244 feature = FeatureList->Feature + i;
245 if (tag == feature->FeatureTag)
247 if (feature_table[i])
250 for (j = 0; j < feature->LookupCount; j++)
251 lookup_indices[n++] = feature->LookupListIndex[j];
252 feature_table[i] = use_it;
262 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
263 int count, OTF_GlyphID *ids)
265 OTF_Glyph *gbeg = gstring->glyphs + gidx;
266 OTF_Glyph *gend = gstring->glyphs + gstring->used;
270 for (g = gbeg, i = 0; g < gend && i < count; g++)
271 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
273 return (i < count ? -1 : g - gbeg);
277 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
280 int i = rule->BacktrackGlyphCount;
287 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
288 if (! IGNORED_GLYPH (g, flag) && --i == 0)
292 if (match_ids (gstring, j, flag,
293 rule->BacktrackGlyphCount, rule->Backtrack)
298 i = match_ids (gstring, gidx, flag,
299 rule->InputGlyphCount - 1, rule->Input);
303 i = match_ids (gstring, gidx, flag,
304 rule->LookaheadGlyphCount, rule->LookAhead);
311 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
312 int flag, int count, unsigned *classes)
314 OTF_Glyph *gbeg = gstring->glyphs + gidx;
315 OTF_Glyph *gend = gstring->glyphs + gstring->used;
319 for (g = gbeg, i = 0; g < gend && i < count; g++)
320 if (! IGNORED_GLYPH (g, flag)
321 && get_class_def (class_def, g->glyph_id) != classes[i++])
323 return (i < count ? -1 : g - gbeg);
327 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
328 OTF_ClassDef *BacktrackClassDef,
329 OTF_ClassDef *InputClassDef,
330 OTF_ClassDef *LookaheadClassDef,
331 OTF_ChainClassRule *rule)
333 int i = rule->BacktrackGlyphCount;
340 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
341 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
345 if (match_classes (BacktrackClassDef, gstring, j, flag,
346 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
350 i = match_classes (InputClassDef, gstring, gidx, flag,
351 rule->InputGlyphCount - 1, rule->Input);
355 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
356 rule->LookaheadGlyphCount, rule->LookAhead);
364 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
365 OTF_Coverage *coverages)
367 OTF_Glyph *gbeg = gstring->glyphs + gidx;
368 OTF_Glyph *gend = gstring->glyphs + gstring->used;
372 for (g = gbeg, i = 0; g < gend && i < count; g++)
373 if (! IGNORED_GLYPH (g, flag)
374 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
376 return (i < count ? -1 : g - gbeg);
380 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
381 OTF_GSUB_ChainContext3 *context3)
383 int i = context3->BacktrackGlyphCount;
390 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
391 if (! IGNORED_GLYPH (g, flag) && --i == 0)
395 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
396 context3->Backtrack) < 0)
400 if (context3->InputGlyphCount > 1)
402 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
403 context3->Input + 1);
408 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
409 context3->LookAhead) < 0)
415 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
416 OTF_GlyphString *gstring, int gidx, int alternate_subst)
418 char *errfmt = "GSUB Looking up%s";
420 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
421 unsigned int flag = (lookup->LookupFlag
422 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
423 int orig_gidx = gidx;
424 OTF_Glyph *g = gstring->glyphs + gidx;
427 if (IGNORED_GLYPH (g, flag))
430 /* Try all subtables until one of them handles the current glyph. */
431 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
433 unsigned lookup_type = lookup->LookupType;
434 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
437 if (lookup_type == 7)
439 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
441 lookup_type = extension1->ExtensionLookupType;
442 subtable = extension1->ExtensionSubtable;
446 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
447 : (lookup_type == 3))
450 if (subtable->Coverage.offset)
452 coverage_idx = get_coverage_index (&subtable->Coverage,
454 if (coverage_idx < 0)
461 if (subtable->Format == 1)
462 g->glyph_id += subtable->u.single1.DeltaGlyphID;
464 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
469 if (subtable->Format == 1)
471 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
472 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
474 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
475 seq->Substitute, seq->GlyphCount);
476 gidx += seq->GlyphCount;
479 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
483 if (subtable->Format == 1)
485 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
486 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
488 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
489 altset->Alternate, altset->GlyphCount);
490 gidx += altset->GlyphCount;;
493 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
497 if (subtable->Format == 1)
499 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
500 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
504 for (j = 0; j < ligset->LigatureCount; j++)
508 lig = ligset->Ligature + j;
509 n = match_ids (gstring, gidx + 1, flag,
510 lig->CompCount - 1, lig->Component);
513 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
520 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
524 if (subtable->Format == 1)
526 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
527 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
532 for (j = 0; j < set->RuleCount; j++)
534 rule = set->Rule + j;
535 if (match_ids (gstring, gidx + 1, flag,
536 rule->GlyphCount - 1, rule->Input) < 0)
538 orig_used = gstring->used;
539 for (k = 0; k < rule->LookupCount; k++)
540 lookup_gsub (otf, lookup_list,
541 rule->LookupRecord[k].LookupListIndex,
543 gidx + rule->LookupRecord[k].SequenceIndex,
545 gidx += rule->GlyphCount + (gstring->used - orig_used);
549 else if (subtable->Format == 2)
551 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
558 class = get_class_def (&context2->ClassDef, g->glyph_id);
559 set = context2->ClassSet + class;
561 for (j = 0; j < set->ClassRuleCnt; j++)
563 rule = set->ClassRule + j;
564 if (match_classes (&context2->ClassDef,
565 gstring, gidx + 1, flag,
566 rule->GlyphCount - 1, rule->Class)
569 orig_used = gstring->used;
570 for (k = 0; k < rule->LookupCount; k++)
571 lookup_gsub (otf, lookup_list,
572 rule->LookupRecord[k].LookupListIndex,
574 gidx + rule->LookupRecord[k].SequenceIndex,
576 gidx += rule->GlyphCount + (gstring->used - orig_used);
580 else /* subtable->Format == 3 */
582 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
586 if (match_coverages (gstring, gidx + 1, flag,
587 context3->GlyphCount - 1,
588 context3->Coverage + 1) < 0)
590 orig_used = gstring->used;
591 for (j = 0; j < context3->LookupCount; j++)
592 lookup_gsub (otf, lookup_list,
593 context3->LookupRecord[j].LookupListIndex,
595 gidx + context3->LookupRecord[j].SequenceIndex,
597 gidx += context3->GlyphCount + (gstring->used - orig_used);
602 if (subtable->Format == 1)
604 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
605 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
609 for (j = 0; j < set->ChainRuleCount; j++)
611 OTF_ChainRule *rule = set->ChainRule + j;
613 if (gidx < rule->BacktrackGlyphCount
614 || (gidx + rule->InputGlyphCount
615 + rule->LookaheadGlyphCount) > gstring->used)
617 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
619 orig_used = gstring->used;
620 for (k = 0; k < rule->LookupCount; k++)
621 lookup_gsub (otf, lookup_list,
622 rule->LookupRecord[k].LookupListIndex,
624 gidx + rule->LookupRecord[k].SequenceIndex,
626 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
630 else if (subtable->Format == 2)
632 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
633 OTF_ChainClassSet *set;
638 class = get_class_def (&context2->InputClassDef, g->glyph_id);
639 set = context2->ChainClassSet + class;
640 for (j = 0; j < set->ChainClassRuleCnt; j++)
642 OTF_ChainClassRule *rule = set->ChainClassRule + j;
645 if (gidx < rule->BacktrackGlyphCount
646 || (gidx + rule->InputGlyphCount
647 + rule->LookaheadGlyphCount) > gstring->used)
649 if (match_chain_classes (gstring, gidx, flag,
650 &context2->BacktrackClassDef,
651 &context2->InputClassDef,
652 &context2->LookaheadClassDef,
655 orig_used = gstring->used;
656 for (k = 0; k < rule->LookupCount; k++)
657 lookup_gsub (otf, lookup_list,
658 rule->LookupRecord[k].LookupListIndex,
660 gidx + rule->LookupRecord[k].SequenceIndex,
662 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
668 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
672 if (gidx < context3->BacktrackGlyphCount
673 || (gidx + context3->InputGlyphCount
674 + context3->LookaheadGlyphCount) > gstring->used)
676 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
678 orig_used = gstring->used;
679 for (j = 0; j < context3->LookupCount; j++)
680 lookup_gsub (otf, lookup_list,
681 context3->LookupRecord[j].LookupListIndex,
683 gidx + context3->LookupRecord[j].SequenceIndex,
685 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
691 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
692 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
693 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
696 if (back_gidx > gstring->used || ahead_gidx < 0)
699 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
700 if (get_coverage_index (reverse->Backtrack + j,
701 gstring->glyphs[gidx + 1 + j].glyph_id)
704 if (j < reverse->BacktrackGlyphCount)
706 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
707 if (get_coverage_index (reverse->LookAhead + j,
708 gstring->glyphs[gidx - 1 - j].glyph_id)
711 if (j < reverse->LookaheadGlyphCount)
713 g->glyph_id = reverse->Substitute[coverage_idx];
721 if (gidx == orig_gidx)
730 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
732 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
734 rec->XPlacement = anchor->XCoordinate;
735 rec->YPlacement = anchor->YCoordinate;
736 if (anchor->AnchorFormat == 1)
739 else if (anchor->AnchorFormat == 2)
740 /* Not yet implemented */
742 else if (anchor->AnchorFormat == 3)
743 /* Not yet implemented */
750 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
751 OTF_GlyphString *gstring, int gidx)
753 char *errfmt = "GPOS Looking up%s";
755 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
756 unsigned int flag = (lookup->LookupFlag
757 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
758 int orig_gidx = gidx;
759 OTF_Glyph *g = gstring->glyphs + gidx;
762 if (IGNORED_GLYPH (g, flag)
763 || g->positioning_type)
766 /* Try all subtables until one of them handles the current glyph. */
767 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
769 unsigned lookup_type = lookup->LookupType;
770 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
773 if (lookup_type == 9)
775 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
777 lookup_type = extension1->ExtensionLookupType;
778 subtable = extension1->ExtensionSubtable;
781 if (subtable->Coverage.offset)
783 coverage_idx = get_coverage_index (&subtable->Coverage,
785 if (coverage_idx < 0)
792 g->positioning_type = lookup_type;
793 if (subtable->Format == 1)
795 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
797 g->f.f1.format = single1->ValueFormat;
798 g->f.f1.value = &single1->Value;
800 else if (subtable->Format == 2)
802 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
804 g->f.f1.format = single2->ValueFormat;
805 g->f.f1.value = single2->Value + coverage_idx;
814 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
815 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
816 next_gidx++, nextg++);
818 if (next_gidx >= gstring->used
819 || nextg->positioning_type)
821 if (subtable->Format == 1)
823 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
824 OTF_PairSet *set = pair1->PairSet + coverage_idx;
827 for (j = 0; j < set->PairValueCount; j++)
828 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
830 if (pair1->ValueFormat1)
832 g->positioning_type = lookup_type;
833 g->f.f2.format = pair1->ValueFormat1;
834 g->f.f2.value = &set->PairValueRecord[j].Value1;
837 if (pair1->ValueFormat2)
839 nextg->positioning_type = lookup_type;
840 nextg->f.f2.format = pair1->ValueFormat2;
841 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
847 else if (subtable->Format == 2)
849 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
850 unsigned class1, class2;
852 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
853 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
854 if (pair2->ValueFormat1)
856 g->positioning_type = lookup_type;
857 g->f.f2.format = pair2->ValueFormat1;
859 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
862 if (pair2->ValueFormat2)
864 nextg->positioning_type = lookup_type;
865 nextg->f.f2.format = pair2->ValueFormat2;
867 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
876 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
878 g->positioning_type = lookup_type;
880 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
882 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
889 if (subtable->Format == 1)
891 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
892 OTF_MarkRecord *mark_record;
893 OTF_AnchorRecord *base_record;
895 int coverage_idx_base;
898 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
900 if (baseg < gstring->glyphs)
903 = get_coverage_index (&mark_base1->BaseCoverage,
905 if (coverage_idx_base < 0)
907 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
909 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
910 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
912 = &base_record->Anchor[mark_record->Class];
913 g->positioning_type = lookup_type;
920 if (subtable->Format == 1)
922 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
924 int coverage_idx_lig;
925 OTF_MarkRecord *mark_record;
926 OTF_LigatureAttach *attach;
927 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
930 for (j = 0; j < mark_lig1->ClassCount; j++)
934 (ligg >= gstring->glyphs
935 && (IGNORED_GLYPH (ligg, flag)
936 || ligg->GlyphClass > OTF_GlyphClassLigature));
938 if (ligg->positioning_type == 5
939 && ligg->MarkAttachClass < mark_lig1->ClassCount)
940 num_class[ligg->MarkAttachClass]++;
941 if (ligg < gstring->glyphs)
944 = get_coverage_index (&mark_lig1->LigatureCoverage,
946 if (coverage_idx_lig < 0)
948 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
949 g->MarkAttachClass = mark_record->Class;
950 attach = (mark_lig1->LigatureArray.LigatureAttach
952 for (j = 0; j < attach->ComponentCount; j++)
954 OTF_Anchor *lig_anchor
955 = attach->ComponentRecord[j].LigatureAnchor;
957 if (lig_anchor[mark_record->Class].AnchorFormat
958 && num_class[mark_record->Class]-- == 0)
960 g->positioning_type = lookup_type;
961 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
962 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
972 if (subtable->Format == 1)
974 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
975 OTF_MarkRecord *mark1_record;
976 OTF_AnchorRecord *mark2_record;
978 int coverage_idx_base;
981 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
983 if (prevg < gstring->glyphs)
986 = get_coverage_index (&mark_mark1->Mark2Coverage,
988 if (coverage_idx_base < 0)
990 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
992 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
993 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
995 = &mark2_record->Anchor[mark1_record->Class];
996 g->positioning_type = lookup_type;
1002 if (subtable->Format == 1)
1004 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1005 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1010 for (j = 0; j < set->RuleCount; j++)
1012 rule = set->Rule + j;
1013 if (match_ids (gstring, gidx + 1, flag,
1014 rule->GlyphCount - 1, rule->Input) < 0)
1016 orig_used = gstring->used;
1017 for (k = 0; k < rule->LookupCount; k++)
1018 lookup_gpos (lookup_list,
1019 rule->LookupRecord[k].LookupListIndex,
1021 gidx + rule->LookupRecord[k].SequenceIndex);
1022 gidx += rule->GlyphCount + (gstring->used - orig_used);
1026 else if (subtable->Format == 2)
1028 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1030 OTF_ClassRule *rule;
1035 class = get_class_def (&context2->ClassDef, g->glyph_id);
1036 set = context2->ClassSet + class;
1038 for (j = 0; j < set->ClassRuleCnt; j++)
1040 rule = set->ClassRule + j;
1041 if (match_classes (&context2->ClassDef,
1042 gstring, gidx + 1, flag,
1043 rule->GlyphCount - 1, rule->Class)
1046 orig_used = gstring->used;
1047 for (k = 0; k < rule->LookupCount; k++)
1048 lookup_gpos (lookup_list,
1049 rule->LookupRecord[k].LookupListIndex,
1051 gidx + rule->LookupRecord[k].SequenceIndex);
1052 gidx += rule->GlyphCount + (gstring->used - orig_used);
1056 else /* subtable->Format == 3 */
1058 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1062 if (match_coverages (gstring, gidx + 1, flag,
1063 context3->GlyphCount - 1,
1064 context3->Coverage + 1) < 0)
1066 orig_used = gstring->used;
1067 for (j = 0; j < context3->LookupCount; j++)
1068 lookup_gpos (lookup_list,
1069 context3->LookupRecord[j].LookupListIndex,
1071 gidx + context3->LookupRecord[j].SequenceIndex);
1072 gidx += context3->GlyphCount + (gstring->used - orig_used);
1077 if (subtable->Format == 1)
1079 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1080 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1084 for (j = 0; j < set->ChainRuleCount; j++)
1086 OTF_ChainRule *rule = set->ChainRule + j;
1088 if (gidx < rule->BacktrackGlyphCount
1089 || (gidx + rule->InputGlyphCount
1090 + rule->LookaheadGlyphCount) > gstring->used)
1092 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1094 orig_used = gstring->used;
1095 for (k = 0; k < rule->LookupCount; k++)
1096 lookup_gpos (lookup_list,
1097 rule->LookupRecord[k].LookupListIndex,
1099 gidx + rule->LookupRecord[k].SequenceIndex);
1100 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1104 else if (subtable->Format == 2)
1106 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1107 OTF_ChainClassSet *set;
1112 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1113 set = context2->ChainClassSet + class;
1114 for (j = 0; j < set->ChainClassRuleCnt; j++)
1116 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1119 if (gidx < rule->BacktrackGlyphCount
1120 || (gidx + rule->InputGlyphCount
1121 + rule->LookaheadGlyphCount) > gstring->used)
1123 if (match_chain_classes (gstring, gidx, flag,
1124 &context2->BacktrackClassDef,
1125 &context2->InputClassDef,
1126 &context2->LookaheadClassDef,
1129 orig_used = gstring->used;
1130 for (k = 0; k < rule->LookupCount; k++)
1131 lookup_gpos (lookup_list,
1132 rule->LookupRecord[k].LookupListIndex,
1134 gidx + rule->LookupRecord[k].SequenceIndex);
1135 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1139 else if (subtable->Format == 3)
1141 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1145 if (gidx < context3->BacktrackGlyphCount
1146 || (gidx + context3->InputGlyphCount
1147 + context3->LookaheadGlyphCount) > gstring->used)
1149 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1151 orig_used = gstring->used;
1152 for (j = 0; j < context3->LookupCount; j++)
1153 lookup_gpos (lookup_list,
1154 context3->LookupRecord[j].LookupListIndex,
1156 gidx + context3->LookupRecord[j].SequenceIndex);
1157 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1160 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1167 if (gidx == orig_gidx)
1173 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1177 for (i = 0; i < gstring->used; i++)
1179 c = gstring->glyphs[i].c;
1180 if (c < 0 || c >= 256)
1181 gstring->glyphs[i].glyph_id = 0;
1183 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1189 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1195 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1198 int segCount = sub4->segCountX2 / 2;
1200 for (i = 0; i < gstring->used; i++)
1202 c = gstring->glyphs[i].c;
1204 gstring->glyphs[i].glyph_id = 0;
1205 for (j = 0; j < segCount; j++)
1207 OTF_cmapSegument *seg = sub4->segments + i;
1209 if (c >= seg->startCount && c <= seg->endCount)
1211 if (seg->idRangeOffset == 0xFFFF)
1212 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1214 gstring->glyphs[i].glyph_id
1215 = sub4->glyphIdArray[seg->idRangeOffset
1216 + (c - seg->startCount)];
1226 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1232 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1238 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1244 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1254 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1260 && OTF_get_table (otf, "cmap") < 0)
1264 for (i = 0; i < gstring->used; i++)
1265 if (! gstring->glyphs[i].glyph_id)
1267 int c = gstring->glyphs[i].c;
1268 if (c < 32 || ! cmap->unicode_table)
1269 gstring->glyphs[i].glyph_id = 0;
1271 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1278 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1279 int platform_id, int encoding_id)
1283 char *errfmt = "CMAP Looking up%s";
1285 OTF_EncodingRecord *enc;
1288 && OTF_get_table (otf, "cmap") < 0)
1292 for (i = 0; i < cmap->numTables; i++)
1293 if (cmap->EncodingRecord[i].platformID == platform_id
1294 && cmap->EncodingRecord[i].encodingID == encoding_id)
1296 if (i == cmap->numTables)
1297 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1298 enc = cmap->EncodingRecord + i;
1299 switch (enc->subtable.format)
1301 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1302 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1303 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1304 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1305 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1306 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1307 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1309 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1314 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1317 && OTF_get_table (otf, "cmap") < 0)
1320 || code > otf->cmap->max_glyph_id
1321 || ! otf->cmap->decode_table)
1323 return otf->cmap->decode_table[code];
1327 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1333 && OTF_get_table (otf, "GDEF") < 0)
1337 if (gdef->glyph_class_def.offset)
1338 for (i = 0; i < gstring->used; i++)
1339 gstring->glyphs[i].GlyphClass
1340 = get_class_def (&gdef->glyph_class_def,
1341 gstring->glyphs[i].glyph_id);
1343 if (gdef->mark_attach_class_def.offset)
1344 for (i = 0; i < gstring->used; i++)
1345 gstring->glyphs[i].MarkAttachClass
1346 = get_class_def (&gdef->mark_attach_class_def,
1347 gstring->glyphs[i].glyph_id);
1353 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1354 const char *script, const char *language,
1355 const char *features,
1356 int alternate_subst)
1358 char *errfmt = "GSUB driving%s";
1361 OTF_LangSys *LangSys;
1362 int *lookup_indices;
1365 for (i = 0; i < gstring->used; i++)
1367 gstring->glyphs[i].positioning_type = 0;
1368 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1371 if (OTF_get_table (otf, "GSUB") < 0)
1374 if (gsub->FeatureList.FeatureCount == 0
1375 || gsub->LookupList.LookupCount == 0)
1378 LangSys = get_langsys (&gsub->ScriptList, script, language);
1382 /* One lookup may be used by multiple features. */
1383 lookup_indices = alloca (sizeof (int)
1384 * gsub->LookupList.LookupCount
1385 * (gsub->FeatureList.FeatureCount + 1));
1386 if (! lookup_indices)
1387 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1388 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1389 features, lookup_indices);
1393 for (i = 0; i < n; i++)
1395 int index = lookup_indices[i];
1398 if (gsub->LookupList.Lookup[index].LookupType != 8)
1401 while (gidx < gstring->used)
1403 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1411 gidx = gstring->used - 1;
1414 gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1426 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1427 const char *script, const char *language, const char *features)
1429 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1433 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1434 const char *script, const char *language, const char *features)
1436 char *errfmt = "GPOS driving%s";
1439 OTF_LangSys *LangSys;
1440 int *lookup_indices;
1443 for (i = 0; i < gstring->used; i++)
1444 gstring->glyphs[i].positioning_type = 0;
1446 if (OTF_get_table (otf, "GPOS") < 0)
1449 if (gpos->FeatureList.FeatureCount == 0
1450 || gpos->LookupList.LookupCount == 0)
1453 LangSys = get_langsys (&gpos->ScriptList, script, language);
1457 /* One lookup may be used by multiple features. */
1458 lookup_indices = alloca (sizeof (int)
1459 * gpos->LookupList.LookupCount
1460 * (gpos->FeatureList.FeatureCount + 1));
1461 if (! lookup_indices)
1462 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1463 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1464 features, lookup_indices);
1468 for (i = 0; i < n; i++)
1470 int index = lookup_indices[i];
1473 while (gidx < gstring->used)
1475 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1485 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1486 const char *script, const char *language,
1487 const char *gsub_features, const char *gpos_features)
1489 if (OTF_drive_cmap (otf, gstring) < 0)
1491 if (OTF_drive_gdef (otf, gstring) < 0)
1494 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1497 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1503 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1504 const char *script, const char *language,
1505 const char *features)
1507 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);