From e3f35893d64112de70839da517c31e239a250b6a Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Sun, 24 May 2009 17:46:04 -0700 Subject: [PATCH] several small fixes in polygon code --- lib/gfxpoly/active.c | 2 +- lib/gfxpoly/convert.c | 34 +++++++-------- lib/gfxpoly/poly.c | 24 +++++++---- lib/gfxpoly/test.c | 112 +++++++++++++++++++++++++++++++------------------ lib/gfxtools.c | 31 ++++++++++++++ lib/gfxtools.h | 1 + 6 files changed, 136 insertions(+), 68 deletions(-) diff --git a/lib/gfxpoly/active.c b/lib/gfxpoly/active.c index 5a2c451..340d5bc 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 5619f79..ad884f1 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 4bbd776..ca81be1 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 6a41566..c990ca2 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;i100000) { - 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 e79e6fe..8ee2ff4 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 ea511fa..7b7377d 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 -- 1.7.10.4