numerous bigfixes in stroke->polygon conversion
authorMatthias Kramm <kramm@quiss.org>
Fri, 5 Jun 2009 12:52:55 +0000 (14:52 +0200)
committerMatthias Kramm <kramm@quiss.org>
Fri, 5 Jun 2009 12:52:55 +0000 (14:52 +0200)
lib/gfxpoly/Makefile
lib/gfxpoly/convert.c
lib/gfxpoly/convert.h
lib/gfxpoly/poly.c
lib/gfxpoly/poly.h
lib/gfxpoly/stroke.c
lib/gfxpoly/test.c
lib/gfxpoly/test_stroke.c [new file with mode: 0644]
lib/gfxpoly/wind.c
lib/gfxtools.c

index 46a994d..36b6b2e 100644 (file)
@@ -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
index 0fc2b7f..732033b 100644 (file)
@@ -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;t<parts;t++) {
-       nx = convert_coord((double)(t*t*x + 2*t*(parts-t)*sx + (parts-t)*(parts-t)*i->lastx)/(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;t<stroke->num_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;
+}
+
index c1bb9c3..6eb745c 100644 (file)
@@ -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__
index 226584a..72d5ab1 100644 (file)
@@ -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);
+}
index 186075a..270734f 100644 (file)
@@ -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
index ed5911c..7d5c380 100644 (file)
@@ -1,9 +1,11 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>
-#include <assert.h>
 #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;
 }
+
index c58c3d5..ccf2a3f 100644 (file)
@@ -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 (file)
index 0000000..9068c57
--- /dev/null
@@ -0,0 +1,130 @@
+#include <math.h>
+#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);
+}
index c630f0f..db92905 100644 (file)
@@ -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<<master;
-    if(left.wind_nr == (1<<context->num_polygons)-1)
-        left.is_filled = 1;
+    left.is_filled = (left.wind_nr == (1<<context->num_polygons)-1);
     return left;
 }
 
@@ -108,8 +106,7 @@ windstate_t union_add(windcontext_t*context, windstate_t left, fillstyle_t*edge,
 {
     assert(master<sizeof(left.wind_nr)*8); //up to 32/64 polygons max
     left.wind_nr ^= 1<<master;
-    if(left.wind_nr!=0)
-        left.is_filled = 1;
+    left.is_filled = (left.wind_nr!=0);
     return left;
 }
 
index c9b8153..f754379 100644 (file)
@@ -86,7 +86,8 @@ static void linedraw_splineTo(gfxdrawer_t*d, gfxcoord_t sx, gfxcoord_t sy, gfxco
 
     if(!i->start) {
        fprintf(stderr, "Error: drawing startpoint is a spline\n");
-       linedraw_moveTo(d, 0, 0);
+       linedraw_moveTo(d, x, y);
+       return;
     }
 
     l->type = gfx_splineTo;