+ swf_RestoreTagPos(t);
+ return id;
+}
+
+int swf_FontExtract_GlyphNames(int id, SWFFONT * f, TAG * tag)
+{
+ U16 fid;
+ U16 maxcode;
+ U8 flags;
+ swf_SaveTagPos(tag);
+ swf_SetTagPos(tag, 0);
+
+ fid = swf_GetU16(tag);
+
+ if (fid == id) {
+ int num = swf_GetU16(tag);
+ int t;
+ f->glyphnames = rfx_alloc(sizeof(char *) * num);
+ for (t = 0; t < num; t++) {
+ f->glyphnames[t] = strdup(swf_GetString(tag));
+ }
+ }
+
+ swf_RestoreTagPos(tag);
+ return id;
+}
+
+
+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);
+}