From: kramm Date: Mon, 16 May 2005 11:43:06 +0000 (+0000) Subject: fixed several font-stroke related bugs X-Git-Tag: release-0-7-0~84 X-Git-Url: http://git.asbjorn.it/?a=commitdiff_plain;h=1d75a2772012bc5cbf238f7d363c650daa6f4c6a;p=swftools.git fixed several font-stroke related bugs --- diff --git a/pdf2swf/SWFOutputDev.cc b/pdf2swf/SWFOutputDev.cc index 43f106f..0475ab2 100644 --- a/pdf2swf/SWFOutputDev.cc +++ b/pdf2swf/SWFOutputDev.cc @@ -237,6 +237,9 @@ public: 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; @@ -270,8 +273,11 @@ public: 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; }; @@ -356,6 +362,7 @@ SWFOutputDev::SWFOutputDev() 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"); @@ -693,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(); @@ -720,13 +734,13 @@ 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 dashphase = 0; double * ldash = 0; state->getLineDash(&ldash, &dashnum, &dashphase); + gfxline_t*line2 = 0; + if(dashnum && ldash) { float * dash = (float*)malloc(sizeof(float)*(dashnum+1)); int t; @@ -743,8 +757,7 @@ void SWFOutputDev::stroke(GfxState *state) dump_outline(line); } - gfxline_t*line2 = gfxtool_dash_line(line, dash, dashphase); - gfxline_free(line); + line2 = gfxtool_dash_line(line, dash, dashphase); line = line2; msg(" After dashing:"); } @@ -764,41 +777,45 @@ void SWFOutputDev::stroke(GfxState *state) } 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 %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); @@ -810,11 +827,17 @@ void SWFOutputDev::eoFill(GfxState *state) 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); @@ -822,7 +845,6 @@ void SWFOutputDev::clip(GfxState *state) swfoutput_startclip(&output, line); states[statepos].clipping++; - gfxline_free(line); } void SWFOutputDev::eoClip(GfxState *state) { @@ -891,6 +913,12 @@ GBool SWFOutputDev::useGradients() 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) { @@ -917,30 +945,75 @@ 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;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(); - msg(" beginString(%s) render=%d", s->getCString(), render); + 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); - 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())); + + 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; } -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) @@ -949,14 +1022,7 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, if(states[statepos].textRender != render) msg(" 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(); @@ -966,10 +1032,6 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, 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; @@ -1009,19 +1071,76 @@ void SWFOutputDev::drawChar(GfxState *state, double x, double y, 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); } - swfoutput_drawchar(&output, x1, y1, name, c, u, &col); + 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) { - msg(" endString()"); + 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; + } + } } void SWFOutputDev::endTextObject(GfxState *state) { - if(states[statepos].textRender != state->getRender()) + 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"); - msg(" endTextObject()"); + + 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: @@ -1378,7 +1497,8 @@ char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font) msg(" Collection: %s", c.getCString()); }*/ - if (font->getType() == fontType1C) { + //if (font->getType() == fontType1C) { + if (0) { //font->getType() == fontType1C) { if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) { fclose(f); msg(" Couldn't read embedded font file"); @@ -1641,6 +1761,7 @@ int SWFOutputDev::setGfxFont(char*id, char*filename) current_font_id = l->id; current_gfxfont = l->font; font = l->font; + swfoutput_gfxaddfont(&this->output, id, current_gfxfont); return 1; } l = l->next; @@ -1659,6 +1780,7 @@ int SWFOutputDev::setGfxFont(char*id, char*filename) } else { this->fontlist = l; } + swfoutput_gfxaddfont(&this->output, id, current_gfxfont); return 1; } @@ -1683,17 +1805,18 @@ void SWFOutputDev::updateFont(GfxState *state) } } - /* second, see if swfoutput already has this font - cached- if so, we are done */ - setGfxFont(fontid, 0); - 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(" updateFont(%s) [cached]", fontid); - free(fontid); return; - } + }*/ // look for Type 3 font if (gfxFont->getType() == fontType3) { @@ -1746,7 +1869,7 @@ void SWFOutputDev::updateFont(GfxState *state) 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);