X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgfxpoly%2Fstroke.c;h=9735c1be601a4c548fb1ea4082738772afe445ac;hp=70a51d02427365b521ed0e57843496f4528a9d74;hb=be6d3cbb485c5f7e9dd6fe22bf54245c79b10b71;hpb=3c6c2c2a98a273483285119b9cc0b782aa8a79c8 diff --git a/lib/gfxpoly/stroke.c b/lib/gfxpoly/stroke.c index 70a51d0..9735c1b 100644 --- a/lib/gfxpoly/stroke.c +++ b/lib/gfxpoly/stroke.c @@ -37,17 +37,15 @@ static void draw_arc(gfxdrawer_t*draw, double x, double y, double a1, double a2, possible values for step */ double r2 = r*(2-sqrt(0.5+0.5*cos(step))); + draw->lineTo(draw, x+cos(a1)*r,y+sin(a1)*r); for(t=1;t<=steps;t++) { double a = a1 + t*step; double c = cos(a)*r; double s = sin(a)*r; double xx = c + x; double yy = s + y; - //double dx = (s*step/2 + lastx); - //double dy = (-c*step/2 + lasty); double dx = x + cos(a-step/2)*r2; double dy = y + sin(a-step/2)*r2; - //draw->lineTo(draw, xx, yy); draw->splineTo(draw, dx, dy, xx, yy); lastx = xx; lasty = yy; @@ -62,38 +60,43 @@ static void draw_single_stroke(gfxpoint_t*p, int num, gfxdrawer_t*draw, double w /* remove duplicate points */ int s=1,t; + gfxpoint_t last = p[0]; for(t=1;t2 && p[0].x == p[num-1].x && p[0].y == p[num-1].y); int start = 0; int end = num-1; int incr = 1; int pos = 0; - double alimit = atan(limit / width); - + double lastw=0; /* iterate through the points two times: first forward, then backward, adding a stroke outline to the right side and line caps after each pass */ int pass; - double lastw=0; for(pass=0;pass<2;pass++) { + if(closed) { + double dx = p[end].x - p[end-incr].x; + double dy = p[end].y - p[end-incr].y; + lastw = atan2(dy,dx); + if(lastw<0) lastw+=M_PI*2; + } + int pos; for(pos=start;pos!=end;pos+=incr) { //printf("%d) %.2f %.2f\n", pos, p[pos].x, p[pos].y); double dx = p[pos+incr].x - p[pos].x; double dy = p[pos+incr].y - p[pos].y; - double l = sqrt(dx*dx+dy*dy); double w = atan2(dy,dx); if(w<0) w+=M_PI*2; - if(pos!=start) { + if(closed || pos!=start) { double d = w-lastw; leftright_t turn; if(d>=0 && dlineTo(draw, p[pos].x+addx, p[pos].y+addy); - } else { - /* convert to bevel join, which always looks the same (is - independent of miterLimit TODO: verify this */ - } + double xw = M_PI/2 - d/2; + if(xw>0) { + double r2 = 1.0 / sin(M_PI/2-d/2); + if(r2 < limit) { + r2 *= width; + double addx = cos(lastw-M_PI/2+d/2)*r2; + double addy = sin(lastw-M_PI/2+d/2)*r2; + draw->lineTo(draw, p[pos].x+addx, p[pos].y+addy); + } + } } } double addx = cos(w-M_PI/2)*width; double addy = sin(w-M_PI/2)*width; draw->lineTo(draw, p[pos].x+addx, p[pos].y+addy); - //printf("-- %.2f %.2f (angle:%d)\n", px1, py1, (int)(180*w/M_PI)); double px2 = p[pos+incr].x + addx; double py2 = p[pos+incr].y + addy; - //printf("-- %.2f %.2f (angle:%d)\n", px2, py2, (int)(180*w/M_PI)); draw->lineTo(draw, p[pos+incr].x+addx, p[pos+incr].y+addy); - lastw = w; } - /* draw stroke ends. We draw duplicates of some points here. The drawer - implementation should be smart enough to remove them. */ - double c = cos(lastw-M_PI/2)*width; - double s = sin(lastw-M_PI/2)*width; - if(cap == gfx_capButt) { - draw->lineTo(draw, p[pos].x+c, p[pos].y+s); - draw->lineTo(draw, p[pos].x-c, p[pos].y-s); - } else if(cap == gfx_capRound) { - draw->lineTo(draw, p[pos].x+c, p[pos].y+s); - draw_arc(draw, p[pos].x, p[pos].y, lastw-M_PI/2, lastw+M_PI/2, width); - } else if(cap == gfx_capSquare) { + + if(closed) { + draw->close(draw); + } else { + /* draw stroke ends. We draw duplicates of some points here. The drawer + implementation should be smart enough to remove them. */ double c = cos(lastw-M_PI/2)*width; double s = sin(lastw-M_PI/2)*width; - draw->lineTo(draw, p[pos].x+c, p[pos].y+s); - draw->lineTo(draw, p[pos].x+c-s, p[pos].y+s+c); - draw->lineTo(draw, p[pos].x-c-s, p[pos].y-s+c); - draw->lineTo(draw, p[pos].x-c, p[pos].y-s); + if(cap == gfx_capButt) { + draw->lineTo(draw, p[pos].x+c, p[pos].y+s); + draw->lineTo(draw, p[pos].x-c, p[pos].y-s); + } else if(cap == gfx_capRound) { + draw_arc(draw, p[pos].x, p[pos].y, lastw-M_PI/2, lastw+M_PI/2, width); + } else if(cap == gfx_capSquare) { + double c = cos(lastw-M_PI/2)*width; + double s = sin(lastw-M_PI/2)*width; + draw->lineTo(draw, p[pos].x+c, p[pos].y+s); + draw->lineTo(draw, p[pos].x+c-s, p[pos].y+s+c); + draw->lineTo(draw, p[pos].x-c-s, p[pos].y-s+c); + draw->lineTo(draw, p[pos].x-c, p[pos].y-s); + } + lastw += M_PI; // for dots } start=num-1; end=0; incr=-1; - lastw += M_PI; // for dots } - draw->close(draw); + if(!closed) + draw->close(draw); } -static void draw_stroke(gfxline_t*start, gfxdrawer_t*draw, double width, gfx_capType cap, gfx_joinType join, double miterLimit) +void draw_stroke(gfxline_t*start, gfxdrawer_t*draw, double width, gfx_capType cap, gfx_joinType join, double miterLimit) { if(!start) return;