From: Matthias Kramm Date: Fri, 5 Jun 2009 12:52:55 +0000 (+0200) Subject: numerous bigfixes in stroke->polygon conversion X-Git-Tag: version-0-9-1~336 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=7be8967177293d3a0b4b8a286f16b740933ac583;hp=1ec6bb9a0eb63847e814b987014b2f1afcb7def6 numerous bigfixes in stroke->polygon conversion --- diff --git a/lib/gfxpoly/Makefile b/lib/gfxpoly/Makefile index 46a994d..36b6b2e 100644 --- a/lib/gfxpoly/Makefile +++ b/lib/gfxpoly/Makefile @@ -1,7 +1,7 @@ all: test stroke include ../../Makefile.common -CC = gcc -g +CC = gcc -O3 -fomit-frame-pointer #CC = gcc -O3 ../libbase.a: ../q.c ../q.h ../mem.c ../mem.h @@ -33,12 +33,15 @@ renderpoly.o: renderpoly.c wind.h poly.h renderpoly.h xrow.o: xrow.c xrow.h ../q.h ../mem.h $(CC) -c xrow.c -o xrow.o -stroke: stroke.c ../libgfx.a ../libbase.a ../librfxswf.a ../libgfxswf.a - $(CC) stroke.c ../libgfx.a ../libbase.a ../librfxswf.a ../libgfxswf.a -o stroke $(LIBS) +stroke.o: stroke.c poly.h convert.h wind.h + $(CC) -c stroke.c -o stroke.o + +stroke: test_stroke.c stroke.o $(OBJS) ../libgfx.a ../libbase.a ../librfxswf.a ../libgfxswf.a + $(CC) test_stroke.c stroke.o $(OBJS) ../libgfx.a ../libbase.a ../librfxswf.a ../libgfxswf.a -o stroke $(LIBS) SWF = ../librfxswf.a ../libpdf.a ../libgfx.a -lstdc++ test: ../libbase.a ../libgfx.a test.c $(OBJS) poly.h convert.h $(CC) test.c $(OBJS) $(SWF) ../libbase.a ../libgfx.a -o test $(LIBS) clean: - rm -f *.o test + rm -f *.o test stroke diff --git a/lib/gfxpoly/convert.c b/lib/gfxpoly/convert.c index 0fc2b7f..732033b 100644 --- a/lib/gfxpoly/convert.c +++ b/lib/gfxpoly/convert.c @@ -230,7 +230,7 @@ void gfxpolywriter_init(polywriter_t*w) data->poly->strokes = 0; } -gfxpoly_t* gfxpoly_from_gfxline(gfxline_t*line, double gridsize) +gfxpoly_t* gfxpoly_from_fill(gfxline_t*line, double gridsize) { polywriter_t writer; gfxpolywriter_init(&writer); @@ -261,8 +261,10 @@ void gfxpoly_destroy(gfxpoly_t*poly) typedef struct _polydraw_internal { + double lx, ly; int32_t lastx, lasty; double z; + char last; polywriter_t writer; } polydraw_internal_t; @@ -274,31 +276,45 @@ static void polydraw_moveTo(gfxdrawer_t*d, gfxcoord_t _x, gfxcoord_t _y) if(i->lastx != x || i->lasty != y) { i->writer.moveto(&i->writer, x, y); } + i->lx = _x; + i->ly = _y; i->lastx = x; i->lasty = y; + i->last = 1; } static void polydraw_lineTo(gfxdrawer_t*d, gfxcoord_t _x, gfxcoord_t _y) { polydraw_internal_t*i = (polydraw_internal_t*)d->internal; + if(!i->last) { + polydraw_moveTo(d, _x, _y); + return; + } int32_t x = convert_coord(_x, i->z); int32_t y = convert_coord(_y, i->z); if(i->lastx != x || i->lasty != y) { i->writer.lineto(&i->writer, x, y); } + i->lx = _x; + i->ly = _y; i->lastx = x; i->lasty = y; + i->last = 1; } static void polydraw_splineTo(gfxdrawer_t*d, gfxcoord_t sx, gfxcoord_t sy, gfxcoord_t x, gfxcoord_t y) { polydraw_internal_t*i = (polydraw_internal_t*)d->internal; - double c = fabs(x-2*sx+i->lastx) + fabs(y-2*sy+i->lasty); + if(!i->last) { + polydraw_moveTo(d, x, y); + return; + } + double c = fabs(x-2*sx+i->lx) + fabs(y-2*sy+i->ly); int parts = (int)(sqrt(c)*SUBFRACTION); if(!parts) parts = 1; int t; int32_t nx,ny; for(t=0;tlastx)/(double)(parts*parts), i->z); - ny = convert_coord((double)(t*t*y + 2*t*(parts-t)*sy + (parts-t)*(parts-t)*i->lasty)/(double)(parts*parts), i->z); + nx = convert_coord((double)(t*t*x + 2*t*(parts-t)*sx + (parts-t)*(parts-t)*i->lx)/(double)(parts*parts), i->z); + ny = convert_coord((double)(t*t*y + 2*t*(parts-t)*sy + (parts-t)*(parts-t)*i->ly)/(double)(parts*parts), i->z); if(nx != i->lastx || ny != i->lasty) { i->writer.lineto(&i->writer, nx, ny); i->lastx = nx; i->lasty = ny; @@ -308,8 +324,12 @@ static void polydraw_splineTo(gfxdrawer_t*d, gfxcoord_t sx, gfxcoord_t sy, gfxco ny = convert_coord(y,i->z); if(nx != i->lastx || ny != i->lasty) { i->writer.lineto(&i->writer, nx, ny); - i->lastx = nx; i->lasty = ny; } + i->lx = x; + i->ly = y; + i->lastx = nx; + i->lasty = ny; + i->last = 1; } static void* polydraw_result(gfxdrawer_t*d) { @@ -335,3 +355,30 @@ void gfxdrawer_target_poly(gfxdrawer_t*d, double gridsize) i->z = 1.0 / gridsize; } +gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly) +{ + gfxpolystroke_t*stroke; + int count = 0; + for(stroke=poly->strokes;stroke;stroke=stroke->next) { + assert(stroke->num_points); + count += stroke->num_points; + } + if(!count) return 0; + gfxline_t*l = malloc(sizeof(gfxline_t)*count); + count = 0; + /* TODO: it might make sense to concatenate strokes */ + for(stroke=poly->strokes;stroke;stroke=stroke->next) { + int t; + for(t=0;tnum_points;t++) { + l[count+t].x = stroke->points[t].x * poly->gridsize; + l[count+t].y = stroke->points[t].y * poly->gridsize; + l[count+t].type = gfx_lineTo; + l[count+t].next = &l[count+t+1]; + } + l[count].type = gfx_moveTo; + count+=stroke->num_points; + } + l[count-1].next = 0; + return l; +} + diff --git a/lib/gfxpoly/convert.h b/lib/gfxpoly/convert.h index c1bb9c3..6eb745c 100644 --- a/lib/gfxpoly/convert.h +++ b/lib/gfxpoly/convert.h @@ -17,8 +17,10 @@ typedef struct _polywriter void gfxdrawer_target_poly(gfxdrawer_t*d, double gridsize); void gfxpolywriter_init(polywriter_t*w); -gfxpoly_t* gfxpoly_from_gfxline(gfxline_t*line, double gridsize); +gfxpoly_t* gfxpoly_from_fill(gfxline_t*line, double gridsize); gfxpoly_t* gfxpoly_from_file(const char*filename, double gridsize); void gfxpoly_destroy(gfxpoly_t*poly); +gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly); + #endif //__poly_convert_h__ diff --git a/lib/gfxpoly/poly.c b/lib/gfxpoly/poly.c index 226584a..72d5ab1 100644 --- a/lib/gfxpoly/poly.c +++ b/lib/gfxpoly/poly.c @@ -146,6 +146,15 @@ typedef struct _status { } status_t; +int gfxpoly_num_segments(gfxpoly_t*poly) +{ + gfxpolystroke_t*stroke = poly->strokes; + int count = 0; + for(;stroke;stroke=stroke->next) { + count++; + } + return count; +} int gfxpoly_size(gfxpoly_t*poly) { int s,t; @@ -371,10 +380,6 @@ static void advance_stroke(queue_t*queue, hqueue_t*hqueue, gfxpolystroke_t*strok } } if(s) { -#ifdef DEBUG - fprintf(stderr, "attaching contingency of stroke %08x to segment [%d] %s\n", - stroke, s, s->delta.y?"":"(horizontal)"); -#endif s->stroke = stroke; s->stroke_pos = pos; } @@ -935,7 +940,8 @@ static void recalculate_windings(status_t*status, segrange_t*range) s->fs_out = status->windrule->diff(&wind, &s->wind); #ifdef DEBUG - fprintf(stderr, "[%d] %s/%d/%s/%s %s\n", s->nr, s->dir==DIR_UP?"up":"down", s->wind.wind_nr, s->wind.is_filled?"fill":"nofill", s->fs_out?"draw":"omit", + fprintf(stderr, "[%d] dir=%s wind=%d wind.filled=%s fs_old/new=%s/%s %s\n", s->nr, s->dir==DIR_UP?"up":"down", s->wind.wind_nr, s->wind.is_filled?"fill":"nofill", + fs_old?"draw":"omit", s->fs_out?"draw":"omit", fs_old!=s->fs_out?"CHANGED":""); #endif assert(!(!s->changed && fs_old!=s->fs_out)); @@ -1202,21 +1208,28 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c e = hqueue_get(&hqueue); } while(e && y == e->p.y); - assert(!fill); // check that polygon is not bleeding +#ifdef CHECKS + char bleeding = fill; + assert(!bleeding); +#endif } actlist_destroy(actlist); hqueue_destroy(&hqueue); } -gfxpoly_t* gfxpoly_process(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*context) +gfxpoly_t* gfxpoly_process(gfxpoly_t*poly1, gfxpoly_t*poly2, windrule_t*windrule, windcontext_t*context) { - current_polygon = poly; + current_polygon = poly1; status_t status; memset(&status, 0, sizeof(status_t)); queue_init(&status.queue); - gfxpoly_enqueue(poly, &status.queue, 0, /*polygon nr*/0); + gfxpoly_enqueue(poly1, &status.queue, 0, /*polygon nr*/0); + if(poly2) { + assert(poly1->gridsize == poly2->gridsize); + gfxpoly_enqueue(poly2, &status.queue, 0, /*polygon nr*/1); + } status.windrule = windrule; status.context = context; @@ -1279,10 +1292,19 @@ gfxpoly_t* gfxpoly_process(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*co xrow_destroy(status.xrow); gfxpoly_t*p = (gfxpoly_t*)malloc(sizeof(gfxpoly_t)); - p->gridsize = poly->gridsize; + p->gridsize = poly1->gridsize; p->strokes = status.strokes; - gfxpoly_dump(p); add_horizontals(p, &windrule_evenodd, context); // output is always even/odd return p; } + +static windcontext_t twopolygons = {2}; +gfxpoly_t* gfxpoly_intersect(gfxpoly_t*p1, gfxpoly_t*p2) +{ + return gfxpoly_process(p1, p2, &windrule_intersect, &twopolygons); +} +gfxpoly_t* gfxpoly_union(gfxpoly_t*p1, gfxpoly_t*p2) +{ + return gfxpoly_process(p1, p2, &windrule_union, &twopolygons); +} diff --git a/lib/gfxpoly/poly.h b/lib/gfxpoly/poly.h index 186075a..270734f 100644 --- a/lib/gfxpoly/poly.h +++ b/lib/gfxpoly/poly.h @@ -22,7 +22,7 @@ typedef struct _point { } point_t; typedef struct _fillstyle { - char is_filled; + void*internal; } fillstyle_t; typedef struct _windstate @@ -115,10 +115,14 @@ typedef struct _segment { void gfxpoly_fail(char*expr, char*file, int line, const char*function); char gfxpoly_check(gfxpoly_t*poly); +int gfxpoly_num_segments(gfxpoly_t*poly); int gfxpoly_size(gfxpoly_t*poly); void gfxpoly_dump(gfxpoly_t*poly); void gfxpoly_save(gfxpoly_t*poly, const char*filename); -gfxpoly_t* gfxpoly_process(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*context); +gfxpoly_t* gfxpoly_process(gfxpoly_t*poly1, gfxpoly_t*poly2, windrule_t*windrule, windcontext_t*context); + +gfxpoly_t* gfxpoly_intersect(gfxpoly_t*p1, gfxpoly_t*p2); +gfxpoly_t* gfxpoly_union(gfxpoly_t*p1, gfxpoly_t*p2); #ifndef CHECKS #ifdef assert diff --git a/lib/gfxpoly/stroke.c b/lib/gfxpoly/stroke.c index ed5911c..7d5c380 100644 --- a/lib/gfxpoly/stroke.c +++ b/lib/gfxpoly/stroke.c @@ -1,9 +1,11 @@ #include #include #include -#include #include "../gfxdevice.h" #include "../gfxtools.h" +#include "poly.h" +#include "wind.h" +#include "convert.h" /* notice: left/right for a coordinate system where y goes up, not down */ typedef enum {LEFT=0, RIGHT=1} leftright_t; @@ -45,7 +47,7 @@ static void draw_arc(gfxdrawer_t*draw, double x, double y, double a1, double a2, //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->lineTo(draw, xx, yy); draw->splineTo(draw, dx, dy, xx, yy); lastx = xx; lasty = yy; @@ -56,10 +58,6 @@ static void draw_single_stroke(gfxpoint_t*p, int num, gfxdrawer_t*draw, double w { char do_draw=0; leftright_t lastdir = LEFT; - int start = 0; - int end = num-1; - int incr = 1; - int pos = 0; width/=2; if(width<=0) @@ -75,6 +73,11 @@ static void draw_single_stroke(gfxpoint_t*p, int num, gfxdrawer_t*draw, double w num--; } } + + int start = 0; + int end = num-1; + int incr = 1; + int pos = 0; double alimit = atan(limit / width); @@ -82,9 +85,9 @@ static void draw_single_stroke(gfxpoint_t*p, int num, gfxdrawer_t*draw, double w 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++) { int pos; - double lastw=0; 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; @@ -130,16 +133,20 @@ static void draw_single_stroke(gfxpoint_t*p, int num, gfxdrawer_t*draw, double w lastw = w; } - /* draw stroke ends */ + /* draw stroke ends. We draw duplicates of some points here. The drawer + implementationshould 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) { - 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, 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) { 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); @@ -147,6 +154,7 @@ static void draw_single_stroke(gfxpoint_t*p, int num, gfxdrawer_t*draw, double w start=num-1; end=0; incr=-1; + lastw += M_PI; // for dots } } @@ -206,61 +214,16 @@ static void draw_stroke(gfxline_t*start, gfxdrawer_t*draw, double width, gfx_cap free(points); } -int main() +static windcontext_t onepolygon = {1}; +gfxpoly_t* gfxpoly_from_stroke(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit, double gridsize) { - gfxline_t l[4]; - l[0].type = gfx_moveTo; - l[0].x = 100;l[0].sx=2; - l[0].y = 100;l[0].sy=2; - l[0].next = &l[1]; - l[1].type = gfx_lineTo; - l[1].x = 100;l[1].sx=2; - l[1].y = 200;l[1].sy=-2; - l[1].next = &l[2]; - l[2].type = gfx_lineTo; - l[2].x = 250;l[2].sx=4; - l[2].y = 200;l[2].sy=0; - l[2].next = &l[3]; - l[3].type = gfx_lineTo; - l[3].x = 200;l[3].sx=0; - l[3].y = 150;l[3].sy=4; - l[3].next = 0; - - - gfxdevice_t dev; - gfxdevice_swf_init(&dev); - dev.setparameter(&dev, "framerate", "25.0"); - int t; - for(t=0;t<300;t++) { - dev.startpage(&dev, 700,700); - gfxline_t*g = l; - while(g) { - g->x += g->sx; - g->y += g->sy; - if(g->x<200) {g->x=400-g->x;g->sx=-g->sx;} - if(g->y<200) {g->y=400-g->y;g->sy=-g->sy;} - if(g->x>500) {g->x=1000-g->x;g->sx=-g->sx;} - if(g->y>500) {g->y=1000-g->y;g->sy=-g->sy;} - g = g->next; - } - gfxdrawer_t d; - gfxdrawer_target_gfxline(&d); - double width = t/3.0; - if(width>50) width=100-width; - - draw_stroke(l, &d, width, gfx_capRound, gfx_joinBevel, 500); - gfxline_t*line = (gfxline_t*)d.result(&d); - //gfxline_dump(line, stdout, ""); - - gfxcolor_t black = {255,0,0,0}; - gfxcolor_t cyan = {255,0,128,128}; - dev.stroke(&dev, l, 2, &black, gfx_capRound, gfx_joinRound, 0); - dev.stroke(&dev, line, 2, &cyan, gfx_capRound, gfx_joinRound, 0); - gfxline_free(line); - dev.endpage(&dev); - } - - gfxresult_t* result = dev.finish(&dev); - result->save(result, "test.swf"); - result->destroy(result); + gfxdrawer_t d; + gfxdrawer_target_poly(&d, gridsize); + draw_stroke(line, &d, width, cap_style, joint_style, miterLimit); + gfxpoly_t*poly = (gfxpoly_t*)d.result(&d); + assert(gfxpoly_check(poly)); + gfxpoly_t*poly2 = gfxpoly_process(poly, 0, &windrule_circular, &onepolygon); + gfxpoly_destroy(poly); + return poly2; } + diff --git a/lib/gfxpoly/test.c b/lib/gfxpoly/test.c index c58c3d5..ccf2a3f 100644 --- a/lib/gfxpoly/test.c +++ b/lib/gfxpoly/test.c @@ -134,6 +134,7 @@ gfxline_t* make_circles(int n) } static windcontext_t onepolygon = {1}; +static windcontext_t twopolygons = {2}; int test_speed() { @@ -154,9 +155,9 @@ int test_speed() m.ty = 400*1.41/2; gfxline_t*l = gfxline_clone(b); gfxline_transform(l, &m); - gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05); + gfxpoly_t*poly = gfxpoly_from_fill(b, 0.05); - gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon); + gfxpoly_t*poly2 = gfxpoly_process(poly, 0, &windrule_evenodd, &onepolygon); gfxpoly_destroy(poly); gfxpoly_destroy(poly2); gfxline_free(l); @@ -164,6 +165,37 @@ int test_speed() gfxline_free(b); } +int test0(int argn, char*argv[]) +{ + gfxline_t*box1 = gfxline_makerectangle(-100,-100,100,100); + gfxline_t*box2 = gfxline_makerectangle(-100,-100,100,100); + gfxline_t*box3 = gfxline_makerectangle(-100,-100,100,100); + //gfxline_append(box2, box3); + + gfxmatrix_t matrix; + memset(&matrix, 0, sizeof(gfxmatrix_t)); + double ua=M_PI/4; + matrix.m00=cos(ua);matrix.m10=sin(ua); + matrix.m01=-sin(ua);matrix.m11=cos(ua); + //gfxline_transform(box1, &matrix); + + //gfxline_t*b = 0; + //b = gfxline_append(b, box1); + //b = gfxline_append(b, box2); + //gfxline_dump(b, stderr, ""); + + gfxpoly_t*poly1 = gfxpoly_from_fill(box1, 0.05); + gfxpoly_t*poly2 = gfxpoly_from_fill(box2, 0.05); + + gfxline_free(box1); + gfxline_free(box2); + gfxpoly_t*poly3 = gfxpoly_process(poly1, poly2, &windrule_intersect, &twopolygons); + gfxpoly_destroy(poly1); + gfxpoly_destroy(poly2); + gfxpoly_destroy(poly3); +} + + int test1(int argn, char*argv[]) { gfxline_t*box1 = gfxline_makerectangle(50,50,150,150); @@ -184,7 +216,7 @@ int test1(int argn, char*argv[]) //gfxline_transform(b, &matrix); gfxline_dump(b, stderr, ""); - gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05); + gfxpoly_t*poly = gfxpoly_from_fill(b, 0.05); gfxline_free(box1); gfxline_free(box2); @@ -192,7 +224,7 @@ int test1(int argn, char*argv[]) gfxline_free(star); gfxpoly_dump(poly); - gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon); + gfxpoly_t*poly2 = gfxpoly_process(poly, 0, &windrule_evenodd, &onepolygon); gfxpoly_destroy(poly); gfxpoly_destroy(poly2); } @@ -211,11 +243,11 @@ int test_square(int width, int height, int num, double gridsize, char bitmaptest line[num-1].y = line[0].y; line[num-1].next = 0; - gfxpoly_t*poly1 = gfxpoly_from_gfxline(line, gridsize); + gfxpoly_t*poly1 = gfxpoly_from_fill(line, gridsize); gfxline_free(line); windrule_t*rule = &windrule_circular; - gfxpoly_t*poly2 = gfxpoly_process(poly1, rule, &onepolygon); + gfxpoly_t*poly2 = gfxpoly_process(poly1, 0, rule, &onepolygon); if(bitmaptest) { intbbox_t bbox = intbbox_new(0, 0, width, height); unsigned char*bitmap1 = render_polygon(poly1, &bbox, 1.0, rule, &onepolygon); @@ -287,9 +319,9 @@ void test3(int argn, char*argv[]) gfxline_t*l = gfxline_clone(line); gfxline_transform(l, &m); - gfxpoly_t*poly1 = gfxpoly_from_gfxline(l, 0.05); + gfxpoly_t*poly1 = gfxpoly_from_fill(l, 0.05); - gfxpoly_t*poly2 = gfxpoly_process(poly1, rule, &onepolygon); + gfxpoly_t*poly2 = gfxpoly_process(poly1, 0, rule, &onepolygon); tag = swf_InsertTag(tag, ST_DEFINESHAPE); SHAPE* s; @@ -405,7 +437,7 @@ void test4(int argn, char*argv[]) continue; } - gfxpoly_t*poly2 = gfxpoly_process(poly1, rule, &onepolygon); + gfxpoly_t*poly2 = gfxpoly_process(poly1, 0, rule, &onepolygon); int pass; for(pass=0;pass<2;pass++) { @@ -443,11 +475,11 @@ static int max_segments = 0; static int max_any_segments = 0; void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) { - //gfxpoly_t*c = gfxpoly_from_gfxline(line, 0.05); + //gfxpoly_t*c = gfxpoly_from_fill(line, 0.05); //gfxpoly_free(c); - //gfxpoly_t*poly1 = gfxpoly_from_gfxline(line, 0.05); - gfxpoly_t*poly1 = gfxpoly_from_gfxline(line, 0.05); + //gfxpoly_t*poly1 = gfxpoly_from_fill(line, 0.05); + gfxpoly_t*poly1 = gfxpoly_from_fill(line, 0.05); //gfxline_dump(line, stderr, ""); //gfxpoly_dump(poly); @@ -483,7 +515,7 @@ void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) fprintf(stderr, "bad polygon or error in renderer\n"); return; } - gfxpoly_t*poly2 = gfxpoly_process(poly1, rule, &onepolygon); + gfxpoly_t*poly2 = gfxpoly_process(poly1, 0, rule, &onepolygon); unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_evenodd, &onepolygon); if(!bitmap_ok(&bbox, bitmap2)) { save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png"); @@ -593,6 +625,6 @@ void test5(int argn, char*argv[]) int main(int argn, char*argv[]) { - test4(argn, argv); + test0(argn, argv); } diff --git a/lib/gfxpoly/test_stroke.c b/lib/gfxpoly/test_stroke.c new file mode 100644 index 0000000..9068c57 --- /dev/null +++ b/lib/gfxpoly/test_stroke.c @@ -0,0 +1,130 @@ +#include +#include "../gfxtools.h" +#include "stroke.h" + +int main() +{ + gfxline_t l[512], f[256*5]; + + int width=700,height=700; + gfxdevice_t dev; + gfxdevice_swf_init(&dev); + dev.setparameter(&dev, "framerate", "25.0"); + int t; + for(t=0;t<300;t++) { + dev.startpage(&dev, 700,700); + /*gfxline_t*g = l; + while(g) { + g->x += g->sx; + g->y += g->sy; + if(g->sx || g->sy) { + if(g->x<200) {g->x=400-g->x;g->sx=-g->sx;} + if(g->y<200) {g->y=400-g->y;g->sy=-g->sy;} + if(g->x>500) {g->x=1000-g->x;g->sx=-g->sx;} + if(g->y>500) {g->y=1000-g->y;g->sy=-g->sy;} + } + g = g->next; + }*/ + + int i; + for(i=0;i<512;i++) { + double a = i*0.05+t*M_PI/150; + double r = 50+i*0.5; + l[i].x = cos(a)*r + width/2; + l[i].y = sin(a)*r + height/2; + l[i].sx = (int)((l[i].x-width/2)/30); + l[i].sy = (int)((l[i].y-height/2)/30); + l[i].sx = l[i].sy = 0; + l[i].type = gfx_lineTo; + l[i].next = &l[i+1]; + } + l[0].type = gfx_moveTo; + l[i-1].next = 0; + + int xx,yy; + i = 0; + for(yy=0;yy<16;yy++) + for(xx=0;xx<16;xx++) if((xx^yy)&1) { + double x = -128+xx*64+t*128.0/300; + double y = -128+yy*64;//+t*64.0/300; + f[i].x = x; + f[i].y = y; + f[i].next = &f[i+1];f[i++].type = gfx_moveTo; + f[i].x = x+64; + f[i].y = y; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + f[i].x = x+64; + f[i].y = y+64; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + f[i].x = x; + f[i].y = y+64; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + f[i].x = x; + f[i].y = y; + f[i].next = &f[i+1];f[i++].type = gfx_lineTo; + } + f[i-1].next = 0; + + double width = 40; + + //gfxdrawer_t d; + //gfxdrawer_target_gfxline(&d); + //draw_stroke(l, &d, width, gfx_capRound, gfx_joinBevel, 500); + //gfxline_t*line = (gfxline_t*)d.result(&d); + + //gfxpoly_t*p = gfxpoly_fromstroke(l, width, gfx_capRound, gfx_joinRound, 500); + gfxpoly_t*p1 = gfxpoly_from_stroke(l, width, gfx_capRound, gfx_joinRound, 500, 0.05); + assert(gfxpoly_check(p1)); + + //gfxpoly_t*p2 = gfxpoly_from_fill(f, 0.05); + gfxline_t*l2 = gfxline_clone(l); + + double c = cos(t*M_PI/75); + double s = sin(t*M_PI/75); + static int x1 = 0, xdir = 1; + static int y1 = 0, ydir = 5; + x1+=xdir; if(x1>=150) {x1=300-x1;xdir=-xdir;} if(x1<-150) {x1=-300-x1;xdir=-xdir;} + y1+=ydir; if(y1>=150) {y1=300-y1;ydir=-ydir;} if(y1<-150) {y1=-300-y1;ydir=-ydir;} + gfxmatrix_t m = { c, s, -(350+x1)*c-350*s+350, + -s, c, 350*s-(350+x1)*c+350}; + gfxline_transform(l2, &m); + gfxpoly_t*p2 = gfxpoly_from_stroke(l2, width, gfx_capRound, gfx_joinRound, 500, 0.05); + assert(gfxpoly_check(p2)); + + gfxpoly_t*p3 = gfxpoly_intersect(p1, p2); + assert(gfxpoly_check(p3)); + + //gfxpoly_t*p4 = gfxpoly_from_fill(f, 0.05); + //gfxpoly_t*p5 = gfxpoly_intersect(p1, p4); + + gfxline_t*line = gfxline_from_gfxpoly(p3); + gfxpoly_destroy(p1); + gfxpoly_destroy(p2); + gfxpoly_destroy(p3); + + //gfxline_dump(line, stdout, ""); + + gfxcolor_t blue = {255,0,0,255}; + gfxline_t*r = gfxline_makerectangle(0,0,700,700); + dev.fill(&dev, r, &blue); + + gfxcolor_t black = {255,0,0,64}; + gfxcolor_t white = {255,255,255,255}; + gfxcolor_t cyan = {255,0,192,192}; + //dev.stroke(&dev, l, 2, &black, gfx_capRound, gfx_joinRound, 0); + //dev.stroke(&dev, line, 2, &cyan, gfx_capRound, gfx_joinRound, 0); + dev.fill(&dev, line, &black); + gfxmatrix_t m2 = {1.0, 0, -10, + 0, 1.0, -10}; + gfxline_transform(line, &m2); + dev.fill(&dev, line, &cyan); + dev.stroke(&dev, line, 2.0, &white, gfx_capRound, gfx_joinRound, 0); + + gfxline_free(line); + dev.endpage(&dev); + } + + gfxresult_t* result = dev.finish(&dev); + result->save(result, "test.swf"); + result->destroy(result); +} diff --git a/lib/gfxpoly/wind.c b/lib/gfxpoly/wind.c index c630f0f..db92905 100644 --- a/lib/gfxpoly/wind.c +++ b/lib/gfxpoly/wind.c @@ -69,8 +69,7 @@ windrule_t windrule_circular = { windstate_t intersect_start(windcontext_t*context) { - windstate_t w; - return w; + return windstate_nonfilled; } windstate_t intersect_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master) @@ -78,8 +77,7 @@ windstate_t intersect_add(windcontext_t*context, windstate_t left, fillstyle_t*e assert(master < context->num_polygons); left.wind_nr ^= 1<num_polygons)-1) - left.is_filled = 1; + left.is_filled = (left.wind_nr == (1<num_polygons)-1); return left; } @@ -108,8 +106,7 @@ windstate_t union_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, { assert(masterstart) { fprintf(stderr, "Error: drawing startpoint is a spline\n"); - linedraw_moveTo(d, 0, 0); + linedraw_moveTo(d, x, y); + return; } l->type = gfx_splineTo;