X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2Fswfoutput.cc;h=4fda3bf62e0bd93dd065620faafccc00aff6cffb;hb=74117d78b1944fcee9e6b258ce152091e45ef845;hp=5bfe250886a76d51a70a873f9496e2c9b4888f97;hpb=55c7d6d3f99d7ede34037879619111e79b6b60e3;p=swftools.git diff --git a/pdf2swf/swfoutput.cc b/pdf2swf/swfoutput.cc index 5bfe250..4fda3bf 100644 --- a/pdf2swf/swfoutput.cc +++ b/pdf2swf/swfoutput.cc @@ -151,7 +151,9 @@ typedef struct _swfoutput_internal RGBA strokergb; RGBA fillrgb; int drawmode; - int x1,y1,x2,y2; + + int shapeposx; + int shapeposy; } swfoutput_internal; @@ -167,10 +169,10 @@ static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*grad static void swf_drawchar(gfxdevice_t*dev, char*fontid, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix); static void swf_addfont(gfxdevice_t*dev, char*fontid, gfxfont_t*font); static void swf_drawlink(gfxdevice_t*dev, gfxline_t*line, char*action); +static void swf_startframe(gfxdevice_t*dev, int width, int height); +static void swf_endframe(gfxdevice_t*dev); static gfxresult_t* swf_finish(gfxdevice_t*driver); -int getCharID(SWFFONT *font, int charnr, char *charname, int u); - static swfoutput_internal* init_internal_struct() { swfoutput_internal*i = (swfoutput_internal*)malloc(sizeof(swfoutput_internal)); @@ -213,7 +215,7 @@ static swfoutput_internal* init_internal_struct() i->config_storeallcharacters=0; i->config_enablezlib=0; i->config_insertstoptag=0; - i->config_flashversion=5; + i->config_flashversion=6; i->config_splinemaxerror=1; i->config_fontsplinemaxerror=1; i->config_filloverlap=0; @@ -255,16 +257,6 @@ static void starttext(gfxdevice_t* dev); static void endshape(gfxdevice_t* dev); static void endtext(gfxdevice_t* dev); -// matrix multiplication. changes p0 -static void transform (plotxy*p0,struct swfmatrix*m) -{ - 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->m31; - p0->y = y + m->m32; -} - // write a move-to command into the swf static int moveto(gfxdevice_t*dev, TAG*tag, plotxy p0) { @@ -422,91 +414,6 @@ static void startFill(gfxdevice_t*dev) } } -/* draw an outline. These are generated by pdf2swf and by t1lib - (representing characters). */ -/*void drawpath(gfxdevice_t*dev, SWF_OUTLINE*outline, struct swfmatrix*m, int log) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - if( i->tag->id != ST_DEFINESHAPE && - i->tag->id != ST_DEFINESHAPE2 && - i->tag->id != ST_DEFINESHAPE3) - { - msg(" internal error: drawpath needs a shape tag, not %d\n",i->tag->id); - exit(1); - } - double x=0,y=0; - double lastx=0,lasty=0; - double firstx=0,firsty=0; - int init=1; - - while (outline) - { - x += (outline->dest.x/(float)0xffff); - y += (outline->dest.y/(float)0xffff); - if(outline->type == SWF_PATHTYPE_MOVE) - { - //if(!init && fill && dev->drawmode != DRAWMODE_EOFILL && !ignoredraworder) - if(i->config_filloverlap && !init && i->fill && dev->drawmode != DRAWMODE_EOFILL) { - // drawmode=FILL (not EOFILL) means that - // seperate shapes do not cancel each other out. - // On SWF side, we need to start a new shape for each - // closed polygon, because SWF only knows EOFILL. - // - endshape(dev); - startshape(dev); - startFill(dev); - } - - if(((int)(lastx*20) != (int)(firstx*20) || - (int)(lasty*20) != (int)(firsty*20)) && - i->fill && !init) - { - plotxy p0; - plotxy p1; - p0.x=lastx; - p0.y=lasty; - p1.x=firstx; - p1.y=firsty; - if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y); - line(dev,i->tag, p0, p1); - } - firstx=x; - firsty=y; - init = 0; - } - else if(outline->type == SWF_PATHTYPE_LINE) - { - plotxy p0; - plotxy p1; - p0.x=lastx; - p0.y=lasty; - p1.x=x; - p1.y=y; - if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y); - line(dev,i->tag, p0,p1); - } - else { - msg(" drawpath: unknown outline type:%d\n", outline->type); - } - lastx=x; - lasty=y; - outline = outline->link; - } - if(((int)(lastx*20) != (int)(firstx*20) || - (int)(lasty*20) != (int)(firsty*20)) && - i->fill) - { - plotxy p0; - plotxy p1; - p0.x=lastx; - p0.y=lasty; - p1.x=firstx; - p1.y=firsty; - if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y); - line(dev, i->tag, p0, p1); - } -}*/ - static inline int colorcompare(gfxdevice_t*dev, RGBA*a,RGBA*b) { @@ -519,7 +426,7 @@ static inline int colorcompare(gfxdevice_t*dev, RGBA*a,RGBA*b) return 1; } -static SRECT getcharacterbbox(gfxdevice_t*dev, SWFFONT*font) +static SRECT getcharacterbbox(gfxdevice_t*dev, SWFFONT*font, MATRIX* m) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; SRECT r; @@ -555,6 +462,8 @@ static SRECT getcharacterbbox(gfxdevice_t*dev, SWFFONT*font) b.xmax += 20; b.ymax += 20; + b = swf_TurnRect(b, m); + if(debug) printf("(%f,%f,%f,%f) -> (%f,%f,%f,%f) [font %d/%d, char %d]\n", font->layout->bounds[i->chardata[t].charid].xmin/20.0, font->layout->bounds[i->chardata[t].charid].ymin/20.0, @@ -738,11 +647,8 @@ static void putcharacter(gfxdevice_t*dev, int fontid, int charid, int x,int y, i If we set it to low, however, the char positions will be inaccurate */ #define FONT_INTERNAL_SIZE 4 -static int font_active = 0; -static char* font_active_filename = 0; - /* process a character. */ -static int drawchar(gfxdevice_t*dev, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m, gfxcolor_t*col) +static int drawchar(gfxdevice_t*dev, SWFFONT *swffont, int charid, swfmatrix*m, gfxcolor_t*col) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; if(!swffont) { @@ -750,21 +656,8 @@ static int drawchar(gfxdevice_t*dev, SWFFONT *swffont, char*character, int charn return 0; } - int charid = getCharID(swffont, charnr, character, u); - if(font_active) { - char buf[1024]; - sprintf(buf, "%s.usage", font_active_filename); - FILE*fi = fopen(buf, "ab+"); - if(fi) { - fprintf(fi, "%d %d %d %s\n", charnr, u, charid, character); - fclose(fi); - } else - msg(" Couldn't write to %s", buf); - } - - if(charid<0) { - msg(" Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)", - FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars); + if(charid<0 || charid>=swffont->numchars) { + msg(" No character %d in font %s ", charid, FIXNULL((char*)swffont->name)); return 0; } /*if(swffont->glyph[charid].shape->bitlen <= 16) { @@ -773,7 +666,6 @@ static int drawchar(gfxdevice_t*dev, SWFFONT *swffont, char*character, int charn return 0; }*/ - if(i->shapeid>=0) endshape(dev); if(i->textid<0) @@ -796,36 +688,6 @@ static int drawchar(gfxdevice_t*dev, SWFFONT *swffont, char*character, int charn putcharacter(dev, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE, rgba); swf_FontUseGlyph(swffont, charid); return 1; - - /*else - { - SWF_OUTLINE*outline = font->getOutline(character, charnr); - char* charname = character; - - if(!outline) { - msg(" Didn't find character '%s' (%d) in current charset (%s)", - FIXNULL(character),charnr,FIXNULL(font->getName())); - return; - } - - swfmatrix m2=*m; - m2.m11/=100; - m2.m21/=100; - m2.m12/=100; - m2.m22/=100; - - if(textid>=0) - endtext(dev); - if(shapeid<0) - startshape(dev); - - startFill(dev); - - int lf = fill; - fill = 1; - drawpath(tag, outline, &m2, 0); - fill = lf; - }*/ } static void endtext(gfxdevice_t*dev) @@ -838,200 +700,23 @@ static void endtext(gfxdevice_t*dev) swf_SetU16(i->tag, i->textid); SRECT r; - r = getcharacterbbox(dev, i->swffont); + r = getcharacterbbox(dev, i->swffont, &i->fontmatrix); swf_SetRect(i->tag,&r); - MATRIX m; - swf_GetMatrix(0, &m); /* set unit matrix- the real matrix is in the placeobject */ - swf_SetMatrix(i->tag,&m); + swf_SetMatrix(i->tag,&i->fontmatrix); msg(" Placing text (%d characters) as ID %d", i->chardatapos, i->textid); putcharacters(dev, i->tag); swf_SetU8(i->tag,0); i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2); - MATRIX m2; - swf_MatrixJoin(&m2,&i->fontmatrix, &i->page_matrix); - swf_ObjectPlace(i->tag,i->textid,getNewDepth(dev),&m2,NULL,NULL); + swf_ObjectPlace(i->tag,i->textid,getNewDepth(dev),&i->page_matrix,NULL,NULL); i->textid = -1; } -int getCharID(SWFFONT *font, int charnr, char *charname, int u) -{ - int t; - if(charname && font->glyphnames) { - for(t=0;tnumchars;t++) { - if(font->glyphnames[t] && !strcmp(font->glyphnames[t],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;tnumchars;t++) { - if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) { - msg(" Char [%d,>>%s<<,%d] maps to %d\n", charnr, charname, u, t); - return t; - } - } - } - - if(u>0 && font->encoding != 255) { - /* try to use the unicode id */ - if(u>=0 && umaxascii && font->ascii2glyph[u]>=0) { - msg(" Char [%d,%s,>%d<] maps to %d\n", charnr, charname, u, font->ascii2glyph[u]); - return font->ascii2glyph[u]; - } - } - - if(font->encoding != FONT_ENCODING_UNICODE) { - /* the following only works if the font encoding - is US-ASCII based. It's needed for fonts which return broken unicode - indices */ - if(charnr>=0 && charnrmaxascii && font->ascii2glyph[charnr]>=0) { - msg(" Char [>%d<,%s,%d] maps to %d\n", charnr, charname, u, font->ascii2glyph[charnr]); - return font->ascii2glyph[charnr]; - } - } - - if(charnr>=0 && charnrnumchars) { - msg(" Char [>%d<,%s,%d] maps to %d\n", charnr, charname, u, charnr); - return charnr; - } - - return -1; -} - -/* set's the t1 font index of the font to use for swfoutput_drawchar(). */ -static void swfoutput_setfont(gfxdevice_t*dev, char*fontid, char*filename) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - font_active = 0; - fontlist_t*last=0,*iterator; - if(!fontid) { - msg(" No fontid"); - return; - } - - if(i->swffont && i->swffont->name && !strcmp((char*)i->swffont->name,fontid)) - return; - - /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope - with multiple fonts */ - endtext(dev); - - iterator = i->fontlist; - while(iterator) { - if(!strcmp((char*)iterator->swffont->name,fontid)) { - i->swffont = iterator->swffont; - return; - } - last = iterator; - iterator = iterator->next; - } - - if(!filename) { - msg(" No filename given for font- internal error?"); - return; - } - - swf_SetLoadFontParameters(64,/*skip unused*/0,/*full unicode*/1); - SWFFONT*swffont = swf_LoadFont(filename); - - if(i->config_dumpfonts) { - font_active = 1; - font_active_filename = strdup(filename); - } - - if(swffont == 0) { - msg(" Couldn't load font %s (%s)", fontid, filename); - swffont = swf_LoadFont(0); - } - - if(swffont->glyph2ascii) { - int t; - int bad = 0; - /* check whether the Unicode indices look o.k. - If they don't, disable the unicode lookup by setting - the encoding to 255 */ - for(t=0;tnumchars;t++) { - int c = swffont->glyph2ascii[t]; - if(c && c < 32 && swffont->glyph[t].shape->bitlen > 16) { - // the character maps into the unicode control character range - // between 0001-001f. Yet it is not empty. Treat the one - // mapping as broken, and look how many of those we find. - bad ++; - } - } - if(bad>5) { - msg(" Font %s has bad unicode mapping", fontid); - swffont->encoding = 255; - } - } - - if(swffont->encoding != FONT_ENCODING_UNICODE && swffont->encoding != 255) { - msg(" Non-unicode mapping for font %s (%s)", fontid, filename); - } - - swf_FontSetID(swffont, getNewID(dev)); - - if(getScreenLogLevel() >= LOGLEVEL_DEBUG) { - // print font information - msg(" Font %s (%s)",fontid, filename); - msg(" | ID: %d", swffont->id); - msg(" | Version: %d", swffont->version); - msg(" | Name: %s", swffont->name); - msg(" | Numchars: %d", swffont->numchars); - msg(" | Maxascii: %d", swffont->maxascii); - msg(" | Style: %d", swffont->style); - msg(" | Encoding: %d", swffont->encoding); - for(int iii=0; iiinumchars;iii++) { - msg(" | Glyph %d) name=%s, unicode=%d size=%d bbox=(%.2f,%.2f,%.2f,%.2f)\n", iii, swffont->glyphnames?swffont->glyphnames[iii]:"", swffont->glyph2ascii[iii], swffont->glyph[iii].shape->bitlen, - swffont->layout->bounds[iii].xmin/20.0, - swffont->layout->bounds[iii].ymin/20.0, - swffont->layout->bounds[iii].xmax/20.0, - swffont->layout->bounds[iii].ymax/20.0 - ); - int t; - for(t=0;tmaxascii;t++) { - if(swffont->ascii2glyph[t] == iii) - msg(" | - maps to %d",t); - } - } - } - - /* set the font name to the ID we use here */ - if(swffont->name) free(swffont->name); - swffont->name = (U8*)strdup(fontid); - - iterator = new fontlist_t; - iterator->swffont = swffont; - iterator->next = 0; - - if(last) - last->next = iterator; - else - i->fontlist = iterator; - - i->swffont = swffont; -} - -static int swfoutput_queryfont(gfxdevice_t*dev, char*fontid) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - fontlist_t *iterator = i->fontlist; - while(iterator) { - if(!strcmp((char*)iterator->swffont->name,fontid)) - return 1; - iterator = iterator->next; - } - return 0; -} - -/* set's the matrix which is to be applied to characters drawn by - swfoutput_drawchar() */ +/* set's the matrix which is to be applied to characters drawn by swfoutput_drawchar() */ static void swfoutput_setfontmatrix(gfxdevice_t*dev,double m11,double m21, double m12,double m22) { @@ -1060,20 +745,6 @@ static void swfoutput_setfontmatrix(gfxdevice_t*dev,double m11,double m21, i->fontmatrix = m; } -/* draws a character at x,y. */ -int swfoutput_drawchar(gfxdevice_t* dev,double x,double y,char*character, int charnr, int u, gfxcolor_t* color) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - swfmatrix m; - m.m11 = i->fontm11; - m.m12 = i->fontm12; - m.m21 = i->fontm21; - m.m22 = i->fontm22; - m.m31 = x; - m.m32 = y; - return drawchar(dev, i->swffont, character, charnr, u, &m, color); -} - static void endpage(gfxdevice_t*dev) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; @@ -1086,7 +757,39 @@ static void endpage(gfxdevice_t*dev) i->pagefinished = 1; } -void swfoutput_pagefeed(gfxdevice_t*dev) +void swf_startframe(gfxdevice_t*dev, int width, int height) +{ + swfoutput_internal*i = (swfoutput_internal*)dev->internal; + if(!i->firstpage && !i->pagefinished) + endpage(dev); + msg(" Starting new SWF page of size %dx%d", width, height); + + swf_GetMatrix(0, &i->page_matrix); + i->page_matrix.tx = 0; + i->page_matrix.ty = 0; + i->min_x = 0; + i->min_y = 0; + i->max_x = width; + i->max_y = height; + + /* set clipping/background rectangle */ + /* TODO: this should all be done in SWFOutputDev */ + //setBackground(dev, x1, y1, x2, y2); + + /* increase SWF's bounding box */ + SRECT r; + r.xmin = 0; + r.ymin = 0; + r.xmax = width*20; + r.ymax = height*20; + swf_ExpandRect2(&i->swf->movieSize, &r); + + i->lastframeno = i->frameno; + i->firstpage = 0; + i->pagefinished = 0; +} + +void swf_endframe(gfxdevice_t*dev) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; @@ -1142,47 +845,14 @@ static void setBackground(gfxdevice_t*dev, int x1, int y1, int x2, int y2) swf_ObjectPlaceClip(i->tag,shapeid,getNewDepth(dev),0,0,0,65535); } -void swfoutput_newpage(gfxdevice_t*dev, int x1, int y1, int x2, int y2) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - if(!i->firstpage && !i->pagefinished) - endpage(dev); - - swf_GetMatrix(0, &i->page_matrix); - i->page_matrix.tx = 0; - i->page_matrix.ty = 0; - i->min_x = x1; - i->min_y = y1; - i->max_x = x2; - i->max_y = y2; - - x1*=20;y1*=20;x2*=20;y2*=20; - - /* set clipping/background rectangle */ - /* TODO: this should all be done in SWFOutputDev */ - //setBackground(dev, x1, y1, x2, y2); - - /* increase SWF's bounding box */ - SRECT r; - r.xmin = x1; - r.ymin = y1; - r.xmax = x2; - r.ymax = y2; - swf_ExpandRect2(&i->swf->movieSize, &r); - - i->lastframeno = i->frameno; - i->firstpage = 0; - i->pagefinished = 0; -} - /* initialize the swf writer */ void gfxdevice_swf_init(gfxdevice_t* dev) { memset(dev, 0, sizeof(gfxdevice_t)); dev->internal = init_internal_struct(); - dev->startpage = 0; - dev->endpage = 0; + dev->startpage = swf_startframe; + dev->endpage = swf_endframe; dev->finish = swf_finish; dev->fillbitmap = swf_fillbitmap; dev->setparameter = swf_setparameter; @@ -1202,7 +872,7 @@ void gfxdevice_swf_init(gfxdevice_t* dev) SRECT r; RGBA rgb; - msg(" initializing swf output for size %d*%d\n", i->max_x,i->max_y); + msg(" initializing swf output\n", i->max_x,i->max_y); i->swffont = 0; @@ -1368,6 +1038,8 @@ static void endshape_noput(gfxdevice_t*dev) i->shape=0; } i->fill=0; + i->shapeposx=0; + i->shapeposy=0; } static void endshape(gfxdevice_t*dev) @@ -1401,14 +1073,19 @@ static void endshape(gfxdevice_t*dev) msg(" Placing shape id %d", i->shapeid); i->tag = swf_InsertTag(i->tag,ST_PLACEOBJECT2); - swf_ObjectPlace(i->tag,i->shapeid,getNewDepth(dev),&i->page_matrix,NULL,NULL); + MATRIX m = i->page_matrix; + m.tx += i->shapeposx; + m.ty += i->shapeposy; + swf_ObjectPlace(i->tag,i->shapeid,getNewDepth(dev),&m,NULL,NULL); swf_ShapeFree(i->shape); i->shape = 0; i->shapeid = -1; i->bboxrectpos = -1; - i->fill=0; + i->fill=0; + i->shapeposx=0; + i->shapeposy=0; } void wipeSWF(SWF*swf) @@ -1461,7 +1138,7 @@ void swfoutput_finalize(gfxdevice_t*dev) } if(i->frameno == i->lastframeno) // fix: add missing pagefeed - swfoutput_pagefeed(dev); + dev->endpage(dev); endpage(dev); fontlist_t *tmp,*iterator = i->fontlist; @@ -1665,7 +1342,8 @@ void swf_drawlink(gfxdevice_t*dev, gfxline_t*points, char*url) if(url[t]<'0' || url[t]>'9') nodigit = 1; if(!nodigit) { - int page = atoi(&url[4]); + int page = atoi(&url[4]) - 1; + if(page<0) page = 0; swfoutput_linktopage(dev, page, points); } } else { @@ -1945,36 +1623,6 @@ for(t=0;tinternal; - dev->stroke(dev, line, width, col, cap_style, joint_style, miterLimit); -} -void swfoutput_fillgfxline(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*col) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - dev->fill(dev, line, col); -} -void swfoutput_startclip(gfxdevice_t*dev, gfxline_t*line) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - dev->startclip(dev, line); -} -void swfoutput_endclip(gfxdevice_t*dev) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - dev->endclip(dev); -} -void swfoutput_gfxaddfont(gfxdevice_t*dev, char*fontid, gfxfont_t*font) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - dev->addfont(dev, fontid, font); -} -void swfoutput_gfxdrawchar(gfxdevice_t*dev, char*fontid, int glyph, gfxcolor_t*c, gfxmatrix_t*m) -{ - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - dev->drawchar(dev, fontid, glyph, c, m); -} int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value) { @@ -2061,14 +1709,16 @@ static CXFORM gfxcxform_to_cxform(gfxcxform_t* c) return cx; } -static ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit) +static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line) { ArtVpath *vec = NULL; - ArtSVP *svp = NULL; int pos=0,len=0; gfxline_t*l2; double x=0,y=0; + /* factor which determines into how many line fragments a spline is converted */ + double subfraction = 2.4;//0.3 + l2 = line; while(l2) { if(l2->type == gfx_moveTo) { @@ -2076,7 +1726,7 @@ static ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_ } if(l2->type == gfx_lineTo) { pos ++; } if(l2->type == gfx_splineTo) { - int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))/3); + int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))*subfraction); if(!parts) parts = 1; pos += parts + 1; } @@ -2106,7 +1756,7 @@ static ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_ assert(pos<=len); } else if(l2->type == gfx_splineTo) { int i; - int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))/3); + int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))*subfraction); if(!parts) parts = 1; for(i=0;i<=parts;i++) { double t = (double)i/(double)parts; @@ -2122,8 +1772,22 @@ static ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_ l2 = l2->next; } vec[pos].code = ART_END; - - svp = art_svp_vpath_stroke (vec, + + return vec; +} + +static ArtSVP* gfxfillToSVP(gfxline_t*line) +{ + ArtVpath* vec = gfxline_to_ArtVpath(line); + ArtSVP *svp = art_svp_from_vpath(vec); + free(vec); + return svp; +} + +static ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit) +{ + ArtVpath* vec = gfxline_to_ArtVpath(line); + ArtSVP *svp = art_svp_vpath_stroke (vec, (joint_style==gfx_joinMiter)?ART_PATH_STROKE_JOIN_MITER: ((joint_style==gfx_joinRound)?ART_PATH_STROKE_JOIN_ROUND: ((joint_style==gfx_joinBevel)?ART_PATH_STROKE_JOIN_BEVEL:ART_PATH_STROKE_JOIN_BEVEL)), @@ -2204,8 +1868,6 @@ static int add_image(swfoutput_internal*i, gfximage_t*img, int targetwidth, int return -1; /* TODO: cache images */ - *newwidth = sizex; - *newheight = sizey; if(newsizex Scaling %dx%d image to %dx%d", sizex, sizey, newsizex, newsizey); @@ -2213,7 +1875,9 @@ static int add_image(swfoutput_internal*i, gfximage_t*img, int targetwidth, int *newwidth = sizex = newsizex; *newheight = sizey = newsizey; mem = newpic; - + } else { + *newwidth = newsizex = sizex; + *newheight = newsizey = sizey; } int num_colors = swf_ImageGetNumberOfPaletteEntries(mem,sizex,sizey,0); @@ -2454,25 +2118,64 @@ static int gfxline_fix_short_edges(gfxline_t*line) return 0; } +static char is_inside_page(gfxdevice_t*dev, gfxcoord_t x, gfxcoord_t y) +{ + swfoutput_internal*i = (swfoutput_internal*)dev->internal; + if(xmin_x || x>i->max_x) return 0; + if(ymin_y || y>i->max_y) return 0; + return 1; +} + +static void show_path(ArtSVP*path) +{ + int t; + printf("Segments: %d\n", path->n_segs); + for(t=0;tn_segs;t++) { + ArtSVPSeg* seg = &path->segs[t]; + printf("Segment %d: %d points, %s, BBox: (%f,%f,%f,%f)\n", + t, seg->n_points, seg->dir==0?"UP ":"DOWN", + seg->bbox.x0, seg->bbox.y0, seg->bbox.x1, seg->bbox.y1); + int p; + for(p=0;pn_points;p++) { + ArtPoint* point = &seg->points[p]; + printf(" (%f,%f)\n", point->x, point->y); + } + } + printf("\n"); +} + +gfxline_t* gfxline_move(gfxline_t*line, double x, double y) +{ + gfxline_t*l = line = gfxline_clone(line); + + while(l) { + l->x += x; + l->y += y; + l->sx += x; + l->sy += y; + l = l->next; + } + return line; +} + +#define NORMALIZE_POLYGON_POSITIONS + static void swf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; int type = gfxline_type(line); int has_dots = gfxline_has_dots(line); + gfxbbox_t r = gfxline_getbbox(line); + int is_outside_page = !is_inside_page(dev, r.xmin, r.ymin) || !is_inside_page(dev, r.xmax, r.ymax); /* TODO: * split line into segments, and perform this check for all segments */ - if(!has_dots && + + if(!has_dots && (width <= i->config_caplinewidth || (cap_style == gfx_capRound && joint_style == gfx_joinRound) - || (cap_style == gfx_capRound && type<=2))) { - msg(" draw as stroke, type=%d dots=%d", type, has_dots); - endtext(dev); - swfoutput_setstrokecolor(dev, color->r, color->g, color->b, color->a); - swfoutput_setlinewidth(dev, width); - startshape(dev); - stopFill(dev); - drawgfxline(dev, line); - } else { + || (cap_style == gfx_capRound && type<=2))) {} else + { + /* convert line to polygon */ msg(" draw as polygon, type=%d dots=%d", type, has_dots); if(has_dots) gfxline_fix_short_edges(line); @@ -2482,20 +2185,67 @@ static void swf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcol dev->fill(dev, gfxline, color); free(gfxline); art_svp_free(svp); + return; } + + msg(" draw as stroke, type=%d dots=%d", type, has_dots); + endtext(dev); + +#ifdef NORMALIZE_POLYGON_POSITIONS + endshape(dev); + double startx = 0, starty = 0; + if(line && line->type == gfx_moveTo) { + startx = line->x; + starty = line->y; + } + line = gfxline_move(line, -startx, -starty); + i->shapeposx = (int)(startx*20); + i->shapeposy = (int)(starty*20); +#endif + + swfoutput_setstrokecolor(dev, color->r, color->g, color->b, color->a); + swfoutput_setlinewidth(dev, width); + startshape(dev); + stopFill(dev); + drawgfxline(dev, line); + +#ifdef NORMALIZE_POLYGON_POSITIONS + free(line); //account for _move +#endif + } static void swf_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; + gfxbbox_t r = gfxline_getbbox(line); + int is_outside_page = !is_inside_page(dev, r.xmin, r.ymin) || !is_inside_page(dev, r.xmax, r.ymax); + endtext(dev); if(!i->config_ignoredraworder) endshape(dev); + +#ifdef NORMALIZE_POLYGON_POSITIONS + endshape(dev); + double startx = 0, starty = 0; + if(line && line->type == gfx_moveTo) { + startx = line->x; + starty = line->y; + } + line = gfxline_move(line, -startx, -starty); + i->shapeposx = (int)(startx*20); + i->shapeposy = (int)(starty*20); +#endif + swfoutput_setfillcolor(dev, color->r, color->g, color->b, color->a); startshape(dev); startFill(dev); i->fill=1; drawgfxline(dev, line); msg(" end of swf_fill (shapeid=%d)", i->shapeid); + +#ifdef NORMALIZE_POLYGON_POSITIONS + free(line); //account for _move +#endif } static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) { @@ -2649,5 +2399,5 @@ static void swf_drawchar(gfxdevice_t*dev, char*fontid, int glyph, gfxcolor_t*col m.m22 = i->fontm22; m.m31 = matrix->tx; m.m32 = matrix->ty; - drawchar(dev, i->swffont, 0, glyph, -1, &m, color); + drawchar(dev, i->swffont, glyph, &m, color); }