8 #define GSTRING_DELETE(gstring, from, len) \
10 memmove (gstring->glyphs + from, gstring->glyphs + from + len, \
11 sizeof (OTF_Glyph) * (gstring->used - from - len)); \
12 gstring->used -= len; \
16 #define GSTRING_INSERT(gstring, pos, len) \
18 if (gstring->used + len > gstring->size) \
20 char *errfmt = "GSTRING%s"; \
22 gstring->size = gstring->used + len; \
23 gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \
25 if (! gstring->glyphs) \
26 OTF_ERROR (OTF_ERROR_MEMORY, ""); \
28 memmove (gstring->glyphs + pos + len, gstring->glyphs + pos, \
29 sizeof (OTF_Glyph) * (gstring->used - pos)); \
30 gstring->used += len; \
35 gstring_subst (OTF_GlyphString *gstring, int from, int to,
36 OTF_GlyphID *ids, int num)
43 GSTRING_INSERT (gstring, from, (num - len));
45 GSTRING_DELETE (gstring, from, (len - num));
46 for (i = 0; i < num; i++)
47 gstring->glyphs[from + i].glyph_id = ids[i];
53 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
57 if (coverage->CoverageFormat == 1)
59 for (i = 0; i < coverage->Count; i++)
60 if (coverage->table.GlyphArray[i] == id)
65 for (i = 0; i < coverage->Count; i++)
66 if (coverage->table.RangeRecord[i].Start <= id
67 && coverage->table.RangeRecord[i].End >= id)
68 return (coverage->table.RangeRecord[i].StartCoverageIndex
69 + (id - coverage->table.RangeRecord[i].Start));
75 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
77 if (class_def->ClassFormat == 1)
79 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
81 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
82 return class_def->f.f1.ClassValueArray[idx];
88 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
89 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
90 && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
91 return class_def->f.f2.ClassRangeRecord[i].Class;
97 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
100 OTF_Tag script_tag = OTF_tag (script);
101 OTF_Tag langsys_tag = OTF_tag (language);
104 for (i = 0; i < script_list->ScriptCount; i++)
105 if (script_list->Script[i].ScriptTag == script_tag)
107 OTF_Script *script = script_list->Script + i;
110 return &script->DefaultLangSys;
111 for (j = 0; j < script->LangSysCount; j++)
112 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
113 return script->LangSys + j;
114 return &script->DefaultLangSys;
121 get_feature_index (OTF_LangSys *LangSys, OTF_FeatureList *FeatureList,
122 char *features, int *feature_index)
129 int len = strlen (features) + 1;
132 for (p1 = p0; *p1; p1++)
138 int this_len = strlen (p0) + 1;
139 OTF_Tag tag = OTF_tag (p0);
145 for (i = 0; i < FeatureList->FeatureCount; i++)
146 if (tag == FeatureList->Feature[i].FeatureTag)
148 feature_index[nfeatures++] = i;
149 if (nfeatures == FeatureList->FeatureCount)
159 for (; nfeatures < LangSys->FeatureCount; nfeatures++)
160 feature_index[nfeatures] = LangSys->FeatureIndex[nfeatures];
167 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
171 if (gstring->used - gidx < count)
173 for (i = 0; i < count; i++)
174 if (gstring->glyphs[gidx + i].glyph_id != ids[i])
180 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
181 int count, unsigned *classes)
185 if (gstring->used - gidx < count)
187 for (i = 0; i < count; i++)
188 if (get_class_def (class_def, gstring->glyphs[gidx + i].glyph_id)
195 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
196 OTF_GlyphString *gstring, int gidx)
198 char *errfmt = "GSUB Looking up%s";
200 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
201 unsigned int flag = lookup->LookupFlag;
202 int orig_gidx = gidx;
203 OTF_Glyph *g = gstring->glyphs + gidx;
208 && (flag & (1 << g->GlyphClass))))
211 /* Try all subtables until one of them handles the current glyph. */
212 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
214 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
217 if (subtable->Coverage.offset)
219 coverage_idx = get_coverage_index (&subtable->Coverage,
221 if (coverage_idx < 0)
225 switch (lookup->LookupType)
228 if (subtable->Format == 1)
229 g->glyph_id += subtable->u.single1.DeltaGlyphID;
231 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
237 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
238 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
240 gstring_subst (gstring, gidx, gidx + 1,
241 seq->Substitute, seq->GlyphCount);
242 gidx += seq->GlyphCount;
247 if (subtable->Format == 1)
249 OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
250 OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
252 g->glyph_id = altset->Alternate[0];
256 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
260 if (subtable->Format == 1)
262 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
263 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
267 for (j = 0; j < ligset->LigatureCount; j++)
269 lig = ligset->Ligature + j;
270 if (match_ids (gstring, gidx + 1,
271 lig->CompCount - 1, lig->Component) < 0)
273 gstring_subst (gstring, gidx, gidx + lig->CompCount,
280 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
284 if (subtable->Format == 1)
286 OTF_GSUB_Context1 *context1 = &subtable->u.context1;
287 OTF_RuleSet *set = context1->SubRuleSet + coverage_idx;
292 for (j = 0; j < set->RuleCount; j++)
294 rule = set->Rule + j;
295 if (match_ids (gstring, gidx + 1,
296 rule->GlyphCount - 1, rule->Input) < 0)
298 orig_used = gstring->used;
299 for (k = 0; k < rule->LookupCount; k++)
300 lookup_gsub (lookup_list,
301 rule->LookupRecord[k].LookupListIndex,
303 gidx + rule->LookupRecord[k].SequenceIndex);
304 gidx += rule->GlyphCount + (gstring->used - orig_used);
308 else if (subtable->Format == 2)
310 OTF_GSUB_Context2 *context2 = &subtable->u.context2;
317 class = get_class_def (&context2->ClassDef, g->glyph_id);
318 set = context2->SubClassSet + class;
319 for (j = 0; j < set->ClassRuleCnt; j++)
321 rule = set->ClassRule + j;
322 if (match_classes (&context2->ClassDef,
324 rule->GlyphCount - 1, rule->Class)
327 orig_used = gstring->used;
328 for (k = 0; k < rule->LookupCount; k++)
329 lookup_gsub (lookup_list,
330 rule->LookupRecord[k].LookupListIndex,
332 gidx + rule->LookupRecord[k].SequenceIndex);
333 gidx += rule->GlyphCount + (gstring->used - orig_used);
337 else /* subtable->Format == 3 */
339 OTF_GSUB_Context3 *context3 = &subtable->u.context3;
343 if (gstring->used - gidx < context3->GlyphCount)
345 /* Start from the secoding coverage_idx because the
346 first one is the same as subtable->Coverage and thus
348 for (j = 1; j < context3->GlyphCount; j++)
349 if (get_coverage_index (context3->Coverage + j,
350 gstring->glyphs[gidx + j].glyph_id)
353 if (j < context3->GlyphCount)
355 orig_used = gstring->used;
356 for (k = 0; k < context3->SubstCount; k++)
357 lookup_gsub (lookup_list,
358 context3->LookupRecord[k].LookupListIndex,
360 gidx + context3->LookupRecord[k].SequenceIndex);
361 gidx += context3->GlyphCount + (gstring->used - orig_used);
366 if (subtable->Format == 1)
367 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)");
368 else if (subtable->Format == 2)
369 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)");
372 OTF_GSUB_ChainContext3 *context3
373 = &subtable->u.chain_context3;
374 int back_gidx = gidx - context3->BacktrackGlyphCount;
375 int fore_gidx = gidx + context3->InputGlyphCount;
380 || fore_gidx + context3->LookaheadGlyphCount > gstring->used)
383 for (j = 0; j < context3->BacktrackGlyphCount; j++)
384 if (get_coverage_index (context3->Backtrack + j,
385 gstring->glyphs[back_gidx + j].glyph_id)
388 if (j < context3->BacktrackGlyphCount)
391 /* Start from the secode coverage_idx because the first
392 one is the same as subtable->Coverage and thus
394 for (j = 1; j < context3->InputGlyphCount; j++)
395 if (get_coverage_index (context3->Input + j,
396 gstring->glyphs[gidx + j].glyph_id)
399 if (j < context3->InputGlyphCount)
402 for (j = 0; j < context3->LookaheadGlyphCount; j++)
403 if (get_coverage_index (context3->LookAhead + j,
404 gstring->glyphs[fore_gidx + j].glyph_id)
407 if (j < context3->LookaheadGlyphCount)
410 orig_used = gstring->used;
411 for (j = 0; j < context3->SubstCount; j++)
412 lookup_gsub (lookup_list,
413 context3->LookupRecord[j].LookupListIndex,
415 gidx + context3->LookupRecord[j].SequenceIndex);
416 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
424 if (gidx == orig_gidx)
426 //printf ("not applied\n");
431 // printf ("done\n");
440 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
442 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
444 rec->XPlacement = anchor->XCoordinate;
445 rec->YPlacement = anchor->YCoordinate;
446 if (anchor->AnchorFormat == 1)
449 else if (anchor->AnchorFormat == 2)
450 /* Not yet implemented */
452 else if (anchor->AnchorFormat == 3)
453 /* Not yet implemented */
460 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
461 OTF_GlyphString *gstring, int gidx)
463 char *errfmt = "GPOS Looking up%s";
465 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
466 unsigned int flag = lookup->LookupFlag;
467 int orig_gidx = gidx;
468 OTF_Glyph *g = gstring->glyphs + gidx;
473 && (flag & (1 << g->GlyphClass))))
476 /* Try all subtables until one of them handles the current glyph. */
477 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
479 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
482 // printf ("subtype:%d ", subtable->Format);
483 if (subtable->Coverage.offset)
485 coverage_idx = get_coverage_index (&subtable->Coverage,
487 if (coverage_idx < 0)
489 // printf ("not covererd ");
494 switch (lookup->LookupType)
497 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
500 if (gidx + 1 >= gstring->used)
502 if (subtable->Format == 1)
503 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
504 else if (subtable->Format == 2)
506 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
507 unsigned class1, class2;
509 printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
511 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
512 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
513 g->positioning_type = lookup->LookupType;
514 g->f.f2.format = pair2->ValueFormat1;
516 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
517 if (pair2->ValueFormat2)
520 g->positioning_type = lookup->LookupType;
521 g->f.f2.format = pair2->ValueFormat2;
523 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
529 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
534 if (subtable->Format == 1)
536 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
537 OTF_MarkRecord *mark_record;
538 OTF_AnchorRecord *base_record;
539 int coverage_idx_base
540 = get_coverage_index (&mark_base1->BaseCoverage,
543 if (coverage_idx_base < 0)
545 printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
546 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
548 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
549 g->f.f4.mark_anchor = &mark_record->MarkAnchor;
551 = &base_record->Anchor[mark_record->Class];
552 g->positioning_type = lookup->LookupType;
556 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
560 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
566 if (subtable->Format == 1)
568 OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
569 OTF_MarkRecord *mark1_record;
570 OTF_AnchorRecord *mark2_record;
571 int coverage_idx_base
572 = get_coverage_index (&mark_mark1->Mark2Coverage,
575 if (coverage_idx_base < 0)
577 printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
578 mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
580 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
581 g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
583 = &mark2_record->Anchor[mark1_record->Class];
584 g->positioning_type = lookup->LookupType;
588 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
592 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
596 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
600 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
607 if (gidx == orig_gidx)
609 // printf ("not applied\n");
614 // printf ("done\n");
620 lookup_cmap (OTF_cmap *cmap, int c)
624 if (! cmap || ! cmap->Unicode)
627 switch (cmap->Unicode->subtable.format)
634 OTF_EncodingSubtable4 *sub4 = cmap->Unicode->subtable.f.f4;
635 int segCount = sub4->segCountX2 / 2;
637 for (i = 0; i < segCount; i++)
638 if (c <= sub4->segments[i].endCount)
640 if (i == segCount || c < sub4->segments[i].startCount)
642 if (sub4->segments[i].idRangeOffset == 0xFFFF)
643 return c + sub4->segments[i].idDelta;
644 return sub4->glyphIdArray[sub4->segments[i].idRangeOffset
645 + (c - sub4->segments[i].startCount)];
657 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
663 && OTF_get_table (otf, "cmap") < 0)
667 for (i = 0; i < gstring->used; i++)
668 gstring->glyphs[i].glyph_id = lookup_cmap (cmap, gstring->glyphs[i].c);
675 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
681 && OTF_get_table (otf, "GDEF") < 0)
685 if (gdef->glyph_class_def.offset)
686 for (i = 0; i < gstring->used; i++)
687 gstring->glyphs[i].GlyphClass
688 = get_class_def (&gdef->glyph_class_def,
689 gstring->glyphs[i].glyph_id);
691 if (gdef->mark_attach_class_def.offset)
692 for (i = 0; i < gstring->used; i++)
693 gstring->glyphs[i].MarkAttachClass
694 = get_class_def (&gdef->mark_attach_class_def,
695 gstring->glyphs[i].glyph_id);
702 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
703 char *script, char *language, char *features)
705 char *errfmt = "GSUB driving%s";
708 OTF_LangSys *LangSys;
714 && OTF_get_table (otf, "GSUB") < 0)
718 LangSys = get_langsys (&gsub->ScriptList, script, language);
722 feature_index = alloca (sizeof (int) * gsub->FeatureList.FeatureCount);
724 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
726 nfeatures = get_feature_index (LangSys, &gsub->FeatureList,
727 features, feature_index);
729 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " no feature");
731 for (i = 0; i < nfeatures; i++)
733 OTF_Feature *feature = gsub->FeatureList.Feature + feature_index[i];
735 for (j = 0; j < feature->LookupCount; j++)
739 while (gidx < gstring->used)
740 gidx = lookup_gsub (&gsub->LookupList, feature->LookupListIndex[j],
749 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
750 char *script, char *language, char *features)
752 char *errfmt = "GPOS driving%s";
755 OTF_LangSys *LangSys;
761 && OTF_get_table (otf, "GPOS") < 0)
765 LangSys = get_langsys (&gpos->ScriptList, script, language);
769 feature_index = alloca (sizeof (int) * gpos->FeatureList.FeatureCount);
771 OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
773 nfeatures = get_feature_index (LangSys, &gpos->FeatureList,
774 features, feature_index);
776 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " no feature");
778 for (i = 0; i < nfeatures; i++)
780 OTF_Feature *feature = gpos->FeatureList.Feature + feature_index[i];
782 for (j = 0; j < feature->LookupCount; j++)
786 while (gidx < gstring->used)
787 gidx = lookup_gpos (&gpos->LookupList, feature->LookupListIndex[j],
796 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
797 char *script, char *language,
798 char *gsub_features, char *gpos_features)
800 if (OTF_drive_cmap (otf, gstring) < 0)
802 if (OTF_drive_gdef (otf, gstring) < 0)
804 if ((! gsub_features || gsub_features[0])
805 && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
807 if ((! gpos_features || gpos_features[0])
808 && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)