From: kramm Date: Sun, 19 Jun 2005 12:42:47 +0000 (+0000) Subject: * several cleanups X-Git-Tag: release-0-7-0~41 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=b9042754dba87cf5c924274c221b265a3e6c54fd * several cleanups * the only public funciton is gfxdevice_swf_init() now * fixed spline->line quality --- diff --git a/pdf2swf/swfoutput.cc b/pdf2swf/swfoutput.cc index 5bfe250..17e0fd2 100644 --- a/pdf2swf/swfoutput.cc +++ b/pdf2swf/swfoutput.cc @@ -151,7 +151,6 @@ typedef struct _swfoutput_internal RGBA strokergb; RGBA fillrgb; int drawmode; - int x1,y1,x2,y2; } swfoutput_internal; @@ -167,6 +166,8 @@ 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); @@ -255,16 +256,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 +413,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 +425,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 +461,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, @@ -796,36 +704,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,23 +716,19 @@ 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; } @@ -904,134 +778,7 @@ int getCharID(SWFFONT *font, int charnr, char *charname, int u) 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 +807,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 +819,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 +907,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 +934,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; @@ -1461,7 +1193,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; @@ -1945,36 +1677,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 +1763,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 = 1.2;//0.3 + l2 = line; while(l2) { if(l2->type == gfx_moveTo) { @@ -2076,7 +1780,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 +1810,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 +1826,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)), @@ -2454,14 +2172,44 @@ 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"); +} + + 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))) { @@ -2487,6 +2235,9 @@ static void swf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcol 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);