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 && ((flag) >> 8) != (g)->MarkAttachClass))
40 #define GSTRING_DELETE(gstring, from, len) \
42 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
43 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
44 gstring->used -= len; \
48 #define GSTRING_INSERT(gstring, pos, len) \
50 if (gstring->used + len > gstring->size) \
52 char *errfmt = "GSTRING%s"; \
54 gstring->size = gstring->used + len; \
55 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
57 if (! gstring->glyphs) \
58 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
60 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
61 sizeof (OTF_Glyph) * (gstring->used - pos)); \
62 gstring->used += len; \
67 gstring_subst (OTF_GlyphString *gstring, int from, int to, int flag,
68 OTF_GlyphID *ids, int num)
73 int c = gstring->glyphs[from].c;
74 int from_idx = gstring->glyphs[from].f.index.from;
75 int to_idx = gstring->glyphs[to - 1].f.index.to;
78 for (i = non_ignored_idx = to - 1; i >= from; i--)
80 OTF_Glyph *g = gstring->glyphs + i;
81 if (IGNORED_GLYPH (g, flag))
85 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
86 gstring->glyphs[non_ignored_idx--] = temp;
92 GSTRING_INSERT (gstring, from, (num - len));
94 GSTRING_DELETE (gstring, from, (len - num));
95 for (i = 0; i < num; i++)
97 gstring->glyphs[from + i].c = c;
98 gstring->glyphs[from + i].glyph_id = ids[i];
99 gstring->glyphs[from + i].f.index.from = from_idx;
100 gstring->glyphs[from + i].f.index.to = to_idx;
107 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
111 if (coverage->CoverageFormat == 1)
113 for (i = 0; i < coverage->Count; i++)
114 if (coverage->table.GlyphArray[i] == id)
119 for (i = 0; i < coverage->Count; i++)
120 if (coverage->table.RangeRecord[i].Start <= id
121 && coverage->table.RangeRecord[i].End >= id)
122 return (coverage->table.RangeRecord[i].StartCoverageIndex
123 + (id - coverage->table.RangeRecord[i].Start));
129 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
131 if (class_def->ClassFormat == 1)
133 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
135 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
136 return class_def->f.f1.ClassValueArray[idx];
142 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
143 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
144 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
145 return class_def->f.f2.ClassRangeRecord[i].Class;
151 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
154 OTF_Tag script_tag = OTF_tag (script);
155 OTF_Tag langsys_tag = OTF_tag (language);
157 OTF_Tag dflt_tag = OTF_tag ("DFLT");
158 OTF_Script *dflt = NULL;
160 for (i = 0; i < script_list->ScriptCount; i++)
162 OTF_Script *script = script_list->Script + i;
164 if (script_list->Script[i].ScriptTag == dflt_tag)
166 if (script_list->Script[i].ScriptTag == script_tag)
169 return &script->DefaultLangSys;
170 for (j = 0; j < script->LangSysCount; j++)
171 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
172 return script->LangSys + j;
173 return &script->DefaultLangSys;
178 dflt = script_list->Script;
180 return &dflt->DefaultLangSys;
181 for (j = 0; j < dflt->LangSysCount; j++)
182 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
183 return dflt->LangSys + j;
184 return &dflt->DefaultLangSys;
188 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
189 char *features, int *lookup_indices)
192 OTF_Feature *feature;
193 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
195 for (i = 0; i < FeatureList->FeatureCount; i++)
196 feature_table[i] = 0;
204 if (*features == '*')
206 /* Consume all remaining features. */
207 for (i = 0; i < FeatureList->FeatureCount; i++)
208 if (! feature_table[i])
210 feature = FeatureList->Feature + i;
211 for (j = 0; j < feature->LookupCount; j++)
212 lookup_indices[n++] = feature->LookupListIndex[j];
217 if (*features == '~')
218 use_it = -1, features++;
219 for (i = 0; *features && *features != ','; i++, features++)
220 tagname[i] = *features;
226 tag = OTF_tag (tagname);
227 for (i = 0; i < FeatureList->FeatureCount; i++)
229 feature = FeatureList->Feature + i;
230 if (tag == feature->FeatureTag)
232 if (feature_table[i])
235 for (j = 0; j < feature->LookupCount; j++)
236 lookup_indices[n++] = feature->LookupListIndex[j];
237 feature_table[i] = use_it;
247 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
248 int count, OTF_GlyphID *ids)
250 OTF_Glyph *gbeg = gstring->glyphs + gidx;
251 OTF_Glyph *gend = gstring->glyphs + gstring->used;
255 for (g = gbeg, i = 0; g < gend && i < count; g++)
256 if (! IGNORED_GLYPH (g, flag) && 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;
272 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
273 if (! IGNORED_GLYPH (g, flag) && --i == 0)
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 (! IGNORED_GLYPH (g, flag)
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;
325 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
326 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
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 (! IGNORED_GLYPH (g, flag)
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;
375 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
376 if (! IGNORED_GLYPH (g, flag) && --i == 0)
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
407 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
408 int orig_gidx = gidx;
409 OTF_Glyph *g = gstring->glyphs + gidx;
412 if (IGNORED_GLYPH (g, flag))
415 /* Try all subtables until one of them handles the current glyph. */
416 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
418 unsigned lookup_type = lookup->LookupType;
419 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
422 if (lookup_type == 7)
424 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
426 lookup_type = extension1->ExtensionLookupType;
427 subtable = extension1->ExtensionSubtable;
430 if (subtable->Coverage.offset)
432 coverage_idx = get_coverage_index (&subtable->Coverage,
434 if (coverage_idx < 0)
441 if (subtable->Format == 1)
442 g->glyph_id += subtable->u.single1.DeltaGlyphID;
444 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
450 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
451 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
453 gstring_subst (gstring, gidx, gidx + 1, flag,
454 seq->Substitute, seq->GlyphCount);
455 gidx += seq->GlyphCount;
460 /* For the moment, we always ignore this feature. */
462 if (subtable->Format == 1)
464 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
465 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
467 g->glyph_id = altset->Alternate[0];
471 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
475 if (subtable->Format == 1)
477 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
478 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
482 for (j = 0; j < ligset->LigatureCount; j++)
486 lig = ligset->Ligature + j;
487 n = match_ids (gstring, gidx + 1, flag,
488 lig->CompCount - 1, lig->Component);
491 gstring_subst (gstring, gidx, gidx + 1 + n, flag,
498 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
502 if (subtable->Format == 1)
504 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
505 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
510 for (j = 0; j < set->RuleCount; j++)
512 rule = set->Rule + j;
513 if (match_ids (gstring, gidx + 1, flag,
514 rule->GlyphCount - 1, rule->Input) < 0)
516 orig_used = gstring->used;
517 for (k = 0; k < rule->LookupCount; k++)
518 lookup_gsub (lookup_list,
519 rule->LookupRecord[k].LookupListIndex,
521 gidx + rule->LookupRecord[k].SequenceIndex);
522 gidx += rule->GlyphCount + (gstring->used - orig_used);
526 else if (subtable->Format == 2)
528 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
535 class = get_class_def (&context2->ClassDef, g->glyph_id);
536 set = context2->ClassSet + class;
538 for (j = 0; j < set->ClassRuleCnt; j++)
540 rule = set->ClassRule + j;
541 if (match_classes (&context2->ClassDef,
542 gstring, gidx + 1, flag,
543 rule->GlyphCount - 1, rule->Class)
546 orig_used = gstring->used;
547 for (k = 0; k < rule->LookupCount; k++)
548 lookup_gsub (lookup_list,
549 rule->LookupRecord[k].LookupListIndex,
551 gidx + rule->LookupRecord[k].SequenceIndex);
552 gidx += rule->GlyphCount + (gstring->used - orig_used);
556 else /* subtable->Format == 3 */
558 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
562 if (match_coverages (gstring, gidx + 1, flag,
563 context3->GlyphCount - 1,
564 context3->Coverage + 1) < 0)
566 orig_used = gstring->used;
567 for (j = 0; j < context3->LookupCount; j++)
568 lookup_gsub (lookup_list,
569 context3->LookupRecord[j].LookupListIndex,
571 gidx + context3->LookupRecord[j].SequenceIndex);
572 gidx += context3->GlyphCount + (gstring->used - orig_used);
577 if (subtable->Format == 1)
579 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
580 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
584 for (j = 0; j < set->ChainRuleCount; j++)
586 OTF_ChainRule *rule = set->ChainRule + j;
588 if (gidx < rule->BacktrackGlyphCount
589 || (gidx + rule->InputGlyphCount
590 + rule->LookaheadGlyphCount) > gstring->used)
592 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
594 orig_used = gstring->used;
595 for (k = 0; k < rule->LookupCount; k++)
596 lookup_gsub (lookup_list,
597 rule->LookupRecord[k].LookupListIndex,
599 gidx + rule->LookupRecord[k].SequenceIndex);
600 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
604 else if (subtable->Format == 2)
606 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
607 OTF_ChainClassSet *set;
612 class = get_class_def (&context2->InputClassDef, g->glyph_id);
613 set = context2->ChainClassSet + class;
614 for (j = 0; j < set->ChainClassRuleCnt; j++)
616 OTF_ChainClassRule *rule = set->ChainClassRule + j;
619 if (gidx < rule->BacktrackGlyphCount
620 || (gidx + rule->InputGlyphCount
621 + rule->LookaheadGlyphCount) > gstring->used)
623 if (match_chain_classes (gstring, gidx, flag,
624 &context2->BacktrackClassDef,
625 &context2->InputClassDef,
626 &context2->LookaheadClassDef,
629 orig_used = gstring->used;
630 for (k = 0; k < rule->LookupCount; k++)
631 lookup_gsub (lookup_list,
632 rule->LookupRecord[k].LookupListIndex,
634 gidx + rule->LookupRecord[k].SequenceIndex);
635 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
641 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
645 if (gidx < context3->BacktrackGlyphCount
646 || (gidx + context3->InputGlyphCount
647 + context3->LookaheadGlyphCount) > gstring->used)
649 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
651 orig_used = gstring->used;
652 for (j = 0; j < context3->LookupCount; j++)
653 lookup_gsub (lookup_list,
654 context3->LookupRecord[j].LookupListIndex,
656 gidx + context3->LookupRecord[j].SequenceIndex);
657 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
663 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
664 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
665 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
668 if (back_gidx > gstring->used || ahead_gidx < 0)
671 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
672 if (get_coverage_index (reverse->Backtrack + j,
673 gstring->glyphs[gidx + 1 + j].glyph_id)
676 if (j < reverse->BacktrackGlyphCount)
678 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
679 if (get_coverage_index (reverse->LookAhead + j,
680 gstring->glyphs[gidx - 1 - j].glyph_id)
683 if (j < reverse->LookaheadGlyphCount)
685 g->glyph_id = reverse->Substitute[coverage_idx];
693 if (gidx == orig_gidx)
702 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
704 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
706 rec->XPlacement = anchor->XCoordinate;
707 rec->YPlacement = anchor->YCoordinate;
708 if (anchor->AnchorFormat == 1)
711 else if (anchor->AnchorFormat == 2)
712 /* Not yet implemented */
714 else if (anchor->AnchorFormat == 3)
715 /* Not yet implemented */
722 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
723 OTF_GlyphString *gstring, int gidx)
725 char *errfmt = "GPOS Looking up%s";
727 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
728 unsigned int flag = (lookup->LookupFlag
729 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
730 int orig_gidx = gidx;
731 OTF_Glyph *g = gstring->glyphs + gidx;
734 if (IGNORED_GLYPH (g, flag)
735 || g->positioning_type)
738 /* Try all subtables until one of them handles the current glyph. */
739 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
741 unsigned lookup_type = lookup->LookupType;
742 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
745 if (lookup_type == 9)
747 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
749 lookup_type = extension1->ExtensionLookupType;
750 subtable = extension1->ExtensionSubtable;
753 if (subtable->Coverage.offset)
755 coverage_idx = get_coverage_index (&subtable->Coverage,
757 if (coverage_idx < 0)
764 g->positioning_type = lookup_type;
765 if (subtable->Format == 1)
767 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
769 g->f.f1.format = single1->ValueFormat;
770 g->f.f1.value = &single1->Value;
772 else if (subtable->Format == 2)
774 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
776 g->f.f1.format = single2->ValueFormat;
777 g->f.f1.value = single2->Value + coverage_idx;
786 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
787 next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
788 next_gidx++, nextg++);
790 if (next_gidx >= gstring->used
791 || nextg->positioning_type)
793 if (subtable->Format == 1)
795 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
796 OTF_PairSet *set = pair1->PairSet + coverage_idx;
799 for (j = 0; j < set->PairValueCount; j++)
800 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
802 if (pair1->ValueFormat1)
804 g->positioning_type = lookup_type;
805 g->f.f2.format = pair1->ValueFormat1;
806 g->f.f2.value = &set->PairValueRecord[j].Value1;
809 if (pair1->ValueFormat2)
811 nextg->positioning_type = lookup_type;
812 nextg->f.f2.format = pair1->ValueFormat2;
813 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
819 else if (subtable->Format == 2)
821 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
822 unsigned class1, class2;
824 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
825 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
826 if (pair2->ValueFormat1)
828 g->positioning_type = lookup_type;
829 g->f.f2.format = pair2->ValueFormat1;
831 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
834 if (pair2->ValueFormat2)
836 nextg->positioning_type = lookup_type;
837 nextg->f.f2.format = pair2->ValueFormat2;
839 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
848 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
850 g->positioning_type = lookup_type;
852 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
854 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
861 if (subtable->Format == 1)
863 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
864 OTF_MarkRecord *mark_record;
865 OTF_AnchorRecord *base_record;
867 int coverage_idx_base;
870 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
872 if (baseg < gstring->glyphs)
875 = get_coverage_index (&mark_base1->BaseCoverage,
877 if (coverage_idx_base < 0)
879 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
881 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
882 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
884 = &base_record->Anchor[mark_record->Class];
885 g->positioning_type = lookup_type;
892 if (subtable->Format == 1)
894 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
896 int coverage_idx_lig;
897 OTF_MarkRecord *mark_record;
898 OTF_LigatureAttach *attach;
899 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
902 for (j = 0; j < mark_lig1->ClassCount; j++)
906 ligg >= gstring->glyphs && IGNORED_GLYPH (ligg, flag);
908 if (ligg->positioning_type == 5
909 && ligg->MarkAttachClass < mark_lig1->ClassCount)
910 num_class[ligg->MarkAttachClass]++;
911 if (ligg < gstring->glyphs)
914 = get_coverage_index (&mark_lig1->LigatureCoverage,
916 if (coverage_idx_lig < 0)
918 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
919 g->MarkAttachClass = mark_record->Class;
920 attach = (mark_lig1->LigatureArray.LigatureAttach
922 for (j = 0; j < attach->ComponentCount; j++)
924 OTF_Anchor *lig_anchor
925 = attach->ComponentRecord[j].LigatureAnchor;
927 if (lig_anchor[mark_record->Class].AnchorFormat
928 && num_class[mark_record->Class]-- == 0)
930 g->positioning_type = lookup_type;
931 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
932 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
942 if (subtable->Format == 1)
944 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
945 OTF_MarkRecord *mark1_record;
946 OTF_AnchorRecord *mark2_record;
948 int coverage_idx_base;
951 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
953 if (prevg < gstring->glyphs)
956 = get_coverage_index (&mark_mark1->Mark2Coverage,
958 if (coverage_idx_base < 0)
960 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
962 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
963 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
965 = &mark2_record->Anchor[mark1_record->Class];
966 g->positioning_type = lookup_type;
972 if (subtable->Format == 1)
974 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
975 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
980 for (j = 0; j < set->RuleCount; j++)
982 rule = set->Rule + j;
983 if (match_ids (gstring, gidx + 1, flag,
984 rule->GlyphCount - 1, rule->Input) < 0)
986 orig_used = gstring->used;
987 for (k = 0; k < rule->LookupCount; k++)
988 lookup_gpos (lookup_list,
989 rule->LookupRecord[k].LookupListIndex,
991 gidx + rule->LookupRecord[k].SequenceIndex);
992 gidx += rule->GlyphCount + (gstring->used - orig_used);
996 else if (subtable->Format == 2)
998 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1000 OTF_ClassRule *rule;
1005 class = get_class_def (&context2->ClassDef, g->glyph_id);
1006 set = context2->ClassSet + class;
1008 for (j = 0; j < set->ClassRuleCnt; j++)
1010 rule = set->ClassRule + j;
1011 if (match_classes (&context2->ClassDef,
1012 gstring, gidx + 1, flag,
1013 rule->GlyphCount - 1, rule->Class)
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 /* subtable->Format == 3 */
1028 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1032 if (match_coverages (gstring, gidx + 1, flag,
1033 context3->GlyphCount - 1,
1034 context3->Coverage + 1) < 0)
1036 orig_used = gstring->used;
1037 for (j = 0; j < context3->LookupCount; j++)
1038 lookup_gpos (lookup_list,
1039 context3->LookupRecord[j].LookupListIndex,
1041 gidx + context3->LookupRecord[j].SequenceIndex);
1042 gidx += context3->GlyphCount + (gstring->used - orig_used);
1047 if (subtable->Format == 1)
1049 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1050 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1054 for (j = 0; j < set->ChainRuleCount; j++)
1056 OTF_ChainRule *rule = set->ChainRule + j;
1058 if (gidx < rule->BacktrackGlyphCount
1059 || (gidx + rule->InputGlyphCount
1060 + rule->LookaheadGlyphCount) > gstring->used)
1062 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1064 orig_used = gstring->used;
1065 for (k = 0; k < rule->LookupCount; k++)
1066 lookup_gpos (lookup_list,
1067 rule->LookupRecord[k].LookupListIndex,
1069 gidx + rule->LookupRecord[k].SequenceIndex);
1070 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1074 else if (subtable->Format == 2)
1076 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1077 OTF_ChainClassSet *set;
1082 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1083 set = context2->ChainClassSet + class;
1084 for (j = 0; j < set->ChainClassRuleCnt; j++)
1086 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1089 if (gidx < rule->BacktrackGlyphCount
1090 || (gidx + rule->InputGlyphCount
1091 + rule->LookaheadGlyphCount) > gstring->used)
1093 if (match_chain_classes (gstring, gidx, flag,
1094 &context2->BacktrackClassDef,
1095 &context2->InputClassDef,
1096 &context2->LookaheadClassDef,
1099 orig_used = gstring->used;
1100 for (k = 0; k < rule->LookupCount; k++)
1101 lookup_gpos (lookup_list,
1102 rule->LookupRecord[k].LookupListIndex,
1104 gidx + rule->LookupRecord[k].SequenceIndex);
1105 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1109 else if (subtable->Format == 3)
1111 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1115 if (gidx < context3->BacktrackGlyphCount
1116 || (gidx + context3->InputGlyphCount
1117 + context3->LookaheadGlyphCount) > gstring->used)
1119 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1121 orig_used = gstring->used;
1122 for (j = 0; j < context3->LookupCount; j++)
1123 lookup_gpos (lookup_list,
1124 context3->LookupRecord[j].LookupListIndex,
1126 gidx + context3->LookupRecord[j].SequenceIndex);
1127 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1130 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1137 if (gidx == orig_gidx)
1143 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1147 for (i = 0; i < gstring->used; i++)
1149 c = gstring->glyphs[i].c;
1150 if (c < 0 || c >= 256)
1151 gstring->glyphs[i].glyph_id = 0;
1153 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1159 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1165 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1168 int segCount = sub4->segCountX2 / 2;
1170 for (i = 0; i < gstring->used; i++)
1172 c = gstring->glyphs[i].c;
1174 gstring->glyphs[i].glyph_id = 0;
1175 for (j = 0; j < segCount; j++)
1177 OTF_cmapSegument *seg = sub4->segments + i;
1179 if (c >= seg->startCount && c <= seg->endCount)
1181 if (seg->idRangeOffset == 0xFFFF)
1182 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1184 gstring->glyphs[i].glyph_id
1185 = sub4->glyphIdArray[seg->idRangeOffset
1186 + (c - seg->startCount)];
1196 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1202 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1208 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1214 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1224 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1230 && OTF_get_table (otf, "cmap") < 0)
1234 for (i = 0; i < gstring->used; i++)
1235 if (! gstring->glyphs[i].glyph_id)
1237 int c = gstring->glyphs[i].c;
1238 if (c < 32 || ! cmap->unicode_table)
1239 gstring->glyphs[i].glyph_id = 0;
1241 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1248 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1249 int platform_id, int encoding_id)
1253 char *errfmt = "CMAP Looking up%s";
1255 OTF_EncodingRecord *enc;
1258 && OTF_get_table (otf, "cmap") < 0)
1262 for (i = 0; i < cmap->numTables; i++)
1263 if (cmap->EncodingRecord[i].platformID == platform_id
1264 && cmap->EncodingRecord[i].encodingID == encoding_id)
1266 if (i == cmap->numTables)
1267 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1268 enc = cmap->EncodingRecord + i;
1269 switch (enc->subtable.format)
1271 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1272 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1273 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1274 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1275 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1276 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1277 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1279 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1284 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1287 && OTF_get_table (otf, "cmap") < 0)
1290 || code > otf->cmap->max_glyph_id
1291 || ! otf->cmap->decode_table)
1293 return otf->cmap->decode_table[code];
1297 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1303 && OTF_get_table (otf, "GDEF") < 0)
1307 if (gdef->glyph_class_def.offset)
1308 for (i = 0; i < gstring->used; i++)
1309 gstring->glyphs[i].GlyphClass
1310 = get_class_def (&gdef->glyph_class_def,
1311 gstring->glyphs[i].glyph_id);
1313 if (gdef->mark_attach_class_def.offset)
1314 for (i = 0; i < gstring->used; i++)
1315 gstring->glyphs[i].MarkAttachClass
1316 = get_class_def (&gdef->mark_attach_class_def,
1317 gstring->glyphs[i].glyph_id);
1324 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1325 char *script, char *language, char *features)
1327 char *errfmt = "GSUB driving%s";
1330 OTF_LangSys *LangSys;
1331 int *lookup_indices;
1334 for (i = 0; i < gstring->used; i++)
1335 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1338 && OTF_get_table (otf, "GSUB") < 0)
1341 if (gsub->FeatureList.FeatureCount == 0
1342 || gsub->LookupList.LookupCount == 0)
1345 LangSys = get_langsys (&gsub->ScriptList, script, language);
1349 /* One lookup may be used by multiple features. */
1350 lookup_indices = alloca (sizeof (int)
1351 * gsub->LookupList.LookupCount
1352 * (gsub->FeatureList.FeatureCount + 1));
1353 if (! lookup_indices)
1354 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1355 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1356 features, lookup_indices);
1360 for (i = 0; i < n; i++)
1362 int index = lookup_indices[i];
1365 if (gsub->LookupList.Lookup[index].LookupType != 8)
1368 while (gidx < gstring->used)
1370 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1377 gidx = gstring->used - 1;
1380 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1391 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1392 char *script, char *language, char *features)
1394 char *errfmt = "GPOS driving%s";
1397 OTF_LangSys *LangSys;
1398 int *lookup_indices;
1402 && OTF_get_table (otf, "GPOS") < 0)
1405 if (gpos->FeatureList.FeatureCount == 0
1406 || gpos->LookupList.LookupCount == 0)
1409 LangSys = get_langsys (&gpos->ScriptList, script, language);
1413 /* One lookup may be used by multiple features. */
1414 lookup_indices = alloca (sizeof (int)
1415 * gpos->LookupList.LookupCount
1416 * (gpos->FeatureList.FeatureCount + 1));
1417 if (! lookup_indices)
1418 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1419 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1420 features, lookup_indices);
1424 for (i = 0; i < gstring->used; i++)
1425 gstring->glyphs[i].positioning_type = 0;
1427 for (i = 0; i < n; i++)
1429 int index = lookup_indices[i];
1432 while (gidx < gstring->used)
1434 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1444 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1445 char *script, char *language,
1446 char *gsub_features, char *gpos_features)
1448 if (OTF_drive_cmap (otf, gstring) < 0)
1450 if (OTF_drive_gdef (otf, gstring) < 0)
1453 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1456 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)