1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 extern int debug_flag;
37 #define USHORT unsigned short
39 /* Return nonzero (-1 if ID is zero, 1 otherwise) if OTF_Glyph *G
40 should be ignored according to LookupFlag FLAG. */
41 #define IGNORED_GLYPH(g, flag) \
42 ((g)->glyph_id == 0 ? -1 \
43 : (((flag) & (1 << (g)->GlyphClass)) \
44 || (((flag) & OTF_MarkAttachmentType) \
45 && (g)->GlyphClass == OTF_GlyphClassMark \
46 && ((flag) >> 8) != (g)->MarkAttachClass)))
48 #define GSTRING_DELETE(gstring, from, len) \
50 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
51 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
52 gstring->used -= len; \
56 #define GSTRING_INSERT(gstring, pos, len) \
58 if (gstring->used + len > gstring->size) \
60 char *errfmt = "GSTRING%s"; \
62 gstring->size = gstring->used + len; \
64 = (OTF_Glyph *) realloc (gstring->glyphs, \
65 sizeof (OTF_Glyph) * gstring->size); \
66 if (! gstring->glyphs) \
67 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
69 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
70 sizeof (OTF_Glyph) * (gstring->used - pos)); \
71 gstring->used += len; \
75 static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID);
78 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
79 OTF_GlyphID *ids, int num)
84 int from_idx = gstring->glyphs[from].f.index.from;
85 int to_idx = gstring->glyphs[to - 1].f.index.to;
88 for (i = non_ignored_idx = to - 1; i >= from; i--)
90 OTF_Glyph *g = gstring->glyphs + i;
92 if (IGNORED_GLYPH (g, flag) == 1)
94 /* Move this glyph to the next of the current target of
98 memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
99 temp.f.index.from = from_idx;
100 temp.f.index.to = to_idx;
101 gstring->glyphs[non_ignored_idx--] = temp;
107 GSTRING_INSERT (gstring, from, (num - len));
109 GSTRING_DELETE (gstring, from, (len - num));
110 for (i = 0; i < num; i++)
112 if (gstring->glyphs[from + i].glyph_id != ids[i])
114 gstring->glyphs[from + i].c = 0;
115 if (otf->gdef && otf->gdef->glyph_class_def.offset)
116 gstring->glyphs[from + i].GlyphClass
117 = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
119 gstring->glyphs[from + i].GlyphClass = 0;
120 if (otf->gdef && otf->gdef->mark_attach_class_def.offset)
121 gstring->glyphs[from + i].MarkAttachClass
122 = get_class_def (&otf->gdef->mark_attach_class_def, ids[i]);
124 gstring->glyphs[from + i].glyph_id = ids[i];
125 gstring->glyphs[from + i].positioning_type = 1;
126 gstring->glyphs[from + i].f.index.from = from_idx;
127 gstring->glyphs[from + i].f.index.to = to_idx;
134 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
138 if (coverage->CoverageFormat == 1)
140 for (i = 0; i < coverage->Count; i++)
141 if (coverage->table.GlyphArray[i] == id)
146 for (i = 0; i < coverage->Count; i++)
147 if (coverage->table.RangeRecord[i].Start <= id
148 && coverage->table.RangeRecord[i].End >= id)
149 return (coverage->table.RangeRecord[i].StartCoverageIndex
150 + (id - coverage->table.RangeRecord[i].Start));
156 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
158 if (class_def->ClassFormat == 1)
160 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
162 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
163 return class_def->f.f1.ClassValueArray[idx];
169 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
170 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
171 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
172 return class_def->f.f2.ClassRangeRecord[i].Class;
178 get_langsys (OTF_ScriptList *script_list,
179 const char *script, const char *language)
182 OTF_Tag script_tag = OTF_tag (script);
183 OTF_Tag langsys_tag = OTF_tag (language);
185 OTF_Tag dflt_tag = OTF_tag ("DFLT");
186 OTF_Script *dflt = NULL;
188 for (i = 0; i < script_list->ScriptCount; i++)
190 OTF_Script *script = script_list->Script + i;
192 if (script_list->Script[i].ScriptTag == dflt_tag)
194 if (script_list->Script[i].ScriptTag == script_tag)
197 return &script->DefaultLangSys;
198 for (j = 0; j < script->LangSysCount; j++)
199 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
200 return script->LangSys + j;
201 return &script->DefaultLangSys;
206 dflt = script_list->Script;
208 return &dflt->DefaultLangSys;
209 for (j = 0; j < dflt->LangSysCount; j++)
210 if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
211 return dflt->LangSys + j;
212 return &dflt->DefaultLangSys;
216 setup_lookup_flags (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
217 OTF_LangSys *LangSys,
218 const char *features, USHORT *lookup_flags)
221 OTF_Feature *feature;
222 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
226 for (i = 0; i < FeatureList->FeatureCount; i++)
227 feature_table[i] = 0;
228 memset (lookup_flags, 0, sizeof (USHORT) * LookupList->LookupCount);
236 if (*features == '*')
238 /* Consume all remaining features. */
239 for (i = 0; i < LangSys->FeatureCount; i++)
241 int index = LangSys->FeatureIndex[i];
243 if (! feature_table[index])
245 feature = FeatureList->Feature + index;
246 for (j = 0; j < feature->LookupCount; j++)
247 lookup_flags[feature->LookupListIndex[j]] = index + 1;
253 if (*features == '~')
254 use_it = -1, features++;
255 for (i = 0; *features && *features != ','; i++, features++)
256 tagname[i] = *features;
262 tag = OTF_tag (tagname);
263 for (i = 0; i < LangSys->FeatureCount; i++)
265 int index = LangSys->FeatureIndex[i];
267 feature = FeatureList->Feature + index;
268 if (tag == feature->FeatureTag)
270 if (feature_table[i])
273 for (j = 0; j < feature->LookupCount; j++)
274 lookup_flags[feature->LookupListIndex[j]] = index + 1;
275 feature_table[i] = use_it;
284 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
285 int count, OTF_GlyphID *ids, int direction)
287 OTF_Glyph *g = gstring->glyphs + gidx;
288 OTF_Glyph *gend = gstring->glyphs + (direction > 0 ? gstring->used : -1);
291 for (i = j = 0; i < count && g != gend; j++, g += direction)
292 if (! IGNORED_GLYPH (g, flag)
293 && g->glyph_id != ids[i++])
295 return (i < count ? -1 : j);
299 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
302 int i = rule->BacktrackGlyphCount;
306 || match_ids (gstring, gidx - 1, flag, i, rule->Backtrack, -1) < 0))
309 i = match_ids (gstring, gidx, flag,
310 rule->InputGlyphCount - 1, rule->Input, 1);
314 i = match_ids (gstring, gidx, flag,
315 rule->LookaheadGlyphCount, rule->LookAhead, 1);
322 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
323 int flag, int count, unsigned *classes, int direction)
325 OTF_Glyph *g = gstring->glyphs + gidx;
326 OTF_Glyph *gend = gstring->glyphs + (direction > 0 ? gstring->used : -1);
329 for (i = j = 0; i < count && g != gend; j++, g += direction)
330 if (! IGNORED_GLYPH (g, flag)
331 && get_class_def (class_def, g->glyph_id) != classes[i++])
333 return (i < count ? -1 : j);
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;
347 || match_classes (BacktrackClassDef, gstring, gidx - 1, flag, i,
348 rule->Backtrack, -1) < 0))
351 i = match_classes (InputClassDef, gstring, gidx, flag,
352 rule->InputGlyphCount - 1, rule->Input, 1);
356 i = match_classes (LookaheadClassDef, gstring, gidx, flag,
357 rule->LookaheadGlyphCount, rule->LookAhead, 1);
365 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
366 OTF_Coverage *coverages, int direction)
368 OTF_Glyph *g = gstring->glyphs + gidx;
369 OTF_Glyph *gend = gstring->glyphs + (direction > 0 ? gstring->used : - 1);
372 for (i = j = 0; i < count && g != gend; j++, g += direction)
373 if (! IGNORED_GLYPH (g, flag)
374 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
376 return (i < count ? -1 : j);
380 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
381 OTF_GSUB_ChainContext3 *context3)
383 int i = context3->BacktrackGlyphCount;
387 || match_coverages (gstring, gidx - 1, flag, i,
388 context3->Backtrack, -1) < 0))
391 if (context3->InputGlyphCount > 1)
393 i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
394 context3->Input + 1, 1);
399 if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
400 context3->LookAhead, 1) < 0)
405 /* Apply the lookup indexed by LOOKUP_LIST_INDEX in LOOKUP_LIST to the
406 glyphs indexed by GIDX in GSTRING and the followings. If
407 successfully applied, return the index of the next glyph to apply
408 the lookup. If not applied, return GIDX. If error happened,
412 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
413 OTF_GlyphString *gstring, int gidx, int alternate_subst)
415 char *errfmt = "GSUB Looking up%s";
417 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
418 unsigned int flag = (lookup->LookupFlag
419 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
420 int orig_gidx = gidx;
421 OTF_Glyph *g = gstring->glyphs + gidx;
424 if (IGNORED_GLYPH (g, flag))
427 /* Try all subtables until one of them handles the current glyph. */
428 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
430 unsigned lookup_type = lookup->LookupType;
431 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
434 if (lookup_type == 7)
436 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
438 lookup_type = extension1->ExtensionLookupType;
439 subtable = extension1->ExtensionSubtable;
443 ? (alternate_subst == 1
444 && lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
445 : (lookup_type == 3))
448 if (subtable->Coverage.offset)
450 coverage_idx = get_coverage_index (&subtable->Coverage,
452 if (coverage_idx < 0)
459 if (subtable->Format == 1)
460 g->glyph_id += subtable->u.single1.DeltaGlyphID;
462 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
463 if (otf->gdef && otf->gdef->glyph_class_def.offset)
465 = get_class_def (&otf->gdef->glyph_class_def, g->glyph_id);
468 if (otf->gdef && otf->gdef->mark_attach_class_def.offset)
470 = get_class_def (&otf->gdef->mark_attach_class_def, g->glyph_id);
471 g->positioning_type = 1;
476 if (subtable->Format == 1)
478 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
479 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
481 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
482 seq->Substitute, seq->GlyphCount);
483 gidx += seq->GlyphCount;
486 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
490 if (subtable->Format == 1)
492 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
493 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
495 if (alternate_subst == 1)
496 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
497 altset->Alternate, altset->GlyphCount);
499 gstring_subst (otf, gstring, gidx, gidx + 1, flag,
500 altset->Alternate, 1);
501 gidx += altset->GlyphCount;;
504 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
508 if (subtable->Format == 1)
510 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
511 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
515 for (j = 0; j < ligset->LigatureCount; j++)
519 lig = ligset->Ligature + j;
520 n = match_ids (gstring, gidx + 1, flag,
521 lig->CompCount - 1, lig->Component, 1);
524 gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
531 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
535 if (subtable->Format == 1)
537 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
538 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
543 for (j = 0; j < set->RuleCount; j++)
545 rule = set->Rule + j;
546 if (match_ids (gstring, gidx + 1, flag,
547 rule->GlyphCount - 1, rule->Input, 1) < 0)
549 orig_used = gstring->used;
550 for (k = 0; k < rule->LookupCount; k++)
551 lookup_gsub (otf, lookup_list,
552 rule->LookupRecord[k].LookupListIndex,
554 gidx + rule->LookupRecord[k].SequenceIndex,
555 alternate_subst ? alternate_subst : 2);
556 gidx += rule->GlyphCount + (gstring->used - orig_used);
560 else if (subtable->Format == 2)
562 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
569 class = get_class_def (&context2->ClassDef, g->glyph_id);
570 set = context2->ClassSet + class;
572 for (j = 0; j < set->ClassRuleCnt; j++)
574 rule = set->ClassRule + j;
575 if (match_classes (&context2->ClassDef,
576 gstring, gidx + 1, flag,
577 rule->GlyphCount - 1, rule->Class, 1)
580 orig_used = gstring->used;
581 for (k = 0; k < rule->LookupCount; k++)
582 lookup_gsub (otf, lookup_list,
583 rule->LookupRecord[k].LookupListIndex,
585 gidx + rule->LookupRecord[k].SequenceIndex,
586 alternate_subst ? alternate_subst : 2);
587 gidx += rule->GlyphCount + (gstring->used - orig_used);
591 else /* subtable->Format == 3 */
593 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
597 if (match_coverages (gstring, gidx + 1, flag,
598 context3->GlyphCount - 1,
599 context3->Coverage + 1, 1) < 0)
601 orig_used = gstring->used;
602 for (j = 0; j < context3->LookupCount; j++)
603 lookup_gsub (otf, lookup_list,
604 context3->LookupRecord[j].LookupListIndex,
606 gidx + context3->LookupRecord[j].SequenceIndex,
607 alternate_subst ? alternate_subst : 2);
608 gidx += context3->GlyphCount + (gstring->used - orig_used);
613 if (subtable->Format == 1)
615 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
616 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
620 for (j = 0; j < set->ChainRuleCount; j++)
622 OTF_ChainRule *rule = set->ChainRule + j;
624 if (gidx < rule->BacktrackGlyphCount
625 || (gidx + rule->InputGlyphCount
626 + rule->LookaheadGlyphCount) > gstring->used)
628 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
630 orig_used = gstring->used;
631 for (k = 0; k < rule->LookupCount; k++)
632 lookup_gsub (otf, lookup_list,
633 rule->LookupRecord[k].LookupListIndex,
635 gidx + rule->LookupRecord[k].SequenceIndex,
636 alternate_subst ? alternate_subst : 2);
637 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
641 else if (subtable->Format == 2)
643 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
644 OTF_ChainClassSet *set;
649 class = get_class_def (&context2->InputClassDef, g->glyph_id);
650 set = context2->ChainClassSet + class;
651 for (j = 0; j < set->ChainClassRuleCnt; j++)
653 OTF_ChainClassRule *rule = set->ChainClassRule + j;
656 if (gidx < rule->BacktrackGlyphCount
657 || (gidx + rule->InputGlyphCount
658 + rule->LookaheadGlyphCount) > gstring->used)
660 if (match_chain_classes (gstring, gidx, flag,
661 &context2->BacktrackClassDef,
662 &context2->InputClassDef,
663 &context2->LookaheadClassDef,
666 orig_used = gstring->used;
667 for (k = 0; k < rule->LookupCount; k++)
668 lookup_gsub (otf, lookup_list,
669 rule->LookupRecord[k].LookupListIndex,
671 gidx + rule->LookupRecord[k].SequenceIndex,
672 alternate_subst ? alternate_subst : 2);
673 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
679 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
683 if (gidx < context3->BacktrackGlyphCount
684 || (gidx + context3->InputGlyphCount
685 + context3->LookaheadGlyphCount) > gstring->used)
687 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
689 orig_used = gstring->used;
690 for (j = 0; j < context3->LookupCount; j++)
691 lookup_gsub (otf, lookup_list,
692 context3->LookupRecord[j].LookupListIndex,
694 gidx + context3->LookupRecord[j].SequenceIndex,
695 alternate_subst ? alternate_subst : 2);
696 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
702 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
703 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
704 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
707 if (back_gidx > gstring->used || ahead_gidx < 0)
710 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
711 if (get_coverage_index (reverse->Backtrack + j,
712 gstring->glyphs[gidx + 1 + j].glyph_id)
715 if (j < reverse->BacktrackGlyphCount)
717 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
718 if (get_coverage_index (reverse->LookAhead + j,
719 gstring->glyphs[gidx - 1 - j].glyph_id)
722 if (j < reverse->LookaheadGlyphCount)
724 g->glyph_id = reverse->Substitute[coverage_idx];
725 g->positioning_type = 1;
741 gstring_insert_for_gpos (OTF_GlyphString *gstring, int gidx)
744 int orig_gidx = gidx++;
746 while (gidx < gstring->used
747 && ! gstring->glyphs[gidx].glyph_id
748 && (gstring->glyphs[gidx].positioning_type & 0xF))
750 GSTRING_INSERT (gstring, gidx, 1);
751 gstring->glyphs[gidx] = gstring->glyphs[orig_gidx];
752 gstring->glyphs[gidx].glyph_id = 0;
757 print_anchor (char *head, OTF_Anchor *anchor)
759 if (anchor->AnchorFormat == 1)
760 fprintf (stderr, " %s(X:%d Y:%d)", head,
761 anchor->XCoordinate, anchor->YCoordinate);
762 else if (anchor->AnchorFormat == 2)
763 fprintf (stderr, " %s(X:%d Y:%d AP:%d)", head,
764 anchor->XCoordinate, anchor->YCoordinate,
765 anchor->f.f1.AnchorPoint);
767 fprintf (stderr, " %s(X:%d Y:%d +alpha)", head,
768 anchor->XCoordinate, anchor->YCoordinate);
772 print_glyph_positioning (OTF_Glyph *g, int type)
775 fprintf (stderr, " %0X=", g->glyph_id);
776 switch (g->positioning_type & 0xF)
780 int format = g->f.f1.format;
782 if (format & OTF_XPlacement)
783 fprintf (stderr, "X:%d", g->f.f1.value->XPlacement);
784 if (format & OTF_XPlaDevice)
785 fprintf (stderr, "+alpha");
786 if (format & OTF_YPlacement)
787 fprintf (stderr, "Y:%d", g->f.f1.value->YPlacement);
788 if (format & OTF_YPlaDevice)
789 fprintf (stderr, "+alpha");
790 if (format & OTF_XAdvance)
791 fprintf (stderr, "X+:%d", g->f.f1.value->XAdvance);
792 if (format & OTF_XAdvDevice)
793 fprintf (stderr, "+alpha");
797 print_anchor ("entry", g->f.f3.entry_anchor);
798 print_anchor ("exit", g->f.f3.entry_anchor);
801 print_anchor ("mark", g->f.f4.mark_anchor);
802 print_anchor ("base", g->f.f4.base_anchor);
805 print_anchor ("mark", g->f.f5.mark_anchor);
806 print_anchor ("lig", g->f.f5.ligature_anchor);
809 print_anchor ("mark1", g->f.f6.mark1_anchor);
810 print_anchor ("mark2", g->f.f6.mark2_anchor);
815 /* See the comment of lookup_gsub. */
818 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
819 OTF_GlyphString *gstring, int gidx, int accumulate)
821 char *errfmt = "GPOS Looking up%s";
823 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
824 unsigned int flag = (lookup->LookupFlag
825 & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
826 int orig_gidx = gidx;
827 OTF_Glyph *g = gstring->glyphs + gidx;
831 fprintf (stderr, "[GPOS] glyph:%04X lookup:%02d",
832 g->glyph_id, lookup_list_index);
833 if (IGNORED_GLYPH (g, flag))
836 fprintf (stderr, " glyph ignored\n");
840 /* Try all subtables until one of them handles the current glyph. */
841 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
843 unsigned lookup_type = lookup->LookupType;
844 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
846 int positioning_type;
847 enum OTF_ValueFormat format;
848 OTF_ValueRecord *value;
849 OTF_Anchor *anchor1, *anchor2;
851 if (lookup_type == 9)
853 OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
855 lookup_type = extension1->ExtensionLookupType;
856 subtable = extension1->ExtensionSubtable;
860 fprintf (stderr, "/%d", lookup_type);
861 if (subtable->Coverage.offset)
863 coverage_idx = get_coverage_index (&subtable->Coverage,
865 if (coverage_idx < 0)
872 if (subtable->Format == 1)
874 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
876 format = single1->ValueFormat;
877 value = &single1->Value;
879 else if (subtable->Format == 2)
881 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
883 format = single2->ValueFormat;
884 value = single2->Value + coverage_idx;
886 if (accumulate && (g->positioning_type & 0xF))
888 gidx = gstring_insert_for_gpos (gstring, gidx);
889 g = gstring->glyphs + gidx;
892 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
893 g->f.f1.format = format;
894 g->f.f1.value = value;
896 print_glyph_positioning (g, 0);
905 for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
906 next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
907 next_gidx++, nextg++);
909 if (next_gidx >= gstring->used)
911 if (subtable->Format == 1)
913 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
914 OTF_PairSet *set = pair1->PairSet + coverage_idx;
917 for (j = 0; j < set->PairValueCount; j++)
918 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
920 if (pair1->ValueFormat1)
922 if (accumulate && (g->positioning_type & 0xF))
924 gidx = gstring_insert_for_gpos (gstring, gidx);
925 g = gstring->glyphs + gidx;
926 next_gidx += gidx - orig_gidx;
927 nextg = gstring->glyphs + next_gidx;
930 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
931 g->f.f2.format = pair1->ValueFormat1;
932 g->f.f2.value = &set->PairValueRecord[j].Value1;
934 print_glyph_positioning (g, 1);
938 if (pair1->ValueFormat2)
940 if (accumulate && (g->positioning_type & 0xF))
942 gidx = gstring_insert_for_gpos (gstring, gidx);
943 g = gstring->glyphs + gidx;
946 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
947 g->f.f2.format = pair1->ValueFormat2;
948 g->f.f2.value = &set->PairValueRecord[j].Value2;
950 print_glyph_positioning (g, 2);
955 else if (subtable->Format == 2)
957 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
958 unsigned class1, class2;
960 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
961 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
962 if (pair2->ValueFormat1)
964 if (accumulate && (g->positioning_type & 0xF))
966 gidx = gstring_insert_for_gpos (gstring, gidx);
967 g = gstring->glyphs + gidx;
968 next_gidx += gidx - orig_gidx;
969 nextg = gstring->glyphs + next_gidx;
972 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
973 g->f.f2.format = pair2->ValueFormat1;
975 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
977 print_glyph_positioning (g, 1);
981 if (pair2->ValueFormat2)
983 if (accumulate && (g->positioning_type & 0xF))
985 gidx = gstring_insert_for_gpos (gstring, gidx);
986 g = gstring->glyphs + gidx;
989 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
990 g->f.f2.format = pair2->ValueFormat2;
992 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
994 print_glyph_positioning (g, 2);
1002 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
1005 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
1006 g->f.f3.entry_anchor
1007 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
1009 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
1011 print_glyph_positioning (g, 0);
1019 if (subtable->Format == 1)
1021 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
1022 OTF_MarkRecord *mark_record;
1023 OTF_AnchorRecord *base_record;
1025 int coverage_idx_base;
1026 unsigned int this_flag = flag | OTF_IgnoreMarks;
1029 baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
1031 if (baseg < gstring->glyphs)
1034 = get_coverage_index (&mark_base1->BaseCoverage,
1036 if (coverage_idx_base < 0)
1038 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
1040 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
1041 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
1043 = &base_record->Anchor[mark_record->Class];
1045 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
1047 print_glyph_positioning (g, 0);
1055 if (subtable->Format == 1)
1057 OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
1059 int coverage_idx_lig;
1060 OTF_MarkRecord *mark_record;
1061 OTF_LigatureAttach *attach;
1062 int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
1065 for (j = 0; j < mark_lig1->ClassCount; j++)
1069 (ligg >= gstring->glyphs
1070 && (IGNORED_GLYPH (ligg, flag)
1071 || ligg->GlyphClass > OTF_GlyphClassLigature));
1073 if ((ligg->positioning_type & 0xF) == 5
1074 && ligg->MarkAttachClass < mark_lig1->ClassCount)
1075 num_class[ligg->MarkAttachClass]++;
1076 if (ligg < gstring->glyphs)
1079 = get_coverage_index (&mark_lig1->LigatureCoverage,
1081 if (coverage_idx_lig < 0)
1083 mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
1084 g->MarkAttachClass = mark_record->Class;
1085 attach = (mark_lig1->LigatureArray.LigatureAttach
1086 + coverage_idx_lig);
1087 for (j = 0; j < attach->ComponentCount; j++)
1089 OTF_Anchor *lig_anchor
1090 = attach->ComponentRecord[j].LigatureAnchor;
1092 if (lig_anchor[mark_record->Class].AnchorFormat
1093 && num_class[mark_record->Class]-- == 0)
1096 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
1097 g->f.f5.mark_anchor = &mark_record->MarkAnchor;
1098 g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
1100 print_glyph_positioning (g, 0);
1111 if (subtable->Format == 1)
1113 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
1114 OTF_MarkRecord *mark1_record;
1115 OTF_AnchorRecord *mark2_record;
1117 int coverage_idx_base;
1120 prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
1122 if (prevg < gstring->glyphs)
1125 = get_coverage_index (&mark_mark1->Mark2Coverage,
1127 if (coverage_idx_base < 0)
1129 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
1131 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
1132 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
1133 g->f.f6.mark2_anchor
1134 = &mark2_record->Anchor[mark1_record->Class];
1136 = (g->positioning_type & 0xFFFFFFF0) | lookup_type;
1138 print_glyph_positioning (g, 0);
1145 if (subtable->Format == 1)
1147 OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1148 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1153 for (j = 0; j < set->RuleCount; j++)
1155 rule = set->Rule + j;
1156 if (match_ids (gstring, gidx + 1, flag,
1157 rule->GlyphCount - 1, rule->Input, 1) < 0)
1159 orig_used = gstring->used;
1160 for (k = 0; k < rule->LookupCount; k++)
1161 lookup_gpos (lookup_list,
1162 rule->LookupRecord[k].LookupListIndex,
1164 gidx + rule->LookupRecord[k].SequenceIndex,
1166 gidx += rule->GlyphCount + (gstring->used - orig_used);
1170 else if (subtable->Format == 2)
1172 OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1174 OTF_ClassRule *rule;
1179 class = get_class_def (&context2->ClassDef, g->glyph_id);
1180 set = context2->ClassSet + class;
1182 for (j = 0; j < set->ClassRuleCnt; j++)
1184 rule = set->ClassRule + j;
1185 if (match_classes (&context2->ClassDef,
1186 gstring, gidx + 1, flag,
1187 rule->GlyphCount - 1, rule->Class, 1)
1190 orig_used = gstring->used;
1191 for (k = 0; k < rule->LookupCount; k++)
1192 lookup_gpos (lookup_list,
1193 rule->LookupRecord[k].LookupListIndex,
1195 gidx + rule->LookupRecord[k].SequenceIndex,
1197 gidx += rule->GlyphCount + (gstring->used - orig_used);
1201 else /* subtable->Format == 3 */
1203 OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1207 if (match_coverages (gstring, gidx + 1, flag,
1208 context3->GlyphCount - 1,
1209 context3->Coverage + 1, 1) < 0)
1211 orig_used = gstring->used;
1212 for (j = 0; j < context3->LookupCount; j++)
1213 lookup_gpos (lookup_list,
1214 context3->LookupRecord[j].LookupListIndex,
1216 gidx + context3->LookupRecord[j].SequenceIndex,
1218 gidx += context3->GlyphCount + (gstring->used - orig_used);
1223 if (subtable->Format == 1)
1225 OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1226 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1230 for (j = 0; j < set->ChainRuleCount; j++)
1232 OTF_ChainRule *rule = set->ChainRule + j;
1234 if (gidx < rule->BacktrackGlyphCount
1235 || (gidx + rule->InputGlyphCount
1236 + rule->LookaheadGlyphCount) > gstring->used)
1238 if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1240 orig_used = gstring->used;
1241 for (k = 0; k < rule->LookupCount; k++)
1242 lookup_gpos (lookup_list,
1243 rule->LookupRecord[k].LookupListIndex,
1245 gidx + rule->LookupRecord[k].SequenceIndex,
1247 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1251 else if (subtable->Format == 2)
1253 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1254 OTF_ChainClassSet *set;
1259 class = get_class_def (&context2->InputClassDef, g->glyph_id);
1260 set = context2->ChainClassSet + class;
1261 for (j = 0; j < set->ChainClassRuleCnt; j++)
1263 OTF_ChainClassRule *rule = set->ChainClassRule + j;
1266 if (gidx < rule->BacktrackGlyphCount
1267 || (gidx + rule->InputGlyphCount
1268 + rule->LookaheadGlyphCount) > gstring->used)
1270 if (match_chain_classes (gstring, gidx, flag,
1271 &context2->BacktrackClassDef,
1272 &context2->InputClassDef,
1273 &context2->LookaheadClassDef,
1276 orig_used = gstring->used;
1277 for (k = 0; k < rule->LookupCount; k++)
1278 lookup_gpos (lookup_list,
1279 rule->LookupRecord[k].LookupListIndex,
1281 gidx + rule->LookupRecord[k].SequenceIndex,
1283 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1287 else if (subtable->Format == 3)
1289 OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1293 if (gidx < context3->BacktrackGlyphCount
1294 || (gidx + context3->InputGlyphCount
1295 + context3->LookaheadGlyphCount) > gstring->used)
1297 if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1299 orig_used = gstring->used;
1300 for (j = 0; j < context3->LookupCount; j++)
1301 lookup_gpos (lookup_list,
1302 context3->LookupRecord[j].LookupListIndex,
1304 gidx + context3->LookupRecord[j].SequenceIndex,
1306 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1309 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1318 if (gidx == orig_gidx)
1319 fprintf (stderr, " no match\n");
1321 fprintf (stderr, "\n");
1327 lookup_encoding_0 (int c, OTF_EncodingSubtable *sub)
1329 return ((c < 0 || c >= 256)
1331 : sub->f.f0->glyphIdArray[c]);
1335 lookup_encoding_2 (int c, OTF_EncodingSubtable *sub)
1341 lookup_encoding_4 (int c, OTF_EncodingSubtable *sub)
1344 OTF_EncodingSubtable4 *sub4;
1349 segCount = sub4->segCountX2 / 2;
1350 for (i = 0; i < segCount; i++)
1352 OTF_cmapSegment *seg = sub4->segments + i;
1354 if (c >= seg->startCount && c <= seg->endCount)
1356 if (seg->idRangeOffset == 0xFFFF)
1357 return c + seg->idDelta;
1359 return sub4->glyphIdArray[seg->idRangeOffset
1360 + (c - seg->startCount)];
1367 lookup_encoding_6 (int c, OTF_EncodingSubtable *sub)
1373 lookup_encoding_8 (int c, OTF_EncodingSubtable *sub)
1379 lookup_encoding_10 (int c, OTF_EncodingSubtable *sub)
1385 lookup_encoding_12 (int c, OTF_EncodingSubtable *sub)
1387 OTF_EncodingSubtable12 *sub12;
1388 OTF_cmapGroup *g, *gend;
1394 gend = sub12->Groups + sub12->nGroups;
1397 if (g->startCharCode <= c && c <= g->endCharCode)
1398 return (g->startGlyphID + (c - g->startCharCode));
1404 typedef unsigned (*lookup_cmap_func) (int, OTF_EncodingSubtable *);
1406 static lookup_cmap_func lookup_cmap_func_table[] =
1408 lookup_encoding_0, lookup_encoding_2, lookup_encoding_4, lookup_encoding_6,
1409 lookup_encoding_8, lookup_encoding_10, lookup_encoding_12
1413 get_GlyphID (OTF_cmap *cmap, int c)
1415 OTF_EncodingSubtable *sub;
1416 lookup_cmap_func lookupper;
1418 if (c < 0x10000 && cmap->unicode_table)
1419 return cmap->unicode_table[c];
1420 if (cmap->table_index < 0)
1422 sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1423 lookupper = lookup_cmap_func_table[sub->format / 2];
1424 return lookupper (c, sub);
1428 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1430 unsigned nRecords = sub14->nRecords;
1431 OTF_VariationSelectorRecord *record;
1434 for (i = 0; i < nRecords; i++)
1436 record = &sub14->Records[i];
1437 if (record->varSelector == c2)
1439 if (record->defaultUVSOffset)
1441 OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1442 unsigned numUVRs = record->numUnicodeValueRanges;
1443 unsigned top = numUVRs, bottom = 0, middle;
1445 if (uVRs[0].startUnicodeValue <= c1)
1447 unsigned additionalCount, startUnicodeValue;
1451 middle = (top + bottom) / 2;
1452 if (c1 < uVRs[middle].startUnicodeValue)
1454 else if (bottom == middle)
1459 startUnicodeValue = uVRs[bottom].startUnicodeValue;
1460 additionalCount = uVRs[bottom].additionalCount;
1461 if (c1 <= startUnicodeValue + additionalCount)
1462 return get_GlyphID (cmap, c1);
1465 if (record->nonDefaultUVSOffset)
1467 OTF_UVSMapping *uvsMappings = record->uvsMappings;
1468 unsigned numUVSMs = record->numUVSMappings;
1469 unsigned top = numUVSMs, bottom = 0, middle;
1471 if (uvsMappings[0].unicodeValue <= c1)
1475 middle = (top + bottom) / 2;
1476 if (c1 < uvsMappings[middle].unicodeValue)
1478 else if (bottom == middle)
1483 if (uvsMappings[bottom].unicodeValue == c1)
1484 return uvsMappings[bottom].glyphID;
1494 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1496 OTF_EncodingSubtable14 *sub14;
1497 int c1 = gstring->glyphs[idx - 1].c;
1498 int c2 = gstring->glyphs[idx].c;
1502 gstring->glyphs[idx].glyph_id = 0;
1503 for (i = 0; i < cmap->numTables; i++)
1504 if (cmap->EncodingRecord[i].subtable.format == 14)
1506 if (i == cmap->numTables)
1508 code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1511 gstring->glyphs[idx - 1].glyph_id = code;
1512 gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1514 memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1515 sizeof (OTF_Glyph) * (gstring->used - idx));
1521 /* Table of GlyphClass and MarkAttackClass.
1523 For the Nth element CHAR, CHAR and the succeeding characters
1524 (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1526 This table is generated from the General Category (GC) property of
1527 characters defined in the Unicode Character Database. */
1529 static int glyph_class_table[] =
1530 { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1531 0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1532 0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1533 0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1534 0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1535 0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1536 0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1537 0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1538 0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1539 0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1540 0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1541 0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1542 0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1543 0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1544 0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1545 0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1546 0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1547 0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1548 0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1549 0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1550 0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1551 0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1552 0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1553 0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1554 0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1555 0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1556 0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1557 0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1558 0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1560 static int get_class_def_auto (int c)
1562 static int table_size
1563 = sizeof glyph_class_table / sizeof glyph_class_table[0];
1566 if (c >= glyph_class_table[table_size - 1])
1569 high = table_size - 1;
1572 mid = (low + high) / 2;
1573 if (c < glyph_class_table[mid])
1575 else if (c >= glyph_class_table[mid + 1])
1580 return ((mid % 2) ? 3 : 1);
1588 (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1591 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1595 OTF_EncodingSubtable *sub;
1596 lookup_cmap_func lookupper;
1599 && OTF_get_table (otf, "cmap") < 0)
1603 if (cmap->table_index < 0)
1607 sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1608 lookupper = lookup_cmap_func_table[sub->format / 2];
1610 for (i = 0; i < gstring->used; i++)
1611 if (! gstring->glyphs[i].glyph_id)
1613 int c = gstring->glyphs[i].c;
1614 if (c < 32 || ! cmap->unicode_table)
1615 gstring->glyphs[i].glyph_id = 0;
1616 else if (UVS_P (c) && i > 0)
1617 check_cmap_uvs (cmap, gstring, i);
1618 else if (c < 0x10000)
1619 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1621 gstring->glyphs[i].glyph_id = lookupper (c, sub);
1628 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1629 int platform_id, int encoding_id)
1633 char *errfmt = "CMAP Looking up%s";
1635 OTF_EncodingRecord *enc;
1636 lookup_cmap_func lookupper;
1639 && OTF_get_table (otf, "cmap") < 0)
1643 for (i = 0; i < cmap->numTables; i++)
1644 if (cmap->EncodingRecord[i].platformID == platform_id
1645 && cmap->EncodingRecord[i].encodingID == encoding_id)
1647 if (i == cmap->numTables)
1648 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1649 enc = cmap->EncodingRecord + i;
1650 if (enc->subtable.format > 12)
1651 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1652 lookupper = lookup_cmap_func_table[enc->subtable.format / 2];
1654 for (i = 0; i < gstring->used; i++)
1655 if (! gstring->glyphs[i].glyph_id)
1657 int c = gstring->glyphs[i].c;
1658 if (c < 32 || ! cmap->unicode_table)
1659 gstring->glyphs[i].glyph_id = 0;
1660 else if (UVS_P (c) && i > 0)
1661 check_cmap_uvs (cmap, gstring, i);
1662 else if (c < 0x10000)
1663 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1665 gstring->glyphs[i].glyph_id = lookupper (c, &enc->subtable);
1671 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1674 && OTF_get_table (otf, "cmap") < 0)
1677 || code > otf->cmap->max_glyph_id
1678 || ! otf->cmap->decode_table)
1680 return otf->cmap->decode_table[code];
1684 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1688 OTF_EncodingSubtable14 *sub14;
1690 memset (code, 0, sizeof (OTF_GlyphID) * 256);
1692 && OTF_get_table (otf, "cmap") < 0)
1695 for (i = 0; i < cmap->numTables; i++)
1696 if (cmap->EncodingRecord[i].subtable.format == 14)
1698 if (i == cmap->numTables)
1700 sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1701 for (i = 0, n = 0; i < 256; i++)
1703 int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1705 if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1712 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1718 OTF_get_table (otf, "GDEF");
1721 if (gdef && gdef->glyph_class_def.offset)
1722 for (i = 0; i < gstring->used; i++)
1723 gstring->glyphs[i].GlyphClass
1724 = get_class_def (&gdef->glyph_class_def,
1725 gstring->glyphs[i].glyph_id);
1727 for (i = 0; i < gstring->used; i++)
1728 gstring->glyphs[i].GlyphClass
1729 = get_class_def_auto (gstring->glyphs[i].c);
1731 if (gdef->mark_attach_class_def.offset)
1732 for (i = 0; i < gstring->used; i++)
1733 gstring->glyphs[i].MarkAttachClass
1734 = get_class_def (&gdef->mark_attach_class_def,
1735 gstring->glyphs[i].glyph_id);
1741 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1742 const char *script, const char *language,
1743 const char *features,
1744 int alternate_subst, int with_log)
1746 char *errfmt = "GSUB driving%s";
1749 OTF_LangSys *LangSys;
1750 USHORT *lookup_flags;
1754 for (i = 0; i < gstring->used; i++)
1756 gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1757 gstring->glyphs[i].positioning_type = 0;
1760 if (OTF_get_table (otf, "GSUB") < 0)
1763 if (gsub->FeatureList.FeatureCount == 0
1764 || gsub->LookupList.LookupCount == 0)
1767 LangSys = get_langsys (&gsub->ScriptList, script, language);
1771 lookup_flags = alloca (sizeof (USHORT) * gsub->LookupList.LookupCount);
1773 || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1774 features, lookup_flags) < 0)
1775 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1777 for (i = 0; i < gsub->LookupList.LookupCount; i++)
1781 if (! lookup_flags[i]) continue;
1783 if (gsub->LookupList.Lookup[i].LookupType != 8)
1786 while (gidx < gstring->used)
1788 int result = lookup_gsub (otf, &gsub->LookupList, i, gstring,
1789 gidx, alternate_subst);
1793 for (; gidx < result; gidx++)
1794 gstring->glyphs[gidx].positioning_type
1795 = ((with_log && gstring->glyphs[gidx].positioning_type)
1796 ? (lookup_flags[i] << 4) : 0);
1803 gidx = gstring->used - 1;
1806 int result = lookup_gsub (otf, &gsub->LookupList, i, gstring,
1807 gidx, alternate_subst);
1811 for (; gidx > result; gidx--)
1812 gstring->glyphs[gidx].positioning_type
1813 = ((with_log && gstring->glyphs[gidx].positioning_type)
1814 ? (lookup_flags[i] << 4) : 0);
1825 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1826 const char *script, const char *language, const char *features)
1829 OTF_get_table (otf, "cmap");
1830 return OTF_drive_gsub_internal (otf, gstring, script, language, features,
1835 OTF_drive_gsub_with_log (OTF *otf, OTF_GlyphString *gstring,
1836 const char *script, const char *language,
1837 const char *features)
1840 OTF_get_table (otf, "cmap");
1841 return OTF_drive_gsub_internal (otf, gstring, script, language, features,
1846 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1847 const char *script, const char *language,
1848 const char *features,
1849 int accumulate, int with_log)
1851 char *errfmt = "GPOS driving%s";
1854 OTF_LangSys *LangSys;
1855 USHORT *lookup_flags;
1858 for (i = 0; i < gstring->used; i++)
1859 gstring->glyphs[i].positioning_type = 0;
1861 if (OTF_get_table (otf, "GPOS") < 0)
1864 if (gpos->FeatureList.FeatureCount == 0
1865 || gpos->LookupList.LookupCount == 0)
1868 LangSys = get_langsys (&gpos->ScriptList, script, language);
1872 lookup_flags = alloca (sizeof (USHORT) * gpos->LookupList.LookupCount);
1874 || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1875 features, lookup_flags) < 0)
1876 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1878 for (i = 0; i < gpos->LookupList.LookupCount; i++)
1882 if (! lookup_flags[i]) continue;
1884 while (gidx < gstring->used)
1886 int result = lookup_gpos (&gpos->LookupList, i, gstring, gidx,
1891 for (; gidx < result; gidx++)
1893 int positioning_type
1894 = gstring->glyphs[gidx].positioning_type & 0xF;
1896 if (with_log && positioning_type)
1897 gstring->glyphs[gidx].positioning_type
1898 = positioning_type | (lookup_flags[i] << 4);
1909 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1910 const char *script, const char *language, const char *features)
1913 OTF_get_table (otf, "cmap");
1914 return OTF_drive_gpos_internal (otf, gstring, script, language, features,
1919 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1920 const char *script, const char *language, const char *features)
1923 OTF_get_table (otf, "cmap");
1924 return OTF_drive_gpos_internal (otf, gstring, script, language, features,
1929 OTF_drive_gpos_with_log (OTF *otf, OTF_GlyphString *gstring,
1930 const char *script, const char *language,
1931 const char *features)
1934 OTF_get_table (otf, "cmap");
1935 return OTF_drive_gpos_internal (otf, gstring, script, language, features,
1940 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1941 const char *script, const char *language,
1942 const char *gsub_features, const char *gpos_features)
1944 if (OTF_drive_cmap (otf, gstring) < 0)
1946 if (OTF_drive_gdef (otf, gstring) < 0)
1949 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1952 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1958 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1959 const char *script, const char *language,
1960 const char *features)
1962 return OTF_drive_gsub_internal (otf, gstring, script, language, features,
1967 iterate_coverage (OTF *otf, const char *feature,
1968 OTF_Feature_Callback callback,
1969 OTF_Coverage *coverage)
1973 if (coverage->CoverageFormat == 1)
1975 for (i = 0; i < coverage->Count; i++)
1976 if (callback (otf, feature, coverage->table.GlyphArray[i]) < 0)
1981 for (i = 0; i < coverage->Count; i++)
1983 OTF_RangeRecord *range = coverage->table.RangeRecord + i;
1985 for (id = range->Start; id <= range->End; id++)
1986 if (callback (otf, feature, id) < 0)
1994 iterate_feature (OTF *otf, const char *feature,
1995 OTF_Feature_Callback callback,
2000 for (i = 0; i < lookup->SubTableCount; i++)
2002 unsigned lookup_type = lookup->LookupType;
2003 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
2005 if (lookup_type == 7)
2007 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
2009 lookup_type = extension1->ExtensionLookupType;
2010 subtable = extension1->ExtensionSubtable;
2013 if ((lookup_type >= 1 && lookup_type <= 3) || lookup_type == 8)
2015 if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
2019 else if (lookup_type == 4)
2021 OTF_GSUB_Ligature1 *lig1;
2023 if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
2026 lig1 = &subtable->u.ligature1;
2027 for (j = 0; j < lig1->LigSetCount; j++)
2029 OTF_LigatureSet *ligset = lig1->LigatureSet + j;
2031 for (k = 0; k < ligset->LigatureCount; k++)
2033 OTF_Ligature *lig = ligset->Ligature + k;
2034 for (l = 0; l < lig->CompCount - 1; l++)
2035 if (callback (otf, feature, lig->Component[l]) < 0)
2040 else if (lookup_type == 6)
2042 if (subtable->Format == 1)
2044 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
2045 for (j = 0; j < context1->ChainRuleSetCount; j++)
2047 OTF_ChainRuleSet *set = context1->ChainRuleSet + j;
2048 for (k = 0; k < set->ChainRuleCount; k++)
2050 OTF_ChainRule *rule = set->ChainRule + k;
2051 for (l = 0; l < rule->LookupCount; l++)
2054 = (otf->gsub->LookupList.Lookup
2055 + rule->LookupRecord[l].LookupListIndex);
2056 if (iterate_feature (otf, feature, callback, lkup)
2063 else if (subtable->Format == 2)
2065 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
2067 for (j = 0; j < context2->ChainClassSetCnt; j++)
2069 OTF_ChainClassSet *set = context2->ChainClassSet + j;
2070 for (k = 0; k < set->ChainClassRuleCnt; j++)
2072 OTF_ChainClassRule *rule = set->ChainClassRule + k;
2074 for (l = 0; l < rule->LookupCount; l++)
2077 = (otf->gsub->LookupList.Lookup
2078 + rule->LookupRecord[k].LookupListIndex);
2079 if (iterate_feature (otf, feature, callback, lkup)
2088 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
2089 for (j = 0; j < context3->LookupCount; j++)
2092 = (otf->gsub->LookupList.Lookup
2093 + context3->LookupRecord[j].LookupListIndex);
2094 if (iterate_feature (otf, feature, callback, lkup) < 0)
2104 OTF_iterate_gsub_feature (OTF *otf, OTF_Feature_Callback callback,
2105 const char *script, const char *language,
2106 const char *feature)
2108 char *errfmt = "GSUB iterate feature%s";
2113 OTF_LangSys *langsys;
2114 USHORT *lookup_flags;
2116 if (OTF_get_table (otf, "GSUB") < 0)
2119 if (gsub->FeatureList.FeatureCount == 0
2120 || gsub->LookupList.LookupCount == 0)
2122 langsys = get_langsys (&gsub->ScriptList, script, language);
2125 lookup_flags = alloca (sizeof (USHORT) * gsub->LookupList.LookupCount);
2127 || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, langsys,
2128 feature, lookup_flags) < 0)
2129 OTF_ERROR (OTF_ERROR_MEMORY, " feature");
2131 for (i = 0; i < gsub->LookupList.LookupCount; i++)
2132 if (lookup_flags[i])
2133 if (iterate_feature (otf, feature, callback, gsub->LookupList.Lookup + i)