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 if (gstring->glyphs[from + i].glyph_id != ids[i])
107 gstring->glyphs[from + i].c = 0;
109 gstring->glyphs[from + i].GlyphClass
110 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
112 gstring->glyphs[from + i].GlyphClass = 0;
114 gstring->glyphs[from + i].glyph_id = ids[i];
115 gstring->glyphs[from + i].positioning_type = 0;
116 gstring->glyphs[from + i].f.index.from = from_idx;
117 gstring->glyphs[from + i].f.index.to = to_idx;
124 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
128 if (coverage->CoverageFormat == 1)
130 for (i = 0; i < coverage->Count; i++)
131 if (coverage->table.GlyphArray[i] == id)
136 for (i = 0; i < coverage->Count; i++)
137 if (coverage->table.RangeRecord[i].Start <= id
138 && coverage->table.RangeRecord[i].End >= id)
139 return (coverage->table.RangeRecord[i].StartCoverageIndex
140 + (id - coverage->table.RangeRecord[i].Start));
146 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
148 if (class_def->ClassFormat == 1)
150 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
152 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
153 return class_def->f.f1.ClassValueArray[idx];
159 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
160 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
161 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
162 return class_def->f.f2.ClassRangeRecord[i].Class;
168 get_langsys (OTF_ScriptList *script_list,
169 const char *script, const char *language)
172 OTF_Tag script_tag = OTF_tag (script);
173 OTF_Tag langsys_tag = OTF_tag (language);
175 OTF_Tag dflt_tag = OTF_tag ("DFLT");
176 OTF_Script *dflt = NULL;
178 for (i = 0; i < script_list->ScriptCount; i++)
180 OTF_Script *script = script_list->Script + i;
182 if (script_list->Script[i].ScriptTag == dflt_tag)
184 if (script_list->Script[i].ScriptTag == script_tag)
187 return &script->DefaultLangSys;
188 for (j = 0; j < script->LangSysCount; j++)
189 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
190 return script->LangSys + j;
191 return &script->DefaultLangSys;
196 dflt = script_list->Script;
198 return &dflt->DefaultLangSys;
199 for (j = 0; j < dflt->LangSysCount; j++)
200 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
201 return dflt->LangSys + j;
202 return &dflt->DefaultLangSys;
206 setup_lookup_flags (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
207 OTF_LangSys *LangSys,
208 const char *features, char *lookup_flags)
211 OTF_Feature *feature;
212 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
216 for (i = 0; i < FeatureList->FeatureCount; i++)
217 feature_table[i] = 0;
218 memset (lookup_flags, 0, LookupList->LookupCount);
226 if (*features == '*')
228 /* Consume all remaining features. */
229 for (i = 0; i < LangSys->FeatureCount; i++)
231 int index = LangSys->FeatureIndex[i];
233 if (! feature_table[index])
235 feature = FeatureList->Feature + index;
236 for (j = 0; j < feature->LookupCount; j++)
237 lookup_flags[feature->LookupListIndex[j]] = 1;
243 if (*features == '~')
244 use_it = -1, features++;
245 for (i = 0; *features && *features != ','; i++, features++)
246 tagname[i] = *features;
252 tag = OTF_tag (tagname);
253 for (i = 0; i < LangSys->FeatureCount; i++)
255 feature = FeatureList->Feature + LangSys->FeatureIndex[i];
256 if (tag == feature->FeatureTag)
258 if (feature_table[i])
261 for (j = 0; j < feature->LookupCount; j++)
262 lookup_flags[feature->LookupListIndex[j]] = 1;
263 feature_table[i] = use_it;
272 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
273 int count, OTF_GlyphID *ids)
275 OTF_Glyph *gbeg = gstring->glyphs + gidx;
276 OTF_Glyph *gend = gstring->glyphs + gstring->used;
280 for (g = gbeg, i = 0; g < gend && i < count; g++)
281 if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
283 return (i < count ? -1 : g - gbeg);
287 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
290 int i = rule->BacktrackGlyphCount;
297 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
298 if (! IGNORED_GLYPH (g, flag) && --i == 0)
302 if (match_ids (gstring, j, flag,
303 rule->BacktrackGlyphCount, rule->Backtrack)
308 i = match_ids (gstring, gidx, flag,
309 rule->InputGlyphCount - 1, rule->Input);
313 i = match_ids (gstring, gidx, flag,
314 rule->LookaheadGlyphCount, rule->LookAhead);
321 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
322 int flag, int count, unsigned *classes)
324 OTF_Glyph *gbeg = gstring->glyphs + gidx;
325 OTF_Glyph *gend = gstring->glyphs + gstring->used;
329 for (g = gbeg, i = 0; g < gend && i < count; g++)
330 if (! IGNORED_GLYPH (g, flag)
331 && get_class_def (class_def, g->glyph_id) != classes[i++])
333 return (i < count ? -1 : g - gbeg);
337 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
338 OTF_ClassDef *BacktrackClassDef,
339 OTF_ClassDef *InputClassDef,
340 OTF_ClassDef *LookaheadClassDef,
341 OTF_ChainClassRule *rule)
343 int i = rule->BacktrackGlyphCount;
350 for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
351 if (! IGNORED_GLYPH (g, flag) && i-- == 0)
355 if (match_classes (BacktrackClassDef, gstring, j, flag,
356 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
360 i = match_classes (InputClassDef, gstring, gidx, flag,
361 rule->InputGlyphCount - 1, rule->Input);
365 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
366 rule->LookaheadGlyphCount, rule->LookAhead);
374 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
375 OTF_Coverage *coverages)
377 OTF_Glyph *gbeg = gstring->glyphs + gidx;
378 OTF_Glyph *gend = gstring->glyphs + gstring->used;
382 for (g = gbeg, i = 0; g < gend && i < count; g++)
383 if (! IGNORED_GLYPH (g, flag)
384 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
386 return (i < count ? -1 : g - gbeg);
390 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
391 OTF_GSUB_ChainContext3 *context3)
393 int i = context3->BacktrackGlyphCount;
400 for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
401 if (! IGNORED_GLYPH (g, flag) && --i == 0)
405 if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
406 context3->Backtrack) < 0)
410 if (context3->InputGlyphCount > 1)
412 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
413 context3->Input + 1);
418 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
419 context3->LookAhead) < 0)
425 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
426 OTF_GlyphString *gstring, int gidx, int alternate_subst)
428 char *errfmt = "GSUB Looking up%s";
430 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
431 unsigned int flag = (lookup->LookupFlag
432 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
433 int orig_gidx = gidx;
434 OTF_Glyph *g = gstring->glyphs + gidx;
437 if (IGNORED_GLYPH (g, flag))
440 /* Try all subtables until one of them handles the current glyph. */
441 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
443 unsigned lookup_type = lookup->LookupType;
444 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
447 if (lookup_type == 7)
449 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
451 lookup_type = extension1->ExtensionLookupType;
452 subtable = extension1->ExtensionSubtable;
456 ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
457 : (lookup_type == 3))
460 if (subtable->Coverage.offset)
462 coverage_idx = get_coverage_index (&subtable->Coverage,
464 if (coverage_idx < 0)
471 if (subtable->Format == 1)
472 g->glyph_id += subtable->u.single1.DeltaGlyphID;
474 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
479 if (subtable->Format == 1)
481 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
482 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
484 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
485 seq->Substitute, seq->GlyphCount);
486 gidx += seq->GlyphCount;
489 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
493 if (subtable->Format == 1)
495 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
496 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
498 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
499 altset->Alternate, altset->GlyphCount);
500 gidx += altset->GlyphCount;;
503 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
507 if (subtable->Format == 1)
509 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
510 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
514 for (j = 0; j < ligset->LigatureCount; j++)
518 lig = ligset->Ligature + j;
519 n = match_ids (gstring, gidx + 1, flag,
520 lig->CompCount - 1, lig->Component);
523 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
530 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
534 if (subtable->Format == 1)
536 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
537 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
542 for (j = 0; j < set->RuleCount; j++)
544 rule = set->Rule + j;
545 if (match_ids (gstring, gidx + 1, flag,
546 rule->GlyphCount - 1, rule->Input) < 0)
548 orig_used = gstring->used;
549 for (k = 0; k < rule->LookupCount; k++)
550 lookup_gsub (otf, lookup_list,
551 rule->LookupRecord[k].LookupListIndex,
553 gidx + rule->LookupRecord[k].SequenceIndex,
555 gidx += rule->GlyphCount + (gstring->used - orig_used);
559 else if (subtable->Format == 2)
561 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
568 class = get_class_def (&context2->ClassDef, g->glyph_id);
569 set = context2->ClassSet + class;
571 for (j = 0; j < set->ClassRuleCnt; j++)
573 rule = set->ClassRule + j;
574 if (match_classes (&context2->ClassDef,
575 gstring, gidx + 1, flag,
576 rule->GlyphCount - 1, rule->Class)
579 orig_used = gstring->used;
580 for (k = 0; k < rule->LookupCount; k++)
581 lookup_gsub (otf, lookup_list,
582 rule->LookupRecord[k].LookupListIndex,
584 gidx + rule->LookupRecord[k].SequenceIndex,
586 gidx += rule->GlyphCount + (gstring->used - orig_used);
590 else /* subtable->Format == 3 */
592 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
596 if (match_coverages (gstring, gidx + 1, flag,
597 context3->GlyphCount - 1,
598 context3->Coverage + 1) < 0)
600 orig_used = gstring->used;
601 for (j = 0; j < context3->LookupCount; j++)
602 lookup_gsub (otf, lookup_list,
603 context3->LookupRecord[j].LookupListIndex,
605 gidx + context3->LookupRecord[j].SequenceIndex,
607 gidx += context3->GlyphCount + (gstring->used - orig_used);
612 if (subtable->Format == 1)
614 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
615 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
619 for (j = 0; j < set->ChainRuleCount; j++)
621 OTF_ChainRule *rule = set->ChainRule + j;
623 if (gidx < rule->BacktrackGlyphCount
624 || (gidx + rule->InputGlyphCount
625 + rule->LookaheadGlyphCount) > gstring->used)
627 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
629 orig_used = gstring->used;
630 for (k = 0; k < rule->LookupCount; k++)
631 lookup_gsub (otf, lookup_list,
632 rule->LookupRecord[k].LookupListIndex,
634 gidx + rule->LookupRecord[k].SequenceIndex,
636 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
640 else if (subtable->Format == 2)
642 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
643 OTF_ChainClassSet *set;
648 class = get_class_def (&context2->InputClassDef, g->glyph_id);
649 set = context2->ChainClassSet + class;
650 for (j = 0; j < set->ChainClassRuleCnt; j++)
652 OTF_ChainClassRule *rule = set->ChainClassRule + j;
655 if (gidx < rule->BacktrackGlyphCount
656 || (gidx + rule->InputGlyphCount
657 + rule->LookaheadGlyphCount) > gstring->used)
659 if (match_chain_classes (gstring, gidx, flag,
660 &context2->BacktrackClassDef,
661 &context2->InputClassDef,
662 &context2->LookaheadClassDef,
665 orig_used = gstring->used;
666 for (k = 0; k < rule->LookupCount; k++)
667 lookup_gsub (otf, lookup_list,
668 rule->LookupRecord[k].LookupListIndex,
670 gidx + rule->LookupRecord[k].SequenceIndex,
672 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
678 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
682 if (gidx < context3->BacktrackGlyphCount
683 || (gidx + context3->InputGlyphCount
684 + context3->LookaheadGlyphCount) > gstring->used)
686 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
688 orig_used = gstring->used;
689 for (j = 0; j < context3->LookupCount; j++)
690 lookup_gsub (otf, lookup_list,
691 context3->LookupRecord[j].LookupListIndex,
693 gidx + context3->LookupRecord[j].SequenceIndex,
695 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
701 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
702 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
703 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
706 if (back_gidx > gstring->used || ahead_gidx < 0)
709 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
710 if (get_coverage_index (reverse->Backtrack + j,
711 gstring->glyphs[gidx + 1 + j].glyph_id)
714 if (j < reverse->BacktrackGlyphCount)
716 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
717 if (get_coverage_index (reverse->LookAhead + j,
718 gstring->glyphs[gidx - 1 - j].glyph_id)
721 if (j < reverse->LookaheadGlyphCount)
723 g->glyph_id = reverse->Substitute[coverage_idx];
731 if (gidx == orig_gidx)
740 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
742 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
744 rec->XPlacement = anchor->XCoordinate;
745 rec->YPlacement = anchor->YCoordinate;
746 if (anchor->AnchorFormat == 1)
749 else if (anchor->AnchorFormat == 2)
750 /* Not yet implemented */
752 else if (anchor->AnchorFormat == 3)
753 /* Not yet implemented */
759 gstring_insert_for_gpos (OTF_GlyphString *gstring, int gidx)
762 int orig_gidx = gidx++;
764 while (gidx < gstring->used
765 && ! gstring->glyphs[gidx].glyph_id
766 && gstring->glyphs[gidx].positioning_type)
768 GSTRING_INSERT (gstring, gidx, 1);
769 gstring->glyphs[gidx] = gstring->glyphs[orig_gidx];
770 gstring->glyphs[gidx].glyph_id = 0;
775 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
776 OTF_GlyphString *gstring, int gidx, int accumulate)
778 char *errfmt = "GPOS Looking up%s";
780 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
781 unsigned int flag = (lookup->LookupFlag
782 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
783 int orig_gidx = gidx;
784 OTF_Glyph *g = gstring->glyphs + gidx;
787 if (IGNORED_GLYPH (g, flag))
790 /* Try all subtables until one of them handles the current glyph. */
791 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
793 unsigned lookup_type = lookup->LookupType;
794 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
796 int positioning_type;
797 enum OTF_ValueFormat format;
798 OTF_ValueRecord *value;
799 OTF_Anchor *anchor1, *anchor2;
801 if (lookup_type == 9)
803 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
805 lookup_type = extension1->ExtensionLookupType;
806 subtable = extension1->ExtensionSubtable;
809 if (subtable->Coverage.offset)
811 coverage_idx = get_coverage_index (&subtable->Coverage,
813 if (coverage_idx < 0)
820 positioning_type = lookup_type;
821 if (subtable->Format == 1)
823 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
825 format = single1->ValueFormat;
826 value = &single1->Value;
828 else if (subtable->Format == 2)
830 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
832 format = single2->ValueFormat;
833 value = single2->Value + coverage_idx;
835 if (accumulate && g->positioning_type)
837 gidx = gstring_insert_for_gpos (gstring, gidx);
838 g = gstring->glyphs + gidx;
840 g->positioning_type = positioning_type;
841 g->f.f1.format = format;
842 g->f.f1.value = value;
851 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
852 next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
853 next_gidx++, nextg++);
855 if (next_gidx >= gstring->used
856 || nextg->positioning_type)
858 if (subtable->Format == 1)
860 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
861 OTF_PairSet *set = pair1->PairSet + coverage_idx;
864 for (j = 0; j < set->PairValueCount; j++)
865 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
867 if (pair1->ValueFormat1)
869 if (accumulate && g->positioning_type)
871 gidx = gstring_insert_for_gpos (gstring, gidx);
872 g = gstring->glyphs + gidx;
873 next_gidx += gidx - orig_gidx;
874 nextg = gstring->glyphs + next_gidx;
876 g->positioning_type = lookup_type;
877 g->f.f2.format = pair1->ValueFormat1;
878 g->f.f2.value = &set->PairValueRecord[j].Value1;
882 if (pair1->ValueFormat2)
884 if (accumulate && g->positioning_type)
886 gidx = gstring_insert_for_gpos (gstring, gidx);
887 g = gstring->glyphs + gidx;
889 g->positioning_type = lookup_type;
890 g->f.f2.format = pair1->ValueFormat2;
891 g->f.f2.value = &set->PairValueRecord[j].Value2;
897 else if (subtable->Format == 2)
899 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
900 unsigned class1, class2;
902 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
903 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
904 if (pair2->ValueFormat1)
906 if (accumulate && g->positioning_type)
908 gidx = gstring_insert_for_gpos (gstring, gidx);
909 g = gstring->glyphs + gidx;
910 next_gidx += gidx - orig_gidx;
911 nextg = gstring->glyphs + next_gidx;
913 g->positioning_type = lookup_type;
914 g->f.f2.format = pair2->ValueFormat1;
916 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
920 if (pair2->ValueFormat2)
922 if (accumulate && g->positioning_type)
924 gidx = gstring_insert_for_gpos (gstring, gidx);
925 g = gstring->glyphs + gidx;
927 g->positioning_type = lookup_type;
928 g->f.f2.format = pair2->ValueFormat2;
930 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
939 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
941 if (accumulate && g->positioning_type)
943 gidx = gstring_insert_for_gpos (gstring, gidx);
944 g = gstring->glyphs + gidx;
946 g->positioning_type = lookup_type;
948 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
950 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
957 if (subtable->Format == 1)
959 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
960 OTF_MarkRecord *mark_record;
961 OTF_AnchorRecord *base_record;
963 int coverage_idx_base;
964 unsigned int this_flag = flag | OTF_IgnoreMarks;
967 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
969 if (baseg < gstring->glyphs)
972 = get_coverage_index (&mark_base1->BaseCoverage,
974 if (coverage_idx_base < 0)
976 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
978 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
979 if (accumulate && g->positioning_type)
981 gidx = gstring_insert_for_gpos (gstring, gidx);
982 g = gstring->glyphs + gidx;
984 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
986 = &base_record->Anchor[mark_record->Class];
987 g->positioning_type = lookup_type;
994 if (subtable->Format == 1)
996 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
998 int coverage_idx_lig;
999 OTF_MarkRecord *mark_record;
1000 OTF_LigatureAttach *attach;
1001 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
1004 for (j = 0; j < mark_lig1->ClassCount; j++)
1008 (ligg >= gstring->glyphs
1009 && (IGNORED_GLYPH (ligg, flag)
1010 || ligg->GlyphClass > OTF_GlyphClassLigature));
1012 if (ligg->positioning_type == 5
1013 && ligg->MarkAttachClass < mark_lig1->ClassCount)
1014 num_class[ligg->MarkAttachClass]++;
1015 if (ligg < gstring->glyphs)
1018 = get_coverage_index (&mark_lig1->LigatureCoverage,
1020 if (coverage_idx_lig < 0)
1022 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
1023 g->MarkAttachClass = mark_record->Class;
1024 attach = (mark_lig1->LigatureArray.LigatureAttach
1025 + coverage_idx_lig);
1026 for (j = 0; j < attach->ComponentCount; j++)
1028 OTF_Anchor *lig_anchor
1029 = attach->ComponentRecord[j].LigatureAnchor;
1031 if (lig_anchor[mark_record->Class].AnchorFormat
1032 && num_class[mark_record->Class]-- == 0)
1034 if (accumulate && g->positioning_type)
1036 gidx = gstring_insert_for_gpos (gstring, gidx);
1037 g = gstring->glyphs + gidx;
1039 g->positioning_type = lookup_type;
1040 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
1041 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
1051 if (subtable->Format == 1)
1053 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
1054 OTF_MarkRecord *mark1_record;
1055 OTF_AnchorRecord *mark2_record;
1057 int coverage_idx_base;
1060 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
1062 if (prevg < gstring->glyphs)
1065 = get_coverage_index (&mark_mark1->Mark2Coverage,
1067 if (coverage_idx_base < 0)
1069 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
1071 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
1072 if (accumulate && g->positioning_type)
1074 gidx = gstring_insert_for_gpos (gstring, gidx);
1075 g = gstring->glyphs + gidx;
1077 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
1078 g->f.f6.mark2_anchor
1079 = &mark2_record->Anchor[mark1_record->Class];
1080 g->positioning_type = lookup_type;
1086 if (subtable->Format == 1)
1088 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1089 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1094 for (j = 0; j < set->RuleCount; j++)
1096 rule = set->Rule + j;
1097 if (match_ids (gstring, gidx + 1, flag,
1098 rule->GlyphCount - 1, rule->Input) < 0)
1100 orig_used = gstring->used;
1101 for (k = 0; k < rule->LookupCount; k++)
1102 lookup_gpos (lookup_list,
1103 rule->LookupRecord[k].LookupListIndex,
1105 gidx + rule->LookupRecord[k].SequenceIndex,
1107 gidx += rule->GlyphCount + (gstring->used - orig_used);
1111 else if (subtable->Format == 2)
1113 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1115 OTF_ClassRule *rule;
1120 class = get_class_def (&context2->ClassDef, g->glyph_id);
1121 set = context2->ClassSet + class;
1123 for (j = 0; j < set->ClassRuleCnt; j++)
1125 rule = set->ClassRule + j;
1126 if (match_classes (&context2->ClassDef,
1127 gstring, gidx + 1, flag,
1128 rule->GlyphCount - 1, rule->Class)
1131 orig_used = gstring->used;
1132 for (k = 0; k < rule->LookupCount; k++)
1133 lookup_gpos (lookup_list,
1134 rule->LookupRecord[k].LookupListIndex,
1136 gidx + rule->LookupRecord[k].SequenceIndex,
1138 gidx += rule->GlyphCount + (gstring->used - orig_used);
1142 else /* subtable->Format == 3 */
1144 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1148 if (match_coverages (gstring, gidx + 1, flag,
1149 context3->GlyphCount - 1,
1150 context3->Coverage + 1) < 0)
1152 orig_used = gstring->used;
1153 for (j = 0; j < context3->LookupCount; j++)
1154 lookup_gpos (lookup_list,
1155 context3->LookupRecord[j].LookupListIndex,
1157 gidx + context3->LookupRecord[j].SequenceIndex,
1159 gidx += context3->GlyphCount + (gstring->used - orig_used);
1164 if (subtable->Format == 1)
1166 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1167 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1171 for (j = 0; j < set->ChainRuleCount; j++)
1173 OTF_ChainRule *rule = set->ChainRule + j;
1175 if (gidx < rule->BacktrackGlyphCount
1176 || (gidx + rule->InputGlyphCount
1177 + rule->LookaheadGlyphCount) > gstring->used)
1179 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1181 orig_used = gstring->used;
1182 for (k = 0; k < rule->LookupCount; k++)
1183 lookup_gpos (lookup_list,
1184 rule->LookupRecord[k].LookupListIndex,
1186 gidx + rule->LookupRecord[k].SequenceIndex,
1188 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1192 else if (subtable->Format == 2)
1194 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1195 OTF_ChainClassSet *set;
1200 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1201 set = context2->ChainClassSet + class;
1202 for (j = 0; j < set->ChainClassRuleCnt; j++)
1204 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1207 if (gidx < rule->BacktrackGlyphCount
1208 || (gidx + rule->InputGlyphCount
1209 + rule->LookaheadGlyphCount) > gstring->used)
1211 if (match_chain_classes (gstring, gidx, flag,
1212 &context2->BacktrackClassDef,
1213 &context2->InputClassDef,
1214 &context2->LookaheadClassDef,
1217 orig_used = gstring->used;
1218 for (k = 0; k < rule->LookupCount; k++)
1219 lookup_gpos (lookup_list,
1220 rule->LookupRecord[k].LookupListIndex,
1222 gidx + rule->LookupRecord[k].SequenceIndex,
1224 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1228 else if (subtable->Format == 3)
1230 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1234 if (gidx < context3->BacktrackGlyphCount
1235 || (gidx + context3->InputGlyphCount
1236 + context3->LookaheadGlyphCount) > gstring->used)
1238 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1240 orig_used = gstring->used;
1241 for (j = 0; j < context3->LookupCount; j++)
1242 lookup_gpos (lookup_list,
1243 context3->LookupRecord[j].LookupListIndex,
1245 gidx + context3->LookupRecord[j].SequenceIndex,
1247 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1250 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1257 if (gidx == orig_gidx)
1263 lookup_encoding_0 (int c, OTF_EncodingSubtable *sub)
1265 return ((c < 0 || c >= 256)
1267 : sub->f.f0->glyphIdArray[c]);
1271 lookup_encoding_2 (int c, OTF_EncodingSubtable *sub)
1277 lookup_encoding_4 (int c, OTF_EncodingSubtable *sub)
1280 OTF_EncodingSubtable4 *sub4;
1285 segCount = sub4->segCountX2 / 2;
1286 for (i = 0; i < segCount; i++)
1288 OTF_cmapSegment *seg = sub4->segments + i;
1290 if (c >= seg->startCount && c <= seg->endCount)
1292 if (seg->idRangeOffset == 0xFFFF)
1293 return c + seg->idDelta;
1295 return sub4->glyphIdArray[seg->idRangeOffset
1296 + (c - seg->startCount)];
1303 lookup_encoding_6 (int c, OTF_EncodingSubtable *sub)
1309 lookup_encoding_8 (int c, OTF_EncodingSubtable *sub)
1315 lookup_encoding_10 (int c, OTF_EncodingSubtable *sub)
1321 lookup_encoding_12 (int c, OTF_EncodingSubtable *sub)
1323 OTF_EncodingSubtable12 *sub12;
1324 OTF_cmapGroup *g, *gend;
1330 gend = sub12->Groups + sub12->nGroups;
1333 if (g->startCharCode <= c && c <= g->endCharCode)
1334 return (g->startGlyphID + (c - g->startCharCode));
1340 typedef unsigned (*lookup_cmap_func) (int, OTF_EncodingSubtable *);
1342 static lookup_cmap_func lookup_cmap_func_table[] =
1344 lookup_encoding_0, lookup_encoding_2, lookup_encoding_4, lookup_encoding_6,
1345 lookup_encoding_8, lookup_encoding_10, lookup_encoding_12
1349 get_GlyphID (OTF_cmap *cmap, int c)
1351 OTF_EncodingSubtable *sub;
1352 lookup_cmap_func lookupper;
1354 if (c < 0x10000 && cmap->unicode_table)
1355 return cmap->unicode_table[c];
1356 if (cmap->table_index < 0)
1358 sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1359 lookupper = lookup_cmap_func_table[sub->format / 2];
1360 return lookupper (c, sub);
1364 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1366 unsigned nRecords = sub14->nRecords;
1367 OTF_VariationSelectorRecord *record;
1370 for (i = 0; i < nRecords; i++)
1372 record = &sub14->Records[i];
1373 if (record->varSelector == c2)
1375 if (record->defaultUVSOffset)
1377 OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1378 unsigned numUVRs = record->numUnicodeValueRanges;
1379 unsigned top = numUVRs, bottom = 0, middle;
1381 if (uVRs[0].startUnicodeValue <= c1)
1383 unsigned additionalCount, startUnicodeValue;
1387 middle = (top + bottom) / 2;
1388 if (c1 < uVRs[middle].startUnicodeValue)
1390 else if (bottom == middle)
1395 startUnicodeValue = uVRs[bottom].startUnicodeValue;
1396 additionalCount = uVRs[bottom].additionalCount;
1397 if (c1 <= startUnicodeValue + additionalCount)
1398 return get_GlyphID (cmap, c1);
1401 if (record->nonDefaultUVSOffset)
1403 OTF_UVSMapping *uvsMappings = record->uvsMappings;
1404 unsigned numUVSMs = record->numUVSMappings;
1405 unsigned top = numUVSMs, bottom = 0, middle;
1407 if (uvsMappings[0].unicodeValue <= c1)
1411 middle = (top + bottom) / 2;
1412 if (c1 < uvsMappings[middle].unicodeValue)
1414 else if (bottom == middle)
1419 if (uvsMappings[bottom].unicodeValue == c1)
1420 return uvsMappings[bottom].glyphID;
1430 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1432 OTF_EncodingSubtable14 *sub14;
1433 int c1 = gstring->glyphs[idx - 1].c;
1434 int c2 = gstring->glyphs[idx].c;
1438 gstring->glyphs[idx].glyph_id = 0;
1439 for (i = 0; i < cmap->numTables; i++)
1440 if (cmap->EncodingRecord[i].subtable.format == 14)
1442 if (i == cmap->numTables)
1444 code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1447 gstring->glyphs[idx - 1].glyph_id = code;
1448 gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1450 memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1451 sizeof (OTF_Glyph) * (gstring->used - idx));
1457 /* Table of GlyphClass and MarkAttackClass.
1459 For the Nth element CHAR, CHAR and the succeeding characters
1460 (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1462 This table is generated from the General Category (GC) property of
1463 characters defined in the Unicode Character Database. */
1465 static int glyph_class_table[] =
1466 { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1467 0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1468 0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1469 0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1470 0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1471 0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1472 0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1473 0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1474 0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1475 0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1476 0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1477 0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1478 0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1479 0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1480 0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1481 0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1482 0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1483 0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1484 0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1485 0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1486 0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1487 0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1488 0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1489 0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1490 0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1491 0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1492 0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1493 0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1494 0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1496 int get_class_def_auto (int c)
1498 static int table_size
1499 = sizeof glyph_class_table / sizeof glyph_class_table[0];
1502 if (c >= glyph_class_table[table_size - 1])
1505 high = table_size - 1;
1508 mid = (low + high) / 2;
1509 if (c < glyph_class_table[mid])
1511 else if (c >= glyph_class_table[mid + 1])
1516 return ((mid % 2) ? 3 : 1);
1524 (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1527 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1531 OTF_EncodingSubtable *sub;
1532 lookup_cmap_func lookupper;
1535 && OTF_get_table (otf, "cmap") < 0)
1539 if (cmap->table_index < 0)
1543 sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1544 lookupper = lookup_cmap_func_table[sub->format / 2];
1546 for (i = 0; i < gstring->used; i++)
1547 if (! gstring->glyphs[i].glyph_id)
1549 int c = gstring->glyphs[i].c;
1550 if (c < 32 || ! cmap->unicode_table)
1551 gstring->glyphs[i].glyph_id = 0;
1552 else if (UVS_P (c) && i > 0)
1553 check_cmap_uvs (cmap, gstring, i);
1554 else if (c < 0x10000)
1555 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1557 gstring->glyphs[i].glyph_id = lookupper (c, sub);
1564 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1565 int platform_id, int encoding_id)
1569 char *errfmt = "CMAP Looking up%s";
1571 OTF_EncodingRecord *enc;
1572 lookup_cmap_func lookupper;
1575 && OTF_get_table (otf, "cmap") < 0)
1579 for (i = 0; i < cmap->numTables; i++)
1580 if (cmap->EncodingRecord[i].platformID == platform_id
1581 && cmap->EncodingRecord[i].encodingID == encoding_id)
1583 if (i == cmap->numTables)
1584 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1585 enc = cmap->EncodingRecord + i;
1586 if (enc->subtable.format > 12)
1587 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1588 lookupper = lookup_cmap_func_table[enc->subtable.format / 2];
1590 for (i = 0; i < gstring->used; i++)
1591 if (! gstring->glyphs[i].glyph_id)
1593 int c = gstring->glyphs[i].c;
1594 if (c < 32 || ! cmap->unicode_table)
1595 gstring->glyphs[i].glyph_id = 0;
1596 else if (UVS_P (c) && i > 0)
1597 check_cmap_uvs (cmap, gstring, i);
1598 else if (c < 0x10000)
1599 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1601 gstring->glyphs[i].glyph_id = lookupper (c, &enc->subtable);
1607 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1610 && OTF_get_table (otf, "cmap") < 0)
1613 || code > otf->cmap->max_glyph_id
1614 || ! otf->cmap->decode_table)
1616 return otf->cmap->decode_table[code];
1620 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1624 OTF_EncodingSubtable14 *sub14;
1626 memset (code, 0, sizeof (OTF_GlyphID) * 256);
1628 && OTF_get_table (otf, "cmap") < 0)
1631 for (i = 0; i < cmap->numTables; i++)
1632 if (cmap->EncodingRecord[i].subtable.format == 14)
1634 if (i == cmap->numTables)
1636 sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1637 for (i = 0, n = 0; i < 256; i++)
1639 int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1641 if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1649 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1655 && OTF_get_table (otf, "GDEF") < 0)
1659 if (gdef->glyph_class_def.offset)
1660 for (i = 0; i < gstring->used; i++)
1661 gstring->glyphs[i].GlyphClass
1662 = get_class_def (&gdef->glyph_class_def,
1663 gstring->glyphs[i].glyph_id);
1665 for (i = 0; i < gstring->used; i++)
1666 gstring->glyphs[i].GlyphClass
1667 = get_class_def_auto (gstring->glyphs[i].c);
1669 if (gdef->mark_attach_class_def.offset)
1670 for (i = 0; i < gstring->used; i++)
1671 gstring->glyphs[i].MarkAttachClass
1672 = get_class_def (&gdef->mark_attach_class_def,
1673 gstring->glyphs[i].glyph_id);
1679 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1680 const char *script, const char *language,
1681 const char *features,
1682 int alternate_subst)
1684 char *errfmt = "GSUB driving%s";
1687 OTF_LangSys *LangSys;
1691 for (i = 0; i < gstring->used; i++)
1693 gstring->glyphs[i].positioning_type = 0;
1694 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1697 if (OTF_get_table (otf, "GSUB") < 0)
1700 if (gsub->FeatureList.FeatureCount == 0
1701 || gsub->LookupList.LookupCount == 0)
1704 LangSys = get_langsys (&gsub->ScriptList, script, language);
1708 lookup_flags = alloca (gsub->LookupList.LookupCount);
1710 || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1711 features, lookup_flags) < 0)
1712 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1714 for (i = 0; i < gsub->LookupList.LookupCount; i++)
1718 if (! lookup_flags[i]) continue;
1720 if (gsub->LookupList.Lookup[i].LookupType != 8)
1723 while (gidx < gstring->used)
1725 gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1733 gidx = gstring->used - 1;
1736 gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1748 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1749 const char *script, const char *language, const char *features)
1752 OTF_get_table (otf, "cmap");
1753 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1757 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1758 const char *script, const char *language,
1759 const char *features,
1762 char *errfmt = "GPOS driving%s";
1765 OTF_LangSys *LangSys;
1769 for (i = 0; i < gstring->used; i++)
1770 gstring->glyphs[i].positioning_type = 0;
1772 if (OTF_get_table (otf, "GPOS") < 0)
1775 if (gpos->FeatureList.FeatureCount == 0
1776 || gpos->LookupList.LookupCount == 0)
1779 LangSys = get_langsys (&gpos->ScriptList, script, language);
1783 lookup_flags = alloca (gpos->LookupList.LookupCount);
1785 || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1786 features, lookup_flags) < 0)
1787 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1789 for (i = 0; i < gpos->LookupList.LookupCount; i++)
1793 if (! lookup_flags[i]) continue;
1795 while (gidx < gstring->used)
1797 gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx, accumulate);
1807 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1808 const char *script, const char *language, const char *features)
1811 OTF_get_table (otf, "cmap");
1812 return OTF_drive_gpos_internal (otf, gstring, script, language, features, 0);
1816 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1817 const char *script, const char *language, const char *features)
1820 OTF_get_table (otf, "cmap");
1821 return OTF_drive_gpos_internal (otf, gstring, script, language, features, 1);
1825 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1826 const char *script, const char *language,
1827 const char *gsub_features, const char *gpos_features)
1829 if (OTF_drive_cmap (otf, gstring) < 0)
1831 if (OTF_drive_gdef (otf, gstring) < 0)
1834 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1837 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1843 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1844 const char *script, const char *language,
1845 const char *features)
1847 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);