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 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1267 for (i = 0; i < gstring->used; i++)
1269 c = gstring->glyphs[i].c;
1270 if (c < 0 || c >= 256)
1271 gstring->glyphs[i].glyph_id = 0;
1273 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1279 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1285 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1288 int segCount = sub4->segCountX2 / 2;
1290 for (i = 0; i < gstring->used; i++)
1292 c = gstring->glyphs[i].c;
1294 gstring->glyphs[i].glyph_id = 0;
1295 for (j = 0; j < segCount; j++)
1297 OTF_cmapSegment *seg = sub4->segments + i;
1299 if (c >= seg->startCount && c <= seg->endCount)
1301 if (seg->idRangeOffset == 0xFFFF)
1302 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1304 gstring->glyphs[i].glyph_id
1305 = sub4->glyphIdArray[seg->idRangeOffset
1306 + (c - seg->startCount)];
1316 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1322 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1328 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1334 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1340 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1342 unsigned nRecords = sub14->nRecords;
1343 OTF_VariationSelectorRecord *record;
1346 for (i = 0; i < nRecords; i++)
1348 record = &sub14->Records[i];
1349 if (record->varSelector == c2)
1351 if (record->defaultUVSOffset)
1353 OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1354 unsigned numUVRs = record->numUnicodeValueRanges;
1355 unsigned top = numUVRs, bottom = 0, middle;
1357 if (uVRs[0].startUnicodeValue <= c1)
1359 unsigned additionalCount, startUnicodeValue;
1363 middle = (top + bottom) / 2;
1364 if (c1 < uVRs[middle].startUnicodeValue)
1366 else if (bottom == middle)
1371 startUnicodeValue = uVRs[bottom].startUnicodeValue;
1372 additionalCount = uVRs[bottom].additionalCount;
1373 if (c1 <= startUnicodeValue + additionalCount)
1374 return cmap->unicode_table[c1];
1377 if (record->nonDefaultUVSOffset)
1379 OTF_UVSMapping *uvsMappings = record->uvsMappings;
1380 unsigned numUVSMs = record->numUVSMappings;
1381 unsigned top = numUVSMs, bottom = 0, middle;
1383 if (uvsMappings[0].unicodeValue <= c1)
1387 middle = (top + bottom) / 2;
1388 if (c1 < uvsMappings[middle].unicodeValue)
1390 else if (bottom == middle)
1395 if (uvsMappings[bottom].unicodeValue == c1)
1396 return uvsMappings[bottom].glyphID;
1406 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1408 OTF_EncodingSubtable14 *sub14;
1409 int c1 = gstring->glyphs[idx - 1].c;
1410 int c2 = gstring->glyphs[idx].c;
1414 gstring->glyphs[idx].glyph_id = 0;
1415 for (i = 0; i < cmap->numTables; i++)
1416 if (cmap->EncodingRecord[i].subtable.format == 14)
1418 if (i == cmap->numTables)
1420 code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1423 gstring->glyphs[idx - 1].glyph_id = code;
1424 gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1426 memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1427 sizeof (OTF_Glyph) * (gstring->used - idx));
1433 /* Table of GlyphClass and MarkAttackClass.
1435 For the Nth element CHAR, CHAR and the succeeding characters
1436 (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1438 This table is generated from the General Category (GC) property of
1439 characters defined in the Unicode Character Database. */
1441 static int glyph_class_table[] =
1442 { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1443 0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1444 0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1445 0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1446 0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1447 0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1448 0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1449 0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1450 0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1451 0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1452 0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1453 0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1454 0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1455 0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1456 0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1457 0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1458 0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1459 0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1460 0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1461 0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1462 0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1463 0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1464 0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1465 0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1466 0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1467 0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1468 0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1469 0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1470 0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1472 int get_class_def_auto (int c)
1474 static int table_size
1475 = sizeof glyph_class_table / sizeof glyph_class_table[0];
1478 if (c >= glyph_class_table[table_size - 1])
1481 high = table_size - 1;
1484 mid = (low + high) / 2;
1485 if (c < glyph_class_table[mid])
1487 else if (c >= glyph_class_table[mid + 1])
1492 return ((mid % 2) ? 3 : 1);
1500 (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1503 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1509 && OTF_get_table (otf, "cmap") < 0)
1513 for (i = 0; i < gstring->used; i++)
1514 if (! gstring->glyphs[i].glyph_id)
1516 int c = gstring->glyphs[i].c;
1517 if (c < 32 || ! cmap->unicode_table)
1518 gstring->glyphs[i].glyph_id = 0;
1519 else if (UVS_P (c) && i > 0)
1520 check_cmap_uvs (cmap, gstring, i);
1522 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1529 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1530 int platform_id, int encoding_id)
1534 char *errfmt = "CMAP Looking up%s";
1536 OTF_EncodingRecord *enc;
1539 && OTF_get_table (otf, "cmap") < 0)
1543 for (i = 0; i < cmap->numTables; i++)
1544 if (cmap->EncodingRecord[i].platformID == platform_id
1545 && cmap->EncodingRecord[i].encodingID == encoding_id)
1547 if (i == cmap->numTables)
1548 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1549 enc = cmap->EncodingRecord + i;
1550 switch (enc->subtable.format)
1552 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1553 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1554 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1555 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1556 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1557 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1558 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1560 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1565 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1568 && OTF_get_table (otf, "cmap") < 0)
1571 || code > otf->cmap->max_glyph_id
1572 || ! otf->cmap->decode_table)
1574 return otf->cmap->decode_table[code];
1578 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1582 OTF_EncodingSubtable14 *sub14;
1584 memset (code, 0, sizeof (OTF_GlyphID) * 256);
1586 && OTF_get_table (otf, "cmap") < 0)
1589 for (i = 0; i < cmap->numTables; i++)
1590 if (cmap->EncodingRecord[i].subtable.format == 14)
1592 if (i == cmap->numTables)
1594 sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1595 for (i = 0, n = 0; i < 256; i++)
1597 int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1599 if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1607 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1613 && OTF_get_table (otf, "GDEF") < 0)
1617 if (gdef->glyph_class_def.offset)
1618 for (i = 0; i < gstring->used; i++)
1619 gstring->glyphs[i].GlyphClass
1620 = get_class_def (&gdef->glyph_class_def,
1621 gstring->glyphs[i].glyph_id);
1623 for (i = 0; i < gstring->used; i++)
1624 gstring->glyphs[i].GlyphClass
1625 = get_class_def_auto (gstring->glyphs[i].c);
1627 if (gdef->mark_attach_class_def.offset)
1628 for (i = 0; i < gstring->used; i++)
1629 gstring->glyphs[i].MarkAttachClass
1630 = get_class_def (&gdef->mark_attach_class_def,
1631 gstring->glyphs[i].glyph_id);
1637 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1638 const char *script, const char *language,
1639 const char *features,
1640 int alternate_subst)
1642 char *errfmt = "GSUB driving%s";
1645 OTF_LangSys *LangSys;
1649 for (i = 0; i < gstring->used; i++)
1651 gstring->glyphs[i].positioning_type = 0;
1652 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1655 if (OTF_get_table (otf, "GSUB") < 0)
1658 if (gsub->FeatureList.FeatureCount == 0
1659 || gsub->LookupList.LookupCount == 0)
1662 LangSys = get_langsys (&gsub->ScriptList, script, language);
1666 lookup_flags = alloca (gsub->LookupList.LookupCount);
1668 || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1669 features, lookup_flags) < 0)
1670 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1672 for (i = 0; i < gsub->LookupList.LookupCount; i++)
1676 if (! lookup_flags[i]) continue;
1678 if (gsub->LookupList.Lookup[i].LookupType != 8)
1681 while (gidx < gstring->used)
1683 gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1691 gidx = gstring->used - 1;
1694 gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1706 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1707 const char *script, const char *language, const char *features)
1710 OTF_get_table (otf, "cmap");
1711 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1715 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1716 const char *script, const char *language,
1717 const char *features,
1720 char *errfmt = "GPOS driving%s";
1723 OTF_LangSys *LangSys;
1727 for (i = 0; i < gstring->used; i++)
1728 gstring->glyphs[i].positioning_type = 0;
1730 if (OTF_get_table (otf, "GPOS") < 0)
1733 if (gpos->FeatureList.FeatureCount == 0
1734 || gpos->LookupList.LookupCount == 0)
1737 LangSys = get_langsys (&gpos->ScriptList, script, language);
1741 lookup_flags = alloca (gpos->LookupList.LookupCount);
1743 || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1744 features, lookup_flags) < 0)
1745 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1747 for (i = 0; i < gpos->LookupList.LookupCount; i++)
1751 if (! lookup_flags[i]) continue;
1753 while (gidx < gstring->used)
1755 gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx, accumulate);
1765 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1766 const char *script, const char *language, const char *features)
1769 OTF_get_table (otf, "cmap");
1770 return OTF_drive_gpos_internal (otf, gstring, script, language, features, 0);
1774 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1775 const char *script, const char *language, const char *features)
1778 OTF_get_table (otf, "cmap");
1779 return OTF_drive_gpos_internal (otf, gstring, script, language, features, 1);
1783 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1784 const char *script, const char *language,
1785 const char *gsub_features, const char *gpos_features)
1787 if (OTF_drive_cmap (otf, gstring) < 0)
1789 if (OTF_drive_gdef (otf, gstring) < 0)
1792 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1795 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1801 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1802 const char *script, const char *language,
1803 const char *features)
1805 return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);