diff options
author | Matthias Kramm <kramm@matthias-kramms-macbook-pro.local> | 2009-05-24 17:46:04 -0700 |
---|---|---|
committer | Matthias Kramm <kramm@matthias-kramms-macbook-pro.local> | 2009-05-24 17:46:04 -0700 |
commit | e3f35893d64112de70839da517c31e239a250b6a (patch) | |
tree | 3f4c778bc9407ac5c68695dd5d4221872cf3bb74 | |
parent | 3513ae007a04da02f11cdca9f0d08ddda9eac245 (diff) |
several small fixes in polygon codepolyok
-rw-r--r-- | lib/gfxpoly/active.c | 2 | ||||
-rw-r--r-- | lib/gfxpoly/convert.c | 34 | ||||
-rw-r--r-- | lib/gfxpoly/poly.c | 24 | ||||
-rw-r--r-- | lib/gfxpoly/test.c | 112 | ||||
-rw-r--r-- | lib/gfxtools.c | 31 | ||||
-rw-r--r-- | lib/gfxtools.h | 1 |
6 files changed, 136 insertions, 68 deletions
diff --git a/lib/gfxpoly/active.c b/lib/gfxpoly/active.c index 5a2c4513..340d5bcd 100644 --- a/lib/gfxpoly/active.c +++ b/lib/gfxpoly/active.c @@ -46,7 +46,7 @@ void actlist_verify(actlist_t*a, int32_t y) /* we need to re-evaluate the x of the previous segment. if we try to store it, it might end up being converted to a double, which will make it non-equal to (and possibly larger than) the - "long double" the FPU has in it's register. This only happens + "long double" the FPU has in its register. This only happens when compiler optimizations are turned on. */ assert((XPOS(s, y) - XPOS(l, y)) >= 0); assert(XDIFF(s,l,y) >= 0); diff --git a/lib/gfxpoly/convert.c b/lib/gfxpoly/convert.c index 5619f790..ad884f1b 100644 --- a/lib/gfxpoly/convert.c +++ b/lib/gfxpoly/convert.c @@ -188,24 +188,20 @@ typedef struct _compactpoly { segment_dir_t dir; } compactpoly_t; -void add_segment(compactpoly_t*data, point_t start, segment_dir_t dir) +void finish_segment(compactpoly_t*data) { + if(data->num_points <= 1) + return; if(data->poly->num_strokes == data->strokes_size) { data->strokes_size <<= 1; assert(data->strokes_size > data->poly->num_strokes); - data->poly->strokes = rfx_realloc(data->poly->strokes, data->strokes_size); + data->poly->strokes = rfx_realloc(data->poly->strokes, sizeof(gfxstroke_t)*data->strokes_size); } - data->poly->strokes[data->poly->num_strokes].dir = dir; - data->points[0] = start; - data->num_points = 1; - data->dir = dir; -} -void finish_segment(compactpoly_t*data) -{ - if(data->num_points <= 1) - return; point_t*p = malloc(sizeof(point_t)*data->num_points); - data->poly->strokes[data->poly->num_strokes-1].points = p; + gfxstroke_t*s = &data->poly->strokes[data->poly->num_strokes]; + s->num_points = data->num_points; + s->dir = data->dir; + s->points = p; if(data->dir == DIR_UP) { int t; int s = data->num_points; @@ -232,16 +228,17 @@ static void compactlineto(void*_data, double _x, double _y) point_t p; p.x = convert_coord(_x); p.y = convert_coord(_y); - if(p.y < data->last.y && data->dir != DIR_UP || - p.y > data->last.y && data->dir != DIR_DOWN) { - data->dir = p.y > data->last.y ? DIR_DOWN : DIR_UP; + if(p.y < data->last.y && data->dir != DIR_UP || + p.y >= data->last.y && data->dir != DIR_DOWN) { finish_segment(data); - add_segment(data, data->last, data->dir); + data->dir = p.y > data->last.y ? DIR_DOWN : DIR_UP; + data->points[0] = data->last; + data->num_points = 1; } if(data->points_size == data->num_points) { data->points_size <<= 1; assert(data->points_size > data->num_points); - data->points = rfx_realloc(data->points, data->points_size); + data->points = rfx_realloc(data->points, sizeof(point_t)*data->points_size); } data->points[data->num_points++] = p; } @@ -259,13 +256,14 @@ static void compactinit(compactpoly_t*data, double gridsize) data->strokes_size = 16; data->num_points = 0; data->points_size = 16; + data->dir = DIR_UNKNOWN; data->points = (point_t*)rfx_alloc(sizeof(point_t)*data->points_size); data->poly->strokes = (gfxstroke_t*)rfx_alloc(sizeof(gfxstroke_t)*data->strokes_size); } static gfxcompactpoly_t*compactfinish(compactpoly_t*data) { finish_segment(data); - data->poly->strokes = rfx_realloc(data->poly->strokes, sizeof(gfxstroke_t)*data->poly->num_strokes); + data->poly->strokes = (gfxstroke_t*)rfx_realloc(data->poly->strokes, sizeof(gfxstroke_t)*data->poly->num_strokes); free(data->points); return data->poly; } diff --git a/lib/gfxpoly/poly.c b/lib/gfxpoly/poly.c index 4bbd7765..ca81be1d 100644 --- a/lib/gfxpoly/poly.c +++ b/lib/gfxpoly/poly.c @@ -13,7 +13,10 @@ static gfxpoly_t*current_polygon = 0; void gfxpoly_fail(char*expr, char*file, int line, const char*function) { - if(!current_polygon) {fprintf(stderr, "error outside polygon\n");exit(1);} + if(!current_polygon) { + fprintf(stderr, "assert(%s) failed in %s in line %d: %s\n", expr, file, line, function); + exit(1); + } void*md5 = init_md5(); @@ -110,15 +113,21 @@ static int compare_events(const void*_a,const void*_b) /* we need to schedule end after intersect (so that a segment about to end has a chance to tear up a few other segs first) and start events after end (in order not to confuse the intersection check, which - assumes there's an actual y overlap between active segments)). + assumes there's an actual y overlap between active segments, and + because ending segments in the active list make it difficult to insert + starting segments at the right position)). Horizontal lines come last, because the only purpose they have is to create snapping coordinates for the segments (still) existing in this scanline. */ d = b->type - a->type; if(d) return d; - d = b->p.x - a->p.x; - return d; + return 0; + + /* I don't see any reason why we would need to order by x- at least as long + as we do horizontal lines in a seperate pass */ + //d = b->p.x - a->p.x; + //return d; } gfxpoly_t* gfxpoly_new(double gridsize) @@ -186,6 +195,7 @@ void gfxpoly_dump(gfxpoly_t*poly) { edge_t* s = poly->edges; double g = poly->gridsize; + fprintf(stderr, "polyon %08x (gridsize: %f)\n", poly, poly->gridsize); while(s) { fprintf(stderr, "(%f,%f) -> (%f,%f)\n", s->a.x*g, s->a.y*g, s->b.x*g, s->b.y*g); s = s->next; @@ -358,7 +368,6 @@ static void schedule_crossing(status_t*status, segment_t*s1, segment_t*s2) /* the code that's required (and the checks you can perform) before it can be said with 100% certainty that we indeed have a valid crossing amazes me every time. -mk */ - #ifdef CHECKS assert(s1!=s2); assert(s1->right == s2); @@ -1046,12 +1055,11 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c x = e->p.x; fill ^= 1;//(before.is_filled != after.is_filled); #ifdef DEBUG - fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d before:%d after:%d\n", + fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d\n", y, e->type==EVENT_START?"start":"end", s->nr, left?left->nr:-1, - x, - before.is_filled, after.is_filled); + x); #endif if(e->type == EVENT_END) diff --git a/lib/gfxpoly/test.c b/lib/gfxpoly/test.c index 6a41566e..c990ca28 100644 --- a/lib/gfxpoly/test.c +++ b/lib/gfxpoly/test.c @@ -28,21 +28,17 @@ gfxline_t*mkstar(int x1, int y1, int x2, int y2) gfxline_t* mkrandomshape(int range, int n) { int i; - gfxline_t* line = malloc(sizeof(gfxline_t)*n*2); + gfxline_t* line = malloc(sizeof(gfxline_t)*n); for(i=0;i<n;i++) { line[i].type = i?gfx_lineTo:gfx_moveTo; line[i].x = lrand48()%range - range/2; line[i].y = lrand48()%range - range/2; line[i].next = &line[i+1]; - line[n*2-i-1].type = gfx_lineTo; - line[n*2-i-1].x = line[i].x; - line[n*2-i-1].y = line[i].y; - line[n*2-i-1].next = &line[n*2-i]; } - line[n*2-1].next = 0; line[n-1].x = line[0].x; line[n-1].y = line[0].y; line[n-1].next = 0; + return line; } gfxline_t* mkchessboard() @@ -102,16 +98,35 @@ gfxline_t* mkchessboard() l[4].y = y-sizey; gfxline_append(b, l); } - if(do_centerpiece) - for(t=0;t<5;t++) { - gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10); - gfxmatrix_t matrix; - memset(&matrix, 0, sizeof(gfxmatrix_t)); - double ua=t*0.43; - matrix.m00=cos(ua);matrix.m10=sin(ua); - matrix.m01=-sin(ua);matrix.m11=cos(ua); - gfxline_transform(l, &matrix); - gfxline_append(b, l); + if(do_centerpiece) { + for(t=0;t<5;t++) { + gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10); + gfxmatrix_t matrix; + memset(&matrix, 0, sizeof(gfxmatrix_t)); + double ua=t*0.43; + matrix.m00=cos(ua);matrix.m10=sin(ua); + matrix.m01=-sin(ua);matrix.m11=cos(ua); + gfxline_transform(l, &matrix); + gfxline_append(b, l); + } + gfxline_append(b, gfxline_makecircle(100,100,100,100)); + } + return b; +} + +gfxline_t* make_circles() +{ + gfxline_t*b = 0; + unsigned int c = 0; + int t; + for(t=0;t<30;t++) { + c = crc32_add_byte(c, t); + int x = c%200; + c = crc32_add_byte(c, t); + int y = c%200;; + c = crc32_add_byte(c, t^0x55); + int r = c%100; + b = gfxline_append(b, gfxline_makecircle(x,y,r,r)); } return b; } @@ -120,26 +135,28 @@ static windcontext_t onepolygon = {1}; int test0() { - gfxline_t* b = mkchessboard(); + //gfxline_t* b = mkchessboard(); + //gfxline_t* b = mkrandomshape(100,7); + gfxline_t* b = gfxline_makecircle(100,100,100,100); gfxmatrix_t m; memset(&m, 0, sizeof(gfxmatrix_t)); int t; for(t=0;t<360;t++) { - m.m00 = cos(t*M_PI/180.0); - m.m01 = sin(t*M_PI/180.0); - m.m10 = -sin(t*M_PI/180.0); - m.m11 = cos(t*M_PI/180.0); - m.tx = 400*1.41/2; - m.ty = 400*1.41/2; - gfxline_transform(b, &m); - - gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05); + m.m00 = cos(t*M_PI/180.0); + m.m01 = sin(t*M_PI/180.0); + m.m10 = -sin(t*M_PI/180.0); + m.m11 = cos(t*M_PI/180.0); + m.tx = 400*1.41/2; + m.ty = 400*1.41/2; + gfxline_transform(b, &m); + gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05); + + gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon); + gfxpoly_destroy(poly2); + gfxpoly_destroy(poly); + } gfxline_free(b); - gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon); - gfxpoly_destroy(poly2); - gfxpoly_destroy(poly); -} } int test1(int argn, char*argv[]) @@ -230,9 +247,10 @@ void test3(int argn, char*argv[]) //gfxline_t*line = mkrandomshape(RANGE, N); //windrule_t*rule = &windrule_circular; - gfxline_t*line = mkchessboard(); - //windrule_t*rule = &windrule_evenodd; - windrule_t*rule = &windrule_circular; + //gfxline_t*line = mkchessboard(); + gfxline_t*line = make_circles(); + windrule_t*rule = &windrule_evenodd; + //windrule_t*rule = &windrule_circular; gfxmatrix_t m; memset(&m, 0, sizeof(m)); @@ -250,6 +268,7 @@ void test3(int argn, char*argv[]) int t; for(t=0;t<360;t++) { + fprintf(stderr, "%d\n", t); m.m00 = cos(t*M_PI/180.0); m.m01 = sin(t*M_PI/180.0); m.m10 = -sin(t*M_PI/180.0); @@ -409,19 +428,24 @@ void test4(int argn, char*argv[]) void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) { - gfxcompactpoly_t*c = gfxcompactpoly_from_gfxline(line, 0.05); - gfxcompactpoly_free(c); + //gfxcompactpoly_t*c = gfxcompactpoly_from_gfxline(line, 0.05); + //gfxcompactpoly_free(c); + gfxpoly_t*poly = gfxpoly_from_gfxline(line, 0.05); + + gfxline_dump(line, stderr, ""); + gfxpoly_dump(poly); + if(gfxpoly_size(poly)>100000) { - printf("%d segments (skipping)\n", gfxpoly_size(poly)); + fprintf(stderr, "%d segments (skipping)\n", gfxpoly_size(poly)); return; } else { - printf("%d segments\n", gfxpoly_size(poly)); + //fprintf(stderr, "%d segments\n", gfxpoly_size(poly)); } if(!gfxpoly_check(poly)) { gfxpoly_destroy(poly); - printf("bad polygon\n"); + fprintf(stderr, "bad polygon\n"); return; } @@ -431,7 +455,7 @@ void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) intbbox_t bbox = intbbox_from_polygon(poly, zoom); unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule, &onepolygon); if(!bitmap_ok(&bbox, bitmap1)) { - printf("bad polygon or error in renderer\n"); + fprintf(stderr, "bad polygon or error in renderer\n"); return; } gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon); @@ -521,16 +545,21 @@ void test5(int argn, char*argv[]) continue; char* filename = allocprintf("%s/%s", dir, file->d_name); + if(argn>1) + filename = argv[1]; + gfxdocument_t*doc = driver->open(driver, filename); gfxdevice_t*out = &extract_polygons; int t; for(t=1;t<=doc->num_pages;t++) { - printf("%s (page %d)\n", filename, t); + fprintf(stderr, "%s (page %d)\n", filename, t); gfxpage_t* page = doc->getpage(doc, t); page->render(page, out); page->destroy(page); } doc->destroy(doc); + if(argn>1) + break; free(filename); } closedir(_dir); @@ -539,5 +568,6 @@ void test5(int argn, char*argv[]) int main(int argn, char*argv[]) { - test5(argn, argv); + test3(argn, argv); } + diff --git a/lib/gfxtools.c b/lib/gfxtools.c index e79e6fef..8ee2ff48 100644 --- a/lib/gfxtools.c +++ b/lib/gfxtools.c @@ -834,6 +834,37 @@ gfxline_t*gfxline_makerectangle(int x1,int y1,int x2, int y2) return line; } +gfxline_t*gfxline_makecircle(double x,double y,double rx, double ry) +{ + double C1 = 0.2930; + double C2 = 0.4140; + double begin = 0.7070; + gfxline_t* line = (gfxline_t*)rfx_calloc(sizeof(gfxline_t)*9); + int t; + line[0].type = gfx_moveTo; + line[0].x = x+begin*rx; + line[0].y = y+begin*ry; + for(t=1;t<9;t++) { + line[t-1].next = &line[t]; + line[t].type = gfx_splineTo; + } + line[t].next = 0; +#define R(nr,cx,cy,mx,my) \ + line[nr].sx = line[nr-1].x + (cx); \ + line[nr].sy = line[nr-1].y + (cy); \ + line[nr].x = line[nr].sx + (mx); \ + line[nr].y = line[nr].sy + (my); + R(1, -C1*rx, C1*ry, -C2*rx, 0); + R(2, -C2*rx, 0, -C1*rx, -C1*ry); + R(3, -C1*rx, -C1*ry, 0, -C2*ry); + R(4, 0, -C2*ry, C1*rx, -C1*ry); + R(5, C1*rx, -C1*ry, C2*rx, 0); + R(6, C2*rx, 0, C1*rx, C1*ry); + R(7, C1*rx, C1*ry, 0, C2*ry); + R(8, 0, C2*ry, -C1*rx, C1*ry); + return line; +} + gfxbbox_t* gfxline_isrectangle(gfxline_t*_l) { if(!_l) diff --git a/lib/gfxtools.h b/lib/gfxtools.h index ea511faf..7b7377d0 100644 --- a/lib/gfxtools.h +++ b/lib/gfxtools.h @@ -87,6 +87,7 @@ void gfxfontlist_free(gfxfontlist_t*list, char deletefonts); gfxbbox_t* gfxline_isrectangle(gfxline_t*_l); gfxline_t*gfxline_makerectangle(int x1, int y1, int x2, int y2); +gfxline_t*gfxline_makecircle(double x,double y,double rx, double ry); void gfxline_show(gfxline_t*line, FILE*fi); #ifdef __cplusplus |