X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fdevices%2Fswf.c;h=51a1123d5b39443aa6ce9f8014073957fea4890b;hb=644fa66941dd88b81b2e49638b73714224022c38;hp=4e623b0a2161b3ad7e8da2794535bec681bf4ffd;hpb=c4bf7f42ef038c285b5a53f0a43f68f5c7f339e6;p=swftools.git diff --git a/lib/devices/swf.c b/lib/devices/swf.c index 4e623b0..51a1123 100644 --- a/lib/devices/swf.c +++ b/lib/devices/swf.c @@ -82,10 +82,13 @@ typedef struct _swfoutput_internal int config_filloverlap; int config_protect; int config_bboxvars; + int config_disable_polygon_conversion; RGBA config_linkcolor; float config_minlinewidth; double config_caplinewidth; char* config_linktarget; + char*config_internallinkfunction; + char*config_externallinkfunction; SWF* swf; @@ -154,6 +157,8 @@ typedef struct _swfoutput_internal int shapeposx; int shapeposy; + char* mark; + } swfoutput_internal; static void swf_fillbitmap(gfxdevice_t*driver, gfxline_t*line, gfximage_t*img, gfxmatrix_t*move, gfxcxform_t*cxform); @@ -188,6 +193,8 @@ static swfoutput_internal* init_internal_struct() i->frameno = 0; i->lastframeno = 0; + i->mark = 0; + i->fillstyleid; i->linestyleid; i->swflastx=0; @@ -224,6 +231,8 @@ static swfoutput_internal* init_internal_struct() i->config_minlinewidth=0.05; i->config_caplinewidth=1; i->config_linktarget=0; + i->config_internallinkfunction=0; + i->config_externallinkfunction=0; i->config_linkcolor.r = i->config_linkcolor.g = i->config_linkcolor.b = 255; i->config_linkcolor.a = 0x40; @@ -241,6 +250,7 @@ static U16 getNewID(gfxdevice_t* dev) msg(" ID Table overflow"); id_error=1; i->overflow = 1; + exit(1); } return ++i->currentswfid; } @@ -252,6 +262,7 @@ static U16 getNewDepth(gfxdevice_t* dev) msg(" Depth Table overflow"); id_error=1; i->overflow = 1; + exit(1); } return ++i->depth; } @@ -375,15 +386,18 @@ static void splineto(gfxdevice_t*dev, TAG*tag, plotxy_t control,plotxy_t end) i->swflastx += ex; i->swflasty += ey; - if(cx || cy || ex || ey) { - swf_ShapeSetCurve(tag, i->shape, cx,cy,ex,ey); - addPointToBBox(dev, lastlastx ,lastlasty ); - addPointToBBox(dev, lastlastx+cx,lastlasty+cy); - addPointToBBox(dev, lastlastx+cx+ex,lastlasty+cy+ey); - }/* else if(!i->fill) { - // treat splines of length 0 as plots - plot(dev, lastlastx, lastlasty, tag); - }*/ + if((cx || cy) && (ex || ey)) { + swf_ShapeSetCurve(tag, i->shape, cx,cy,ex,ey); + addPointToBBox(dev, lastlastx ,lastlasty ); + addPointToBBox(dev, lastlastx+cx,lastlasty+cy); + addPointToBBox(dev, lastlastx+cx+ex,lastlasty+cy+ey); + } else if(cx || cy || ex || ey) { + swf_ShapeSetLine(tag, i->shape, cx+ex,cy+ey); + addPointToBBox(dev, lastlastx ,lastlasty ); + addPointToBBox(dev, lastlastx+cx,lastlasty+cy); + addPointToBBox(dev, lastlastx+cx+ex,lastlasty+cy+ey); + } + i->shapeisempty = 0; } @@ -405,7 +419,7 @@ void resetdrawer(gfxdevice_t*dev) static void stopFill(gfxdevice_t*dev) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; - if(i->lastwasfill) + if(i->lastwasfill!=0) { swf_ShapeSetStyle(i->tag,i->shape,i->linestyleid,0x8000,0); i->fillstylechanged = 1; @@ -415,7 +429,7 @@ static void stopFill(gfxdevice_t*dev) static void startFill(gfxdevice_t*dev) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; - if(!i->lastwasfill) + if(i->lastwasfill!=1) { swf_ShapeSetStyle(i->tag,i->shape,0x8000,i->fillstyleid,0); i->fillstylechanged = 1; @@ -915,11 +929,15 @@ static void startshape(gfxdevice_t*dev) if(i->textid>=0) endtext(dev); - i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE); + i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE3); swf_ShapeNew(&i->shape); i->linestyleid = swf_ShapeAddLineStyle(i->shape,i->linewidth,&i->strokergb); i->fillstyleid = swf_ShapeAddSolidFillStyle(i->shape,&i->fillrgb); + if(i->mark) { + RGBA markcol = {0,i->mark[0],i->mark[1],i->mark[2]}; + swf_ShapeAddSolidFillStyle(i->shape,&markcol); + } i->shapeid = getNewID(dev); @@ -942,9 +960,10 @@ static void startshape(gfxdevice_t*dev) swf_SetShapeBits(i->tag,i->shape); /* TODO: do we really need this? */ - swf_ShapeSetAll(i->tag,i->shape,/*x*/0,/*y*/0,i->linestyleid,0,0); - i->swflastx=i->swflasty=0; - i->lastwasfill = 0; + //swf_ShapeSetAll(i->tag,i->shape,/*x*/0,/*y*/0,i->linestyleid,0,0); + //swf_ShapeSetAll(i->tag,i->shape,/*x*/UNDEFINED_COORD,/*y*/UNDEFINED_COORD,i->linestyleid,0,0); + i->swflastx=i->swflasty=UNDEFINED_COORD; + i->lastwasfill = -1; i->shapeisempty = 1; } @@ -993,6 +1012,8 @@ void cancelshape(gfxdevice_t*dev) if(i->shape) {swf_ShapeFree(i->shape);i->shape=0;} i->shapeid = -1; i->bboxrectpos = -1; + +// i->currentswfid--; // this was an *exceptionally* bad idea } void fixAreas(gfxdevice_t*dev) @@ -1025,6 +1046,7 @@ void fixAreas(gfxdevice_t*dev) if(i->linewidth==0) i->linewidth = 1; startshape(dev); + stopFill(dev); moveto(dev, i->tag, r.xmin/20.0,r.ymin/20.0); lineto(dev, i->tag, r.xmax/20.0,r.ymax/20.0); @@ -1149,6 +1171,10 @@ void swfoutput_finalize(gfxdevice_t*dev) if(i->frameno == i->lastframeno) // fix: add missing pagefeed dev->endpage(dev); + if(i->mark) { + free(i->mark);i->mark = 0; + } + endpage(dev); fontlist_t *tmp,*iterator = i->fontlist; while(iterator) { @@ -1374,20 +1400,25 @@ void swf_drawlink(gfxdevice_t*dev, gfxline_t*points, char*url) } void swfoutput_linktourl(gfxdevice_t*dev, char*url, gfxline_t*points) { - ActionTAG* actions; + ActionTAG* actions = 0; swfoutput_internal*i = (swfoutput_internal*)dev->internal; if(i->shapeid>=0) endshape(dev); if(i->textid>=0) endtext(dev); - - if(!i->config_linktarget) { + + if(i->config_externallinkfunction) { + actions = action_PushString(actions, url); //parameter + actions = action_PushInt(actions, 1); //number of parameters (1) + actions = action_PushString(actions, i->config_externallinkfunction); //function name + actions = action_CallFunction(actions); + } else if(!i->config_linktarget) { if(!i->config_opennewwindow) - actions = action_GetUrl(0, url, "_parent"); + actions = action_GetUrl(actions, url, "_parent"); else - actions = action_GetUrl(0, url, "_this"); + actions = action_GetUrl(actions, url, "_this"); } else { - actions = action_GetUrl(0, url, i->config_linktarget); + actions = action_GetUrl(actions, url, i->config_linktarget); } actions = action_End(actions); @@ -1396,15 +1427,22 @@ void swfoutput_linktourl(gfxdevice_t*dev, char*url, gfxline_t*points) void swfoutput_linktopage(gfxdevice_t*dev, int page, gfxline_t*points) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; - ActionTAG* actions; + ActionTAG* actions = 0; if(i->shapeid>=0) endshape(dev); if(i->textid>=0) endtext(dev); - - actions = action_GotoFrame(0, page); - actions = action_End(actions); + + if(!i->config_internallinkfunction) { + actions = action_GotoFrame(actions, page); + actions = action_End(actions); + } else { + actions = action_PushInt(actions, page); //parameter + actions = action_PushInt(actions, 1); //number of parameters (1) + actions = action_PushString(actions, i->config_internallinkfunction); //function name + actions = action_CallFunction(actions); + } drawlink(dev, actions, 0, points,0); } @@ -1665,6 +1703,15 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value) i->config_drawonlyshapes = atoi(value); } else if(!strcmp(name, "ignoredraworder")) { i->config_ignoredraworder = atoi(value); + } else if(!strcmp(name, "mark")) { + if(!value || !value[0]) { + if(i->mark) free(i->mark); + i->mark = 0; + } else { + int t; + i->mark = strdup("..."); + for(t=0;t<3;t++) if(value[t]) i->mark[t] = value[t]; + } } else if(!strcmp(name, "filloverlap")) { i->config_filloverlap = atoi(value); } else if(!strcmp(name, "linksopennewwindow")) { @@ -1677,6 +1724,12 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value) i->config_enablezlib = atoi(value); } else if(!strcmp(name, "bboxvars")) { i->config_bboxvars = atoi(value); + } else if(!strcmp(name, "internallinkfunction")) { + i->config_internallinkfunction = strdup(value); + } else if(!strcmp(name, "externallinkfunction")) { + i->config_externallinkfunction = strdup(value); + } else if(!strcmp(name, "disable_polygon_conversion")) { + i->config_disable_polygon_conversion = atoi(value); } else if(!strcmp(name, "insertstop")) { i->config_insertstoptag = atoi(value); } else if(!strcmp(name, "protect")) { @@ -2047,12 +2100,16 @@ static void swf_startclip(gfxdevice_t*dev, gfxline_t*line) } int myshapeid = getNewID(dev); - i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE); + i->tag = swf_InsertTag(i->tag,ST_DEFINESHAPE3); RGBA col; memset(&col, 0, sizeof(RGBA)); SHAPE*shape; swf_ShapeNew(&shape); int fsid = swf_ShapeAddSolidFillStyle(shape,&col); + if(i->mark) { + RGBA markcol = {0,i->mark[0],i->mark[1],i->mark[2]}; + swf_ShapeAddSolidFillStyle(shape,&markcol); + } swf_SetU16(i->tag,myshapeid); SRECT r = gfxline_getSWFbbox(line); swf_SetRect(i->tag,&r); @@ -2124,12 +2181,24 @@ static int gfxline_type(gfxline_t*line) static int gfxline_has_dots(gfxline_t*line) { int tmplines=0; - double x,y; + double x=0,y=0; double dist = 0; int isline = 0; + int short_gap = 0; while(line) { if(line->type == gfx_moveTo) { - if(isline && dist < 1) { + /* test the length of the preceding line, and assume it is a dot if + it's length is less than 1.0. But *only* if there's a noticable + gap between the previous line and the next moveTo. (I've come + across a PDF where thousands of "dots" were stringed together, + forming a line) */ + int last_short_gap = short_gap; + if((fabs(line->x - x) + fabs(line->y - y)) < 1.0) { + short_gap = 1; + } else { + short_gap = 0; + } + if(isline && dist < 1 && !short_gap && !last_short_gap) { return 1; } dist = 0; @@ -2146,7 +2215,7 @@ static int gfxline_has_dots(gfxline_t*line) y = line->y; line = line->next; } - if(isline && dist < 1) { + if(isline && dist < 1 && !short_gap) { return 1; } return 0; @@ -2225,10 +2294,11 @@ static void swf_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcol /* TODO: * split line into segments, and perform this check for all segments */ - if(!has_dots && - (width <= i->config_caplinewidth + if(i->config_disable_polygon_conversion || + (!has_dots && + (width <= i->config_caplinewidth || (cap_style == gfx_capRound && joint_style == gfx_joinRound) - || (cap_style == gfx_capRound && type<=2))) {} else + || (cap_style == gfx_capRound && type<=2)))) {} else { /* convert line to polygon */ msg(" draw as polygon, type=%d dots=%d", type, has_dots); @@ -2333,13 +2403,14 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, char* id) for(t=0;tnum_glyphs;t++) { drawer_t draw; gfxline_t*line; + int advance = 0; 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); + advance = (int)(font->glyphs[t].advance); swf_Shape01DrawerInit(&draw, 0); line = font->glyphs[t].line; @@ -2359,6 +2430,18 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, char* id) draw.finish(&draw); swffont->glyph[t].shape = swf_ShapeDrawerToShape(&draw); swffont->layout->bounds[t] = swf_ShapeDrawerGetBBox(&draw); + + if(swffont->layout->bounds[t].xmax && swffont->layout->bounds[t].xmax*2 < advance) { + printf("fix bad advance value: bbox=%d, advance=%d (%f)\n", swffont->layout->bounds[t].xmax, advance, font->glyphs[t].advance); + advance = swffont->layout->bounds[t].xmax; + } + + if(advance<32768) { + swffont->glyph[t].advance = advance; + } else { + swffont->glyph[t].advance = 32767; + } + draw.dealloc(&draw); swf_ExpandRect2(&bounds, &swffont->layout->bounds[t]);