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 #define GSTRING_DELETE(gstring, from, len) \
34 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
35 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
36 gstring->used -= len; \
40 #define GSTRING_INSERT(gstring, pos, len) \
42 if (gstring->used + len > gstring->size) \
44 char *errfmt = "GSTRING%s"; \
46 gstring->size = gstring->used + len; \
47 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
49 if (! gstring->glyphs) \
50 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
52 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
53 sizeof (OTF_Glyph) * (gstring->used - pos)); \
54 gstring->used += len; \
59 gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag,
60 OTF_GlyphID *ids, int num)
65 int c = gstring->glyphs[from].c;
66 int from_idx = gstring->glyphs[from].f.index.from;
67 int to_idx = gstring->glyphs[to - 1].f.index.to;
70 for (i = non_ignored_idx = to - 1; i >= from; i--)
71 if (! gstring->glyphs[i].glyph_id
72 || (flag & (1 << gstring->glyphs[i].GlyphClass)))
74 OTF_Glyph temp = gstring->glyphs[i];
76 memmove (gstring->glyphs + i, gstring->glyphs + i + 1,
77 sizeof (OTF_Glyph) * (non_ignored_idx - i));
78 gstring->glyphs[non_ignored_idx--] = temp;
83 GSTRING_INSERT (gstring, from, (num - len));
85 GSTRING_DELETE (gstring, from, (len - num));
86 for (i = 0; i < num; i++)
88 gstring->glyphs[from + i].c = c;
89 gstring->glyphs[from + i].glyph_id = ids[i];
90 gstring->glyphs[from + i].f.index.from = from_idx;
91 gstring->glyphs[from + i].f.index.to = to_idx;
98 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
102 if (coverage->CoverageFormat == 1)
104 for (i = 0; i < coverage->Count; i++)
105 if (coverage->table.GlyphArray[i] == id)
110 for (i = 0; i < coverage->Count; i++)
111 if (coverage->table.RangeRecord[i].Start <= id
112 && coverage->table.RangeRecord[i].End >= id)
113 return (coverage->table.RangeRecord[i].StartCoverageIndex
114 + (id - coverage->table.RangeRecord[i].Start));
120 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
122 if (class_def->ClassFormat == 1)
124 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
126 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
127 return class_def->f.f1.ClassValueArray[idx];
133 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
134 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
135 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
136 return class_def->f.f2.ClassRangeRecord[i].Class;
142 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
145 OTF_Tag script_tag = OTF_tag (script);
146 OTF_Tag langsys_tag = OTF_tag (language);
148 OTF_Tag dflt_tag = OTF_tag ("DFLT");
149 OTF_Script *dflt = NULL;
151 for (i = 0; i < script_list->ScriptCount; i++)
153 OTF_Script *script = script_list->Script + i;
155 if (script_list->Script[i].ScriptTag == dflt_tag)
157 if (script_list->Script[i].ScriptTag == script_tag)
160 return &script->DefaultLangSys;
161 for (j = 0; j < script->LangSysCount; j++)
162 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
163 return script->LangSys + j;
164 return &script->DefaultLangSys;
169 dflt = script_list->Script;
171 return &dflt->DefaultLangSys;
172 for (j = 0; j < dflt->LangSysCount; j++)
173 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
174 return dflt->LangSys + j;
175 return &dflt->DefaultLangSys;
179 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
180 char *features, int *lookup_indices)
183 OTF_Feature *feature;
184 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
186 for (i = 0; i < FeatureList->FeatureCount; i++)
187 feature_table[i] = 0;
195 if (*features == '*')
197 /* Consume all remaining features. */
198 /* We are sure that the last LookupCount elements of
199 lookup_indices are free to be used for this work. */
200 int *free_table = (lookup_indices + (LookupList->LookupCount
201 * FeatureList->FeatureCount));
203 for (i = 0; i < LookupList->LookupCount; i++)
205 for (i = 0; i < FeatureList->FeatureCount; i++)
206 if (! feature_table[i])
208 feature = FeatureList->Feature + i;
209 for (j = 0; j < feature->LookupCount; j++)
210 free_table[feature->LookupListIndex[j]] = 1;
212 for (i = 0; i < LookupList->LookupCount; i++)
214 lookup_indices[n++] = i;
218 if (*features == '~')
219 negate = 1, features++;
220 for (i = 0; *features && *features != ','; i++, features++)
221 tagname[i] = *features;
227 tag = OTF_tag (tagname);
228 for (i = 0; i < FeatureList->FeatureCount; i++)
230 feature = FeatureList->Feature + i;
231 if (tag == feature->FeatureTag)
234 for (j = 0; j < feature->LookupCount; j++)
235 lookup_indices[n++] = feature->LookupListIndex[j];
236 feature_table[i] = 1;
246 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
247 int count, OTF_GlyphID *ids)
249 OTF_Glyph *gbeg = gstring->glyphs + gidx;
250 OTF_Glyph *gend = gstring->glyphs + gstring->used;
254 for (g = gbeg, i = 0; g < gend && i < count; g++)
255 if (g->glyph_id && ! (flag & (1 << g->GlyphClass))
256 && g->glyph_id != ids[i++])
258 return (i < count ? -1 : g - gbeg);
262 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
265 int i = rule->BacktrackGlyphCount;
271 for (j = gidx - 1; j >= 0; j--)
272 if (gstring->glyphs[j].glyph_id
277 if (match_ids (gstring, j, flag,
278 rule->BacktrackGlyphCount, rule->Backtrack)
283 i = match_ids (gstring, gidx, flag,
284 rule->InputGlyphCount - 1, rule->Input);
288 i = match_ids (gstring, gidx, flag,
289 rule->LookaheadGlyphCount, rule->LookAhead);
296 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
297 int flag, int count, unsigned *classes)
299 OTF_Glyph *gbeg = gstring->glyphs + gidx;
300 OTF_Glyph *gend = gstring->glyphs + gstring->used;
304 for (g = gbeg, i = 0; g < gend && i < count; g++)
305 if (g->glyph_id && ! (flag & (1 << g->GlyphClass))
306 && get_class_def (class_def, g->glyph_id) != classes[i++])
308 return (i < count ? -1 : g - gbeg);
312 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
313 OTF_ClassDef *BacktrackClassDef,
314 OTF_ClassDef *InputClassDef,
315 OTF_ClassDef *LookaheadClassDef,
316 OTF_ChainClassRule *rule)
318 int i = rule->BacktrackGlyphCount;
324 for (j = gidx - 1; j >= 0 && i > 0; j--)
325 if (gstring->glyphs[j].glyph_id
330 if (match_classes (BacktrackClassDef, gstring, j, flag,
331 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
335 i = match_classes (InputClassDef, gstring, gidx, flag,
336 rule->InputGlyphCount - 1, rule->Input);
340 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
341 rule->LookaheadGlyphCount, rule->LookAhead);
349 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
350 OTF_Coverage *coverages)
352 OTF_Glyph *gbeg = gstring->glyphs + gidx;
353 OTF_Glyph *gend = gstring->glyphs + gstring->used;
357 for (g = gbeg, i = 0; g < gend && i < count; g++)
358 if (g->glyph_id && ! (flag & (1 << g->GlyphClass))
359 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
361 return (i < count ? -1 : g - gbeg);
365 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
366 OTF_GSUB_ChainContext3 *context3)
368 int i = context3->BacktrackGlyphCount;
374 for (j = gidx - 1; j >= 0; j--)
375 if (gstring->glyphs[j].glyph_id
380 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
381 context3->Backtrack) < 0)
385 if (context3->InputGlyphCount > 1)
387 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
388 context3->Input + 1);
393 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
394 context3->LookAhead) < 0)
400 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
401 OTF_GlyphString *gstring, int gidx)
403 char *errfmt = "GSUB Looking up%s";
405 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
406 unsigned int flag = lookup->LookupFlag & OTF_LookupFlagIgnoreMask;
407 int orig_gidx = gidx;
408 OTF_Glyph *g = gstring->glyphs + gidx;
413 && (flag & (1 << g->GlyphClass))))
416 /* Try all subtables until one of them handles the current glyph. */
417 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
419 unsigned lookup_type = lookup->LookupType;
420 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
423 if (lookup_type == 7)
425 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
427 lookup_type = extension1->ExtensionLookupType;
428 subtable = extension1->ExtensionSubtable;
431 if (subtable->Coverage.offset)
433 coverage_idx = get_coverage_index (&subtable->Coverage,
435 if (coverage_idx < 0)
442 if (subtable->Format == 1)
443 g->glyph_id += subtable->u.single1.DeltaGlyphID;
445 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
451 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
452 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
454 gstring_subst (gstring, gidx, gidx + 1, flag,
455 seq->Substitute, seq->GlyphCount);
456 gidx += seq->GlyphCount;
461 /* For the moment, we always ignore this feature. */
463 if (subtable->Format == 1)
465 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
466 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
468 g->glyph_id = altset->Alternate[0];
472 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
476 if (subtable->Format == 1)
478 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
479 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
483 for (j = 0; j < ligset->LigatureCount; j++)
487 lig = ligset->Ligature + j;
488 n = match_ids (gstring, gidx + 1, flag,
489 lig->CompCount - 1, lig->Component);
492 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
499 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
503 if (subtable->Format == 1)
505 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
506 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
511 for (j = 0; j < set->RuleCount; j++)
513 rule = set->Rule + j;
514 if (match_ids (gstring, gidx + 1, flag,
515 rule->GlyphCount - 1, rule->Input) < 0)
517 orig_used = gstring->used;
518 for (k = 0; k < rule->LookupCount; k++)
519 lookup_gsub (lookup_list,
520 rule->LookupRecord[k].LookupListIndex,
522 gidx + rule->LookupRecord[k].SequenceIndex);
523 gidx += rule->GlyphCount + (gstring->used - orig_used);
527 else if (subtable->Format == 2)
529 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
536 class = get_class_def (&context2->ClassDef, g->glyph_id);
537 set = context2->ClassSet + class;
539 for (j = 0; j < set->ClassRuleCnt; j++)
541 rule = set->ClassRule + j;
542 if (match_classes (&context2->ClassDef,
543 gstring, gidx + 1, flag,
544 rule->GlyphCount - 1, rule->Class)
547 orig_used = gstring->used;
548 for (k = 0; k < rule->LookupCount; k++)
549 lookup_gsub (lookup_list,
550 rule->LookupRecord[k].LookupListIndex,
552 gidx + rule->LookupRecord[k].SequenceIndex);
553 gidx += rule->GlyphCount + (gstring->used - orig_used);
557 else /* subtable->Format == 3 */
559 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
563 if (match_coverages (gstring, gidx + 1, flag,
564 context3->GlyphCount - 1,
565 context3->Coverage + 1) < 0)
567 orig_used = gstring->used;
568 for (j = 0; j < context3->LookupCount; j++)
569 lookup_gsub (lookup_list,
570 context3->LookupRecord[j].LookupListIndex,
572 gidx + context3->LookupRecord[j].SequenceIndex);
573 gidx += context3->GlyphCount + (gstring->used - orig_used);
578 if (subtable->Format == 1)
580 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
581 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
585 for (j = 0; j < set->ChainRuleCount; j++)
587 OTF_ChainRule *rule = set->ChainRule + j;
589 if (gidx < rule->BacktrackGlyphCount
590 || (gidx + rule->InputGlyphCount
591 + rule->LookaheadGlyphCount) > gstring->used)
593 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
595 orig_used = gstring->used;
596 for (k = 0; k < rule->LookupCount; k++)
597 lookup_gsub (lookup_list,
598 rule->LookupRecord[k].LookupListIndex,
600 gidx + rule->LookupRecord[k].SequenceIndex);
601 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
605 else if (subtable->Format == 2)
607 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
608 OTF_ChainClassSet *set;
613 class = get_class_def (&context2->InputClassDef, g->glyph_id);
614 set = context2->ChainClassSet + class;
615 for (j = 0; j < set->ChainClassRuleCnt; j++)
617 OTF_ChainClassRule *rule = set->ChainClassRule + j;
620 if (gidx < rule->BacktrackGlyphCount
621 || (gidx + rule->InputGlyphCount
622 + rule->LookaheadGlyphCount) > gstring->used)
624 if (match_chain_classes (gstring, gidx, flag,
625 &context2->BacktrackClassDef,
626 &context2->InputClassDef,
627 &context2->LookaheadClassDef,
630 orig_used = gstring->used;
631 for (k = 0; k < rule->LookupCount; k++)
632 lookup_gsub (lookup_list,
633 rule->LookupRecord[k].LookupListIndex,
635 gidx + rule->LookupRecord[k].SequenceIndex);
636 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
642 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
646 if (gidx < context3->BacktrackGlyphCount
647 || (gidx + context3->InputGlyphCount
648 + context3->LookaheadGlyphCount) > gstring->used)
650 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
652 orig_used = gstring->used;
653 for (j = 0; j < context3->LookupCount; j++)
654 lookup_gsub (lookup_list,
655 context3->LookupRecord[j].LookupListIndex,
657 gidx + context3->LookupRecord[j].SequenceIndex);
658 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
664 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
665 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
666 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
669 if (back_gidx > gstring->used || ahead_gidx < 0)
672 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
673 if (get_coverage_index (reverse->Backtrack + j,
674 gstring->glyphs[gidx + 1 + j].glyph_id)
677 if (j < reverse->BacktrackGlyphCount)
679 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
680 if (get_coverage_index (reverse->LookAhead + j,
681 gstring->glyphs[gidx - 1 - j].glyph_id)
684 if (j < reverse->LookaheadGlyphCount)
686 g->glyph_id = reverse->Substitute[coverage_idx];
694 if (gidx == orig_gidx)
703 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
705 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
707 rec->XPlacement = anchor->XCoordinate;
708 rec->YPlacement = anchor->YCoordinate;
709 if (anchor->AnchorFormat == 1)
712 else if (anchor->AnchorFormat == 2)
713 /* Not yet implemented */
715 else if (anchor->AnchorFormat == 3)
716 /* Not yet implemented */
723 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
724 OTF_GlyphString *gstring, int gidx)
726 char *errfmt = "GPOS Looking up%s";
728 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
729 unsigned int flag = lookup->LookupFlag & OTF_LookupFlagIgnoreMask;
730 int orig_gidx = gidx;
731 OTF_Glyph *g = gstring->glyphs + gidx;
735 || g->positioning_type
737 && (flag & (1 << g->GlyphClass))))
740 /* Try all subtables until one of them handles the current glyph. */
741 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
743 unsigned lookup_type = lookup->LookupType;
744 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
747 if (lookup_type == 9)
749 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
751 lookup_type = extension1->ExtensionLookupType;
752 subtable = extension1->ExtensionSubtable;
755 if (subtable->Coverage.offset)
757 coverage_idx = get_coverage_index (&subtable->Coverage,
759 if (coverage_idx < 0)
766 g->positioning_type = lookup_type;
767 if (subtable->Format == 1)
769 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
771 g->f.f1.format = single1->ValueFormat;
772 g->f.f1.value = &single1->Value;
774 else if (subtable->Format == 2)
776 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
778 g->f.f1.format = single2->ValueFormat;
779 g->f.f1.value = single2->Value + coverage_idx;
785 int next_gidx = gidx + 1;
788 while (next_gidx < gstring->used
789 && (! gstring->glyphs[next_gidx].glyph_id
791 & (1 << gstring->glyphs[next_gidx].GlyphClass))))
794 if (next_gidx >= gstring->used)
796 nextg = gstring->glyphs + next_gidx;
797 if (nextg->positioning_type)
799 if (subtable->Format == 1)
801 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
802 OTF_PairSet *set = pair1->PairSet + coverage_idx;
805 for (j = 0; j < set->PairValueCount; j++)
806 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
808 if (pair1->ValueFormat1)
810 g->positioning_type = lookup_type;
811 g->f.f2.format = pair1->ValueFormat1;
812 g->f.f2.value = &set->PairValueRecord[j].Value1;
815 if (pair1->ValueFormat2)
817 nextg->positioning_type = lookup_type;
818 nextg->f.f2.format = pair1->ValueFormat2;
819 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
825 else if (subtable->Format == 2)
827 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
828 unsigned class1, class2;
830 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
831 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
832 if (pair2->ValueFormat1)
834 g->positioning_type = lookup_type;
835 g->f.f2.format = pair2->ValueFormat1;
837 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
840 if (pair2->ValueFormat2)
842 nextg->positioning_type = lookup_type;
843 nextg->f.f2.format = pair2->ValueFormat2;
845 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
854 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
856 g->positioning_type = lookup_type;
858 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
860 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
867 if (subtable->Format == 1)
869 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
870 OTF_MarkRecord *mark_record;
871 OTF_AnchorRecord *base_record;
872 OTF_Glyph *baseg = g - 1;
873 int coverage_idx_base;
875 while (baseg >= gstring->glyphs
876 && (! baseg->glyph_id
877 || (baseg->GlyphClass
878 && (flag & (1 << baseg->GlyphClass)))))
881 = get_coverage_index (&mark_base1->BaseCoverage,
884 if (coverage_idx_base < 0)
886 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
888 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
889 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
891 = &base_record->Anchor[mark_record->Class];
892 g->positioning_type = lookup_type;
899 if (subtable->Format == 1)
901 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
902 unsigned class = g->MarkAttachClass;
903 OTF_Glyph *ligg = g - 1;
904 int coverage_idx_lig;
905 OTF_MarkRecord *mark_record;
906 OTF_ComponentRecord *cmp_record;
907 OTF_LigatureAttach *attach;
908 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
911 for (j = 0; j < mark_lig1->ClassCount; j++)
914 while (ligg >= gstring->glyphs
917 && (flag & (1 << ligg->GlyphClass)))))
919 if (ligg->positioning_type == 5
920 && ligg->MarkAttachClass < mark_lig1->ClassCount)
921 num_class[ligg->MarkAttachClass]++;
925 = get_coverage_index (&mark_lig1->LigatureCoverage,
927 if (coverage_idx_lig < 0)
929 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
930 g->MarkAttachClass = mark_record->Class;
931 attach = (mark_lig1->LigatureArray.LigatureAttach
933 for (j = 0; j < attach->ComponentCount; j++)
935 OTF_Anchor *lig_anchor
936 = attach->ComponentRecord[j].LigatureAnchor;
938 if (lig_anchor[mark_record->Class].AnchorFormat
939 && num_class[mark_record->Class]-- == 0)
941 g->positioning_type = lookup_type;
942 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
943 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
953 if (subtable->Format == 1)
955 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
956 OTF_MarkRecord *mark1_record;
957 OTF_AnchorRecord *mark2_record;
958 OTF_Glyph *prevg = g - 1;
959 int coverage_idx_base;
961 while (prevg >= gstring->glyphs
962 && (! prevg->glyph_id
963 || (prevg->GlyphClass
964 && (flag & (1 << prevg->GlyphClass)))))
966 if (prevg < gstring->glyphs)
969 = get_coverage_index (&mark_mark1->Mark2Coverage,
971 if (coverage_idx_base < 0)
973 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
975 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
976 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
978 = &mark2_record->Anchor[mark1_record->Class];
979 g->positioning_type = lookup_type;
985 if (subtable->Format == 1)
987 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
988 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
993 for (j = 0; j < set->RuleCount; j++)
995 rule = set->Rule + j;
996 if (match_ids (gstring, gidx + 1, flag,
997 rule->GlyphCount - 1, rule->Input) < 0)
999 orig_used = gstring->used;
1000 for (k = 0; k < rule->LookupCount; k++)
1001 lookup_gpos (lookup_list,
1002 rule->LookupRecord[k].LookupListIndex,
1004 gidx + rule->LookupRecord[k].SequenceIndex);
1005 gidx += rule->GlyphCount + (gstring->used - orig_used);
1009 else if (subtable->Format == 2)
1011 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1013 OTF_ClassRule *rule;
1018 class = get_class_def (&context2->ClassDef, g->glyph_id);
1019 set = context2->ClassSet + class;
1021 for (j = 0; j < set->ClassRuleCnt; j++)
1023 rule = set->ClassRule + j;
1024 if (match_classes (&context2->ClassDef,
1025 gstring, gidx + 1, flag,
1026 rule->GlyphCount - 1, rule->Class)
1029 orig_used = gstring->used;
1030 for (k = 0; k < rule->LookupCount; k++)
1031 lookup_gpos (lookup_list,
1032 rule->LookupRecord[k].LookupListIndex,
1034 gidx + rule->LookupRecord[k].SequenceIndex);
1035 gidx += rule->GlyphCount + (gstring->used - orig_used);
1039 else /* subtable->Format == 3 */
1041 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1045 if (match_coverages (gstring, gidx + 1, flag,
1046 context3->GlyphCount - 1,
1047 context3->Coverage + 1) < 0)
1049 orig_used = gstring->used;
1050 for (j = 0; j < context3->LookupCount; j++)
1051 lookup_gpos (lookup_list,
1052 context3->LookupRecord[j].LookupListIndex,
1054 gidx + context3->LookupRecord[j].SequenceIndex);
1055 gidx += context3->GlyphCount + (gstring->used - orig_used);
1060 if (subtable->Format == 1)
1062 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1063 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1067 for (j = 0; j < set->ChainRuleCount; j++)
1069 OTF_ChainRule *rule = set->ChainRule + j;
1071 if (gidx < rule->BacktrackGlyphCount
1072 || (gidx + rule->InputGlyphCount
1073 + rule->LookaheadGlyphCount) > gstring->used)
1075 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1077 orig_used = gstring->used;
1078 for (k = 0; k < rule->LookupCount; k++)
1079 lookup_gpos (lookup_list,
1080 rule->LookupRecord[k].LookupListIndex,
1082 gidx + rule->LookupRecord[k].SequenceIndex);
1083 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1087 else if (subtable->Format == 2)
1089 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1090 OTF_ChainClassSet *set;
1095 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1096 set = context2->ChainClassSet + class;
1097 for (j = 0; j < set->ChainClassRuleCnt; j++)
1099 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1102 if (gidx < rule->BacktrackGlyphCount
1103 || (gidx + rule->InputGlyphCount
1104 + rule->LookaheadGlyphCount) > gstring->used)
1106 if (match_chain_classes (gstring, gidx, flag,
1107 &context2->BacktrackClassDef,
1108 &context2->InputClassDef,
1109 &context2->LookaheadClassDef,
1112 orig_used = gstring->used;
1113 for (k = 0; k < rule->LookupCount; k++)
1114 lookup_gpos (lookup_list,
1115 rule->LookupRecord[k].LookupListIndex,
1117 gidx + rule->LookupRecord[k].SequenceIndex);
1118 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1122 else if (subtable->Format == 3)
1124 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1128 if (gidx < context3->BacktrackGlyphCount
1129 || (gidx + context3->InputGlyphCount
1130 + context3->LookaheadGlyphCount) > gstring->used)
1132 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1134 orig_used = gstring->used;
1135 for (j = 0; j < context3->LookupCount; j++)
1136 lookup_gpos (lookup_list,
1137 context3->LookupRecord[j].LookupListIndex,
1139 gidx + context3->LookupRecord[j].SequenceIndex);
1140 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1143 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1150 if (gidx == orig_gidx)
1156 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1160 for (i = 0; i < gstring->used; i++)
1162 c = gstring->glyphs[i].c;
1163 if (c < 0 || c >= 256)
1164 gstring->glyphs[i].glyph_id = 0;
1166 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1172 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1178 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1181 int segCount = sub4->segCountX2 / 2;
1183 for (i = 0; i < gstring->used; i++)
1185 c = gstring->glyphs[i].c;
1187 gstring->glyphs[i].glyph_id = 0;
1188 for (j = 0; j < segCount; j++)
1190 OTF_cmapSegument *seg = sub4->segments + i;
1192 if (c >= seg->startCount && c <= seg->endCount)
1194 if (seg->idRangeOffset == 0xFFFF)
1195 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1197 gstring->glyphs[i].glyph_id
1198 = sub4->glyphIdArray[seg->idRangeOffset
1199 + (c - seg->startCount)];
1209 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1215 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1221 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1227 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1237 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1243 && OTF_get_table (otf, "cmap") < 0)
1247 for (i = 0; i < gstring->used; i++)
1248 if (! gstring->glyphs[i].glyph_id)
1250 int c = gstring->glyphs[i].c;
1251 if (c < 32 || ! cmap->unicode_table)
1252 gstring->glyphs[i].glyph_id = 0;
1254 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1261 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1262 int platform_id, int encoding_id)
1266 char *errfmt = "CMAP Looking up%s";
1268 OTF_EncodingRecord *enc;
1271 && OTF_get_table (otf, "cmap") < 0)
1275 for (i = 0; i < cmap->numTables; i++)
1276 if (cmap->EncodingRecord[i].platformID == platform_id
1277 && cmap->EncodingRecord[i].encodingID == encoding_id)
1279 if (i == cmap->numTables)
1280 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1281 enc = cmap->EncodingRecord + i;
1282 switch (enc->subtable.format)
1284 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1285 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1286 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1287 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1288 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1289 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1290 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1292 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1297 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1300 && OTF_get_table (otf, "cmap") < 0)
1303 || code > otf->cmap->max_glyph_id
1304 || ! otf->cmap->decode_table)
1306 return otf->cmap->decode_table[code];
1310 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1316 && OTF_get_table (otf, "GDEF") < 0)
1320 if (gdef->glyph_class_def.offset)
1321 for (i = 0; i < gstring->used; i++)
1322 gstring->glyphs[i].GlyphClass
1323 = get_class_def (&gdef->glyph_class_def,
1324 gstring->glyphs[i].glyph_id);
1326 if (gdef->mark_attach_class_def.offset)
1327 for (i = 0; i < gstring->used; i++)
1328 gstring->glyphs[i].MarkAttachClass
1329 = get_class_def (&gdef->mark_attach_class_def,
1330 gstring->glyphs[i].glyph_id);
1337 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1338 char *script, char *language, char *features)
1340 char *errfmt = "GSUB driving%s";
1343 OTF_LangSys *LangSys;
1344 int *lookup_indices;
1347 for (i = 0; i < gstring->used; i++)
1348 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1351 && OTF_get_table (otf, "GSUB") < 0)
1354 if (gsub->FeatureList.FeatureCount == 0
1355 || gsub->LookupList.LookupCount == 0)
1358 LangSys = get_langsys (&gsub->ScriptList, script, language);
1362 /* One lookup may be used by multiple features. */
1363 lookup_indices = alloca (sizeof (int)
1364 * gsub->LookupList.LookupCount
1365 * (gsub->FeatureList.FeatureCount + 1));
1366 if (! lookup_indices)
1367 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1368 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1369 features, lookup_indices);
1373 for (i = 0; i < n; i++)
1375 int index = lookup_indices[i];
1378 if (gsub->LookupList.Lookup[index].LookupType != 8)
1381 while (gidx < gstring->used)
1383 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1390 gidx = gstring->used - 1;
1393 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1404 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1405 char *script, char *language, char *features)
1407 char *errfmt = "GPOS driving%s";
1410 OTF_LangSys *LangSys;
1411 int *lookup_indices;
1415 && OTF_get_table (otf, "GPOS") < 0)
1418 if (gpos->FeatureList.FeatureCount == 0
1419 || gpos->LookupList.LookupCount == 0)
1422 LangSys = get_langsys (&gpos->ScriptList, script, language);
1426 /* One lookup may be used by multiple features. */
1427 lookup_indices = alloca (sizeof (int)
1428 * gpos->LookupList.LookupCount
1429 * (gpos->FeatureList.FeatureCount + 1));
1430 if (! lookup_indices)
1431 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1432 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1433 features, lookup_indices);
1437 for (i = 0; i < gstring->used; i++)
1438 gstring->glyphs[i].positioning_type = 0;
1440 for (i = 0; i < n; i++)
1442 int index = lookup_indices[i];
1445 while (gidx < gstring->used)
1447 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1457 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1458 char *script, char *language,
1459 char *gsub_features, char *gpos_features)
1461 if (OTF_drive_cmap (otf, gstring) < 0)
1463 if (OTF_drive_gdef (otf, gstring) < 0)
1466 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1469 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)