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))))
135 // printf ("type %d at %d skiped\n", lookup->LookupType, gidx);
139 //printf ("@%d idx:%d type:%d...",
140 //gidx, lookup_list_index, lookup->LookupType);
142 /* Try all subtables until one of them handles the current glyph. */
143 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
145 OTF_LookupSubTable *subtable = lookup->SubTable + i;
148 // printf ("subtype:%d ", subtable->Format);
149 if (subtable->Coverage.offset)
151 coverage_idx = get_coverage_index (&subtable->Coverage,
153 if (coverage_idx < 0)
155 // printf ("not covererd ");
160 switch (lookup->LookupType)
163 if (subtable->Format == 1)
164 g->glyph_id += subtable->sub.gsub.single1.DeltaGlyphID;
166 g->glyph_id = subtable->sub.gsub.single2.Substitute[coverage_idx];
172 OTF_GSUB_Multiple1 *multiple1 = &subtable->sub.gsub.multiple1;
173 OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
175 gstring_subst (gstring, gidx, gidx + 1,
176 seq->Substitute, seq->GlyphCount);
177 gidx += seq->GlyphCount;
182 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (LookupType not yet supported)");
185 if (subtable->Format == 1)
187 OTF_GSUB_Ligature1 *lig1 = &subtable->sub.gsub.ligature1;
188 OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
191 for (j = 0; j < ligset->LigatureCount; j++)
193 OTF_Ligature *lig = ligset->Ligature + j;
196 if (gstring->used - gidx < lig->CompCount)
198 for (k = 1; k < lig->CompCount; k++)
199 if (gstring->glyphs[gidx + k].glyph_id
200 != lig->Component[k - 1])
202 if (k < lig->CompCount)
204 gstring_subst (gstring, gidx, gidx + lig->CompCount,
211 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
215 if (subtable->Format == 1)
216 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)");
217 else if (subtable->Format == 2)
218 OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)");
221 OTF_GSUB_ChainContext3 *context3
222 = &subtable->sub.gsub.chain_context3;
223 int back_gidx = gidx - context3->BacktrackGlyphCount;
224 int fore_gidx = gidx + context3->InputGlyphCount;
229 || fore_gidx + context3->LookaheadGlyphCount > gstring->used)
232 for (j = 0; j < context3->BacktrackGlyphCount; j++)
233 if (get_coverage_index (context3->Backtrack + j,
234 gstring->glyphs[back_gidx + j].glyph_id)
237 /* Start from the secoding coverage_idx because the
238 first one is the same as subtable->Coverage and thus
240 for (j = 1; j < context3->InputGlyphCount; j++)
241 if (get_coverage_index (context3->Input + j - 1,
242 gstring->glyphs[gidx + j].glyph_id)
245 for (j = 0; j < context3->LookaheadGlyphCount; j++)
246 if (get_coverage_index (context3->LookAhead + j,
247 gstring->glyphs[fore_gidx + j].glyph_id)
251 orig_used = gstring->used;
252 for (j = 0; j < context3->SubstCount; j++)
253 lookup_gsub (lookup_list,
254 context3->SubstLookupRecord[j].LookupListIndex,
256 gidx + context3->SubstLookupRecord[j].SequenceIndex);
257 gidx += context3->InputGlyphCount + (gstring->used - orig_used);
265 if (gidx == orig_gidx)
267 //printf ("not applied\n");
272 // printf ("done\n");
281 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
283 unsigned value_format = OTF_XPlacement | OTF_YPlacement;
285 rec->XPlacement = anchor->XCoordinate;
286 rec->YPlacement = anchor->YCoordinate;
287 if (anchor->AnchorFormat == 1)
290 else if (anchor->AnchorFormat == 2)
291 /* Not yet implemented */
293 else if (anchor->AnchorFormat == 3)
294 /* Not yet implemented */
301 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
302 OTF_GlyphString *gstring, int gidx)
304 char *errfmt = "GPOS Looking up%s";
306 OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
307 unsigned int flag = lookup->LookupFlag;
308 int orig_gidx = gidx;
309 OTF_Glyph *g = gstring->glyphs + gidx;
314 && (flag & (1 << g->GlyphClass))))
316 // printf ("type %d at %d skiped\n", lookup->LookupType, gidx);
320 // printf ("0x%04X@%d idx:%d type:%d...",
321 // g->glyph_id, gidx, lookup_list_index, lookup->LookupType);
323 /* Try all subtables until one of them handles the current glyph. */
324 for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
326 OTF_LookupSubTable *subtable = lookup->SubTable + i;
329 // printf ("subtype:%d ", subtable->Format);
330 if (subtable->Coverage.offset)
332 coverage_idx = get_coverage_index (&subtable->Coverage,
334 if (coverage_idx < 0)
336 // printf ("not covererd ");
341 switch (lookup->LookupType)
344 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
347 if (gidx + 1 >= gstring->used)
349 if (subtable->Format == 1)
350 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
351 else if (subtable->Format == 2)
353 OTF_GPOS_Pair2 *pair2 = &subtable->sub.gpos.pair2;
354 unsigned class1, class2;
356 printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
358 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
359 class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
360 g->positioning_type = lookup->LookupType;
361 g->f.f2.format = pair2->ValueFormat1;
363 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
364 if (pair2->ValueFormat2)
367 g->positioning_type = lookup->LookupType;
368 g->f.f2.format = pair2->ValueFormat2;
370 = &pair2->Class1Record[class1].Class2Record[class2].Value2;
376 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
381 if (subtable->Format == 1)
383 OTF_GPOS_MarkBase1 *mark_base1 = &subtable->sub.gpos.mark_base1;
384 OTF_MarkRecord *mark_record;
385 OTF_BaseRecord *base_record;
386 OTF_Anchor *anchor1, *anchor2;
387 int coverage_idx_base
388 = get_coverage_index (&mark_base1->BaseCoverage,
391 if (coverage_idx_base < 0)
393 printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
394 mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
396 = mark_base1->BaseArray.BaseRecord + coverage_idx_base;
397 anchor1 = &mark_record->MarkAnchor;
398 anchor2 = &base_record->BaseAnchor[mark_record->Class];
399 g->positioning_type = lookup->LookupType;
400 g->f.f4.mark_anchor = anchor1;
401 g->f.f4.base_anchor = anchor2;
405 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
409 OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
416 if (gidx == orig_gidx)
418 // printf ("not applied\n");
423 // printf ("done\n");
429 lookup_cmap (OTF_cmap *cmap, int c)
433 if (! cmap || ! cmap->Unicode)
436 switch (cmap->Unicode->subtable.format)
443 OTF_EncodingSubtable4 *sub4 = cmap->Unicode->subtable.f.f4;
444 int segCount = sub4->segCountX2 / 2;
446 for (i = 0; i < segCount; i++)
447 if (c <= sub4->segments[i].endCount)
449 if (i == segCount || c < sub4->segments[i].startCount)
451 if (sub4->segments[i].idRangeOffset == 0xFFFF)
452 return c + sub4->segments[i].idDelta;
453 return sub4->glyphIdArray[sub4->segments[i].idRangeOffset
454 + (c - sub4->segments[i].startCount)];
466 otf_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
472 && otf_get_table (otf, "cmap") < 0)
476 for (i = 0; i < gstring->used; i++)
477 gstring->glyphs[i].glyph_id = lookup_cmap (cmap, gstring->glyphs[i].c);
484 otf_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
490 && otf_get_table (otf, "GDEF") < 0)
494 if (gdef->glyph_class_def.offset)
495 for (i = 0; i < gstring->used; i++)
496 gstring->glyphs[i].GlyphClass
497 = get_class_def (&gdef->glyph_class_def,
498 gstring->glyphs[i].glyph_id);
500 if (gdef->mark_attach_class_def.offset)
501 for (i = 0; i < gstring->used; i++)
502 gstring->glyphs[i].MarkAttachClass
503 = get_class_def (&gdef->mark_attach_class_def,
504 gstring->glyphs[i].glyph_id);
511 otf_drive_gsub (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
512 OTF_GlyphString *gstring)
515 OTF_LangSys *langsys;
519 && otf_get_table (otf, "GSUB") < 0)
523 langsys = get_langsys (&gsub->ScriptList, script_tag, langsys_tag);
527 for (i = 0; i < langsys->FeatureCount; i++)
530 = gsub->FeatureList.Feature + langsys->FeatureIndex[i];
532 for (j = 0; j < feature->LookupCount; j++)
536 while (gidx < gstring->used)
537 gidx = lookup_gsub (&gsub->LookupList, feature->LookupListIndex[j],
546 otf_drive_gpos (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
547 OTF_GlyphString *gstring)
550 OTF_LangSys *langsys;
554 && otf_get_table (otf, "GPOS") < 0)
558 langsys = get_langsys (&gpos->ScriptList, script_tag, langsys_tag);
562 for (i = 0; i < langsys->FeatureCount; i++)
565 = gpos->FeatureList.Feature + langsys->FeatureIndex[i];
567 for (j = 0; j < feature->LookupCount; j++)
571 while (gidx < gstring->used)
572 gidx = lookup_gpos (&gpos->LookupList, feature->LookupListIndex[j],
581 otf_drive_table (OTF *otf, OTF_Tag script, OTF_Tag langsys,
582 OTF_GlyphString *gstring)
584 if (otf_drive_cmap (otf, gstring) < 0)
586 if (otf_drive_gdef (otf, gstring) < 0)
588 if (otf_drive_gsub (otf, script, langsys, gstring) < 0)
590 if (otf_drive_gpos (otf, script, langsys, gstring) < 0)