X-Git-Url: http://git.asbjorn.it/?a=blobdiff_plain;f=pdf2swf%2FSWFOutputDev.cc;h=0769800f9a77208412e793e76528714e97968a7a;hb=ae8a7acad94dd9c9d7b5d477ce96c5674935ff9b;hp=001c137867d2484cc147a1ff05004680d30db236;hpb=f917bed34c9671d66d41e5aebd161e6dcac32325;p=swftools.git diff --git a/pdf2swf/SWFOutputDev.cc b/pdf2swf/SWFOutputDev.cc index 001c137..0769800 100644 --- a/pdf2swf/SWFOutputDev.cc +++ b/pdf2swf/SWFOutputDev.cc @@ -29,7 +29,7 @@ #ifdef HAVE_SYS_STAT_H #include #endif -#ifdef HAVE_FONTCONFIG_H +#ifdef HAVE_FONTCONFIG #include #endif //xpdf header files @@ -65,7 +65,8 @@ #include "swfoutput.h" #include "../lib/log.h" #include "../lib/gfxdevice.h" -#include "gfxtools.h" +#include "../lib/gfxtools.h" +#include "../lib/gfxfont.h" #include @@ -89,8 +90,8 @@ static int pagepos = 0; /* config */ static double caplinewidth = 3.0; -static int zoom = 72; /* xpdf: 86 */ -static int forceType0Fonts = 0; +static double zoom = 72; /* xpdf: 86 */ +static int forceType0Fonts = 1; static void printInfoString(Dict *infoDict, char *key, char *fmt); static void printInfoDate(Dict *infoDict, char *key, char *fmt); @@ -114,6 +115,24 @@ struct mapping { {"Symbol", "s050000l"}, {"ZapfDingbats", "d050000l"}}; +class SWFOutputState { + public: + int clipping; + int textRender; + SWFOutputState() { + this->clipping = 0; + this->textRender = 0; + } +}; + +typedef struct _fontlist +{ + char*id; + char*filename; + gfxfont_t*font; + _fontlist*next; +} fontlist_t; + class SWFOutputDev: public OutputDev { int outputstarted; struct swfoutput output; @@ -193,6 +212,7 @@ public: //----- text drawing virtual void beginString(GfxState *state, GString *s) ; virtual void endString(GfxState *state) ; + virtual void endTextObject(GfxState *state); virtual void drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, @@ -206,16 +226,23 @@ public: int width, int height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg); - virtual GBool beginType3Char(GfxState *state, - CharCode code, Unicode *u, int uLen); + virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen); virtual void endType3Char(GfxState *state); + virtual void type3D0(GfxState *state, double wx, double wy); + virtual void type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury); + private: void drawGeneralImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap*colorMap, GBool invert, - GBool inlineImg, int mask); - int clipping[64]; - int clippos; + 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 currentpage; @@ -244,6 +271,14 @@ public: int user_movex,user_movey; int user_clipx1,user_clipx2,user_clipy1,user_clipy2; + + gfxline_t* current_text_stroke; + gfxline_t* current_text_clip; + char* current_font_id; + gfxfont_t* current_gfxfont; + gfxmatrix_t current_font_matrix; + + fontlist_t* fontlist; }; static char*getFontID(GfxFont*font); @@ -290,7 +325,7 @@ class InfoOutputDev: public OutputDev GfxFont*font = state->getFont(); if(!font) return; - char*id = getFontID(font); + /*char*id = getFontID(font);*/ /* FIXME*/ num_fonts++; } @@ -315,8 +350,7 @@ SWFOutputDev::SWFOutputDev() linkinfo = 0; pbminfo = 0; type3active = 0; - clippos = 0; - clipping[clippos] = 0; + statepos = 0; outputstarted = 0; xref = 0; substitutepos = 0; @@ -327,6 +361,9 @@ SWFOutputDev::SWFOutputDev() user_clipy1 = 0; user_clipx2 = 0; user_clipy2 = 0; + current_text_stroke = 0; + current_text_clip = 0; + fontlist = 0; memset(&output, 0, sizeof(output)); // printf("SWFOutputDev::SWFOutputDev() \n"); }; @@ -515,13 +552,14 @@ static void showFontError(GfxFont*font, int nr) static void dumpFontInfo(char*loglevel, GfxFont*font) { - char* name = getFontID(font); + char* id = getFontID(font); + char* name = getFontName(font); Ref* r=font->getID(); - msg("%s=========== %s (ID:%d,%d) ==========\n", loglevel, getFontName(font), r->num,r->gen); + msg("%s=========== %s (ID:%d,%d) ==========\n", loglevel, name, r->num,r->gen); GString*gstr = font->getTag(); - msg("%s| Tag: %s\n", loglevel, name); + msg("%s| Tag: %s\n", loglevel, id); if(font->isCIDFont()) msg("%s| is CID font\n", loglevel); @@ -555,10 +593,12 @@ static void dumpFontInfo(char*loglevel, GfxFont*font) Ref embRef; GBool embedded = font->getEmbeddedFontID(&embRef); - if(font->getEmbeddedFontName()) - name = font->getEmbeddedFontName()->getCString(); + char*embeddedName=0; + if(font->getEmbeddedFontName()) { + embeddedName = font->getEmbeddedFontName()->getCString(); + } if(embedded) - msg("%s| Embedded name: %s id: %d\n",loglevel, FIXNULL(name), embRef.num); + msg("%s| Embedded id: %s id: %d\n",loglevel, FIXNULL(embeddedName), embRef.num); gstr = font->getExtFontFile(); if(gstr) @@ -570,11 +610,29 @@ static void dumpFontInfo(char*loglevel, GfxFont*font) if(font->isSymbolic()) msg("%s| is symbolic\n", loglevel); if(font->isItalic()) msg("%s| is italic\n", loglevel); if(font->isBold()) msg("%s| is bold\n", loglevel); + + free(id); + free(name); } //void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) {printf("void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) \n");} //void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) {printf("void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) \n");} + +void dump_outline(gfxline_t*line) +{ + while(line) { + if(line->type == gfx_moveTo) { + msg(" | moveTo %.2f %.2f", line->x,line->y); + } else if(line->type == gfx_lineTo) { + msg(" | lineTo %.2f %.2f", line->x,line->y); + } else if(line->type == gfx_splineTo) { + msg(" | splineTo (%.2f %.2f) %.2f %.2f", line->sx,line->sy, line->x, line->y); + } + line = line->next; + } +} + gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed) { int num = path->getNumSubpaths(); @@ -631,7 +689,8 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed) if(closed && needsfix && (fabs(posx-lastx)+fabs(posy-lasty))>0.001) { draw.lineTo(&draw, lastx, lasty); } - return (gfxline_t*)draw.result(&draw); + gfxline_t*result = (gfxline_t*)draw.result(&draw); + return result; } /*---------------------------------------------------------------------------- @@ -641,6 +700,13 @@ gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed) 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(); @@ -648,13 +714,16 @@ void SWFOutputDev::stroke(GfxState *state) GfxRGB rgb; double opaq = state->getStrokeOpacity(); - state->getStrokeRGB(&rgb); + if(type3active) + state->getFillRGB(&rgb); + else + state->getStrokeRGB(&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); - + gfx_capType capType = gfx_capRound; if(lineCap == 0) capType = gfx_capButt; else if(lineCap == 1) capType = gfx_capRound; @@ -665,96 +734,117 @@ void SWFOutputDev::stroke(GfxState *state) 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 dashstart = 0; + double dashphase = 0; double * ldash = 0; - state->getLineDash(&ldash, &dashnum, &dashstart); + state->getLineDash(&ldash, &dashnum, &dashphase); + + gfxline_t*line2 = 0; + if(dashnum && ldash) { - float * dash = (float*)malloc(sizeof(float)*(dashnum+2)); - dash[0] = dashstart; + float * dash = (float*)malloc(sizeof(float)*(dashnum+1)); int t; + double cut = 0; + int fixzero = 0; + msg(" %d dashes", dashnum); + msg(" | phase: %f", dashphase); for(t=0;t | d%-3d: %f", t, ldash[t]); + } + dash[dashnum] = -1; + if(getLogLevel() >= LOGLEVEL_TRACE) { + dump_outline(line); } - dash[dashnum+1] = 0; - gfxline_t*line2 = gfxtool_dash_line(line, dash); - gfxline_free(line); + line2 = gfxtool_dash_line(line, dash, dashphase); line = line2; + msg(" After dashing:"); } if(getLogLevel() >= LOGLEVEL_TRACE) { - msg(" stroke width=%f join=%s cap=%s dashes=%d\n", + double gray; + state->getStrokeGray(&gray); + msg(" stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x gray=%f\n", width, lineJoin==0?"miter": (lineJoin==1?"round":"bevel"), lineCap==0?"butt": (lineJoin==1?"round":"square"), - dashnum + dashnum, + col.r,col.g,col.b,col.a, + gray ); - //gfxline_show(line, stdout); + dump_outline(line); } swfoutput_drawgfxline(&output, line, width, &col, capType, joinType, miterLimit); - gfxline_free(line); + + if(line2) + gfxline_free(line2); } -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(" fill\n"); - //dump_outline(line); + msg(" 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); if(getLogLevel() >= LOGLEVEL_TRACE) { msg(" eofill\n"); - //dump_outline(line); + dump_outline(line); } 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(" clip\n"); - //dump_outline(line); + dump_outline(line); } swfoutput_startclip(&output, line); - clipping[clippos] ++; - gfxline_free(line); + states[statepos].clipping++; } void SWFOutputDev::eoClip(GfxState *state) { @@ -763,11 +853,11 @@ void SWFOutputDev::eoClip(GfxState *state) if(getLogLevel() >= LOGLEVEL_TRACE) { msg(" eoclip\n"); - //dump_outline(line); + dump_outline(line); } swfoutput_startclip(&output, line); - clipping[clippos] ++; + states[statepos].clipping++; gfxline_free(line); } @@ -789,6 +879,17 @@ SWFOutputDev::~SWFOutputDev() { 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() { @@ -809,14 +910,103 @@ GBool SWFOutputDev::useGradients() return gTrue; } +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) +{ + int len = strlen(str); + int dots = 0; + if(len>=80) { + len = 80; + dots = 1; + } + int t; + for(t=0;t124) { + c = '.'; + } + tmp_printstr[t] = c; + } + if(dots) { + tmp_printstr[len++] = '.'; + tmp_printstr[len++] = '.'; + tmp_printstr[len++] = '.'; + } + tmp_printstr[len] = 0; + return tmp_printstr; +} + + +int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u) +{ + int t; + if(charname) { + for(t=0;tnum_glyphs;t++) { + if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,charname)) { + msg(" 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;tnum_glyphs;t++) { + if(font->glyphs[t].name && !strcasecmp(font->glyphs[t].name,charname)) { + msg(" Char [%d,>>%s<<,%d] maps to %d\n", charnr, charname, u, t); + return t; + } + } + } + + /* try to use the unicode id */ + if(u>=0 && umax_unicode && font->unicode2glyph[u]>=0) { + msg(" Char [%d,%s,>%d<] maps to %d\n", charnr, charname, u, font->unicode2glyph[u]); + return font->unicode2glyph[u]; + } + + if(charnr>=0 && charnrnum_glyphs) { + msg(" 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(); + if(current_text_stroke) { + msg(" Error: Incompatible change of text rendering to %d while inside cliptext", render); + } + + msg(" beginString(%s) render=%d", makeStringPrintable(s->getCString()), render); double m11,m21,m12,m22; // msg(" %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); + + 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(" Text rendering mode %d (%s) not fully supported yet (for text \"%s\")", render, renderModeDesc[render&7], makeStringPrintable(s->getCString()));*/ + states[statepos].textRender = render; } void SWFOutputDev::drawChar(GfxState *state, double x, double y, @@ -824,29 +1014,24 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, double originX, double originY, CharCode c, Unicode *_u, int uLen) { + int render = state->getRender(); // check for invisible text -- this is used by Acrobat Capture - if ((state->getRender() & 3) == 3) + if (render == 3) return; - 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); + + if(states[statepos].textRender != render) + msg(" Internal error: drawChar.render!=beginString.render"); + + gfxcolor_t col = getFillColor(state); Gushort *CIDToGIDMap = 0; GfxFont*font = state->getFont(); if(font->getType() == fontType3) { /* type 3 chars are passed as graphics */ + msg(" 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; @@ -870,9 +1055,8 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, if(font->isCIDFont()) { GfxCIDFont*cfont = (GfxCIDFont*)font; - if(font->getType() == fontCIDType2) { + if(font->getType() == fontCIDType2) CIDToGIDMap = cfont->getCIDToGID(); - } } else { Gfx8BitFont*font8; font8 = (Gfx8BitFont*)font; @@ -880,30 +1064,112 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, if(enc && enc[c]) name = enc[c]; } - if (CIDToGIDMap) { - msg(" drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\"\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name)); - swfoutput_drawchar(&output, x1, y1, name, CIDToGIDMap[c], u, &col); + msg(" 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); + c = CIDToGIDMap[c]; } else { - msg(" drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\"\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name)); - swfoutput_drawchar(&output, x1, y1, name, c, u, &col); + msg(" 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); + } + + int charid = getGfxCharID(current_gfxfont, c, name, u); + if(charid<0) { + msg(" 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(" Drawing glyph %d as shape", charid); + gfxline_t*glyph = current_gfxfont->glyphs[charid].line; + gfxline_t*tglyph = gfxline_clone(glyph); + gfxline_transform(tglyph, &m); + if((render&3) != RENDER_INVISIBLE) { + gfxline_t*add = gfxline_clone(tglyph); + current_text_stroke = gfxline_append(current_text_stroke, add); + } + if(render&RENDER_CLIP) { + gfxline_t*add = gfxline_clone(tglyph); + current_text_clip = gfxline_append(current_text_clip, add); + } + gfxline_free(tglyph); } } -void SWFOutputDev::endString(GfxState *state) { +void SWFOutputDev::endString(GfxState *state) +{ + int render = state->getRender(); + msg(" endString() render=%d textstroke=%08x", render, current_text_stroke); + if(states[statepos].textRender != render) + msg(" 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&3) == RENDER_FILL) { + fillGfxLine(state, current_text_stroke); + gfxline_free(current_text_stroke); + current_text_stroke = 0; + } else if((render&3) == RENDER_FILLSTROKE) { + fillGfxLine(state, current_text_stroke); + strokeGfxline(state, current_text_stroke); + gfxline_free(current_text_stroke); + current_text_stroke = 0; + } else if((render&3) == RENDER_STROKE) { + strokeGfxline(state, current_text_stroke); + gfxline_free(current_text_stroke); + current_text_stroke = 0; + } + } } - -GBool SWFOutputDev::beginType3Char(GfxState *state, - CharCode code, Unicode *u, int uLen) +void SWFOutputDev::endTextObject(GfxState *state) +{ + int render = state->getRender(); + msg(" endTextObject() render=%d textstroke=%08x clipstroke=%08x", render, current_text_stroke, current_text_clip); + if(states[statepos].textRender != render) + msg(" Internal error: drawChar.render!=beginString.render"); + + if(current_text_clip) { + clipToGfxLine(state, current_text_clip); + gfxline_free(current_text_clip); + current_text_clip = 0; + } +} + +/* the logic seems to be as following: + first, beginType3Char is called, with the charcode and the coordinates. + if this function returns true, it already knew about the char and has now drawn it. + if the function returns false, it's a new char, and type3D1 is called with some parameters- + the all draw operations until endType3Char are part of the char (which in this moment is + at the position first passed to beginType3Char). the char ends with endType3Char. + + The drawing operations between beginType3Char and endType3Char are somewhat different to + the normal ones. For example, the fillcolor equals the stroke color. +*/ + +GBool SWFOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen) { msg(" beginType3Char %d, %08x, %d", code, *u, uLen); type3active = 1; - /* the character itself is going to be passed using - drawImageMask() */ + /* the character itself is going to be passed using the draw functions */ return gFalse; /* gTrue= is_in_cache? */ } +void SWFOutputDev::type3D0(GfxState *state, double wx, double wy) { + msg(" type3D0 width=%f height=%f", wx, wy); +} +void SWFOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) { + msg(" type3D1 width=%f height=%f bbox=(%f,%f,%f,%f)", wx, wy, + llx,lly,urx,ury); +} + void SWFOutputDev::endType3Char(GfxState *state) { type3active = 0; @@ -1104,23 +1370,25 @@ void SWFOutputDev::drawLink(Link *link, Catalog *catalog) } void SWFOutputDev::saveState(GfxState *state) { - msg(" saveState\n"); + msg(" saveState\n"); updateAll(state); - if(clippos<64) - clippos ++; - else + if(statepos>=64) { msg(" Too many nested states in pdf."); - clipping[clippos] = 0; + return; + } + statepos ++; + states[statepos].clipping = 0; //? shouldn't this be the current value? + states[statepos].textRender = states[statepos-1].textRender; }; void SWFOutputDev::restoreState(GfxState *state) { - msg(" restoreState\n"); + msg(" restoreState\n"); updateAll(state); - while(clipping[clippos]) { + while(states[statepos].clipping) { swfoutput_endclip(&output); - clipping[clippos]--; + states[statepos].clipping--; } - clippos--; + statepos--; } char* SWFOutputDev::searchFont(char*name) @@ -1188,7 +1456,6 @@ void SWFOutputDev::updateStrokeColor(GfxState *state) GfxRGB rgb; double opaq = state->getStrokeOpacity(); state->getStrokeRGB(&rgb); - //swfoutput_setstrokecolor(&output, (char)(rgb.r*255), (char)(rgb.g*255), (char)(rgb.b*255), (char)(opaq*255)); } @@ -1230,8 +1497,8 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) msg(" Collection: %s", c.getCString()); }*/ - if (font->getType() == fontType1C || - font->getType() == fontCIDType0C) { + //if (font->getType() == fontType1C) { + if (0) { //font->getType() == fontType1C) { if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) { fclose(f); msg(" Couldn't read embedded font file"); @@ -1327,7 +1594,7 @@ char* searchForSuitableFont(GfxFont*gfxFont) if (!fcinitcalled) { msg(" Initializing FontConfig..."); fcinitcalled = true; - if(FcInit()) { + if(!FcInit()) { msg(" FontConfig Initialization failed. Disabling."); config_use_fontconfig = 0; return 0; @@ -1355,7 +1622,7 @@ char* searchForSuitableFont(GfxFont*gfxFont) // if we get an exact match if (strcmp((char *)v, name) == 0) { if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) { - filename = strdup((char*)v); + filename = strdup((char*)v); // mem leak char *nfn = strrchr(filename, '/'); if(nfn) fontname = strdup(nfn+1); else fontname = filename; @@ -1396,7 +1663,7 @@ char* searchForSuitableFont(GfxFont*gfxFont) match = FcFontMatch (0, pattern, &result); if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) { - filename = strdup((char*)v); + filename = strdup((char*)v); // mem leak char *nfn = strrchr(filename, '/'); if(nfn) fontname = strdup(nfn+1); else fontname = filename; @@ -1430,7 +1697,7 @@ char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) } filename = searchFont(fontname); if(!filename) { - msg(" Couldn't find font %s- did you install the default fonts?"); + msg(" Couldn't find font %s- did you install the default fonts?", fontname); return 0; } @@ -1439,12 +1706,12 @@ char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname) exit(1); } if(oldname) { - substitutesource[substitutepos] = oldname; + substitutesource[substitutepos] = strdup(oldname); //mem leak substitutetarget[substitutepos] = fontname; msg(" substituting %s -> %s", FIXNULL(oldname), FIXNULL(fontname)); substitutepos ++; } - return strdup(filename); + return strdup(filename); //mem leak } void unlinkfont(char* filename) @@ -1482,6 +1749,40 @@ void SWFOutputDev::setXRef(PDFDoc*doc, XRef *xref) 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) { @@ -1498,20 +1799,24 @@ void SWFOutputDev::updateFont(GfxState *state) too often */ for(t=0;t updateFont(%s) [cached]", fontid); return; - } + }*/ // look for Type 3 font if (gfxFont->getType() == fontType3) { @@ -1519,6 +1824,7 @@ void SWFOutputDev::updateFont(GfxState *state) type3Warning = gTrue; showFontError(gfxFont, 2); } + free(fontid); return; } @@ -1550,24 +1856,30 @@ void SWFOutputDev::updateFont(GfxState *state) msg(" Font %s %scould not be loaded.", fontname, embedded?"":"(not embedded) "); msg(" Try putting a TTF version of that font (named \"%s.ttf\") into /swftools/fonts", fontname); fileName = substituteFont(gfxFont, fontid); - if(fontid) { fontid = substitutetarget[substitutepos-1]; /*ugly hack*/}; + if(fontid) { free(fontid);fontid = strdup(substitutetarget[substitutepos-1]); /*ugly hack*/}; msg(" Font is now %s (%s)", fontid, fileName); } if(!fileName) { msg(" Couldn't set font %s\n", fontid); + free(fontid); return; } msg(" updateFont(%s) -> %s", fontid, fileName); dumpFontInfo("", gfxFont); - swfoutput_setfont(&output, fontid, fileName); + //swfoutput_setfont(&output, fontid, fileName); + + if(!setGfxFont(fontid, 0)) { + setGfxFont(fontid, fileName); + } if(fileName && del) unlinkfont(fileName); if(fileName) free(fileName); + free(fontid); } #define SQR(x) ((x)*(x)) @@ -1622,7 +1934,7 @@ unsigned char* antialize(unsigned char*data, int width, int height, int newwidth void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap*colorMap, GBool invert, - GBool inlineImg, int mask) + GBool inlineImg, int mask, int*maskColors) { FILE *fi; int c; @@ -1749,7 +2061,7 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, } int x,y; - + if(colorMap->getNumPixelComps()!=1 || str->getKind()==strDCT) { RGBA*pic=new RGBA[width*height]; for (y = 0; y < height; ++y) { @@ -1776,10 +2088,32 @@ void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str, for(t=0;t<256;t++) { pixBuf[0] = t; colorMap->getRGB(pixBuf, &rgb); - pal[t].r = (U8)(rgb.r * 255 + 0.5); - pal[t].g = (U8)(rgb.g * 255 + 0.5); - pal[t].b = (U8)(rgb.b * 255 + 0.5); - pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5); + /*if(maskColors && *maskColors==t) { + msg(" Color %d is transparent", t); + if (imgData->maskColors) { + *alpha = 0; + for (i = 0; i < imgData->colorMap->getNumPixelComps(); ++i) { + if (pix[i] < imgData->maskColors[2*i] || + pix[i] > imgData->maskColors[2*i+1]) { + *alpha = 1; + break; + } + } + } else { + *alpha = 1; + } + if(!*alpha) { + pal[t].r = 0; + pal[t].g = 0; + pal[t].b = 0; + pal[t].a = 0; + } + } else*/ { + pal[t].r = (U8)(rgb.r * 255 + 0.5); + pal[t].g = (U8)(rgb.g * 255 + 0.5); + pal[t].b = (U8)(rgb.b * 255 + 0.5); + pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5); + } } for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) { @@ -1799,14 +2133,19 @@ void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) { + if(states[statepos].textRender & 4) //clipped + return; msg(" drawImageMask %dx%d, invert=%d inline=%d", width, height, invert, inlineImg); - drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1); + drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0); } void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, int *maskColors, GBool inlineImg) { + if(states[statepos].textRender & 4) //clipped + return; + msg(" drawImage %dx%d, %s %s, inline=%d", width, height, colorMap?"colorMap":"no colorMap", maskColors?"maskColors":"no maskColors", @@ -1814,7 +2153,7 @@ void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, if(colorMap) msg(" colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(), colorMap->getBits(),colorMap->getColorSpace()->getMode()); - drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0); + drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0,maskColors); } SWFOutputDev*output = 0; @@ -1871,7 +2210,7 @@ void pdfswf_setparameter(char*name, char*value) caplinewidth = atof(value); } else if(!strcmp(name, "zoom")) { char buf[80]; - zoom = atoi(value); + zoom = atof(value); sprintf(buf, "%f", (double)jpeg_dpi/(double)zoom); swfoutput_setparameter("jpegsubpixels", buf); sprintf(buf, "%f", (double)ppm_dpi/(double)zoom);