X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fgfxpoly%2Fconvert.c;h=9d8ecab32508ab806916ff7aab4880d2eb4a13b1;hb=be6d3cbb485c5f7e9dd6fe22bf54245c79b10b71;hp=3d9763bd99b0fdef0b0ab139e78765858931b80f;hpb=e0a27e1bd83ff2d60745dd6030e0f5ef7ef97b82;p=swftools.git diff --git a/lib/gfxpoly/convert.c b/lib/gfxpoly/convert.c index 3d9763b..9d8ecab 100644 --- a/lib/gfxpoly/convert.c +++ b/lib/gfxpoly/convert.c @@ -264,6 +264,7 @@ typedef struct _polydraw_internal { double lx, ly; int32_t lastx, lasty; + int32_t x0, y0; double z; char last; polywriter_t writer; @@ -279,6 +280,8 @@ static void polydraw_moveTo(gfxdrawer_t*d, gfxcoord_t _x, gfxcoord_t _y) } i->lx = _x; i->ly = _y; + i->x0 = x; + i->y0 = y; i->lastx = x; i->lasty = y; i->last = 1; @@ -332,6 +335,21 @@ static void polydraw_splineTo(gfxdrawer_t*d, gfxcoord_t sx, gfxcoord_t sy, gfxco i->lasty = ny; i->last = 1; } +static void polydraw_close(gfxdrawer_t*d) +{ + polydraw_internal_t*i = (polydraw_internal_t*)d->internal; + assert(!(i->last && (i->x0 == INVALID_COORD || i->y0 == INVALID_COORD))); + if(!i->last) + return; + if(i->lastx != i->x0 || i->lasty != i->y0) { + i->writer.lineto(&i->writer, i->x0, i->y0); + i->lastx = i->x0; + i->lasty = i->y0; + } + i->last = 0; + i->x0 = INVALID_COORD; + i->y0 = INVALID_COORD; +} static void* polydraw_result(gfxdrawer_t*d) { polydraw_internal_t*i = (polydraw_internal_t*)d->internal; @@ -345,17 +363,21 @@ void gfxdrawer_target_poly(gfxdrawer_t*d, double gridsize) { polydraw_internal_t*i = (polydraw_internal_t*)rfx_calloc(sizeof(polydraw_internal_t)); d->internal = i; - i->lastx = 0x7fffffff; // convert_coord can never return this value - i->lasty = 0x7fffffff; + i->lastx = INVALID_COORD; // convert_coord can never return this value + i->lasty = INVALID_COORD; + i->x0 = INVALID_COORD; + i->y0 = INVALID_COORD; d->moveTo = polydraw_moveTo; d->lineTo = polydraw_lineTo; d->splineTo = polydraw_splineTo; + d->close = polydraw_close; d->result = polydraw_result; gfxpolywriter_init(&i->writer); i->writer.setgridsize(&i->writer, gridsize); i->z = 1.0 / gridsize; } +#if 0 gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly) { gfxpolystroke_t*stroke; @@ -382,6 +404,91 @@ gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly) l[count-1].next = 0; return l; } +#endif + +gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly) +{ + gfxpolystroke_t*stroke; + int count = 0; + if(!poly->strokes) + return 0; + dict_t*d = dict_new2(&point_type); + dict_t*todo = dict_new2(&ptr_type); + gfxpolystroke_t*stroke_min= poly->strokes; + int32_t y_min=stroke_min->points[0].y; + for(stroke=poly->strokes;stroke;stroke=stroke->next) { + dict_put(todo, stroke, stroke); + assert(stroke->num_points>1); + count += stroke->num_points; + if(stroke->dir == DIR_UP) { + dict_put(d, &stroke->points[stroke->num_points-1], stroke); + } else { + dict_put(d, &stroke->points[0], stroke); + } + if(stroke->points[0].y < y_min) { + y_min = stroke->points[0].y; + stroke_min = stroke; + } + } + gfxpolystroke_t*next_todo = poly->strokes; + gfxline_t*l = malloc(sizeof(gfxline_t)*count); + count = 0; + stroke = stroke_min; + + point_t last = {INVALID_COORD, INVALID_COORD}; + char should_connect = 0; + while(stroke) { + assert(dict_contains(todo, stroke)); + int t; + int pos = 0; + int incr = 1; + if(stroke->dir == DIR_UP) { + pos = stroke->num_points-1; + incr = -1; + } + /* TODO: keeping the up/down order intact increases the polygon size + considerably. If this is going to be an even/odd polygon, + we could ignore it and save some space */ + if(last.x != stroke->points[pos].x || last.y != stroke->points[pos].y) { + l[count].x = stroke->points[pos].x * poly->gridsize; + l[count].y = stroke->points[pos].y * poly->gridsize; + l[count].type = gfx_moveTo; + l[count].next = &l[count+1]; + count++; + assert(!should_connect); + } + pos += incr; + for(t=1;tnum_points;t++) { + l[count].x = stroke->points[pos].x * poly->gridsize; + l[count].y = stroke->points[pos].y * poly->gridsize; + l[count].type = gfx_lineTo; + l[count].next = &l[count+1]; + count++; + pos += incr; + } + last = stroke->points[pos-incr]; + char del = dict_del(todo, stroke); + assert(del); + assert(!dict_contains(todo, stroke)); + + /* try to find a poly which starts at the point we drew last */ + stroke = dict_lookup(d, &last); + should_connect = 1; + while(!dict_contains(todo, stroke)) { + should_connect = 0; + stroke = next_todo; + if(!next_todo) { + stroke = 0; + break; + } + next_todo = next_todo->next; + } + } + l[count-1].next = 0; + dict_destroy(todo); + dict_destroy(d); + return l; +} static windcontext_t onepolygon = {1}; gfxline_t* gfxpoly_circular_to_evenodd(gfxline_t*line, double gridsize)