+
+void swf_DrawText(drawer_t * draw, SWFFONT * font, int size, const char *text)
+{
+ U8 *s = (U8 *) text;
+ int advance = 0;
+ while (*s) {
+ SHAPE *shape;
+ SHAPE2 *shape2;
+ SHAPELINE *l;
+ U32 c = readUTF8char(&s);
+ int g = font->ascii2glyph[c];
+ shape = font->glyph[g].shape;
+ if (((int) g) < 0) {
+ fprintf(stderr, "No char %d in font %s\n", c, font->name ? (char *) font->name : "?");
+ continue;
+ }
+ shape2 = swf_ShapeToShape2(shape);
+ l = shape2->lines;
+ while (l) {
+ if (l->type == moveTo) {
+ FPOINT to;
+ to.x = l->x * size / 100.0 / 20.0 + advance;
+ to.y = l->y * size / 100.0 / 20.0;
+ draw->moveTo(draw, &to);
+ } else if (l->type == lineTo) {
+ FPOINT to;
+ to.x = l->x * size / 100.0 / 20.0 + advance;
+ to.y = l->y * size / 100.0 / 20.0;
+ draw->lineTo(draw, &to);
+ } else if (l->type == splineTo) {
+ FPOINT mid, to;
+ mid.x = l->sx * size / 100.0 / 20.0 + advance;
+ mid.y = l->sy * size / 100.0 / 20.0;
+ to.x = l->x * size / 100.0 / 20.0 + advance;
+ to.y = l->y * size / 100.0 / 20.0;
+ draw->splineTo(draw, &mid, &to);
+ }
+ l = l->next;
+ }
+ swf_Shape2Free(shape2);
+ advance += font->glyph[g].advance * size / 100.0 / 20.0;
+ }
+}
+
+void swf_WriteFont_AS3(SWFFONT * font, char *filename)
+{
+ if(!font->layout)
+ swf_FontCreateLayout(font);
+
+ SWF swf;
+ memset(&swf, 0, sizeof(SWF));
+ swf.fileVersion = 9;
+ swf.frameRate = 0x4000;
+ swf.movieSize.xmax = 200;
+ swf.movieSize.ymax = 200;
+
+ if(!font->id) font->id=1;
+
+ TAG *tag;
+ swf.firstTag = tag = swf_InsertTag(tag, ST_DEFINEFONT3);
+ swf_FontSetDefine2(tag, font);
+
+ char*name = font->name?(char*)font->name:"font";
+
+ tag = swf_InsertTag(tag, ST_NAMECHARACTER);
+ swf_SetU16(tag, font->id);
+ swf_SetString(tag, name);
+ tag = swf_InsertTag(tag, ST_EXPORTASSETS);
+ swf_SetU16(tag, 1);
+ swf_SetU16(tag, font->id);
+ swf_SetString(tag, name);
+ tag = swf_AddAS3FontDefine(tag, font->id, (char*)font->name);
+
+ tag = swf_InsertTag(tag, ST_END);
+ swf_SaveSWF(&swf, filename);
+ swf_FreeTags(&swf);
+}
+
+void swf_WriteFont(SWFFONT * font, char *filename)
+{
+ if(!font->layout)
+ swf_FontCreateLayout(font);
+
+ char viewer = 1;
+ U16 id = 1;
+ U16 depth = 1;
+
+ font->id = id++;
+
+ SWF swf;
+ memset(&swf, 0, sizeof(SWF));
+ swf.fileVersion = 8;
+ swf.frameRate = 0x4000;
+ swf.movieSize.xmax = 1024*20;
+ swf.movieSize.ymax = 768*20;
+
+ TAG *tag;
+ swf.firstTag = tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
+ swf_SetU8(tag, 0xe0);swf_SetU8(tag, 0xe0);swf_SetU8(tag, 0xff);
+
+ tag = swf_InsertTag(tag, ST_DEFINEFONT3);
+ swf_FontSetDefine2(tag, font);
+
+ if(font->glyphnames) {
+ int c;
+ tag = swf_InsertTag(tag, ST_GLYPHNAMES);
+ swf_SetU16(tag, font->id);
+ swf_SetU16(tag, font->numchars);
+ for (c = 0; c < font->numchars; c++) {
+ if (font->glyphnames[c])
+ swf_SetString(tag, font->glyphnames[c]);
+ else
+ swf_SetString(tag, "");
+ }
+ }
+
+ if(viewer)
+ {
+ RGBA white = {255,255,255,255};
+ RGBA black = {255,0,0,0};
+ RGBA gray50 = {255,128,128,128};
+ RGBA green = {255,0,255,0};
+ int t;
+ SCOORD miny = SCOORD_MAX;
+ SCOORD maxy = SCOORD_MIN;
+ double width = 0;
+ U16 max_advance = 0;
+ char*flags = rfx_calloc(font->numchars);
+ double*xmin = rfx_calloc(sizeof(double)*(font->numchars+1));
+ double*xmax = rfx_calloc(sizeof(double)*(font->numchars+1));
+ int*xpos = rfx_calloc(sizeof(int)*(font->numchars+1));
+ for(t=0;t<font->numchars;t++) {
+ SHAPE*s = font->glyph[t].shape;
+ SHAPE2*s2 = swf_ShapeToShape2(s);
+ SRECT r = swf_GetShapeBoundingBox(s2);
+
+ // inside a definefont3, everything is 20x the resolution:
+ double rx1 = r.xmin / 20.0;
+ double ry1 = r.ymin / 20.0;
+ double rx2 = r.xmax / 20.0;
+ double ry2 = r.ymax / 20.0;
+
+ xmin[t]= rx1;
+ xmax[t]= rx2;
+
+ if(ry1<miny) {miny=ry1;}
+ if(ry2>maxy) {maxy=ry2;}
+ swf_Shape2Free(s2);free(s2);
+ width += font->glyph[t].advance;
+ if(font->glyph[t].advance>max_advance)
+ max_advance = font->glyph[t].advance;
+ }
+
+ if(miny==SCOORD_MAX) miny=maxy=0;
+ if(miny==maxy) maxy=miny+1;
+
+ /* scale the font so that it's 256 pixels high */
+ double scale = (int)((256.0*1024.0/(maxy-miny))*20.0);
+ double overlarge_factor;
+ int fontsize;
+ if(scale > 32767) {
+ fontsize = 32767;
+ overlarge_factor = scale / 32767.0;
+ } else {
+ fontsize = scale;
+ overlarge_factor = 1.0;
+ }
+
+ int textid = id++;
+ int spriteid = id++;
+ SRECT r;
+ r.xmin = 0;
+ r.ymin = miny*fontsize/1024;
+ r.xmax = width*fontsize/20480;
+ r.ymax = maxy*fontsize/1024;
+ tag = swf_InsertTag(tag, ST_DEFINETEXT);
+ swf_SetU16(tag, textid);
+ swf_SetRect(tag, &r);
+ swf_SetMatrix(tag, NULL);
+
+ U8 abits = 15;
+ U8 gbits = swf_CountBits(font->numchars, 0);
+ swf_SetU8(tag, gbits);
+ swf_SetU8(tag, abits);
+
+ RGBA rgb = {255,0,0,0};
+
+ swf_TextSetInfoRecord(tag, font, fontsize, &rgb, SET_TO_ZERO, SET_TO_ZERO);
+ ActionTAG*array = 0;
+ double x=0;
+ array = action_PushString(array, "xpos");
+ for(t=0;t<font->numchars;t++) {
+ swf_SetU8(tag, 1);
+ int width = abs((xmax[t] - xmin[t+1])*fontsize/1024) + 60;
+ array = action_PushInt(array, x/20 +(xmin[t]*scale/1024)/20);
+ x += width * overlarge_factor;
+ swf_SetBits(tag, t, gbits);
+ swf_SetBits(tag, width, abits);
+ swf_SetU8(tag, 128);
+ }
+ array = action_PushInt(array, x/20);
+ array = action_PushInt(array, font->numchars+1);
+ array = action_InitArray(array);
+ array = action_SetVariable(array);
+ swf_SetU8(tag, 0);
+
+ if(font->layout) {
+ tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
+ SHAPE* s;
+ swf_ShapeNew(&s);
+ int ls = swf_ShapeAddLineStyle(s,20,&white);
+ int shapeid = id++;
+ swf_SetU16(tag,shapeid);
+ SRECT r;
+ r.xmin = 0;
+ r.xmax = 1024*20;
+ r.ymin = 0;
+ r.ymax = 256*20;
+ swf_SetRect(tag,&r);
+ swf_SetShapeHeader(tag,s);
+ swf_ShapeSetAll(tag,s,0,0,ls,0,0);
+
+ /* Ç and  are good chars to test ascent/descent extend */
+ int y1 = (-font->layout->ascent-miny*20.0)*256.0/(maxy-miny);
+ int y2 = (font->layout->descent-miny*20.0)*256.0/(maxy-miny);
+
+ swf_ShapeSetMove(tag,s,0,y1);
+ swf_ShapeSetLine(tag,s,width,0);
+ swf_ShapeSetMove(tag,s,0,y2);
+ swf_ShapeSetLine(tag,s,width,0);
+
+ swf_ShapeSetEnd(tag);
+ swf_ShapeFree(s);
+ tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+ swf_ObjectPlace(tag, shapeid, depth++, NULL, NULL, NULL);
+ }
+
+ /* shapes */