X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgfxpoly.c;h=a687e63094cf553ac4ef1a50cdd3ece69b0b81c1;hp=acf2de3dd7aa2778a77bd6e8e0aec370e50cbd34;hb=bdad407fb79c2f7be9f3603694ebdeadc645b52d;hpb=95071265866ba487f424b1c66db70de905601ad8 diff --git a/lib/gfxpoly.c b/lib/gfxpoly.c index acf2de3..a687e63 100644 --- a/lib/gfxpoly.c +++ b/lib/gfxpoly.c @@ -233,6 +233,9 @@ unsigned char* render_svp(ArtSVP*svp, intbbox_t*bbox, double zoom, ArtWindRule r return image; } +#define MAX_WIDTH 8192 +#define MAX_HEIGHT 4096 + intbbox_t get_svp_bbox(ArtSVP*svp, double zoom) { int t; @@ -256,9 +259,23 @@ intbbox_t get_svp_bbox(ArtSVP*svp, double zoom) if(x1 < b.xmin) b.xmin = x1; if(y1 < b.ymin) b.ymin = y1; if(x2 > b.xmax) b.xmax = x2; - if(y2 > b.xmax) b.ymax = y2; + if(y2 > b.ymax) b.ymax = y2; } } + if(b.xmax > (int)(MAX_WIDTH*zoom)) + b.xmax = (int)(MAX_WIDTH*zoom); + if(b.ymax > (int)(MAX_HEIGHT*zoom)) + b.ymax = (int)(MAX_HEIGHT*zoom); + if(b.xmin < -(int)(MAX_WIDTH*zoom)) + b.xmin = -(int)(MAX_WIDTH*zoom); + if(b.ymin < -(int)(MAX_HEIGHT*zoom)) + b.ymin = -(int)(MAX_HEIGHT*zoom); + + if(b.xmin > b.xmax) + b.xmin = b.xmax; + if(b.ymin > b.ymax) + b.ymin = b.ymax; + b.width = b.xmax - b.xmin; b.height = b.ymax - b.ymin; return b; @@ -279,51 +296,39 @@ intbbox_t get_svp_bbox(ArtSVP*svp, double zoom) #define B00000010 0x02 #define B00000001 0x01 -int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2) +static int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2) { - int similar = 0; + if(!data1 || !data2) + return 0; int x,y; int height = bbox->height; int width = bbox->width; int width8 = (width+7) >> 3; unsigned char*l1 = &data1[width8]; unsigned char*l2 = &data2[width8]; - int fail = 0; for(y=1;ytype == gfx_moveTo) { vec[pos].code = ART_MOVETO_OPEN; vec[pos].x = l2->x; vec[pos].y = l2->y; + lastmove=pos; pos++; assert(pos<=len); } else if(l2->type == gfx_lineTo) { @@ -390,6 +397,16 @@ static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line, char fill) } x = l2->x; y = l2->y; + + /* let closed line segments start w/ MOVETO instead of MOVETO_OPEN */ + if(lastmove>=0 && l2->type!=gfx_moveTo && (!l2->next || l2->next->type == gfx_moveTo)) { + if(vec[lastmove].x == l2->x && + vec[lastmove].y == l2->y) { + assert(vec[lastmove].code == ART_MOVETO_OPEN); + vec[lastmove].code = ART_MOVETO; + } + } + l2 = l2->next; } vec[pos++].code = ART_END; @@ -414,7 +431,7 @@ static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line, char fill) } /* Find adjacent identical points. If an ajdacent pair of identical - points is found, the second is removed. + points is found, the second one is removed. So moveto x,y lineto x,y becomes moveto x,y lineto x,y lineto x,y becomes lineto x,y lineto x,y moveto x,y becomes lineto x,y @@ -506,7 +523,13 @@ static double find_shear_value(ArtSVP*svp) } if(!fail) break; - v = lrand48() / 2000000000.0; +#ifdef HAVE_LRAND48 + v = lrand48() / 2000000000.0;; +#elif HAVE_RAND + v = rand() / 2000000000.0; +#else +#error "no lrand48()/rand() implementation found" +#endif tries++; } return v; @@ -657,7 +680,7 @@ int check_svp(ArtSVP*svp) qsort(seg_start, num_segs, sizeof(svp_segment_part_t*), compare_seg_start); qsort(seg_end, num_segs, sizeof(svp_segment_part_t*), compare_seg_end); - double lasty = y[0]+1; + double lasty = num_points?y[0]+1:0; int num_active = 0; int bleed = 0; double bleedy1=0,bleedy2 = 0; @@ -706,7 +729,6 @@ void write_svp_postscript(const char*filename, ArtSVP*svp) { if(!svp) return; - printf("writing %s\n", filename); FILE*fi = fopen(filename, "wb"); int i, j; double xmin=0,ymin=0,xmax=0,ymax=0; @@ -889,7 +911,7 @@ static ArtSVP* gfxfillToSVP(gfxline_t*line, int perturb) //#ifdef SHEAR // double shear = find_shear_value(svp); -// gfxline_t*line = gfxpoly_to_gfxline((gfxpoly_t*)svp); +// gfxline_t*line = gfxline_from_gfxpoly((gfxpoly_t*)svp); // gfxline_t*l = line; // while(l) { // l->y += l->x*shear; @@ -906,11 +928,6 @@ static ArtSVP* gfxfillToSVP(gfxline_t*line, int perturb) //#endif - -extern const ArtSVP* current_svp; -extern void art_report_error(); -extern int art_error_in_intersector; - ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule) { ArtSvpWriter * swr = art_svp_writer_rewind_new(rule); @@ -925,9 +942,9 @@ ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule) current_svp = result; art_report_error(); // might set art_error_in_intersector } else { + msg(" Comparing polygon renderings of size %dx%d and %dx%d", bbox.width, bbox.height, bbox.width, bbox.height); unsigned char*data1 = render_svp(svp, &bbox, zoom, rule); unsigned char*data2 = render_svp(result, &bbox, zoom, ART_WIND_RULE_ODDEVEN); - msg(" Comparing polygon renderings of size %dx%d and %dx%d", bbox.width, bbox.height, bbox.width, bbox.height); if(!compare_bitmaps(&bbox, data1, data2)) { msg(" Bad SVP rewinding result- polygons don't match"); current_svp = result; @@ -946,7 +963,7 @@ ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule) return result; } -gfxline_t* gfxpoly_to_gfxline(gfxpoly_t*poly) +gfxline_t* gfxline_from_gfxpoly(gfxpoly_t*poly) { ArtSVP*svp = (ArtSVP*)poly; int size = 0; @@ -981,10 +998,10 @@ gfxline_t* gfxpoly_to_gfxline(gfxpoly_t*poly) } } -gfxpoly_t* gfxpoly_fillToPoly(gfxline_t*line) +gfxpoly_t* gfxpoly_from_fill(gfxline_t*line, double gridsize) { /* I'm not sure whether doing perturbation here is actually - a good idea- if that line has been run through the machine + a good idea- if that line has been run through the machinery several times already, it might be safer to leave it alone, since it should already be in a format libart can handle */ #ifdef PERTURBATE @@ -1081,7 +1098,7 @@ gfxpoly_t* gfxpoly_union(gfxpoly_t*poly1, gfxpoly_t*poly2) return (gfxpoly_t*)svp; } -gfxpoly_t* gfxpoly_strokeToPoly(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit) +gfxpoly_t* gfxpoly_from_stroke(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit, double gridsize) { ArtVpath* vec = gfxline_to_ArtVpath(line, 0); msg(" Casting gfxline of %d segments to a stroke-polygon", gfxline_len(line)); @@ -1105,31 +1122,26 @@ gfxpoly_t* gfxpoly_strokeToPoly(gfxline_t*line, gfxcoord_t width, gfx_capType ca return (gfxpoly_t*)svp; } -gfxline_t* gfxline_circularToEvenOdd(gfxline_t*line) +gfxline_t* gfxpoly_circular_to_evenodd(gfxline_t*line, double gridsize) { msg(" Converting circular-filled gfxline of %d segments to even-odd filled gfxline", gfxline_len(line)); ArtSVP* svp = gfxfillToSVP(line, 1); - /* TODO: ART_WIND_RULE_POSITIVE means that a shape is visible if - positive and negative line segments add up to something positive. - I *think* that clockwise fill in PDF is defined in a way, however, - that the *last* shape's direction will determine whether something - is filled */ ArtSVP* svp_rewinded; - svp_rewinded = run_intersector(svp, ART_WIND_RULE_POSITIVE); + svp_rewinded = run_intersector(svp, ART_WIND_RULE_NONZERO); if(!svp_rewinded) { art_svp_free(svp); return 0; } - gfxline_t* result = gfxpoly_to_gfxline((gfxpoly_t*)svp_rewinded); + gfxline_t* result = gfxline_from_gfxpoly((gfxpoly_t*)svp_rewinded); art_svp_free(svp); art_svp_free(svp_rewinded); return result; } -gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2) +gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2, double gridsize) { ArtVpath *vec = art_new (ArtVpath, 5+1); vec[0].code = ART_MOVETO; @@ -1155,7 +1167,7 @@ gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2) return (gfxpoly_t*)svp; } -void gfxpoly_free(gfxpoly_t*poly) +void gfxpoly_destroy(gfxpoly_t*poly) { ArtSVP*svp = (ArtSVP*)poly; art_svp_free(svp);