#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#ifdef HAVE_FONTCONFIG_H
+#ifdef HAVE_FONTCONFIG
#include <fontconfig.h>
#endif
//xpdf header files
#include "swfoutput.h"
#include "../lib/log.h"
#include "../lib/gfxdevice.h"
-#include "gfxtools.h"
+#include "../lib/gfxtools.h"
+#include "../lib/gfxfont.h"
#include <math.h>
}
};
+typedef struct _fontlist
+{
+ char*id;
+ char*filename;
+ gfxfont_t*font;
+ _fontlist*next;
+} fontlist_t;
+
class SWFOutputDev: public OutputDev {
int outputstarted;
struct swfoutput output;
void drawGeneralImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap*colorMap, GBool invert,
GBool inlineImg, int mask, int *maskColors);
+ int SWFOutputDev::setGfxFont(char*id, char*filename);
+ void strokeGfxline(GfxState *state, gfxline_t*line);
+ void clipToGfxLine(GfxState *state, gfxline_t*line);
+ void fillGfxLine(GfxState *state, gfxline_t*line);
+
SWFOutputState states[64];
int statepos;
int user_movex,user_movey;
int user_clipx1,user_clipx2,user_clipy1,user_clipy2;
+
+ gfxline_t* current_text_stroke;
+ char* current_font_id;
+ gfxfont_t* current_gfxfont;
+ gfxmatrix_t current_font_matrix;
+
+ fontlist_t* fontlist;
};
static char*getFontID(GfxFont*font);
user_clipy1 = 0;
user_clipx2 = 0;
user_clipy2 = 0;
+ current_text_stroke = 0;
+ fontlist = 0;
memset(&output, 0, sizeof(output));
// printf("SWFOutputDev::SWFOutputDev() \n");
};
void SWFOutputDev::stroke(GfxState *state)
{
GfxPath * path = state->getPath();
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
+ strokeGfxline(state, line);
+ gfxline_free(line);
+}
+
+void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line)
+{
int lineCap = state->getLineCap(); // 0=butt, 1=round 2=square
int lineJoin = state->getLineJoin(); // 0=miter, 1=round 2=bevel
double miterLimit = state->getMiterLimit();
else if(lineJoin == 1) joinType = gfx_joinRound;
else if(lineJoin == 2) joinType = gfx_joinBevel;
- gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
-
int dashnum = 0;
double dashphase = 0;
double * ldash = 0;
}
swfoutput_drawgfxline(&output, line, width, &col, capType, joinType, miterLimit);
- gfxline_free(line);
}
-void SWFOutputDev::fill(GfxState *state)
+
+gfxcolor_t getFillColor(GfxState * state)
{
- GfxPath * path = state->getPath();
- double opaq = state->getFillOpacity();
GfxRGB rgb;
+ double opaq = state->getFillOpacity();
state->getFillRGB(&rgb);
gfxcolor_t col;
col.r = (unsigned char)(rgb.r*255);
col.g = (unsigned char)(rgb.g*255);
col.b = (unsigned char)(rgb.b*255);
col.a = (unsigned char)(opaq*255);
+ return col;
+}
- gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
+void SWFOutputDev::fillGfxLine(GfxState *state, gfxline_t*line)
+{
+ gfxcolor_t col = getFillColor(state);
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> fill %02x%02x%02x%02x\n", col.r, col.g, col.b, col.a);
dump_outline(line);
}
-
swfoutput_fillgfxline(&output, line, &col);
+}
+void SWFOutputDev::fill(GfxState *state)
+{
+ GfxPath * path = state->getPath();
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
+ fillGfxLine(state, line);
gfxline_free(line);
}
void SWFOutputDev::eoFill(GfxState *state)
{
GfxPath * path = state->getPath();
- double opaq = state->getFillOpacity();
- GfxRGB rgb;
- state->getFillRGB(&rgb);
- gfxcolor_t col;
- col.r = (unsigned char)(rgb.r*255);
- col.g = (unsigned char)(rgb.g*255);
- col.b = (unsigned char)(rgb.b*255);
- col.a = (unsigned char)(opaq*255);
+ gfxcolor_t col = getFillColor(state);
gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
swfoutput_fillgfxline(&output, line, &col);
gfxline_free(line);
}
+
void SWFOutputDev::clip(GfxState *state)
{
GfxPath * path = state->getPath();
gfxline_t*line = gfxPath_to_gfxline(state, path, 1);
+ clipToGfxLine(state, line);
+ gfxline_free(line);
+}
+void SWFOutputDev::clipToGfxLine(GfxState *state, gfxline_t*line)
+{
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> clip\n");
dump_outline(line);
swfoutput_startclip(&output, line);
states[statepos].clipping++;
- gfxline_free(line);
}
void SWFOutputDev::eoClip(GfxState *state)
{
{
swfoutput_destroy(&output);
outputstarted = 0;
+
+ fontlist_t*l = this->fontlist;
+ while(l) {
+ fontlist_t*next = l->next;
+ l->next = 0;
+ gfxfont_free(l->font);
+ free(l->id);
+ free(l->filename);
+ free(l);
+ l = next;
+ }
};
GBool SWFOutputDev::upsideDown()
{
char*renderModeDesc[]= {"fill", "stroke", "fill+stroke", "invisible",
"clip+fill", "stroke+clip", "fill+stroke+clip", "clip"};
+#define RENDER_FILL 0
+#define RENDER_STROKE 1
+#define RENDER_FILLSTROKE 2
+#define RENDER_INVISIBLE 3
+#define RENDER_CLIP 4
+
static char tmp_printstr[4096];
char* makeStringPrintable(char*str)
{
return tmp_printstr;
}
+
+int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u)
+{
+ int t;
+ if(charname) {
+ for(t=0;t<font->num_glyphs;t++) {
+ if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,charname)) {
+ msg("<debug> Char [%d,>%s<,%d] maps to %d\n", charnr, charname, u, t);
+ return t;
+ }
+ }
+ /* if we didn't find the character, maybe
+ we can find the capitalized version */
+ for(t=0;t<font->num_glyphs;t++) {
+ if(font->glyphs[t].name && !strcasecmp(font->glyphs[t].name,charname)) {
+ msg("<debug> Char [%d,>>%s<<,%d] maps to %d\n", charnr, charname, u, t);
+ return t;
+ }
+ }
+ }
+
+ /* try to use the unicode id */
+ if(u>=0 && u<font->max_unicode && font->unicode2glyph[u]>=0) {
+ msg("<debug> Char [%d,%s,>%d<] maps to %d\n", charnr, charname, u, font->unicode2glyph[u]);
+ return font->unicode2glyph[u];
+ }
+
+ if(charnr>=0 && charnr<font->num_glyphs) {
+ msg("<debug> Char [>%d<,%s,%d] maps to %d\n", charnr, charname, u, charnr);
+ return charnr;
+ }
+
+ return -1;
+}
+
+
void SWFOutputDev::beginString(GfxState *state, GString *s)
{
int render = state->getRender();
- msg("<trace> beginString(%s) render=%d", s->getCString(), render);
+ if(current_text_stroke)
+ msg("<error> Error: Incompatible change of text rendering to %d while inside cliptext", render);
+
+ msg("<trace> beginString(%s) render=%d", makeStringPrintable(s->getCString()), render);
double m11,m21,m12,m22;
// msg("<debug> %s beginstring \"%s\"\n", gfxstate2str(state), s->getCString());
state->getFontTransMat(&m11, &m12, &m21, &m22);
m11 *= state->getHorizScaling();
m21 *= state->getHorizScaling();
- swfoutput_setfontmatrix(&output, m11, -m21, m12, -m22);
- if(render != 3 && render != 0)
- msg("<warning> Text rendering mode %d (%s) not fully supported yet (for text \"%s\")", render, renderModeDesc[render&7], makeStringPrintable(s->getCString()));
+
+ this->current_font_matrix.m00 = m11 / 1024.0;
+ this->current_font_matrix.m01 = m12 / 1024.0;
+ this->current_font_matrix.m10 = -m21 / 1024.0;
+ this->current_font_matrix.m11 = -m22 / 1024.0;
+ this->current_font_matrix.tx = 0;
+ this->current_font_matrix.ty = 0;
+
+ gfxmatrix_t m = this->current_font_matrix;
+
+ /*if(render != 3 && render != 0)
+ msg("<warning> Text rendering mode %d (%s) not fully supported yet (for text \"%s\")", render, renderModeDesc[render&7], makeStringPrintable(s->getCString()));*/
states[statepos].textRender = render;
}
-static int textCount = 0;
-
void SWFOutputDev::drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
CharCode c, Unicode *_u, int uLen)
{
- textCount++;
-
int render = state->getRender();
// check for invisible text -- this is used by Acrobat Capture
if (render == 3)
if(states[statepos].textRender != render)
msg("<error> Internal error: drawChar.render!=beginString.render");
- GfxRGB rgb;
- double opaq = state->getFillOpacity();
- state->getFillRGB(&rgb);
- gfxcolor_t col;
- col.r = (unsigned char)(rgb.r*255);
- col.g = (unsigned char)(rgb.g*255);
- col.b = (unsigned char)(rgb.b*255);
- col.a = (unsigned char)(opaq*255);
+ gfxcolor_t col = getFillColor(state);
Gushort *CIDToGIDMap = 0;
GfxFont*font = state->getFont();
msg("<debug> type3 char at %f/%f", x, y);
return;
}
- double x1,y1;
- x1 = x;
- y1 = y;
- state->transform(x, y, &x1, &y1);
Unicode u=0;
char*name=0;
if(enc && enc[c])
name = enc[c];
}
-
if (CIDToGIDMap) {
msg("<debug> drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\" render=%d\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name), render);
- swfoutput_drawchar(&output, x1, y1, name, CIDToGIDMap[c], u, &col);
+ c = CIDToGIDMap[c];
} else {
msg("<debug> drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\" render=%d\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name), render);
- swfoutput_drawchar(&output, x1, y1, name, c, u, &col);
+ }
+
+ int charid = getGfxCharID(current_gfxfont, c, name, u);
+ if(charid<0) {
+ msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
+ FIXNULL(name),c, u, FIXNULL((char*)current_font_id), current_gfxfont->num_glyphs);
+ return;
+ }
+
+ gfxmatrix_t m = this->current_font_matrix;
+ state->transform(x, y, &m.tx, &m.ty);
+
+ if(render == RENDER_FILL) {
+ swfoutput_gfxdrawchar(&output, current_font_id, charid, &col, &m);
+ } else {
+ msg("<debug> Drawing glyph %d as shape", charid);
+ gfxline_t*glyph = current_gfxfont->glyphs[charid].line;
+ gfxline_t*tglyph = gfxline_clone(glyph);
+ gfxline_transform(tglyph, &m);
+ current_text_stroke = gfxline_append(current_text_stroke, tglyph);
}
}
void SWFOutputDev::endString(GfxState *state)
{
- msg("<trace> endString()");
+ int render = state->getRender();
+ msg("<trace> endString() render=%d textstroke=%08x", render, current_text_stroke);
+ if(states[statepos].textRender != render)
+ msg("<error> Internal error: drawChar.render!=beginString.render");
+
+ if(current_text_stroke) {
+ /* fillstroke and stroke text rendering objects we can process right
+ now (as there may be texts of other rendering modes in this
+ text object)- clipping objects have to wait until endTextObject,
+ however */
+ if(render == RENDER_FILLSTROKE) {
+ fillGfxLine(state, current_text_stroke);
+ strokeGfxline(state, current_text_stroke);
+ gfxline_free(current_text_stroke);
+ current_text_stroke = 0;
+ } else if(render == RENDER_STROKE) {
+ strokeGfxline(state, current_text_stroke);
+ gfxline_free(current_text_stroke);
+ current_text_stroke = 0;
+ }
+ }
}
void SWFOutputDev::endTextObject(GfxState *state)
{
- msg("<trace> endTextObject()");
+ int render = state->getRender();
+ msg("<trace> endTextObject() render=%d textstroke=%08x", render, current_text_stroke);
+ if(states[statepos].textRender != render)
+ msg("<error> Internal error: drawChar.render!=beginString.render");
+
+ if(current_text_stroke) {
+ if((render&3) == RENDER_FILL || (render&3) == RENDER_FILLSTROKE) {
+ fillGfxLine(state, current_text_stroke);
+ }
+ if((render&3) == RENDER_STROKE || (render&3) == RENDER_FILLSTROKE) {
+ strokeGfxline(state, current_text_stroke);
+ }
+ if((render&4) == RENDER_CLIP) {
+ clipToGfxLine(state, current_text_stroke);
+ }
+ gfxline_free(current_text_stroke);
+ current_text_stroke = 0;
+ }
}
/* the logic seems to be as following:
this->xref = xref;
}
+int SWFOutputDev::setGfxFont(char*id, char*filename)
+{
+ gfxfont_t*font = 0;
+ fontlist_t*last=0,*l = this->fontlist;
+
+ /* TODO: should this be part of the state? */
+ while(l) {
+ last = l;
+ if(!strcmp(l->id, id)) {
+ current_font_id = l->id;
+ current_gfxfont = l->font;
+ font = l->font;
+ swfoutput_gfxaddfont(&this->output, id, current_gfxfont);
+ return 1;
+ }
+ l = l->next;
+ }
+ if(!filename) return 0;
+ font = gfxfont_load(filename);
+ l = new fontlist_t;
+ l->font = font;
+ l->filename = strdup(filename);
+ l->id = strdup(id);
+ l->next = 0;
+ current_font_id = l->id;
+ current_gfxfont = l->font;
+ if(last) {
+ last->next = l;
+ } else {
+ this->fontlist = l;
+ }
+ swfoutput_gfxaddfont(&this->output, id, current_gfxfont);
+ return 1;
+}
void SWFOutputDev::updateFont(GfxState *state)
{
}
}
- /* second, see if swfoutput already has this font
- cached- if so, we are done */
- if(swfoutput_queryfont(&output, fontid))
- {
+ /* second, see if this is a font which was used before-
+ if so, we are done */
+ if(setGfxFont(fontid, 0)) {
+ free(fontid);
+ return;
+ }
+/* if(swfoutput_queryfont(&output, fontid))
swfoutput_setfont(&output, fontid, 0);
msg("<debug> updateFont(%s) [cached]", fontid);
- free(fontid);
return;
- }
+ }*/
// look for Type 3 font
if (gfxFont->getType() == fontType3) {
msg("<verbose> updateFont(%s) -> %s", fontid, fileName);
dumpFontInfo("<verbose>", gfxFont);
- swfoutput_setfont(&output, fontid, fileName);
+ //swfoutput_setfont(&output, fontid, fileName);
+
+ if(!setGfxFont(fontid, 0)) {
+ setGfxFont(fontid, fileName);
+ }
if(fileName && del)
unlinkfont(fileName);
void swf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color);
void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform);
void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix);
+void swf_drawchar(gfxdevice_t*dev, char*fontid, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix);
+void swf_addfont(gfxdevice_t*dev, char*fontid, gfxfont_t*font);
+
+int getCharID(SWFFONT *font, int charnr, char *charname, int u);
static swfoutput_internal* init_internal_struct()
{
i->device.fill = swf_fill;
i->device.fillbitmap = swf_fillbitmap;
i->device.fillgradient = swf_fillgradient;
+ i->device.addfont = swf_addfont;
+ i->device.drawchar = swf_drawchar;
return i;
};
double x,y;
x = m->m11*p0->x+m->m12*p0->y;
y = m->m21*p0->x+m->m22*p0->y;
- p0->x = x + m->m13;
- p0->y = y + m->m23;
+ p0->x = x + m->m31;
+ p0->y = y + m->m32;
}
// write a move-to command into the swf
if(i->textid<0)
starttext(obj);
- float x = m->m13;
- float y = m->m23;
+ float x = m->m31;
+ float y = m->m32;
float det = ((m->m11*m->m22)-(m->m21*m->m12));
if(fabs(det) < 0.0005) {
/* x direction equals y direction- the text is invisible */
/* set's the matrix which is to be applied to characters drawn by
swfoutput_drawchar() */
-void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
- double m21,double m22)
+void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m21,
+ double m12,double m22)
{
+ m11 *= 1024;
+ m12 *= 1024;
+ m21 *= 1024;
+ m22 *= 1024;
swfoutput_internal*i = (swfoutput_internal*)obj->internal;
if(obj->fontm11 == m11 &&
obj->fontm12 == m12 &&
m.m12 = obj->fontm12;
m.m21 = obj->fontm21;
m.m22 = obj->fontm22;
- m.m13 = x;
- m.m23 = y;
+ m.m31 = x;
+ m.m32 = y;
return drawchar(obj, obj->swffont, character, charnr, u, &m, color);
}
TAG*mtag = i->swf.firstTag;
if(iterator->swffont) {
mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
- /*if(!storeallcharacters)
- swf_FontReduce(iterator->swffont);*/
+ if(!config_storeallcharacters)
+ swf_FontReduce(iterator->swffont);
swf_FontSetDefine2(mtag, iterator->swffont);
}
gfxdevice_t*dev = &i->device;
dev->endclip(dev);
}
+void swfoutput_gfxaddfont(struct swfoutput*obj, char*fontid, gfxfont_t*font)
+{
+ swfoutput_internal*i = (swfoutput_internal*)obj->internal;
+ gfxdevice_t*dev = &i->device;
+ dev->addfont(dev, fontid, font);
+}
+void swfoutput_gfxdrawchar(struct swfoutput*obj, char*fontid, int glyph, gfxcolor_t*c, gfxmatrix_t*m)
+{
+ swfoutput_internal*i = (swfoutput_internal*)obj->internal;
+ gfxdevice_t*dev = &i->device;
+ dev->drawchar(dev, fontid, glyph, c, m);
+}
#define IMAGE_TYPE_JPEG 0
#define IMAGE_TYPE_LOSSLESS 1
*newheight = sizey;
if(newsizex<sizex || newsizey<sizey) {
- msg("<notice> Scaling %dx%d image to %dx%d", sizex, sizey, newsizex, newsizey);
+ msg("<verbose> Scaling %dx%d image to %dx%d", sizex, sizey, newsizex, newsizey);
newpic = swf_ImageScale(mem, sizex, sizey, newsizex, newsizey);
*newwidth = sizex = newsizex;
*newheight = sizey = newsizey;
{
msg("<error> Gradient filling not implemented yet");
}
+
+static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, char* id)
+{
+ SWFFONT*swffont = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));
+ int t;
+ swffont->id = -1;
+ swffont->version = 2;
+ swffont->name = (U8*)strdup(id);
+ swffont->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));
+ swffont->layout->ascent = 0; /* ? */
+ swffont->layout->descent = 0;
+ swffont->layout->leading = 0;
+ swffont->layout->bounds = (SRECT*)rfx_calloc(sizeof(SRECT)*font->num_glyphs);
+ swffont->encoding = FONT_ENCODING_UNICODE;
+ swffont->numchars = font->num_glyphs;
+ swffont->maxascii = font->max_unicode;
+ swffont->ascii2glyph = (int*)rfx_calloc(sizeof(int)*swffont->maxascii);
+ swffont->glyph2ascii = (U16*)rfx_calloc(sizeof(U16)*swffont->numchars);
+ swffont->glyph = (SWFGLYPH*)rfx_calloc(sizeof(SWFGLYPH)*swffont->numchars);
+ swffont->glyphnames = (char**)rfx_calloc(sizeof(char*)*swffont->numchars);
+ for(t=0;t<font->max_unicode;t++) {
+ swffont->ascii2glyph[t] = font->unicode2glyph[t];
+ }
+ for(t=0;t<font->num_glyphs;t++) {
+ drawer_t draw;
+ gfxline_t*line;
+ swffont->glyph2ascii[t] = font->glyphs[t].unicode;
+ if(font->glyphs[t].name) {
+ swffont->glyphnames[t] = strdup(font->glyphs[t].name);
+ } else {
+ swffont->glyphnames[t] = 0;
+ }
+ swffont->glyph[t].advance = (int)(font->glyphs[t].advance * 20);
+
+ swf_Shape01DrawerInit(&draw, 0);
+ line = font->glyphs[t].line;
+ while(line) {
+ FPOINT c,to;
+ c.x = line->sx; c.y = line->sy;
+ to.x = line->x; to.y = line->y;
+ if(line->type == gfx_moveTo) {
+ draw.moveTo(&draw, &to);
+ } else if(line->type == gfx_lineTo) {
+ draw.lineTo(&draw, &to);
+ } else if(line->type == gfx_splineTo) {
+ draw.splineTo(&draw, &c, &to);
+ }
+ line = line->next;
+ }
+ draw.finish(&draw);
+ swffont->glyph[t].shape = swf_ShapeDrawerToShape(&draw);
+ draw.dealloc(&draw);
+ }
+ return swffont;
+}
+
+void swf_addfont(gfxdevice_t*dev, char*fontid, gfxfont_t*font)
+{
+ swfoutput_internal*i = (swfoutput_internal*)dev->internal;
+
+ if(i->obj->swffont && i->obj->swffont->name && !strcmp((char*)i->obj->swffont->name,fontid))
+ return; // the requested font is the current font
+
+ fontlist_t*last=0,*l = i->fontlist;
+ while(l) {
+ last = l;
+ if(!strcmp((char*)l->swffont->name, fontid)) {
+ return; // we already know this font
+ }
+ l = l->next;
+ }
+ l = (fontlist_t*)rfx_calloc(sizeof(fontlist_t));
+ l->swffont = gfxfont_to_swffont(font, fontid);
+ l->next = 0;
+ if(last) {
+ last->next = l;
+ } else {
+ i->fontlist = l;
+ }
+ swf_FontSetID(l->swffont, getNewID(i->obj));
+
+ if(getScreenLogLevel() >= LOGLEVEL_DEBUG) {
+ // print font information
+ msg("<debug> Font %s",fontid);
+ msg("<debug> | ID: %d", l->swffont->id);
+ msg("<debug> | Version: %d", l->swffont->version);
+ msg("<debug> | Name: %s", l->swffont->name);
+ msg("<debug> | Numchars: %d", l->swffont->numchars);
+ msg("<debug> | Maxascii: %d", l->swffont->maxascii);
+ msg("<debug> | Style: %d", l->swffont->style);
+ msg("<debug> | Encoding: %d", l->swffont->encoding);
+ for(int iii=0; iii<l->swffont->numchars;iii++) {
+ msg("<debug> | Glyph %d) name=%s, unicode=%d size=%d bbox=(%.2f,%.2f,%.2f,%.2f)\n", iii, l->swffont->glyphnames?l->swffont->glyphnames[iii]:"<nonames>", l->swffont->glyph2ascii[iii], l->swffont->glyph[iii].shape->bitlen,
+ l->swffont->layout->bounds[iii].xmin/20.0,
+ l->swffont->layout->bounds[iii].ymin/20.0,
+ l->swffont->layout->bounds[iii].xmax/20.0,
+ l->swffont->layout->bounds[iii].ymax/20.0
+ );
+ int t;
+ for(t=0;t<l->swffont->maxascii;t++) {
+ if(l->swffont->ascii2glyph[t] == iii)
+ msg("<debug> | - maps to %d",t);
+ }
+ }
+ }
+}
+
+static void swf_switchfont(gfxdevice_t*dev, char*fontid)
+{
+ swfoutput_internal*i = (swfoutput_internal*)dev->internal;
+ swfoutput*obj = i->obj;
+
+ if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
+ return; // the requested font is the current font
+
+ fontlist_t*l = i->fontlist;
+ while(l) {
+ if(!strcmp((char*)l->swffont->name, fontid)) {
+ obj->swffont = l->swffont;
+ return; //done!
+ }
+ l = l->next;
+ }
+ msg("<error> Unknown font id: %s", fontid);
+ return;
+}
+
+void swf_drawchar(gfxdevice_t*dev, char*fontid, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
+{
+ swfoutput_internal*i = (swfoutput_internal*)dev->internal;
+ swfoutput*obj = i->obj;
+
+ if(!obj->swffont || !obj->swffont->name || strcmp((char*)obj->swffont->name,fontid)) // not equal to current font
+ {
+ /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
+ with multiple fonts */
+ endtext(obj);
+
+ swf_switchfont(dev, fontid); // set the current font
+ }
+ swfoutput_setfontmatrix(obj, matrix->m00, matrix->m01, matrix->m10, matrix->m11);
+
+ swfmatrix m;
+ m.m11 = obj->fontm11;
+ m.m12 = obj->fontm12;
+ m.m21 = obj->fontm21;
+ m.m22 = obj->fontm22;
+ m.m31 = matrix->tx;
+ m.m32 = matrix->ty;
+ drawchar(obj, obj->swffont, 0, glyph, -1, &m, color);
+}