1 /* otfdrive.c -- OpenType font driver.
4 by AIST (National Institute of Advanced Industrial Science and Technology)
5 Registration Number H15PRO???
7 This file is part of the OTF library.
9 The OTF library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 The OTF library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with the OTF library; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
31 #define GSTRING_DELETE(gstring, from, len) \
33 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
34 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
35 gstring->used -= len; \
39 #define GSTRING_INSERT(gstring, pos, len) \
41 if (gstring->used + len > gstring->size) \
43 char *errfmt = "GSTRING%s"; \
45 gstring->size = gstring->used + len; \
46 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
48 if (! gstring->glyphs) \
49 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
51 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
52 sizeof (OTF_Glyph) * (gstring->used - pos)); \
53 gstring->used += len; \
58 gstring_subst (OTF_GlyphString *gstring, int from, int to,
59 OTF_GlyphID *ids, int num)
66 GSTRING_INSERT (gstring, from, (num - len));
68 GSTRING_DELETE (gstring, from, (len - num));
69 for (i = 0; i < num; i++)
70 gstring->glyphs[from + i].glyph_id = ids[i];
76 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
80 if (coverage->CoverageFormat == 1)
82 for (i = 0; i < coverage->Count; i++)
83 if (coverage->table.GlyphArray[i] == id)
88 for (i = 0; i < coverage->Count; i++)
89 if (coverage->table.RangeRecord[i].Start <= id
90 && coverage->table.RangeRecord[i].End >= id)
91 return (coverage->table.RangeRecord[i].StartCoverageIndex
92 + (id - coverage->table.RangeRecord[i].Start));
98 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
100 if (class_def->ClassFormat == 1)
102 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
104 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
105 return class_def->f.f1.ClassValueArray[idx];
111 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
112 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
113 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
114 return class_def->f.f2.ClassRangeRecord[i].Class;
120 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
123 OTF_Tag script_tag = OTF_tag (script);
124 OTF_Tag langsys_tag = OTF_tag (language);
127 for (i = 0; i < script_list->ScriptCount; i++)
128 if (script_list->Script[i].ScriptTag == script_tag)
130 OTF_Script *script = script_list->Script + i;
133 return &script->DefaultLangSys;
134 for (j = 0; j < script->LangSysCount; j++)
135 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
136 return script->LangSys + j;
137 return &script->DefaultLangSys;
144 setup_lookup_indices (OTF_LangSys *LangSys, OTF_FeatureList *FeatureList,
145 char *features, int *lookup_indices)
148 OTF_Feature *feature;
149 int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
151 for (i = 0; i < FeatureList->FeatureCount; i++)
152 feature_table[i] = 0;
159 if (*features == '*')
161 /* Consume all remaining features. */
162 for (i = 0; i < FeatureList->FeatureCount; i++)
163 if (! feature_table[i])
165 feature = FeatureList->Feature + i;
166 for (j = 0; j < feature->LookupCount; j++)
167 lookup_indices[n++] = feature->LookupListIndex[j];
172 for (i = 0; *features && *features != ','; i++, features++)
173 tagname[i] = *features;
179 tag = OTF_tag (tagname);
180 for (i = 0; i < FeatureList->FeatureCount; i++)
182 feature = FeatureList->Feature + i;
183 if (tag == feature->FeatureTag)
185 for (j = 0; j < feature->LookupCount; j++)
186 lookup_indices[n++] = feature->LookupListIndex[j];
187 feature_table[i] = 1;
197 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
201 if (gstring->used - gidx < count)
203 for (i = j = 0; i < count; i++, j++)
205 if (! gstring->glyphs[gidx + j].glyph_id)
206 /* Skip this glyph. */
208 else if (ids[i] && gstring->glyphs[gidx + i].glyph_id != ids[i])
215 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
217 if (match_ids (gstring, gidx, rule->BacktrackGlyphCount, rule->Backtrack)
220 gidx += rule->BacktrackGlyphCount + 1;
221 if (match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input)
224 gidx += rule->InputGlyphCount;
225 if (match_ids (gstring, gidx, rule->LookaheadGlyphCount - 1, rule->LookAhead)
232 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
233 int count, unsigned *classes)
237 if (gstring->used - gidx < count)
239 for (i = 0; i < count; i++)
240 if (get_class_def (class_def, gstring->glyphs[gidx + i].glyph_id)
247 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
248 OTF_GlyphString *gstring, int gidx)
250 char *errfmt = "GSUB Looking up%s";
252 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
253 unsigned int flag = lookup->LookupFlag;
254 int orig_gidx = gidx;
255 OTF_Glyph *g = gstring->glyphs + gidx;
260 && (flag & (1 << g->GlyphClass))))
263 /* Try all subtables until one of them handles the current glyph. */
264 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
266 unsigned lookup_type = lookup->LookupType;
267 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
270 if (lookup_type == 7)
272 OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
274 lookup_type = extension1->ExtensionLookupType;
275 subtable = extension1->ExtensionSubtable;
278 if (subtable->Coverage.offset)
280 coverage_idx = get_coverage_index (&subtable->Coverage,
282 if (coverage_idx < 0)
286 switch (lookup->LookupType)
289 if (subtable->Format == 1)
290 g->glyph_id += subtable->u.single1.DeltaGlyphID;
292 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
298 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
299 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
301 gstring_subst (gstring, gidx, gidx + 1,
302 seq->Substitute, seq->GlyphCount);
303 gidx += seq->GlyphCount;
308 if (subtable->Format == 1)
310 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
311 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
313 g->glyph_id = altset->Alternate[0];
317 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
321 if (subtable->Format == 1)
323 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
324 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
328 for (j = 0; j < ligset->LigatureCount; j++)
330 lig = ligset->Ligature + j;
331 if (match_ids (gstring, gidx + 1,
332 lig->CompCount - 1, lig->Component) < 0)
334 gstring_subst (gstring, gidx, gidx + lig->CompCount,
341 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
345 if (subtable->Format == 1)
347 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
348 OTF_RuleSet *set = context1->RuleSet + coverage_idx;
353 for (j = 0; j < set->RuleCount; j++)
355 rule = set->Rule + j;
356 if (match_ids (gstring, gidx + 1,
357 rule->GlyphCount - 1, rule->Input) < 0)
359 orig_used = gstring->used;
360 for (k = 0; k < rule->LookupCount; k++)
361 lookup_gsub (lookup_list,
362 rule->LookupRecord[k].LookupListIndex,
364 gidx + rule->LookupRecord[k].SequenceIndex);
365 gidx += rule->GlyphCount + (gstring->used - orig_used);
369 else if (subtable->Format == 2)
371 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
378 class = get_class_def (&context2->ClassDef, g->glyph_id);
379 set = context2->ClassSet + class;
380 for (j = 0; j < set->ClassRuleCnt; j++)
382 rule = set->ClassRule + j;
383 if (match_classes (&context2->ClassDef,
385 rule->GlyphCount - 1, rule->Class)
388 orig_used = gstring->used;
389 for (k = 0; k < rule->LookupCount; k++)
390 lookup_gsub (lookup_list,
391 rule->LookupRecord[k].LookupListIndex,
393 gidx + rule->LookupRecord[k].SequenceIndex);
394 gidx += rule->GlyphCount + (gstring->used - orig_used);
398 else /* subtable->Format == 3 */
400 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
404 if (gstring->used - gidx < context3->GlyphCount)
406 /* Start from the secoding coverage_idx because the
407 first one is the same as subtable->Coverage and thus
409 for (j = 1; j < context3->GlyphCount; j++)
410 if (get_coverage_index (context3->Coverage + j,
411 gstring->glyphs[gidx + j].glyph_id)
414 if (j < context3->GlyphCount)
416 orig_used = gstring->used;
417 for (k = 0; k < context3->LookupCount; k++)
418 lookup_gsub (lookup_list,
419 context3->LookupRecord[k].LookupListIndex,
421 gidx + context3->LookupRecord[k].SequenceIndex);
422 gidx += context3->GlyphCount + (gstring->used - orig_used);
427 if (subtable->Format == 1)
429 OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
430 OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
434 for (j = 0; j < set->ChainRuleCount; j++)
436 OTF_ChainRule *rule = set->ChainRule + j;
437 int backs = rule->BacktrackGlyphCount;
438 int inputs = rule->InputGlyphCount;
439 int aheads = rule->LookaheadGlyphCount;
441 if (gidx < backs || gidx + inputs + aheads > gstring->used)
443 if (match_chain_ids (gstring, gidx - backs, rule) < 0)
445 orig_used = gstring->used;
446 for (k = 0; k < rule->LookupCount; k++)
447 lookup_gsub (lookup_list,
448 rule->LookupRecord[k].LookupListIndex,
450 gidx + rule->LookupRecord[k].SequenceIndex);
451 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
455 else if (subtable->Format == 2)
457 OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
458 OTF_ChainClassSet *set;
463 // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
464 class = get_class_def (&context2->InputClassDef, g->glyph_id);
465 set = context2->ChainClassSet + class;
466 for (j = 0; j < set->ChainClassRuleCnt; j++)
468 OTF_ChainClassRule *rule = set->ChainClassRule + j;
469 int fore_idx = gidx + rule->InputGlyphCount;
472 if (gidx < rule->BacktrackGlyphCount
473 || (gidx + rule->InputGlyphCount
474 + rule->LookaheadGlyphCount) >= gstring->used)
476 for (k = 0; k < rule->BacktrackGlyphCount; k++)
477 if (get_class_def (&context2->BacktrackClassDef,
478 gstring->glyphs[gidx - 1 - k].glyph_id)
479 != rule->Backtrack[k])
481 if (k < rule->BacktrackGlyphCount)
483 for (k = 1; k < rule->InputGlyphCount; k++)
484 if (get_class_def (&context2->InputClassDef,
485 gstring->glyphs[gidx + k].glyph_id)
486 != rule->Input[k - 1])
488 if (k < rule->InputGlyphCount)
490 for (k = 0; k < rule->LookaheadGlyphCount; k++)
491 if (get_class_def (&context2->LookaheadClassDef,
492 gstring->glyphs[fore_idx + k].glyph_id)
493 != rule->LookAhead[k])
495 if (k < rule->LookaheadGlyphCount)
498 orig_used = gstring->used;
499 for (k = 0; k < rule->LookupCount; k++)
500 lookup_gsub (lookup_list,
501 rule->LookupRecord[k].LookupListIndex,
503 gidx + rule->LookupRecord[k].SequenceIndex);
504 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
510 OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
511 int back_gidx = gidx - context3->BacktrackGlyphCount;
512 int fore_gidx = gidx + context3->InputGlyphCount;
517 || fore_gidx + context3->LookaheadGlyphCount > gstring->used)
520 for (j = 0; j < context3->BacktrackGlyphCount; j++)
521 if (get_coverage_index (context3->Backtrack + j,
522 gstring->glyphs[gidx - 1 - j].glyph_id)
525 if (j < context3->BacktrackGlyphCount)
528 /* Start from the second coverage_idx because the first
529 one is the same as subtable->Coverage and thus
531 for (j = 1; j < context3->InputGlyphCount; j++)
532 if (get_coverage_index (context3->Input + j,
533 gstring->glyphs[gidx + j].glyph_id)
536 if (j < context3->InputGlyphCount)
539 for (j = 0; j < context3->LookaheadGlyphCount; j++)
540 if (get_coverage_index (context3->LookAhead + j,
541 gstring->glyphs[fore_gidx + j].glyph_id)
544 if (j < context3->LookaheadGlyphCount)
547 orig_used = gstring->used;
548 for (j = 0; j < context3->LookupCount; j++)
549 lookup_gsub (lookup_list,
550 context3->LookupRecord[j].LookupListIndex,
552 gidx + context3->LookupRecord[j].SequenceIndex);
553 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
559 OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
560 int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
561 int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
564 if (back_gidx > gstring->used || ahead_gidx < 0)
567 for (j = 0; j < reverse->BacktrackGlyphCount; j++)
568 if (get_coverage_index (reverse->Backtrack + j,
569 gstring->glyphs[gidx + 1 + j].glyph_id)
572 if (j < reverse->BacktrackGlyphCount)
574 for (j = 0; j < reverse->LookaheadGlyphCount; j++)
575 if (get_coverage_index (reverse->LookAhead + j,
576 gstring->glyphs[gidx - 1 - j].glyph_id)
579 if (j < reverse->LookaheadGlyphCount)
581 g->glyph_id = reverse->Substitute[coverage_idx];
589 if (gidx == orig_gidx)
591 //printf ("not applied\n");
596 // printf ("done\n");
605 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
607 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
609 rec->XPlacement = anchor->XCoordinate;
610 rec->YPlacement = anchor->YCoordinate;
611 if (anchor->AnchorFormat == 1)
614 else if (anchor->AnchorFormat == 2)
615 /* Not yet implemented */
617 else if (anchor->AnchorFormat == 3)
618 /* Not yet implemented */
625 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
626 OTF_GlyphString *gstring, int gidx)
628 char *errfmt = "GPOS Looking up%s";
630 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
631 unsigned int flag = lookup->LookupFlag;
632 int orig_gidx = gidx;
633 OTF_Glyph *g = gstring->glyphs + gidx;
638 && (flag & (1 << g->GlyphClass))))
641 /* Try all subtables until one of them handles the current glyph. */
642 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
644 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
647 // printf ("subtype:%d ", subtable->Format);
648 if (subtable->Coverage.offset)
650 coverage_idx = get_coverage_index (&subtable->Coverage,
652 if (coverage_idx < 0)
654 // printf ("not covererd ");
659 switch (lookup->LookupType)
662 g->positioning_type = lookup->LookupType;
663 if (subtable->Format == 1)
665 OTF_GPOS_Single1 *single1 = &subtable->u.single1;
667 g->f.f1.format = single1->ValueFormat;
668 g->f.f1.value = &single1->Value;
670 else if (subtable->Format == 2)
672 OTF_GPOS_Single2 *single2 = &subtable->u.single2;
674 g->f.f1.format = single2->ValueFormat;
675 g->f.f1.value = single2->Value + coverage_idx;
680 if (gidx + 1 >= gstring->used)
682 if (subtable->Format == 1)
684 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
685 OTF_PairSet *set = pair1->PairSet + coverage_idx;
688 for (j = 0; j < set->PairValueCount; j++)
690 if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
693 g->positioning_type = lookup->LookupType;
694 g->f.f2.format = pair1->ValueFormat1;
695 g->f.f2.value = &set->PairValueRecord[j].Value1;
696 if (pair1->ValueFormat2)
699 g->positioning_type = lookup->LookupType;
700 g->f.f2.format = pair1->ValueFormat2;
701 g->f.f2.value = &set->PairValueRecord[j].Value2;
705 else if (subtable->Format == 2)
707 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
708 unsigned class1, class2;
710 // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
712 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
713 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
714 g->positioning_type = lookup->LookupType;
715 g->f.f2.format = pair2->ValueFormat1;
717 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
718 if (pair2->ValueFormat2)
721 g->positioning_type = lookup->LookupType;
722 g->f.f2.format = pair2->ValueFormat2;
724 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
731 OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
733 g->positioning_type = lookup->LookupType;
735 = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
737 = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
744 if (subtable->Format == 1)
746 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
747 OTF_MarkRecord *mark_record;
748 OTF_AnchorRecord *base_record;
749 int coverage_idx_base
750 = get_coverage_index (&mark_base1->BaseCoverage,
753 if (coverage_idx_base < 0)
755 // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
756 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
758 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
759 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
761 = &base_record->Anchor[mark_record->Class];
762 g->positioning_type = lookup->LookupType;
770 if (subtable->Format == 1)
772 /* As the document of this lookup type is quite
773 ambiguous, and we can't know the exact procedure to
775 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
782 if (subtable->Format == 1)
784 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
785 OTF_MarkRecord *mark1_record;
786 OTF_AnchorRecord *mark2_record;
787 int coverage_idx_base
788 = get_coverage_index (&mark_mark1->Mark2Coverage,
791 if (coverage_idx_base < 0)
793 // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
794 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
796 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
797 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
799 = &mark2_record->Anchor[mark1_record->Class];
800 g->positioning_type = lookup->LookupType;
806 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
810 if (subtable->Format == 1)
811 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
812 else if (subtable->Format == 2)
814 OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
815 OTF_ChainClassSet *set;
820 // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
821 class = get_class_def (&context2->InputClassDef, g->glyph_id);
822 set = context2->ChainClassSet + class;
823 for (j = 0; j < set->ChainClassRuleCnt; j++)
825 OTF_ChainClassRule *rule = set->ChainClassRule + j;
826 int fore_idx = gidx + rule->InputGlyphCount;
829 if (gidx < rule->BacktrackGlyphCount
830 || (gidx + rule->InputGlyphCount
831 + rule->LookaheadGlyphCount) >= gstring->used)
833 for (k = 0; k < rule->BacktrackGlyphCount; k++)
834 if (get_class_def (&context2->BacktrackClassDef,
835 gstring->glyphs[gidx - 1 - k].glyph_id)
836 != rule->Backtrack[k])
838 if (k < rule->BacktrackGlyphCount)
840 for (k = 1; k < rule->InputGlyphCount; k++)
841 if (get_class_def (&context2->InputClassDef,
842 gstring->glyphs[gidx + k].glyph_id)
843 != rule->Input[k - 1])
845 if (k < rule->InputGlyphCount)
847 for (k = 0; k < rule->LookaheadGlyphCount; k++)
848 if (get_class_def (&context2->LookaheadClassDef,
849 gstring->glyphs[fore_idx + k].glyph_id)
850 != rule->LookAhead[k])
852 if (k < rule->LookaheadGlyphCount)
855 orig_used = gstring->used;
856 for (k = 0; k < rule->LookupCount; k++)
857 lookup_gpos (lookup_list,
858 rule->LookupRecord[k].LookupListIndex,
860 gidx + rule->LookupRecord[k].SequenceIndex);
861 gidx += rule->InputGlyphCount + (gstring->used - orig_used);
865 else if (subtable->Format == 3)
866 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
868 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
872 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
879 if (gidx == orig_gidx)
881 // printf ("not applied\n");
886 // printf ("done\n");
892 lookup_cmap (OTF_cmap *cmap, int c)
894 char *errfmt = "cmap driving%s";
898 if (! cmap || ! cmap->Unicode)
901 switch (cmap->Unicode->subtable.format)
905 OTF_EncodingSubtable4 *sub4 = cmap->Unicode->subtable.f.f4;
906 int segCount = sub4->segCountX2 / 2;
908 for (i = 0; i < segCount; i++)
909 if (c <= sub4->segments[i].endCount)
911 if (i == segCount || c < sub4->segments[i].startCount)
913 if (sub4->segments[i].idRangeOffset == 0xFFFF)
914 return c + sub4->segments[i].idDelta;
917 return sub4->glyphIdArray[sub4->segments[i].idRangeOffset
918 + (c - sub4->segments[i].startCount)];
923 OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (not yet supported)");
935 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
941 && OTF_get_table (otf, "cmap") < 0)
945 for (i = 0; i < gstring->used; i++)
947 gstring->glyphs[i].glyph_id = lookup_cmap (cmap, gstring->glyphs[i].c);
948 if (gstring->glyphs[i].glyph_id < 0)
956 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
962 && OTF_get_table (otf, "GDEF") < 0)
966 if (gdef->glyph_class_def.offset)
967 for (i = 0; i < gstring->used; i++)
968 gstring->glyphs[i].GlyphClass
969 = get_class_def (&gdef->glyph_class_def,
970 gstring->glyphs[i].glyph_id);
972 if (gdef->mark_attach_class_def.offset)
973 for (i = 0; i < gstring->used; i++)
974 gstring->glyphs[i].MarkAttachClass
975 = get_class_def (&gdef->mark_attach_class_def,
976 gstring->glyphs[i].glyph_id);
983 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
984 char *script, char *language, char *features)
986 char *errfmt = "GSUB driving%s";
989 OTF_LangSys *LangSys;
994 && OTF_get_table (otf, "GSUB") < 0)
997 if (gsub->FeatureList.FeatureCount == 0
998 || gsub->LookupList.LookupCount == 0)
1001 LangSys = get_langsys (&gsub->ScriptList, script, language);
1005 /* One lookup may be used by multiple features. */
1006 lookup_indices = alloca (sizeof (int)
1007 * gsub->LookupList.LookupCount
1008 * gsub->FeatureList.FeatureCount);
1009 if (! lookup_indices)
1010 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1011 n = setup_lookup_indices (LangSys, &gsub->FeatureList,
1012 features, lookup_indices);
1016 for (i = 0; i < n; i++)
1018 int index = lookup_indices[i];
1021 if (gsub->LookupList.Lookup[index].LookupType != 8)
1024 while (gidx < gstring->used)
1026 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1033 gidx = gstring->used - 1;
1036 gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1047 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1048 char *script, char *language, char *features)
1050 char *errfmt = "GPOS driving%s";
1053 OTF_LangSys *LangSys;
1054 int *lookup_indices;
1058 && OTF_get_table (otf, "GPOS") < 0)
1061 if (gpos->FeatureList.FeatureCount == 0
1062 || gpos->LookupList.LookupCount == 0)
1065 LangSys = get_langsys (&gpos->ScriptList, script, language);
1069 /* One lookup may be used by multiple features. */
1070 lookup_indices = alloca (sizeof (int)
1071 * gpos->LookupList.LookupCount
1072 * gpos->FeatureList.FeatureCount);
1073 if (! lookup_indices)
1074 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1075 n = setup_lookup_indices (LangSys, &gpos->FeatureList,
1076 features, lookup_indices);
1080 for (i = 0; i < n; i++)
1082 int index = lookup_indices[i];
1085 while (gidx < gstring->used)
1087 gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1097 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1098 char *script, char *language,
1099 char *gsub_features, char *gpos_features)
1101 if (OTF_drive_cmap (otf, gstring) < 0)
1103 if (OTF_drive_gdef (otf, gstring) < 0)
1106 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1109 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)