From a7f355d5422ffa13494a3fd0cab675828ad14735 Mon Sep 17 00:00:00 2001 From: kramm Date: Wed, 30 Apr 2003 14:35:48 +0000 Subject: [PATCH] added support for line caps. --- pdf2swf/swfoutput.cc | 349 +++++++++++++++++++++++++++++++++++++++++++++++--- pdf2swf/swfoutput.h | 9 ++ 2 files changed, 337 insertions(+), 21 deletions(-) diff --git a/pdf2swf/swfoutput.cc b/pdf2swf/swfoutput.cc index 75f8bda..47ec619 100644 --- a/pdf2swf/swfoutput.cc +++ b/pdf2swf/swfoutput.cc @@ -30,6 +30,8 @@ extern "C" { #define standardEncodingSize 335 extern char *standardEncodingNames[standardEncodingSize]; +#define assert(a) + int opennewwindow=0; int ignoredraworder=0; int drawonlyshapes=0; @@ -38,6 +40,8 @@ int storeallcharacters=0; int enablezlib=0; int insertstoptag=0; int flashversion=4; +int splinemaxerror=1; +int fontsplinemaxerror=1; static int flag_protected = 0; typedef unsigned char u8; @@ -163,10 +167,10 @@ static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmat if(storefont) { /* fonts use a different approximation than shapes */ - num = cspline_approximate(&c, q, 0.05, APPROXIMATE_RECURSIVE_BINARY); + num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY); //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION); } else { - num = cspline_approximate(&c, q, 0.05, APPROXIMATE_RECURSIVE_BINARY); + num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY); } for(t=0;tid != ST_DEFINEFONT && @@ -272,6 +295,289 @@ void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log) } } +plotxy getPivot(T1_OUTLINE*outline, int dir, double line_width, int end) +{ + T1_PATHPOINT next, next2; + double xv=0,yv=0, xv2=0, yv2=0; + plotxy p; + int two = 0; + + if(!end) { + if(outline->type == T1_PATHTYPE_LINE) { + next = outline->dest; + } else { + next = ((T1_BEZIERSEGMENT*)outline)->B; + if(next.x==0 && next.y==0) { + next = ((T1_BEZIERSEGMENT*)outline)->C; + } + if(next.x==0 && next.y==0) { + next = ((T1_BEZIERSEGMENT*)outline)->dest; + } + } + next2 = next; + if(outline->last && outline->last->type != T1_PATHTYPE_MOVE) { + if(outline->type == T1_PATHTYPE_LINE) { + next2 = outline->last->dest; + } else { + T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)(outline->last))->C; + T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)(outline->last))->B; + next2.x = outline->last->dest.x - c.x; + next2.y = outline->last->dest.y - c.y; + if(next2.x==0 && next2.y==0) { + next2.x = outline->last->dest.x - b.x; + next2.y = outline->last->dest.y - b.y; + } + if(next2.x==0 && next2.y==0) { + next2.x = outline->last->dest.x; + next2.y = outline->last->dest.y; + } + } + two = 1; + } + } else { + if(outline->type == T1_PATHTYPE_LINE) { + next = outline->dest; + } else { + T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)outline)->C; + T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)outline)->B; + next.x = outline->dest.x - c.x; + next.y = outline->dest.y - c.y; + if(next.x==0 && next.y==0) { + next.x = outline->dest.x - b.x; + next.y = outline->dest.y - b.y; + } + if(next.x==0 && next.y==0) { + next.x = outline->dest.x; + next.y = outline->dest.y; + } + } + next2 = next; + if(outline->link && outline->link->type != T1_PATHTYPE_MOVE) { + if(outline->type == T1_PATHTYPE_LINE) { + next2 = outline->link->dest; + } else { + next2 = ((T1_BEZIERSEGMENT*)(outline->link))->B; + if(next2.x==0 && next2.y==0) { + next2 = ((T1_BEZIERSEGMENT*)outline->link)->C; + } + if(next2.x==0 && next2.y==0) { + next2 = ((T1_BEZIERSEGMENT*)outline->link)->dest; + } + } + two = 1; + } + } + + if(dir) { + xv = next.y/(float)0xffff; + yv = -next.x/(float)0xffff; + } else { + xv = -next.y/(float)0xffff; + yv = next.x/(float)0xffff; + } + + double r = line_width/sqrt(xv*xv+yv*yv); + xv*=r; + yv*=r; + + if(two) { + if(dir) { + xv2 = next2.y/(float)0xffff; + yv2 = -next2.x/(float)0xffff; + } else { + xv2 = -next2.y/(float)0xffff; + yv2 = next2.x/(float)0xffff; + } + + double r2 = line_width/sqrt(xv2*xv2+yv2*yv2); + xv2*=r2; + yv2*=r2; + xv = (xv+xv2)/2; + yv = (yv+yv2)/2; + double r3 = line_width/sqrt(xv*xv+yv*yv); + xv *= r3; + yv *= r3; + } + + p.x = xv; + p.y = yv; + return p; +} + +void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width) +{ + double lastx=x, lasty=y; + plotxy d,d2; + int back = 0; + + if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) { + endshape(); + startshape(output); + T1_OUTLINE *last, *tmp=outline; + plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3; + double x2 = x; + double y2 = y; + double lx=x,ly=y; + int nr; + while(tmp && tmp->type != T1_PATHTYPE_MOVE) { + last = tmp; + lx += (tmp->dest.x/(float)0xffff); + ly += (tmp->dest.y/(float)0xffff); + tmp = tmp->link; + } + s = getPivot(outline, 0, line_width, 0); + e = getPivot(last, 0, line_width, 1); + + s.x/=2; + s.y/=2; + e.x/=2; + e.y/=2; + + p0.x = x2 + s.x; + p0.y = y2 + s.y; + p1.x = x2 - s.x; + p1.y = y2 - s.y; + p2.x = x2 - s.y - s.x; + p2.y = y2 + s.x - s.y; + p3.x = x2 - s.y + s.x; + p3.y = y2 + s.x + s.y; + m0.x = lx + e.x; + m0.y = ly + e.y; + m1.x = lx - e.x; + m1.y = ly - e.y; + m2.x = lx + e.y - e.x; + m2.y = ly - e.x - e.y; + m3.x = lx + e.y + e.x; + m3.y = ly - e.x + e.y; + + for(nr=0;nr<2;nr++) { + int dir=0; + struct plotxy q0,q1,q2,q3,q4,q5; + startFill(); + if(line_cap == LINE_CAP_BUTT) { + if(dir) { + q0.x = 0; q0.y = 0; + q1.x = sizex; q1.y = 0; + q2.x = sizex; q2.y = sizey; + q3.x = 0; q3.y = sizey; + } else { + q0.x = sizex; q0.y = sizey; + q1.x = 0; q1.y = sizey; + q2.x = 0; q2.y = 0; + q3.x = sizex; q3.y = 0; + } + q4.x = p0.x; + q4.y = p0.y; + moveto(tag, q0); + lineto(tag, q1); + lineto(tag, q2); + lineto(tag, q3); + lineto(tag, q0); + + transform(&q4,m); + lineto(tag, q4); + } + + line(tag, p0, p1, m); + line(tag, p1, p2, m); + line(tag, p2, p3, m); + line(tag, p3, p0, m); + + if(line_cap == LINE_CAP_BUTT) { + lineto(tag, q0); + swf_ShapeSetEnd(tag); + tag = swf_InsertTag(tag, ST_PLACEOBJECT2); + swf_ObjectPlaceClip(tag,shapeid,depth,NULL,NULL,NULL,depth+2-nr); + depth++; + shapeid = -1; + startshape(output); + } + p0 = m0; + p1 = m1; + p2 = m2; + p3 = m3; + } + + stopFill(); + } + + while (outline && outline->type != T1_PATHTYPE_MOVE) + { + x += (outline->dest.x/(float)0xffff); + y += (outline->dest.y/(float)0xffff); + + if(outline->type == T1_PATHTYPE_LINE) + { + plotxy p0, p1; + p0.x=lastx; + p0.y=lasty; + p1.x= x; + p1.y= y; + line(tag, p0, p1, m); + } + else if(outline->type == T1_PATHTYPE_BEZIER) + { + plotxy p0,p1,p2,p3; + T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline; + p3.x=lastx; + p3.y=lasty; + p1.x=o2->C.x/(float)0xffff+lastx; + p1.y=o2->C.y/(float)0xffff+lasty; + p2.x=o2->B.x/(float)0xffff+lastx; + p2.y=o2->B.y/(float)0xffff+lasty; + p0.x=x; + p0.y=y; + spline(tag,p0,p1,p2,p3,m); + } + lastx=x; + lasty=y; + outline = outline->link; + } + if(line_cap == LINE_CAP_BUTT) { + endshape(); + } +} + +void drawpath2poly(struct swfoutput *output, T1_OUTLINE*outline, struct swfmatrix*m, int log, int line_join, int line_cap, double line_width, double miter_limit) +{ + if(tag->id != ST_DEFINEFONT && + tag->id != ST_DEFINESHAPE && + tag->id != ST_DEFINESHAPE2 && + tag->id != ST_DEFINESHAPE3) { + logf(" internal error: drawpath needs a shape tag, not %d\n",tag->id); + exit(1); + } + double x=0,y=0; + double lastx=0,lasty=0; + int valid = 0; + T1_OUTLINE*tmp = outline, *last = 0; + tmp->last = 0; + + while(tmp) { + x += (tmp->dest.x/(float)0xffff); + y += (tmp->dest.y/(float)0xffff); + if(tmp->type == T1_PATHTYPE_MOVE) { + if(valid && last) { + drawShortPath(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width); + } + valid = 0; + last = 0; + lastx = x; + lasty = y; + } else { + if(!last) + last = tmp; + valid++; + } + if(tmp->link) + tmp->link->last = tmp; // make sure list is properly linked in both directions + tmp = tmp->link; + } + if(valid && last) { + drawShortPath(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width); + } +} + static inline int colorcompare(RGBA*a,RGBA*b) { @@ -486,11 +792,7 @@ static void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int cha if(shapeid<0) startshape(obj); - if(!lastwasfill) { - swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0); - fillstylechanged = 1; - } - lastwasfill = 1; + startFill(); int lf = fill; fill = 1; @@ -516,22 +818,27 @@ void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline, if(shapeid<0) startshape(output); - if(lastwasfill && !fill) - { - swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0); - fillstylechanged = 1; - lastwasfill = 0; - } - if(!lastwasfill && fill) - { - swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0); - fillstylechanged = 1; - lastwasfill = 1; - } + if(!fill) + stopFill(); + else + startFill(); drawpath(tag, outline,m, 0); } +void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit) +{ + if(textid>=0) + endtext(); + if(shapeid>=0) + endshape(); + assert(shapeid<0); + startshape(output); + stopFill(); + + drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit); +} + /* SWFFont: copy all t1 font outlines to a local array. */ SWFFont::SWFFont(char*name, int id, char*filename) diff --git a/pdf2swf/swfoutput.h b/pdf2swf/swfoutput.h index 5bd8ee0..fa5b174 100644 --- a/pdf2swf/swfoutput.h +++ b/pdf2swf/swfoutput.h @@ -27,6 +27,8 @@ extern int jpegquality; //default:100; extern int storeallcharacters; // default:0 extern int insertstoptag; //default:0 extern int flashversion; //default:4 +extern int splinemaxerror; //default:1 +extern int fontsplinemaxerror; //default:1 typedef long int twip; @@ -103,6 +105,13 @@ void swfoutput_setlinewidth(struct swfoutput*, double linewidth); void swfoutput_drawchar(struct swfoutput*,double x,double y,char*a, int charnr); void swfoutput_drawpath(struct swfoutput*, T1_OUTLINE*outline, struct swfmatrix*m); +#define LINE_CAP_BUTT 0 +#define LINE_CAP_ROUND 1 +#define LINE_CAP_SQUARE 2 +#define LINE_JOIN_MITER 0 +#define LINE_JOIN_ROUND 1 +#define LINE_JOIN_BEVEL 2 +void swfoutput_drawpath2poly(struct swfoutput*, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit); void swfoutput_startclip(struct swfoutput*, T1_OUTLINE*outline, struct swfmatrix*m); void swfoutput_endclip(struct swfoutput*); int swfoutput_drawimagejpeg(struct swfoutput*, RGBA*pic, int sizex,int sizey, -- 1.7.10.4