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_langsys (OTF_ScriptList *script_list,
76 OTF_Tag script_tag, OTF_Tag langsys_tag)
80 for (i = 0; i < script_list->ScriptCount; i++)
81 if (script_list->Script[i].ScriptTag == script_tag)
83 OTF_Script *script = script_list->Script + i;
86 return &script->DefaultLangSys;
87 for (j = 0; j < script->LangSysCount; j++)
88 if (script->LangSysRecord[j].LangSysTag == langsys_tag)
89 return script->LangSys + j;
90 return &script->DefaultLangSys;
97 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
99 if (class_def->ClassFormat == 1)
101 int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
103 if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
104 return class_def->f.f1.ClassValueArray[idx];
110 for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
111 if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
112 && glyph_id >= class_def->f.f2.ClassRangeRecord[i].End)
113 return class_def->f.f2.ClassRangeRecord[i].Class;
120 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
121 OTF_GlyphString *gstring, int gidx)
123 char *errfmt = "GSUB Looking up%s";
125 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
126 unsigned int flag = lookup->LookupFlag;
127 int orig_gidx = gidx;
128 OTF_Glyph *g = gstring->glyphs + gidx;
133 && (flag & (1 << g->GlyphClass))))
136 /* Try all subtables until one of them handles the current glyph. */
137 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
139 OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
142 if (subtable->Coverage.offset)
144 coverage_idx = get_coverage_index (&subtable->Coverage,
146 if (coverage_idx < 0)
150 switch (lookup->LookupType)
153 if (subtable->Format == 1)
154 g->glyph_id += subtable->u.single1.DeltaGlyphID;
156 g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
162 OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
163 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
165 gstring_subst (gstring, gidx, gidx + 1,
166 seq->Substitute, seq->GlyphCount);
167 gidx += seq->GlyphCount;
172 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (LookupType not yet supported)");
175 if (subtable->Format == 1)
177 OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
178 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
181 for (j = 0; j < ligset->LigatureCount; j++)
183 OTF_Ligature *lig = ligset->Ligature + j;
186 if (gstring->used - gidx < lig->CompCount)
188 for (k = 1; k < lig->CompCount; k++)
189 if (gstring->glyphs[gidx + k].glyph_id
190 != lig->Component[k - 1])
192 if (k < lig->CompCount)
194 gstring_subst (gstring, gidx, gidx + lig->CompCount,
201 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
205 if (subtable->Format == 1)
206 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)");
207 else if (subtable->Format == 2)
208 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)");
211 OTF_GSUB_ChainContext3 *context3
212 = &subtable->u.chain_context3;
213 int back_gidx = gidx - context3->BacktrackGlyphCount;
214 int fore_gidx = gidx + context3->InputGlyphCount;
219 || fore_gidx + context3->LookaheadGlyphCount > gstring->used)
222 for (j = 0; j < context3->BacktrackGlyphCount; j++)
223 if (get_coverage_index (context3->Backtrack + j,
224 gstring->glyphs[back_gidx + j].glyph_id)
227 /* Start from the secoding coverage_idx because the
228 first one is the same as subtable->Coverage and thus
230 for (j = 1; j < context3->InputGlyphCount; j++)
231 if (get_coverage_index (context3->Input + j - 1,
232 gstring->glyphs[gidx + j].glyph_id)
235 for (j = 0; j < context3->LookaheadGlyphCount; j++)
236 if (get_coverage_index (context3->LookAhead + j,
237 gstring->glyphs[fore_gidx + j].glyph_id)
241 orig_used = gstring->used;
242 for (j = 0; j < context3->SubstCount; j++)
243 lookup_gsub (lookup_list,
244 context3->SubstLookupRecord[j].LookupListIndex,
246 gidx + context3->SubstLookupRecord[j].SequenceIndex);
247 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
255 if (gidx == orig_gidx)
257 //printf ("not applied\n");
262 // printf ("done\n");
271 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
273 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
275 rec->XPlacement = anchor->XCoordinate;
276 rec->YPlacement = anchor->YCoordinate;
277 if (anchor->AnchorFormat == 1)
280 else if (anchor->AnchorFormat == 2)
281 /* Not yet implemented */
283 else if (anchor->AnchorFormat == 3)
284 /* Not yet implemented */
291 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
292 OTF_GlyphString *gstring, int gidx)
294 char *errfmt = "GPOS Looking up%s";
296 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
297 unsigned int flag = lookup->LookupFlag;
298 int orig_gidx = gidx;
299 OTF_Glyph *g = gstring->glyphs + gidx;
304 && (flag & (1 << g->GlyphClass))))
307 /* Try all subtables until one of them handles the current glyph. */
308 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
310 OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
313 // printf ("subtype:%d ", subtable->Format);
314 if (subtable->Coverage.offset)
316 coverage_idx = get_coverage_index (&subtable->Coverage,
318 if (coverage_idx < 0)
320 // printf ("not covererd ");
325 switch (lookup->LookupType)
328 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
331 if (gidx + 1 >= gstring->used)
333 if (subtable->Format == 1)
334 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
335 else if (subtable->Format == 2)
337 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
338 unsigned class1, class2;
340 printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
342 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
343 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
344 g->positioning_type = lookup->LookupType;
345 g->f.f2.format = pair2->ValueFormat1;
347 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
348 if (pair2->ValueFormat2)
351 g->positioning_type = lookup->LookupType;
352 g->f.f2.format = pair2->ValueFormat2;
354 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
360 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
365 if (subtable->Format == 1)
367 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
368 OTF_MarkRecord *mark_record;
369 OTF_BaseRecord *base_record;
370 OTF_Anchor *anchor1, *anchor2;
371 int coverage_idx_base
372 = get_coverage_index (&mark_base1->BaseCoverage,
375 if (coverage_idx_base < 0)
377 printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
378 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
380 = mark_base1->BaseArray.BaseRecord + coverage_idx_base;
381 anchor1 = &mark_record->MarkAnchor;
382 anchor2 = &base_record->BaseAnchor[mark_record->Class];
383 g->positioning_type = lookup->LookupType;
384 g->f.f4.mark_anchor = anchor1;
385 g->f.f4.base_anchor = anchor2;
389 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
393 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
400 if (gidx == orig_gidx)
402 // printf ("not applied\n");
407 // printf ("done\n");
413 lookup_cmap (OTF_cmap *cmap, int c)
417 if (! cmap || ! cmap->Unicode)
420 switch (cmap->Unicode->subtable.format)
427 OTF_EncodingSubtable4 *sub4 = cmap->Unicode->subtable.f.f4;
428 int segCount = sub4->segCountX2 / 2;
430 for (i = 0; i < segCount; i++)
431 if (c <= sub4->segments[i].endCount)
433 if (i == segCount || c < sub4->segments[i].startCount)
435 if (sub4->segments[i].idRangeOffset == 0xFFFF)
436 return c + sub4->segments[i].idDelta;
437 return sub4->glyphIdArray[sub4->segments[i].idRangeOffset
438 + (c - sub4->segments[i].startCount)];
450 otf_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
456 && otf_get_table (otf, "cmap") < 0)
460 for (i = 0; i < gstring->used; i++)
461 gstring->glyphs[i].glyph_id = lookup_cmap (cmap, gstring->glyphs[i].c);
468 otf_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
474 && otf_get_table (otf, "GDEF") < 0)
478 if (gdef->glyph_class_def.offset)
479 for (i = 0; i < gstring->used; i++)
480 gstring->glyphs[i].GlyphClass
481 = get_class_def (&gdef->glyph_class_def,
482 gstring->glyphs[i].glyph_id);
484 if (gdef->mark_attach_class_def.offset)
485 for (i = 0; i < gstring->used; i++)
486 gstring->glyphs[i].MarkAttachClass
487 = get_class_def (&gdef->mark_attach_class_def,
488 gstring->glyphs[i].glyph_id);
495 otf_drive_gsub (OTF *otf, char *script, char *language, char *features,
496 OTF_GlyphString *gstring)
499 OTF_LangSys *LangSys;
501 OTF_Tag script_tag, layngsys_tag;
504 && otf_get_table (otf, "GSUB") < 0)
508 script_tag = otf_tag (script);
509 langsys_tag = otf_tag (language);
510 langsys = get_langsys (&gsub->ScriptList, script_tag, langsys_tag);
516 int len = strlen (features);
523 if (i == 4 || *features == ':')
526 tag = otf_tag (name);
529 feature_tags[nfeatures++] = tag;
530 if (nfeatures == langsys->FeatureCount)
534 if (*features == ':')
538 name[i++] = *features++;
541 && (tag = otf_tag (name)))
542 feature_tags[nfeatures++] = tag;
546 for (i = 0; i < langsys->FeatureCount; i++)
547 feature_tags[nfeatures++] =
551 for (i = 0; i < langsys->FeatureCount; i++)
554 = gsub->FeatureList.Feature + langsys->FeatureIndex[i];
556 for (j = 0; j < feature->LookupCount; j++)
560 while (gidx < gstring->used)
561 gidx = lookup_gsub (&gsub->LookupList, feature->LookupListIndex[j],
570 otf_drive_gpos (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
571 OTF_GlyphString *gstring)
574 OTF_LangSys *langsys;
578 && otf_get_table (otf, "GPOS") < 0)
582 langsys = get_langsys (&gpos->ScriptList, script_tag, langsys_tag);
586 for (i = 0; i < langsys->FeatureCount; i++)
589 = gpos->FeatureList.Feature + langsys->FeatureIndex[i];
591 for (j = 0; j < feature->LookupCount; j++)
595 while (gidx < gstring->used)
596 gidx = lookup_gpos (&gpos->LookupList, feature->LookupListIndex[j],
605 otf_drive_tables (OTF *otf, OTF_Tag script, OTF_Tag langsys,
606 OTF_GlyphString *gstring)
608 if (otf_drive_cmap (otf, gstring) < 0)
610 if (otf_drive_gdef (otf, gstring) < 0)
612 if (otf_drive_gsub (otf, script, langsys, gstring) < 0)
614 if (otf_drive_gpos (otf, script, langsys, gstring) < 0)