1 /* otfdrive.c -- OpenType font driver.
3 Copyright (C) 2003, 2004
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H15PRO167
7 This file is part of libotf.
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA. */
32 #define GSTRING_DELETE(gstring, from, len) \
34 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
35 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
36 gstring->used -= len; \
40 #define GSTRING_INSERT(gstring, pos, len) \
42 if (gstring->used + len > gstring->size) \
44 char *errfmt = "GSTRING%s"; \
46 gstring->size = gstring->used + len; \
47 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
49 if (! gstring->glyphs) \
50 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
52 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
53 sizeof (OTF_Glyph) * (gstring->used - pos)); \
54 gstring->used += len; \
59 gstring_subst (OTF_GlyphString *gstring, int from, int to,
60 OTF_GlyphID *ids, int num)
67 GSTRING_INSERT (gstring, from, (num - len));
69 GSTRING_DELETE (gstring, from, (len - num));
70 for (i = 0; i < num; i++)
71 gstring->glyphs[from + i].glyph_id = ids[i];
77 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
81 if (coverage->CoverageFormat == 1)
83 for (i = 0; i < coverage->Count; i++)
84 if (coverage->table.GlyphArray[i] == id)
89 for (i = 0; i < coverage->Count; i++)
90 if (coverage->table.RangeRecord[i].Start <= id
91 && coverage->table.RangeRecord[i].End >= id)
92 return (coverage->table.RangeRecord[i].StartCoverageIndex
93 + (id - coverage->table.RangeRecord[i].Start));
99 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
101 if (class_def->ClassFormat == 1)
103 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
105 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
106 return class_def->f.f1.ClassValueArray[idx];
112 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
113 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
114 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
115 return class_def->f.f2.ClassRangeRecord[i].Class;
121 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
124 OTF_Tag script_tag = OTF_tag (script);
125 OTF_Tag langsys_tag = OTF_tag (language);
128 for (i = 0; i < script_list->ScriptCount; i++)
129 if (script_list->Script[i].ScriptTag == script_tag)
131 OTF_Script *script = script_list->Script + i;
134 return &script->DefaultLangSys;
135 for (j = 0; j < script->LangSysCount; j++)
136 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
137 return script->LangSys + j;
138 return &script->DefaultLangSys;
145 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
146 char *features, int *lookup_indices)
149 OTF_Feature *feature;
150 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
152 for (i = 0; i < FeatureList->FeatureCount; i++)
153 feature_table[i] = 0;
161 if (*features == '*')
163 /* Consume all remaining features. */
164 /* We are sure that the last LookupCount elements of
165 lookup_indices are free to be used for this work. */
166 int *free_table = (lookup_indices + (LookupList->LookupCount
167 * FeatureList->FeatureCount));
169 for (i = 0; i < LookupList->LookupCount; i++)
171 for (i = 0; i < FeatureList->FeatureCount; i++)
172 if (! feature_table[i])
174 feature = FeatureList->Feature + i;
175 for (j = 0; j < feature->LookupCount; j++)
176 free_table[feature->LookupListIndex[j]] = 1;
178 for (i = 0; i < LookupList->LookupCount; i++)
180 lookup_indices[n++] = i;
184 if (*features == '~')
185 negate = 1, features++;
186 for (i = 0; *features && *features != ','; i++, features++)
187 tagname[i] = *features;
193 tag = OTF_tag (tagname);
194 for (i = 0; i < FeatureList->FeatureCount; i++)
196 feature = FeatureList->Feature + i;
197 if (tag == feature->FeatureTag)
200 for (j = 0; j < feature->LookupCount; j++)
201 lookup_indices[n++] = feature->LookupListIndex[j];
202 feature_table[i] = 1;
212 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
214 OTF_Glyph *gbeg = gstring->glyphs + gidx;
215 OTF_Glyph *gend = gstring->glyphs + gstring->used;
219 for (g = gbeg, i = 0; g < gend && i < count; g++)
220 if (g->glyph_id && g->glyph_id != ids[i++])
222 return (i < count ? -1 : g - gbeg);
226 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
228 int i = rule->BacktrackGlyphCount;
234 for (j = gidx - 1; j >= 0; j--)
235 if (gstring->glyphs[j].glyph_id
240 if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
245 i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
249 i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
256 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
257 int count, unsigned *classes)
259 OTF_Glyph *gbeg = gstring->glyphs + gidx;
260 OTF_Glyph *gend = gstring->glyphs + gstring->used;
264 for (g = gbeg, i = 0; g < gend && i < count; g++)
266 && get_class_def (class_def, g->glyph_id) != classes[i++])
268 return (i < count ? -1 : g - gbeg);
272 match_chain_classes (OTF_GlyphString *gstring, int gidx,
273 OTF_ClassDef *BacktrackClassDef,
274 OTF_ClassDef *InputClassDef,
275 OTF_ClassDef *LookaheadClassDef,
276 OTF_ChainClassRule *rule)
278 int i = rule->BacktrackGlyphCount;
284 for (j = gidx - 1; j >= 0 && i > 0; j--)
285 if (gstring->glyphs[j].glyph_id
290 if (match_classes (BacktrackClassDef, gstring, j,
291 rule->BacktrackGlyphCount, rule->Backtrack) < 0);
295 i = match_classes (InputClassDef, gstring, gidx,
296 rule->InputGlyphCount - 1, rule->Input);
300 i = match_classes (LookaheadClassDef, gstring, gidx,
301 rule->LookaheadGlyphCount, rule->LookAhead);
309 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
310 OTF_Coverage *coverages)
312 OTF_Glyph *gbeg = gstring->glyphs + gidx;
313 OTF_Glyph *gend = gstring->glyphs + gstring->used;
317 for (g = gbeg, i = 0; g < gend && i < count; g++)
319 && get_coverage_index (coverages + i++, g->glyph_id) < 0)
321 return (i < count ? -1 : g - gbeg);
325 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
326 OTF_GSUB_ChainContext3 *context3)
328 int i = context3->BacktrackGlyphCount;
334 for (j = gidx - 1; j >= 0; j--)
335 if (gstring->glyphs[j].glyph_id
340 if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
341 context3->Backtrack) < 0)
345 if (context3->InputGlyphCount > 1)
347 i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
348 context3->Input + 1);
353 if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
354 context3->LookAhead) < 0)
360 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
361 OTF_GlyphString *gstring, int gidx)
363 char *errfmt = "GSUB Looking up%s";
365 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
366 unsigned int flag = lookup->LookupFlag;
367 int orig_gidx = gidx;
368 OTF_Glyph *g = gstring->glyphs + gidx;
373 && (flag & (1 << g->GlyphClass))))
376 /* Try all subtables until one of them handles the current glyph. */
377 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
379 unsigned lookup_type = lookup->LookupType;
380 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
383 if (lookup_type == 7)
385 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
387 lookup_type = extension1->ExtensionLookupType;
388 subtable = extension1->ExtensionSubtable;
391 if (subtable->Coverage.offset)
393 coverage_idx = get_coverage_index (&subtable->Coverage,
395 if (coverage_idx < 0)
399 switch (lookup->LookupType)
402 if (subtable->Format == 1)
403 g->glyph_id += subtable->u.single1.DeltaGlyphID;
405 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
411 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
412 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
414 gstring_subst (gstring, gidx, gidx + 1,
415 seq->Substitute, seq->GlyphCount);
416 gidx += seq->GlyphCount;
421 if (subtable->Format == 1)
423 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
424 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
426 g->glyph_id = altset->Alternate[0];
430 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
434 if (subtable->Format == 1)
436 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
437 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
441 for (j = 0; j < ligset->LigatureCount; j++)
445 lig = ligset->Ligature + j;
446 n = match_ids (gstring, gidx + 1,
447 lig->CompCount - 1, lig->Component);
450 gstring_subst (gstring, gidx, gidx + 1 + n,
457 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
461 if (subtable->Format == 1)
463 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
464 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
469 for (j = 0; j < set->RuleCount; j++)
471 rule = set->Rule + j;
472 if (match_ids (gstring, gidx + 1,
473 rule->GlyphCount - 1, rule->Input) < 0)
475 orig_used = gstring->used;
476 for (k = 0; k < rule->LookupCount; k++)
477 lookup_gsub (lookup_list,
478 rule->LookupRecord[k].LookupListIndex,
480 gidx + rule->LookupRecord[k].SequenceIndex);
481 gidx += rule->GlyphCount + (gstring->used - orig_used);
485 else if (subtable->Format == 2)
487 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
494 class = get_class_def (&context2->ClassDef, g->glyph_id);
495 set = context2->ClassSet + class;
497 for (j = 0; j < set->ClassRuleCnt; j++)
499 rule = set->ClassRule + j;
500 if (match_classes (&context2->ClassDef,
502 rule->GlyphCount - 1, rule->Class)
505 orig_used = gstring->used;
506 for (k = 0; k < rule->LookupCount; k++)
507 lookup_gsub (lookup_list,
508 rule->LookupRecord[k].LookupListIndex,
510 gidx + rule->LookupRecord[k].SequenceIndex);
511 gidx += rule->GlyphCount + (gstring->used - orig_used);
515 else /* subtable->Format == 3 */
517 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
521 if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
522 context3->Coverage + 1) < 0)
524 orig_used = gstring->used;
525 for (j = 0; j < context3->LookupCount; j++)
526 lookup_gsub (lookup_list,
527 context3->LookupRecord[j].LookupListIndex,
529 gidx + context3->LookupRecord[j].SequenceIndex);
530 gidx += context3->GlyphCount + (gstring->used - orig_used);
535 if (subtable->Format == 1)
537 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
538 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
542 for (j = 0; j < set->ChainRuleCount; j++)
544 OTF_ChainRule *rule = set->ChainRule + j;
546 if (gidx < rule->BacktrackGlyphCount
547 || (gidx + rule->InputGlyphCount
548 + rule->LookaheadGlyphCount) > gstring->used)
550 if (match_chain_ids (gstring, gidx, rule) < 0)
552 orig_used = gstring->used;
553 for (k = 0; k < rule->LookupCount; k++)
554 lookup_gsub (lookup_list,
555 rule->LookupRecord[k].LookupListIndex,
557 gidx + rule->LookupRecord[k].SequenceIndex);
558 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
562 else if (subtable->Format == 2)
564 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
565 OTF_ChainClassSet *set;
570 class = get_class_def (&context2->InputClassDef, g->glyph_id);
571 set = context2->ChainClassSet + class;
572 for (j = 0; j < set->ChainClassRuleCnt; j++)
574 OTF_ChainClassRule *rule = set->ChainClassRule + j;
577 if (gidx < rule->BacktrackGlyphCount
578 || (gidx + rule->InputGlyphCount
579 + rule->LookaheadGlyphCount) > gstring->used)
581 if (match_chain_classes (gstring, gidx,
582 &context2->BacktrackClassDef,
583 &context2->InputClassDef,
584 &context2->LookaheadClassDef,
587 orig_used = gstring->used;
588 for (k = 0; k < rule->LookupCount; k++)
589 lookup_gsub (lookup_list,
590 rule->LookupRecord[k].LookupListIndex,
592 gidx + rule->LookupRecord[k].SequenceIndex);
593 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
599 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
603 if (gidx < context3->BacktrackGlyphCount
604 || (gidx + context3->InputGlyphCount
605 + context3->LookaheadGlyphCount) > gstring->used)
607 if (match_chain_coverages (gstring, gidx, context3) < 0)
609 orig_used = gstring->used;
610 for (j = 0; j < context3->LookupCount; j++)
611 lookup_gsub (lookup_list,
612 context3->LookupRecord[j].LookupListIndex,
614 gidx + context3->LookupRecord[j].SequenceIndex);
615 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
621 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
622 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
623 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
626 if (back_gidx > gstring->used || ahead_gidx < 0)
629 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
630 if (get_coverage_index (reverse->Backtrack + j,
631 gstring->glyphs[gidx + 1 + j].glyph_id)
634 if (j < reverse->BacktrackGlyphCount)
636 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
637 if (get_coverage_index (reverse->LookAhead + j,
638 gstring->glyphs[gidx - 1 - j].glyph_id)
641 if (j < reverse->LookaheadGlyphCount)
643 g->glyph_id = reverse->Substitute[coverage_idx];
651 if (gidx == orig_gidx)
660 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
662 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
664 rec->XPlacement = anchor->XCoordinate;
665 rec->YPlacement = anchor->YCoordinate;
666 if (anchor->AnchorFormat == 1)
669 else if (anchor->AnchorFormat == 2)
670 /* Not yet implemented */
672 else if (anchor->AnchorFormat == 3)
673 /* Not yet implemented */
680 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
681 OTF_GlyphString *gstring, int gidx)
683 char *errfmt = "GPOS Looking up%s";
685 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
686 unsigned int flag = lookup->LookupFlag;
687 int orig_gidx = gidx;
688 OTF_Glyph *g = gstring->glyphs + gidx;
693 && (flag & (1 << g->GlyphClass))))
696 /* Try all subtables until one of them handles the current glyph. */
697 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
699 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
702 if (subtable->Coverage.offset)
704 coverage_idx = get_coverage_index (&subtable->Coverage,
706 if (coverage_idx < 0)
710 switch (lookup->LookupType)
713 g->positioning_type = lookup->LookupType;
714 if (subtable->Format == 1)
716 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
718 g->f.f1.format = single1->ValueFormat;
719 g->f.f1.value = &single1->Value;
721 else if (subtable->Format == 2)
723 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
725 g->f.f1.format = single2->ValueFormat;
726 g->f.f1.value = single2->Value + coverage_idx;
732 int next_gidx = gidx + 1;
735 while (next_gidx < gstring->used
736 && ! gstring->glyphs[next_gidx].glyph_id)
739 if (next_gidx >= gstring->used)
741 nextg = gstring->glyphs + next_gidx;
742 if (subtable->Format == 1)
744 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
745 OTF_PairSet *set = pair1->PairSet + coverage_idx;
748 for (j = 0; j < set->PairValueCount; j++)
749 if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
751 if (pair1->ValueFormat1)
753 g->positioning_type = lookup->LookupType;
754 g->f.f2.format = pair1->ValueFormat1;
755 g->f.f2.value = &set->PairValueRecord[j].Value1;
758 if (pair1->ValueFormat2)
760 nextg->positioning_type = lookup->LookupType;
761 nextg->f.f2.format = pair1->ValueFormat2;
762 nextg->f.f2.value = &set->PairValueRecord[j].Value2;
768 else if (subtable->Format == 2)
770 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
771 unsigned class1, class2;
773 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
774 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
775 if (pair2->ValueFormat1)
777 g->positioning_type = lookup->LookupType;
778 g->f.f2.format = pair2->ValueFormat1;
780 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
783 if (pair2->ValueFormat2)
785 nextg->positioning_type = lookup->LookupType;
786 nextg->f.f2.format = pair2->ValueFormat2;
788 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
797 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
799 g->positioning_type = lookup->LookupType;
801 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
803 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
810 if (subtable->Format == 1)
812 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
813 OTF_MarkRecord *mark_record;
814 OTF_AnchorRecord *base_record;
815 int coverage_idx_base
816 = get_coverage_index (&mark_base1->BaseCoverage,
819 if (coverage_idx_base < 0)
821 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
823 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
824 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
826 = &base_record->Anchor[mark_record->Class];
827 g->positioning_type = lookup->LookupType;
835 if (subtable->Format == 1)
837 /* As the document of this lookup type is quite
838 ambiguous, and we can't know the exact procedure to
840 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
847 if (subtable->Format == 1)
849 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
850 OTF_MarkRecord *mark1_record;
851 OTF_AnchorRecord *mark2_record;
852 int coverage_idx_base
853 = get_coverage_index (&mark_mark1->Mark2Coverage,
856 if (coverage_idx_base < 0)
858 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
860 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
861 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
863 = &mark2_record->Anchor[mark1_record->Class];
864 g->positioning_type = lookup->LookupType;
870 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
874 if (subtable->Format == 1)
875 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
876 else if (subtable->Format == 2)
878 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
879 OTF_ChainClassSet *set;
884 class = get_class_def (&context2->InputClassDef, g->glyph_id);
885 set = context2->ChainClassSet + class;
886 for (j = 0; j < set->ChainClassRuleCnt; j++)
888 OTF_ChainClassRule *rule = set->ChainClassRule + j;
889 int fore_idx = gidx + rule->InputGlyphCount;
892 if (gidx < rule->BacktrackGlyphCount
893 || (gidx + rule->InputGlyphCount
894 + rule->LookaheadGlyphCount) > gstring->used)
896 for (k = 0; k < rule->BacktrackGlyphCount; k++)
897 if (get_class_def (&context2->BacktrackClassDef,
898 gstring->glyphs[gidx - 1 - k].glyph_id)
899 != rule->Backtrack[k])
901 if (k < rule->BacktrackGlyphCount)
903 for (k = 1; k < rule->InputGlyphCount; k++)
904 if (get_class_def (&context2->InputClassDef,
905 gstring->glyphs[gidx + k].glyph_id)
906 != rule->Input[k - 1])
908 if (k < rule->InputGlyphCount)
910 for (k = 0; k < rule->LookaheadGlyphCount; k++)
911 if (get_class_def (&context2->LookaheadClassDef,
912 gstring->glyphs[fore_idx + k].glyph_id)
913 != rule->LookAhead[k])
915 if (k < rule->LookaheadGlyphCount)
918 orig_used = gstring->used;
919 for (k = 0; k < rule->LookupCount; k++)
920 lookup_gpos (lookup_list,
921 rule->LookupRecord[k].LookupListIndex,
923 gidx + rule->LookupRecord[k].SequenceIndex);
924 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
928 else if (subtable->Format == 3)
929 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
931 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
935 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
942 if (gidx == orig_gidx)
948 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
952 for (i = 0; i < gstring->used; i++)
954 c = gstring->glyphs[i].c;
955 if (c < 0 || c >= 256)
956 gstring->glyphs[i].glyph_id = 0;
958 gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
964 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
970 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
973 int segCount = sub4->segCountX2 / 2;
975 for (i = 0; i < gstring->used; i++)
977 c = gstring->glyphs[i].c;
979 gstring->glyphs[i].glyph_id = 0;
980 for (j = 0; j < segCount; j++)
982 OTF_cmapSegument *seg = sub4->segments + i;
984 if (c >= seg->startCount && c <= seg->endCount)
986 if (seg->idRangeOffset == 0xFFFF)
987 gstring->glyphs[i].glyph_id = c + seg->idDelta;
989 gstring->glyphs[i].glyph_id
990 = sub4->glyphIdArray[seg->idRangeOffset
991 + (c - seg->startCount)];
1001 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1007 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1013 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1019 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1029 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1035 && OTF_get_table (otf, "cmap") < 0)
1039 for (i = 0; i < gstring->used; i++)
1040 if (! gstring->glyphs[i].glyph_id)
1042 int c = gstring->glyphs[i].c;
1043 if (c < 32 || ! cmap->unicode_table)
1044 gstring->glyphs[i].glyph_id = 0;
1046 gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1053 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1054 int platform_id, int encoding_id)
1058 char *errfmt = "CMAP Looking up%s";
1060 OTF_EncodingRecord *enc;
1063 && OTF_get_table (otf, "cmap") < 0)
1067 for (i = 0; i < cmap->numTables; i++)
1068 if (cmap->EncodingRecord[i].platformID == platform_id
1069 && cmap->EncodingRecord[i].encodingID == encoding_id)
1071 if (i == cmap->numTables)
1072 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1073 enc = cmap->EncodingRecord + i;
1074 switch (enc->subtable.format)
1076 case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1077 case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1078 case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1079 case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1080 case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1081 case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1082 case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1084 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1089 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1092 && OTF_get_table (otf, "cmap") < 0)
1095 || code > otf->cmap->max_glyph_id
1096 || ! otf->cmap->decode_table)
1098 return otf->cmap->decode_table[code];
1102 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1108 && OTF_get_table (otf, "GDEF") < 0)
1112 if (gdef->glyph_class_def.offset)
1113 for (i = 0; i < gstring->used; i++)
1114 gstring->glyphs[i].GlyphClass
1115 = get_class_def (&gdef->glyph_class_def,
1116 gstring->glyphs[i].glyph_id);
1118 if (gdef->mark_attach_class_def.offset)
1119 for (i = 0; i < gstring->used; i++)
1120 gstring->glyphs[i].MarkAttachClass
1121 = get_class_def (&gdef->mark_attach_class_def,
1122 gstring->glyphs[i].glyph_id);
1129 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1130 char *script, char *language, char *features)
1132 char *errfmt = "GSUB driving%s";
1135 OTF_LangSys *LangSys;
1136 int *lookup_indices;
1140 && OTF_get_table (otf, "GSUB") < 0)
1143 if (gsub->FeatureList.FeatureCount == 0
1144 || gsub->LookupList.LookupCount == 0)
1147 LangSys = get_langsys (&gsub->ScriptList, script, language);
1151 /* One lookup may be used by multiple features. */
1152 lookup_indices = alloca (sizeof (int)
1153 * gsub->LookupList.LookupCount
1154 * (gsub->FeatureList.FeatureCount + 1));
1155 if (! lookup_indices)
1156 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1157 n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1158 features, lookup_indices);
1162 for (i = 0; i < n; i++)
1164 int index = lookup_indices[i];
1167 if (gsub->LookupList.Lookup[index].LookupType != 8)
1170 while (gidx < gstring->used)
1172 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1179 gidx = gstring->used - 1;
1182 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1193 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1194 char *script, char *language, char *features)
1196 char *errfmt = "GPOS driving%s";
1199 OTF_LangSys *LangSys;
1200 int *lookup_indices;
1204 && OTF_get_table (otf, "GPOS") < 0)
1207 if (gpos->FeatureList.FeatureCount == 0
1208 || gpos->LookupList.LookupCount == 0)
1211 LangSys = get_langsys (&gpos->ScriptList, script, language);
1215 /* One lookup may be used by multiple features. */
1216 lookup_indices = alloca (sizeof (int)
1217 * gpos->LookupList.LookupCount
1218 * (gpos->FeatureList.FeatureCount + 1));
1219 if (! lookup_indices)
1220 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1221 n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1222 features, lookup_indices);
1226 for (i = 0; i < n; i++)
1228 int index = lookup_indices[i];
1231 while (gidx < gstring->used)
1233 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1243 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1244 char *script, char *language,
1245 char *gsub_features, char *gpos_features)
1247 if (OTF_drive_cmap (otf, gstring) < 0)
1249 if (OTF_drive_gdef (otf, gstring) < 0)
1252 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1255 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)