+int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag)
+{
+ int t, glyphcount;
+ int maxcode;
+ int fid;
+ U8 flags1, flags2, namelen;
+ swf_SaveTagPos(tag);
+ swf_SetTagPos(tag, 0);
+ font->version = 2;
+ fid = swf_GetU16(tag);
+ if (id && id != fid)
+ return id;
+ font->id = fid;
+ flags1 = swf_GetU8(tag);
+ flags2 = swf_GetU8(tag); //reserved flags
+
+ if (flags1 & 1)
+ font->style |= FONT_STYLE_BOLD;
+ if (flags1 & 2)
+ font->style |= FONT_STYLE_ITALIC;
+ if (flags1 & 16)
+ font->encoding |= FONT_ENCODING_ANSI;
+ if (flags1 & 32)
+ font->encoding |= FONT_ENCODING_UNICODE;
+ if (flags1 & 64)
+ font->encoding |= FONT_ENCODING_SHIFTJIS;
+
+ namelen = swf_GetU8(tag);
+ font->name = (U8 *) rfx_alloc(namelen + 1);
+ font->name[namelen] = 0;
+ swf_GetBlock(tag, font->name, namelen);
+ font->version = 2;
+ glyphcount = swf_GetU16(tag);
+ font->numchars = glyphcount;
+
+ font->glyph = (SWFGLYPH *) rfx_calloc(sizeof(SWFGLYPH) * glyphcount);
+ font->glyph2ascii = (U16 *) rfx_calloc(sizeof(U16) * glyphcount);
+
+ if (flags1 & 8) { // wide offsets
+ for (t = 0; t < glyphcount; t++)
+ swf_GetU32(tag); //offset[t]
+
+ if (glyphcount) /* this _if_ is not in the specs */
+ swf_GetU32(tag); // fontcodeoffset
+ } else {
+ for (t = 0; t < glyphcount; t++)
+ swf_GetU16(tag); //offset[t]
+
+ if (glyphcount) /* this _if_ is not in the specs */
+ swf_GetU16(tag); // fontcodeoffset
+ }
+ /* TODO: we should use the offset positions, not just
+ blindly read in shapes */
+ for (t = 0; t < glyphcount; t++)
+ swf_GetSimpleShape(tag, &(font->glyph[t].shape));
+
+ maxcode = 0;
+ for (t = 0; t < glyphcount; t++) {
+ int code;
+ if (flags1 & 4) // wide codes
+ code = swf_GetU16(tag);
+ else
+ code = swf_GetU8(tag);
+ font->glyph2ascii[t] = code;
+ if (code > maxcode)
+ maxcode = code;
+ }
+ maxcode++;
+ if (maxcode < 256)
+ maxcode = 256;
+ font->maxascii = maxcode;
+ font->ascii2glyph = (int *) rfx_alloc(sizeof(int) * maxcode);
+ memset(font->ascii2glyph, -1, sizeof(int) * maxcode);
+ for (t = 0; t < glyphcount; t++) {
+ font->ascii2glyph[font->glyph2ascii[t]] = t;
+ }
+
+ if (flags1 & 128) { // has layout
+ U16 kerningcount;
+ font->layout = (SWFLAYOUT *) rfx_alloc(sizeof(SWFLAYOUT));
+ font->layout->ascent = swf_GetU16(tag);
+ font->layout->descent = swf_GetU16(tag);
+ font->layout->leading = swf_GetU16(tag);
+ for (t = 0; t < glyphcount; t++) {
+ S16 advance = swf_GetS16(tag);
+ font->glyph[t].advance = advance;
+ }
+ font->layout->bounds = rfx_alloc(glyphcount * sizeof(SRECT));
+ for (t = 0; t < glyphcount; t++) {
+ swf_ResetReadBits(tag);
+ swf_GetRect(tag, &font->layout->bounds[t]);
+ }
+
+ kerningcount = swf_GetU16(tag);
+ font->layout->kerningcount = kerningcount;
+
+ font->layout->kerning = (SWFKERNING *) rfx_alloc(sizeof(SWFKERNING) * kerningcount);
+ if (kerningcount) {
+ font->layout->kerning = rfx_alloc(sizeof(*font->layout->kerning) * kerningcount);
+ for (t = 0; t < kerningcount; t++) {
+ if (flags1 & 4) { // wide codes
+ font->layout->kerning[t].char1 = swf_GetU16(tag);
+ font->layout->kerning[t].char2 = swf_GetU16(tag);
+ } else {
+ font->layout->kerning[t].char1 = swf_GetU8(tag);
+ font->layout->kerning[t].char2 = swf_GetU8(tag);
+ }
+ font->layout->kerning[t].adjustment = swf_GetS16(tag);
+ }
+ }
+ }
+ swf_RestoreTagPos(t);
+ return font->id;
+}
+
+
+#define FEDTJ_PRINT 0x01
+#define FEDTJ_MODIFY 0x02
+#define FEDTJ_CALLBACK 0x04
+
+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);
+ }
+ 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]);
+ }
+ rfx_free(f->glyphnames);
+ f->glyphnames = 0;
+ }
+
+}
+static void font_freeusage(SWFFONT*f)
+{
+ if (f->use) {
+ if(f->use->chars) {
+ rfx_free(f->use->chars);f->use->chars = 0;
+ }
+ rfx_free(f->use); f->use = 0;
+ }
+}
+static void font_freelayout(SWFFONT*f)
+{
+ if (f->layout) {
+ swf_LayoutFree(f->layout);
+ f->layout = 0;
+ }
+}
+static void font_freename(SWFFONT*f)
+{
+ if (f->name) {
+ rfx_free(f->name);
+ f->name = 0;
+ }
+}
+
+int swf_FontReduce(SWFFONT * f)
+{
+ int i, j;
+ int max_unicode = 0;
+ if ((!f) || (!f->use) || f->use->is_reduced)
+ return -1;
+
+ j = 0;
+
+ for (i = 0; i < f->numchars; i++) {
+ if (f->glyph[i].shape && f->use->chars[i]) {
+ f->glyph2ascii[j] = f->glyph2ascii[i];
+ f->glyph[j] = f->glyph[i];
+ f->use->chars[i] = j;
+ j++;
+ } else {
+ f->glyph2ascii[i] = 0;
+ if(f->glyph[i].shape) {
+ swf_ShapeFree(f->glyph[i].shape);
+ f->glyph[i].shape = 0;
+ f->glyph[i].advance = 0;
+ }
+ f->use->chars[i] = -1;
+ j++; //TODO: remove
+ }
+ }
+ for (i = 0; i < f->maxascii; i++) {
+ if(f->use->chars[f->ascii2glyph[i]]<0) {
+ f->ascii2glyph[i] = -1;
+ } else {
+ f->ascii2glyph[i] = f->use->chars[f->ascii2glyph[i]];
+ max_unicode = i;
+ }
+ }
+ f->maxascii = max_unicode;
+ f->use->is_reduced = 1;
+ f->numchars = j;
+ font_freelayout(f);
+ font_freeglyphnames(f);
+ font_freename(f);
+ return j;
+}
+
+void swf_FontSort(SWFFONT * font)
+{
+ int i, j, k;
+ int *newplace;
+ int *newpos;
+ if (!font)
+ return;