X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fdevices%2Fpolyops.c;h=ab9aa8c80cb6651000e559cc21dcac886a4f6634;hb=85c68ce7c98ce23b0f0512bc1c83ff4be86c3114;hp=b5bb1d306b4e7329557ad1e94df548b6ef0ff3da;hpb=18d9b33fa47e1c24cfd2451247e30342c452d3eb;p=swftools.git diff --git a/lib/devices/polyops.c b/lib/devices/polyops.c index b5bb1d3..ab9aa8c 100644 --- a/lib/devices/polyops.c +++ b/lib/devices/polyops.c @@ -25,19 +25,16 @@ #include #endif #include -#include #include #include #include "../mem.h" #include "../gfxdevice.h" #include "../gfxtools.h" #include "../gfxpoly.h" -#include "../log.h" #include "polyops.h" typedef struct _clip { gfxpoly_t*poly; - int openclips; struct _clip*next; } clip_t; @@ -45,9 +42,6 @@ typedef struct _internal { gfxdevice_t*out; clip_t*clip; gfxpoly_t*polyunion; - - int good_polygons; - int bad_polygons; } internal_t; static int verbose = 0; @@ -91,56 +85,19 @@ void polyops_startclip(struct _gfxdevice*dev, gfxline_t*line) dbg("polyops_startclip"); internal_t*i = (internal_t*)dev->internal; - gfxpoly_t* oldclip = i->clip?i->clip->poly:0; gfxpoly_t* poly = gfxpoly_fillToPoly(line); - if(poly) - i->good_polygons++; - else - i->bad_polygons++; - - gfxpoly_t* currentclip = 0; - int type = 0; - - /* we can't rely on gfxpoly actually being able to convert - a gfxline into a gfxpoly- for polygons which are too - complex or just degenerate, this might fail. So handle - all the cases where polygon conversion or intersection - might go awry */ - if(!poly && !oldclip) { - i->out->startclip(i->out,line); - currentclip = 0; - type = 1; - } else if(!poly && oldclip) { - gfxline_t*oldclipline = gfxpoly_to_gfxline(oldclip); - i->out->startclip(i->out,oldclipline); - i->out->startclip(i->out,line); - currentclip = 0; - type = 2; - } else if(poly && oldclip) { - gfxpoly_t*intersection = gfxpoly_intersect(poly, oldclip); - if(intersection) { - i->good_polygons++; - // this case is what usually happens - gfxpoly_free(poly);poly=0; - currentclip = intersection; - type = 0; - } else { - i->bad_polygons++; - gfxline_t*oldclipline = gfxpoly_to_gfxline(oldclip); - i->out->startclip(i->out, oldclipline); - currentclip = poly; - type = 1; - } - } else if(poly && !oldclip) { - currentclip = poly; - type = 0; - } - clip_t*n = i->clip; - i->clip = (clip_t*)rfx_calloc(sizeof(clip_t)); - i->clip->next = n; - i->clip->poly = currentclip; - i->clip->openclips = type; + if(i->clip) { + gfxpoly_t*old = i->clip->poly; + clip_t*n = i->clip; + i->clip = (clip_t*)rfx_calloc(sizeof(clip_t)); + i->clip->next = n; + i->clip->poly = gfxpoly_intersect(poly, old); + gfxpoly_free(poly); + } else { + i->clip = (clip_t*)rfx_calloc(sizeof(clip_t)); + i->clip->poly = poly; + } } void polyops_endclip(struct _gfxdevice*dev) @@ -148,91 +105,42 @@ void polyops_endclip(struct _gfxdevice*dev) dbg("polyops_endclip"); internal_t*i = (internal_t*)dev->internal; - if(!i->clip) { - msg(" endclip without startclip (in: polyops)\n"); - return; - } - - clip_t*old = i->clip; - i->clip = i->clip->next; - if(old->poly) { + if(i->clip) { + clip_t*old = i->clip; + i->clip = i->clip->next; gfxpoly_free(old->poly);old->poly = 0; + old->next = 0;free(old); + } else { + fprintf(stderr, "Error: endclip without startclip\n"); } - int t; - for(t=0;topenclips;t++) - i->out->endclip(i->out); - - old->next = 0;free(old); } static void addtounion(struct _gfxdevice*dev, gfxpoly_t*poly) { internal_t*i = (internal_t*)dev->internal; - if(poly && i->polyunion) { + if(i->polyunion) { gfxpoly_t*old = i->polyunion; - gfxpoly_t*newpoly = gfxpoly_union(poly,i->polyunion); - i->polyunion = newpoly; + i->polyunion = gfxpoly_union(poly,i->polyunion); gfxpoly_free(old); } } -static gfxline_t* handle_poly(gfxdevice_t*dev, gfxpoly_t*poly, char*ok) -{ - internal_t*i = (internal_t*)dev->internal; - if(i->clip && i->clip->poly) { - gfxpoly_t*old = poly; - if(poly) { - poly = gfxpoly_intersect(poly, i->clip->poly); - gfxpoly_free(old); - } - } - - if(poly) - i->good_polygons++; - else - i->bad_polygons++; - - addtounion(dev, poly); - gfxline_t*gfxline = 0; - if(poly) { - // this is the case where everything went right - gfxline_t*line = gfxpoly_to_gfxline(poly); - gfxpoly_free(poly); - *ok = 1; - return line; - } else { - if(i->clip && i->clip->poly) { - /* convert current clipping from a polygon to an - actual "startclip" written to the output */ - assert(i->clip->openclips <= 1); - gfxline_t*clipline = gfxpoly_to_gfxline(i->clip->poly); - i->out->startclip(i->out, clipline); - gfxline_free(clipline); - gfxpoly_free(i->clip->poly);i->clip->poly = 0; - i->clip->openclips++; - return 0; - } else { - return 0; - } - } -} - void polyops_stroke(struct _gfxdevice*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit) { dbg("polyops_stroke"); internal_t*i = (internal_t*)dev->internal; - + //i->out->stroke(i->out, line, width, color, cap_style, joint_style, miterLimit); gfxpoly_t* poly = gfxpoly_strokeToPoly(line, width, cap_style, joint_style, miterLimit); - char ok = 0; - gfxline_t*line2 = handle_poly(dev, poly, &ok); - - if(ok) { - if(i->out && line2) i->out->fill(i->out, line2, color); - gfxline_free(line2); - } else { - msg(" .."); - if(i->out) i->out->stroke(i->out, line, width, color, cap_style, joint_style, miterLimit); + if(i->clip) { + gfxpoly_t*old = poly; + poly = gfxpoly_intersect(poly, i->clip->poly); + gfxpoly_free(old); } + addtounion(dev, poly); + gfxline_t*gfxline = gfxpoly_to_gfxline(poly); + if(i->out) i->out->fill(i->out, gfxline, color); + gfxline_free(gfxline); + gfxpoly_free(poly); } void polyops_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) @@ -241,49 +149,52 @@ void polyops_fill(struct _gfxdevice*dev, gfxline_t*line, gfxcolor_t*color) internal_t*i = (internal_t*)dev->internal; gfxpoly_t*poly = gfxpoly_fillToPoly(line); - char ok = 0; - gfxline_t*line2 = handle_poly(dev, poly, &ok); - if(ok) { - if(i->out && line2) i->out->fill(i->out, line2, color); - gfxline_free(line2); - } else { - if(i->out) i->out->fill(i->out, line, color); + if(i->clip) { + gfxpoly_t*old = poly; + poly = gfxpoly_intersect(poly, i->clip->poly); + gfxpoly_free(old); } + addtounion(dev,poly); + gfxline_t*gfxline = gfxpoly_to_gfxline(poly); + if(i->out) i->out->fill(i->out, gfxline, color); + gfxline_free(gfxline); + gfxpoly_free(poly); } void polyops_fillbitmap(struct _gfxdevice*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform) { dbg("polyops_fillbitmap"); internal_t*i = (internal_t*)dev->internal; - - gfxpoly_t*poly = gfxpoly_fillToPoly(line); - char ok = 0; - gfxline_t*line2 = handle_poly(dev, poly, &ok); + gfxpoly_t* poly = gfxpoly_fillToPoly(line); - if(ok) { - if(i->out && line2) i->out->fillbitmap(i->out, line2, img, matrix, cxform); - gfxline_free(line2); - } else { - if(i->out) i->out->fillbitmap(i->out, line, img, matrix, cxform); + if(i->clip) { + gfxpoly_t*old = poly; + poly = gfxpoly_intersect(poly, i->clip->poly); + gfxpoly_free(old); } + addtounion(dev,poly); + gfxline_t*gfxline = gfxpoly_to_gfxline(poly); + if(i->out) i->out->fillbitmap(i->out, gfxline, img, matrix, cxform); + gfxline_free(gfxline); + gfxpoly_free(poly); } void polyops_fillgradient(struct _gfxdevice*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix) { dbg("polyops_fillgradient"); internal_t*i = (internal_t*)dev->internal; - - gfxpoly_t*poly = gfxpoly_fillToPoly(line); - char ok = 0; - gfxline_t*line2 = handle_poly(dev, poly, &ok); - - if(ok) { - if(i->out && line2) i->out->fillgradient(i->out, line2, gradient, type, matrix); - gfxline_free(line2); - } else { - if(i->out) i->out->fillgradient(i->out, line, gradient, type, matrix); + gfxpoly_t* poly = gfxpoly_fillToPoly(line); + if(i->clip) { + gfxpoly_t*old = poly; + poly = gfxpoly_intersect(poly, i->clip->poly); + gfxpoly_free(old); } + addtounion(dev,poly); + gfxline_t*gfxline = gfxpoly_to_gfxline(poly); + if(i->out) i->out->fillgradient(i->out, gfxline, gradient, type, matrix); + gfxline_free(gfxline); + gfxpoly_free(poly); } void polyops_addfont(struct _gfxdevice*dev, gfxfont_t*font) @@ -302,26 +213,24 @@ void polyops_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, gfxcol gfxline_t*glyph = gfxline_clone(font->glyphs[glyphnr].line); gfxline_transform(glyph, matrix); - if(i->clip && i->clip->poly) { + if(i->clip) { gfxbbox_t bbox = gfxline_getbbox(glyph); gfxpoly_t*dummybox = gfxpoly_createbox(bbox.xmin,bbox.ymin,bbox.xmax,bbox.ymax); - - char ok=0; - gfxline_t*gfxline = handle_poly(dev, dummybox, &ok); - if(ok) { - gfxbbox_t bbox2 = gfxline_getbbox(gfxline); - double w = bbox2.xmax - bbox2.xmin; - double h = bbox2.ymax - bbox2.ymin; - if(w < 0.001 || h < 0.001) /* character was clipped completely */ { - } else if(fabs((bbox.xmax - bbox.xmin) - w) > 0.05 || - fabs((bbox.ymax - bbox.ymin) - h) > 0.05) { - /* notable change in character size: character was clipped - TODO: how to deal with diagonal cuts? - */ - polyops_fill(dev, glyph, color); - } else { - if(i->out) i->out->drawchar(i->out, font, glyphnr, color, matrix); - } + gfxpoly_t*poly = gfxpoly_intersect(dummybox, i->clip->poly); + gfxline_t*gfxline = gfxpoly_to_gfxline(poly); + gfxbbox_t bbox2 = gfxline_getbbox(gfxline); + double w = bbox2.xmax - bbox2.xmin; + double h = bbox2.ymax - bbox2.ymin; + + addtounion(dev, poly); // TODO: use the whole char, not just the bbox? + + if(w < 0.001 || h < 0.001) /* character was clipped completely */ { + } else if(fabs((bbox.xmax - bbox.xmin) - w) > 0.05 || + fabs((bbox.ymax - bbox.ymin) - h) > 0.05) { + /* notable change in character size: character was clipped + TODO: handle diagonal cuts + */ + polyops_fill(dev, glyph, color); } else { if(i->out) i->out->drawchar(i->out, font, glyphnr, color, matrix); } @@ -351,13 +260,8 @@ gfxresult_t* polyops_finish(struct _gfxdevice*dev) dbg("polyops_finish"); internal_t*i = (internal_t*)dev->internal; - if(i->polyunion) { gfxpoly_free(i->polyunion);i->polyunion=0; - } else { - if(i->bad_polygons) { - msg(" --flatten success rate: %.1f%% (%d failed polygons)", i->good_polygons*100.0 / (i->good_polygons + i->bad_polygons), i->bad_polygons); - } } if(i->out) { return i->out->finish(i->out);