+static int
+swf_FontExtract_DefineTextCallback(int id, SWFFONT * f, TAG * t, int jobs,
+ void (*callback) (void *self,
+ int *chars, int *xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA * color), void *self)
+{
+ U16 cid;
+ SRECT r;
+ MATRIX m;
+ U8 gbits, abits;
+ int fid = 0;
+ RGBA color;
+ int x = 0, y = 0;
+ int fontsize = 0;
+
+ memset(&color, 0, sizeof(color));
+
+ swf_SaveTagPos(t);
+ swf_SetTagPos(t, 0);
+
+ cid = swf_GetU16(t);
+ swf_GetRect(t, &r);
+ swf_GetMatrix(t, &m);
+ gbits = swf_GetU8(t);
+ abits = swf_GetU8(t);
+
+ while (1) {
+ int flags, num;
+ flags = swf_GetU8(t);
+ if (!flags)
+ break;
+
+ if (flags & TF_TEXTCONTROL) {
+ if (flags & TF_HASFONT)
+ fid = swf_GetU16(t);
+ if (flags & TF_HASCOLOR) {
+ color.r = swf_GetU8(t); // rgb
+ color.g = swf_GetU8(t);
+ color.b = swf_GetU8(t);
+ if (swf_GetTagID(t) == ST_DEFINETEXT2)
+ color.a = swf_GetU8(t);
+ else
+ color.a = 255;
+ }
+ if (flags & TF_HASXOFFSET)
+ x = swf_GetS16(t);
+ if (flags & TF_HASYOFFSET)
+ y = swf_GetS16(t);
+ if (flags & TF_HASFONT)
+ fontsize = swf_GetU16(t);
+ }
+
+ num = swf_GetU8(t);
+ if (!num)
+ break;
+
+ {
+ int i;
+ int buf[256];
+ int advance[256];
+ int xpos = 0;
+ for (i = 0; i < num; i++) {
+ int glyph;
+ int adv = 0;
+ advance[i] = xpos;
+ glyph = swf_GetBits(t, gbits);
+ adv = swf_GetBits(t, abits);
+ xpos += adv;
+
+ // <deprecated>
+ if (id == fid) {
+ if (jobs & FEDTJ_PRINT) {
+ int code = f->glyph2ascii[glyph];
+ printf("%c", code);
+ }
+ if (jobs & FEDTJ_MODIFY)
+ f->glyph[glyph].advance = adv * 20; //?
+ } else {
+ if (jobs & FEDTJ_PRINT) {
+ printf("?");
+ }
+ }
+ // </deprecated>
+
+ buf[i] = glyph;
+ }
+ if ((id == fid) && (jobs & FEDTJ_PRINT))
+ printf("\n");
+ if (jobs & FEDTJ_CALLBACK)
+ callback(self, buf, advance, num, fid, fontsize, x, y, &color);
+ x += xpos;
+ }
+ }
+
+ swf_RestoreTagPos(t);
+ return id;
+}
+
+int swf_ParseDefineText(TAG * tag,
+ void (*callback) (void *self, int *chars, int *ypos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA * color), void *self)
+{
+ return swf_FontExtract_DefineTextCallback(-1, 0, tag, FEDTJ_CALLBACK, callback, self);
+}
+
+int swf_FontExtract_DefineText(int id, SWFFONT * f, TAG * t, int jobs)
+{
+ return swf_FontExtract_DefineTextCallback(id, f, t, jobs, 0, 0);
+}
+
+int swf_FontExtract(SWF * swf, int id, SWFFONT * *font)
+{
+ TAG *t;
+ SWFFONT *f;
+
+ if ((!swf) || (!font))
+ return -1;
+
+ f = (SWFFONT *) rfx_calloc(sizeof(SWFFONT));
+
+ t = swf->firstTag;
+
+ while (t) {
+ int nid = 0;
+ switch (swf_GetTagID(t)) {
+ case ST_DEFINEFONT:
+ nid = swf_FontExtract_DefineFont(id, f, t);
+ break;
+
+ case ST_DEFINEFONT2:
+ nid = swf_FontExtract_DefineFont2(id, f, t);
+ break;
+
+ case ST_DEFINEFONTINFO:
+ case ST_DEFINEFONTINFO2:
+ nid = swf_FontExtract_DefineFontInfo(id, f, t);
+ break;
+
+ case ST_DEFINETEXT:
+ case ST_DEFINETEXT2:
+ nid = swf_FontExtract_DefineText(id, f, t, f->layout ? 0 : FEDTJ_MODIFY);
+ break;
+
+ case ST_GLYPHNAMES:
+ nid = swf_FontExtract_GlyphNames(id, f, t);
+ break;
+ }
+ if (nid > 0)
+ id = nid;
+ t = swf_NextTag(t);
+ }
+ if (f->id != id) {
+ rfx_free(f);
+ f = 0;
+ }
+ font[0] = f;
+ return 0;
+}
+
+int swf_FontSetID(SWFFONT * f, U16 id)
+{
+ if (!f)
+ return -1;
+ f->id = id;
+ return 0;
+}
+
+void swf_LayoutFree(SWFLAYOUT * l)
+{
+ if (l) {
+ if (l->kerning)
+ rfx_free(l->kerning);
+ l->kerning = NULL;
+ if (l->bounds)
+ rfx_free(l->bounds);
+ l->bounds = NULL;
+ }
+ rfx_free(l);
+}
+
+
+static void font_freeglyphnames(SWFFONT*f)
+{
+ if (f->glyphnames) {
+ int t;
+ for (t = 0; t < f->numchars; t++) {
+ if (f->glyphnames[t]) {
+ rfx_free(f->glyphnames[t]);
+ f->glyphnames[t] = 0;
+ }
+ }
+ rfx_free(f->glyphnames);
+ f->glyphnames = 0;