diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo/cdcairo.c | 37 | ||||
-rw-r--r-- | src/drv/cddxf.c | 4 | ||||
-rw-r--r-- | src/drv/cdpdf.c | 2 | ||||
-rw-r--r-- | src/drv/cdps.c | 2 | ||||
-rw-r--r-- | src/gdiplus/cdwinp.cpp | 5 | ||||
-rw-r--r-- | src/gdk/cdgdk.c | 2 | ||||
-rw-r--r-- | src/sim/sim_primitives.c | 281 | ||||
-rw-r--r-- | src/svg/cdsvg.c | 126 | ||||
-rw-r--r-- | src/win32/cdwin.c | 71 | ||||
-rw-r--r-- | src/x11/cdx11.c | 2 |
10 files changed, 332 insertions, 200 deletions
diff --git a/src/cairo/cdcairo.c b/src/cairo/cdcairo.c index 286d5ad..55f8b51 100644 --- a/src/cairo/cdcairo.c +++ b/src/cairo/cdcairo.c @@ -228,7 +228,7 @@ static unsigned long sEncodeRGBA(unsigned char r, unsigned char g, unsigned char static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* userdata, int (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* userdata, unsigned char*r, unsigned char*g, unsigned char*b, unsigned char*a)) { - int i, j, offset; + int i, j, offset, ret; unsigned char r, g, b, a; cairo_surface_t* pattern_surface; unsigned long* data; @@ -242,7 +242,12 @@ static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* userdata, i { for (i = 0; i < n; i++) { - int ret = data2rgb(ctxcanvas, n, i, m-1-j, userdata, &r, &g, &b, &a); + /* internal transform, affects also pattern orientation */ + if (ctxcanvas->canvas->invert_yaxis) + ret = data2rgb(ctxcanvas, n, i, m-1-j, userdata, &r, &g, &b, &a); + else + ret = data2rgb(ctxcanvas, n, i, j, userdata, &r, &g, &b, &a); + if (ret == -1) { data++; /* already transparent */ @@ -587,22 +592,28 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2); } -static void sFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2) +static void sFixAngles(cdCtxCanvas* ctxcanvas, double *a1, double *a2) { if (ctxcanvas->canvas->invert_yaxis) { + double t; + /* Cairo angles are clock-wise by default */ - double t = *angle1; - *angle1 = *angle2; - *angle2 = t; - *angle1 *= -CD_DEG2RAD; - *angle2 *= -CD_DEG2RAD; - } - else - { - *angle1 *= CD_DEG2RAD; - *angle2 *= CD_DEG2RAD; + *a1 *= -1; + *a2 *= -1; + + /* swap, so the start angle is the smaller */ + t = *a1; + *a1 = *a2; + *a2 = t; } + /* if NOT inverted means a transformation is set, + so the angle will follow the transformation that includes the axis invertion, + then it is counter-clockwise */ + + /* convert to radians */ + *a1 *= CD_DEG2RAD; + *a2 *= CD_DEG2RAD; } static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) diff --git a/src/drv/cddxf.c b/src/drv/cddxf.c index f8c9a28..c5d0df5 100644 --- a/src/drv/cddxf.c +++ b/src/drv/cddxf.c @@ -683,6 +683,7 @@ static void cdarc (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double bulge = calc_bulge (a, b, t, t+seg_angle); /* and t+seg_angle and write */ writevertex (ctxcanvas, xc, yc, a, b, t, bulge); /* vertex at t */ } + writevertex (ctxcanvas, xc, yc, a, b, t2, 0); /* bulge of last vertex is useless */ fprintf ( ctxcanvas->file, "0\n" ); @@ -731,12 +732,15 @@ static void cdsector (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doub if ((a2-a1) != 360) writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */ + for (i=0, t=t1; i<nseg; i++, t+=seg_angle) { /* calculate bulge between t */ bulge = calc_bulge (a, b, t, t+seg_angle); /* and t+seg_angle and write */ writevertex (ctxcanvas, xc, yc, a, b, t, bulge); /* vertex at t */ } + writevertex (ctxcanvas, xc, yc, a, b, t2, 0); /* bulge of last vertex is useless */ + if ((a2-a1) != 360) writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */ diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c index 4614568..2c48d50 100644 --- a/src/drv/cdpdf.c +++ b/src/drv/cdpdf.c @@ -328,6 +328,8 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl { sUpdateFill(ctxcanvas, 0); + /* angles in degrees counterclockwise, same as CD */ + if (w==h) { PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); diff --git a/src/drv/cdps.c b/src/drv/cdps.c index ce45397..b651994 100644 --- a/src/drv/cdps.c +++ b/src/drv/cdps.c @@ -624,6 +624,8 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a { sUpdateFill(ctxcanvas, 0); + /* angles in degrees counterclockwise, same as CD */ + if (w==h) /* Circulo: PS implementa direto */ { fprintf(ctxcanvas->file, "N %d %d %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2); diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp index 5fbe2db..a2eec55 100644 --- a/src/gdiplus/cdwinp.cpp +++ b/src/gdiplus/cdwinp.cpp @@ -526,6 +526,7 @@ static void cdpattern(cdCtxCanvas* ctxcanvas, int w, int h, const long int *colo { int line_offset_colors; int line_offset = j*stride; + /* internal transform, affects also pattern orientation */ if (ctxcanvas->canvas->invert_yaxis) line_offset_colors = ((h - 1) - j)*w; // Fix up side down else @@ -629,9 +630,11 @@ static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2 { if (ctxcanvas->canvas->invert_yaxis) { - // GDI+ angles are clock-wise by default + // GDI+ angles are clock-wise by default, in degrees *angle1 *= -1; *angle2 *= -1; + + // no need to swap, because we will use (angle2-angle1) } } diff --git a/src/gdk/cdgdk.c b/src/gdk/cdgdk.c index 8521d4e..56055a7 100644 --- a/src/gdk/cdgdk.c +++ b/src/gdk/cdgdk.c @@ -692,6 +692,8 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a return; } + /* angles in 1/64ths of degrees counterclockwise, similar to CD */ + cdgdkCheckSolidStyle(ctxcanvas, 1); gdk_draw_arc(ctxcanvas->wnd, ctxcanvas->gc, FALSE, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); cdgdkCheckSolidStyle(ctxcanvas, 0); diff --git a/src/sim/sim_primitives.c b/src/sim/sim_primitives.c index fc0c96c..9f6f969 100644 --- a/src/sim/sim_primitives.c +++ b/src/sim/sim_primitives.c @@ -119,25 +119,33 @@ static void sFixAngles(cdCanvas* canvas, double *angle1, double *angle2) { if (canvas->invert_yaxis) { - double temp = 360 - *angle1; // TO CHECK - *angle1 = 360 - *angle2; - *angle2 = temp; + double t; - *angle1 *= CD_DEG2RAD; - *angle2 *= CD_DEG2RAD; - } - else - { - *angle1 *= CD_DEG2RAD; - *angle2 *= CD_DEG2RAD; + /* computation is done as if the angles are counterclockwise, + and yaxis is NOT inverted. */ + + /* if yaxis is inverted then must orient clockwise */ + /* change angle orientation */ + *angle1 = 360 - *angle1; + *angle2 = 360 - *angle2; + + /* swap, so the start angle is the smaller */ + t = *angle1; + *angle1 = *angle2; + *angle2 = t; } + + /* convert to radians */ + *angle1 *= CD_DEG2RAD; + *angle2 *= CD_DEG2RAD; } -static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int yc, int width, int height, double angle1, double angle2) +static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int yc, int width, int height, double angle1, double angle2, cdPoint* current) { double c, s, sx, sy, x, y, prev_x, prev_y; double da; - int i, K, k, yc2 = 2*yc, p = 0, new_n; + int i, K, k, p, new_n; +// yc2 = 2*yc, /* number of segments of equivalent poligonal for a full ellipse */ K = cdSimCalcEllipseNumSegments(canvas, xc, yc, width, height); @@ -149,7 +157,7 @@ static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int if (K < 1) K = 1; new_n = *n + K+1; /* add room for K+1 samples */ - poly = (cdPoint*)realloc(poly, sizeof(cdPoint)*new_n); + poly = (cdPoint*)realloc(poly, sizeof(cdPoint)*(new_n+2)); /* add room also for points at start and end */ if (!poly) return NULL; i = *n; @@ -166,11 +174,18 @@ static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int prev_x = x; prev_y = y; + if (current) + { + poly[i] = *current; + i++; + new_n++; /* no need to reallocate */ + } + poly[i].x = _cdRound(x)+xc; poly[i].y = _cdRound(y)+yc; - if (canvas->invert_yaxis) /* must invert because of the angle orientation */ - poly[i].y = yc2 - poly[i].y; +// if (canvas->invert_yaxis) /* must invert because of the angle orientation */ +// poly[i].y = yc2 - poly[i].y; p = i+1; for (k = 1; k < K+1; k++) @@ -181,8 +196,8 @@ static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int poly[p].x = _cdRound(x)+xc; poly[p].y = _cdRound(y)+yc; - if (canvas->invert_yaxis) /* must invert because of the angle orientation */ - poly[p].y = yc2 - poly[p].y; +// if (canvas->invert_yaxis) /* must invert because of the angle orientation */ +// poly[p].y = yc2 - poly[p].y; if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) @@ -196,7 +211,7 @@ static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int return poly; } -static cdfPoint* sfPolyAddArc(cdCanvas* canvas, cdfPoint* poly, int *n, double xc, double yc, double width, double height, double angle1, double angle2) +static cdfPoint* sfPolyAddArc(cdCanvas* canvas, cdfPoint* poly, int *n, double xc, double yc, double width, double height, double angle1, double angle2, cdfPoint* current) { double c, s, sx, sy, x, y, prev_x, prev_y, da; int i, k, p, new_n; @@ -211,7 +226,7 @@ static cdfPoint* sfPolyAddArc(cdCanvas* canvas, cdfPoint* poly, int *n, double x if (K < 1) K = 1; new_n = *n + K+1; /* add room for K+1 samples */ - poly = (cdfPoint*)realloc(poly, sizeof(cdfPoint)*new_n); + poly = (cdfPoint*)realloc(poly, sizeof(cdfPoint)*(new_n+2)); /* add room also for points at start and end */ if (!poly) return NULL; i = *n; @@ -226,11 +241,18 @@ static cdfPoint* sfPolyAddArc(cdCanvas* canvas, cdfPoint* poly, int *n, double x y = (height/2.0f)*sin(angle1); prev_x = x; prev_y = y; + + if (current) + { + poly[i] = *current; + i++; + new_n++; /* no need to reallocate */ + } + poly[i].x = x+xc; poly[i].y = y+yc; p = i+1; - for (k = 1; k < K+1; k++) /* K+1 points */ { x = c*prev_x + sx*prev_y; @@ -263,7 +285,7 @@ void cdSimArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, dou return; } - poly = sPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2); + poly = sPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL); if (poly) { @@ -279,7 +301,7 @@ void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, doubl int n; cdfPoint* poly = NULL; - poly = sfPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2); + poly = sfPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL); if (poly) { @@ -294,14 +316,12 @@ static void sElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int heigh int n; cdPoint* poly = NULL; - poly = sPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2); + poly = sPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL); if (poly[n-1].x != poly[0].x || poly[n-1].y != poly[0].y) { - n++; - poly = (cdPoint*)realloc(poly, sizeof(cdPoint)*n); - if (!poly) return; + n++; /* no need to reallocate */ if (sector) /* cdSector */ { @@ -331,14 +351,12 @@ static void sfElipse(cdCtxCanvas* ctxcanvas, double xc, double yc, double width, int n; cdfPoint* poly = NULL; - poly = sfPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2); + poly = sfPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL); if (poly[n-1].x != poly[0].x || poly[n-1].y != poly[0].y) { - n++; - poly = (cdfPoint*)realloc(poly, sizeof(cdfPoint)*n); - if (!poly) return; + n++; /* no need to reallocate */ if (sector) /* cdSector */ { @@ -561,14 +579,17 @@ static cdPoint* sPolyAddBezier(cdCanvas* canvas, cdPoint* poly, int *n, cdPoint return poly; } -static cdfPoint* sPolyFAddBezier(cdCanvas* canvas, cdfPoint* poly, int *n, cdPoint start, const cdPoint* points) +static cdfPoint* sPolyFAddBezier(cdCanvas* canvas, cdfPoint* poly, int *n, cdfPoint start, const cdPoint* points) { int k, K, new_n, i; cdfPoint pt; - cdfPoint bezier_control[4]; + cdfPoint bezier_control[4], bezier[3]; - sBezierForm(start, points, bezier_control); - K = sBezierNumSegments(canvas, start, points); + bezier[0].x = points[0].x; bezier[1].x = points[1].x; bezier[2].x = points[2].x; + bezier[0].y = points[0].y; bezier[1].y = points[1].y; bezier[2].y = points[2].y; + + sfBezierForm(start, bezier, bezier_control); + K = sfBezierNumSegments(canvas, start, bezier); new_n = *n + K+1; /* add room for K+1 samples */ poly = realloc(poly, sizeof(cdfPoint)*new_n); @@ -622,12 +643,16 @@ static cdfPoint* sfPolyAddBezier(cdCanvas* canvas, cdfPoint* poly, int *n, cdfPo static void sPolyFBezier(cdCanvas* canvas, const cdPoint* points, int n) { int i = 0, poly_n = 0; - cdfPoint* fpoly = NULL; + cdfPoint* fpoly = NULL, start; + + start.x = points[0].x; + start.y = points[0].y; n--; /* first n is 4 */ while (n >= 3) { - fpoly = sPolyFAddBezier(canvas, fpoly, &poly_n, points[i], points+i+1); + fpoly = sPolyFAddBezier(canvas, fpoly, &poly_n, start, points+i+1); + start = fpoly[poly_n-1]; n -= 3; i += 3; } @@ -765,28 +790,132 @@ void cdfSimPolyPath(cdCanvas* canvas, const cdfPoint* poly, int n) yc = poly[i].y, w = poly[i+1].x, h = poly[i+1].y, - a1 = poly[i+2].x/1000.0, - a2 = poly[i+2].y/1000.0; + a1 = poly[i+2].x, + a2 = poly[i+2].y; if (current_set) - { - cdfPoint start_angle; + path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, ¤t); + else + path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, NULL); + + current = path_poly[path_poly_n-1]; + current_set = 1; + + i += 3; + } + break; + case CD_PATH_CURVETO: + if (i+3 > n) break; + if (!current_set) + { + current.x = poly[i].x; + current.y = poly[i].y; + } + path_poly = sfPolyAddBezier(canvas, path_poly, &path_poly_n, current, poly+i); + current = path_poly[path_poly_n-1]; + current_set = 1; + i += 3; + break; + case CD_PATH_CLOSE: + if (path_poly[path_poly_n-1].x != path_poly[0].x || + path_poly[path_poly_n-1].y != path_poly[0].y) + { + path_poly_n++; + path_poly = (cdfPoint*)realloc(path_poly, sizeof(cdfPoint)*path_poly_n); + if (!path_poly) return; + + /* add initial point */ + path_poly[path_poly_n-1].x = path_poly[0].x; + path_poly[path_poly_n-1].y = path_poly[0].y; + } + break; + case CD_PATH_FILL: + if (poly) + canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n); + break; + case CD_PATH_STROKE: + if (poly) + canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n); + break; + case CD_PATH_FILLSTROKE: + if (poly) + { + canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n); + canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n); + } + break; + case CD_PATH_CLIP: + if (poly) + canvas->cxFPoly(canvas->ctxcanvas, CD_CLIP, path_poly, path_poly_n); + break; + } + } - if (canvas->invert_yaxis) - { - start_angle.x = xc + cdRound(w * cos(CD_DEG2RAD * a1) / 2.0); - start_angle.y = yc - cdRound(h * sin(CD_DEG2RAD * a1) / 2.0); - } - else - { - start_angle.x = xc + cdRound(w * cos(CD_DEG2RAD * a2) / 2.0); - start_angle.y = yc + cdRound(h * sin(CD_DEG2RAD * a2) / 2.0); - } + if (path_poly) + free(path_poly); +} - path_poly = sfPolyAddLine(path_poly, &path_poly_n, current, start_angle); - } +static void sSimPolyFPath(cdCanvas* canvas, const cdPoint* poly, int n) +{ + int p, i, current_set = 0, path_poly_n; + cdfPoint current, pt; + cdfPoint* path_poly; - path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2); + current.x = 0; + current.y = 0; + current_set = 0; + + /* starts a new path */ + path_poly = NULL; + path_poly_n = 0; + + i = 0; + for (p=0; p<canvas->path_n; p++) + { + switch(canvas->path[p]) + { + case CD_PATH_NEW: + if (path_poly) + free(path_poly); + path_poly = NULL; + path_poly_n = 0; + current_set = 0; + break; + case CD_PATH_MOVETO: + if (i+1 > n) break; + current.x = poly[i].x; + current.y = poly[i].y; + current_set = 1; + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) break; + pt.x = poly[i].x; + pt.y = poly[i].y; + path_poly = sfPolyAddLine(path_poly, &path_poly_n, current, pt); + current.x = poly[i].x; + current.y = poly[i].y; + current_set = 1; + i++; + break; + case CD_PATH_ARC: + { + double xc, yc, w, h; + double a1, a2; + + if (i+3 > n) break; + + xc = poly[i].x, + yc = poly[i].y, + w = poly[i+1].x, + h = poly[i+1].y, + a1 = poly[i+2].x/1000.0, + a2 = poly[i+2].y/1000.0; + + if (current_set) + path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, ¤t); + else + path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, NULL); current = path_poly[path_poly_n-1]; current_set = 1; @@ -801,9 +930,8 @@ void cdfSimPolyPath(cdCanvas* canvas, const cdfPoint* poly, int n) current.x = poly[i].x; current.y = poly[i].y; } - path_poly = sfPolyAddBezier(canvas, path_poly, &path_poly_n, current, poly+i); - current.x = poly[i+2].x; - current.y = poly[i+2].y; + path_poly = sPolyFAddBezier(canvas, path_poly, &path_poly_n, current, poly+i); + current = path_poly[path_poly_n-1]; current_set = 1; i += 3; break; @@ -852,6 +980,23 @@ void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n) cdPoint current; cdPoint* path_poly; + if (canvas->line_width == 1 && canvas->cxFPoly) + { + int has_curve = 0; + for (p=0; p<canvas->path_n; p++) + { + if (canvas->path[p] == CD_PATH_ARC || + canvas->path[p] == CD_PATH_CURVETO) + has_curve = 1; + if (canvas->path[p] == CD_PATH_STROKE && + has_curve == 1) + { + sSimPolyFPath(canvas, poly, n); + return; + } + } + } + current.x = 0; current.y = 0; current_set = 0; @@ -900,24 +1045,9 @@ void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n) a2 = poly[i+2].y/1000.0; if (current_set) - { - cdPoint start_angle; - - if (canvas->invert_yaxis) - { - start_angle.x = xc + cdRound(w * cos(CD_DEG2RAD * a1) / 2.0); - start_angle.y = yc - cdRound(h * sin(CD_DEG2RAD * a1) / 2.0); - } - else - { - start_angle.x = xc + cdRound(w * cos(CD_DEG2RAD * a2) / 2.0); - start_angle.y = yc + cdRound(h * sin(CD_DEG2RAD * a2) / 2.0); - } - - path_poly = sPolyAddLine(path_poly, &path_poly_n, current, start_angle); - } - - path_poly = sPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2); + path_poly = sPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, ¤t); + else + path_poly = sPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, NULL); current = path_poly[path_poly_n-1]; current_set = 1; @@ -933,8 +1063,7 @@ void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n) current.y = poly[i].y; } path_poly = sPolyAddBezier(canvas, path_poly, &path_poly_n, current, poly+i); - current.x = poly[i+2].x; - current.y = poly[i+2].y; + current = path_poly[path_poly_n-1]; current_set = 1; i += 3; break; diff --git a/src/svg/cdsvg.c b/src/svg/cdsvg.c index fd48559..f84e4b5 100644 --- a/src/svg/cdsvg.c +++ b/src/svg/cdsvg.c @@ -215,10 +215,46 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); } +static void sCalcArc(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double a1, double a2, double *arcStartX, double *arcStartY, double *arcEndX, double *arcEndY, int *largeArc) +{ + if (ctxcanvas->canvas->invert_yaxis==0) + { + double t; + + /* if NOT inverted means a transformation is set, + so the angle will follow the transformation that includes the axis invertion, + then it is clockwise. */ + + /* this situation is inverted compared to the Cairo driver */ + + /* change angle orientation */ + a1 = 360 - a1; + a2 = 360 - a2; + + /* swap, so the start angle is the smaller */ + t = a1; + a1 = a2; + a2 = t; + } + + /* computation is done as if the angles are counterclockwise, + and yaxis is inverted. */ + + *arcStartX = xc + (w/2.0)*cos(a1*CD_DEG2RAD); + *arcStartY = yc - (h/2.0)*sin(a1*CD_DEG2RAD); + *arcEndX = xc + (w/2.0)*cos(a2*CD_DEG2RAD); + *arcEndY = yc - (h/2.0)*sin(a2*CD_DEG2RAD); + + if (fabs(a2-a1) > 180.0) + *largeArc = 1; + else + *largeArc = 0; +} + static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; + int largeArc; if((a1 == 0.0) && (a2 == 360.0)) /* an ellipse/circle */ { @@ -227,20 +263,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl return; } - if (ctxcanvas->canvas->use_matrix) /* Transformation active */ - { - double temp = 360 - a1; - a1 = 360 - a2; - a2 = temp; - } - - arcStartX = (xc+(w/2)*cos(a1*CD_DEG2RAD)); - arcStartY = (yc-(h/2)*sin(a1*CD_DEG2RAD)); - arcEndX = (xc+(w/2)*cos(a2*CD_DEG2RAD)); - arcEndY = (yc-(h/2)*sin(a2*CD_DEG2RAD)); - - if((a2-a1) > 180.0) - largeArc = 1; + sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc); fprintf(ctxcanvas->file, "<path d=\"M%g,%g A%g,%g 0 %d,0 %g,%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n", arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity); @@ -254,7 +277,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; + int largeArc; if((a1 == 0.0) && (a2 == 360.0)) /* an ellipse/circle */ { @@ -263,20 +286,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do return; } - if (ctxcanvas->canvas->use_matrix) /* Transformation active */ - { - double temp = 360 - a1; - a1 = 360 - a2; - a2 = temp; - } - - arcStartX = (xc+(w/2)*cos(a1*CD_DEG2RAD)); - arcStartY = (yc-(h/2)*sin(a1*CD_DEG2RAD)); - arcEndX = (xc+(w/2)*cos(a2*CD_DEG2RAD)); - arcEndY = (yc-(h/2)*sin(a2*CD_DEG2RAD)); - - if((a2-a1) > 180.0) - largeArc = 1; + sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc); fprintf(ctxcanvas->file, "<path d=\"M%g,%g L%g,%g A%g,%g 0 %d,0 %g,%g Z\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", xc, yc, arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, ctxcanvas->opacity); @@ -290,22 +300,9 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; - - if (ctxcanvas->canvas->use_matrix) /* Transformation active */ - { - double temp = 360 - a1; - a1 = 360 - a2; - a2 = temp; - } + int largeArc; - arcStartX = (xc+(w/2)*cos(a1*CD_DEG2RAD)); - arcStartY = (yc-(h/2)*sin(a1*CD_DEG2RAD)); - arcEndX = (xc+(w/2)*cos(a2*CD_DEG2RAD)); - arcEndY = (yc-(h/2)*sin(a2*CD_DEG2RAD)); - - if((a2-a1) > 180.0) - largeArc = 1; + sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc); fprintf(ctxcanvas->file, "<path d=\"M%g,%g A%g,%g 0 %d,0 %g,%g Z\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, ctxcanvas->opacity); @@ -476,7 +473,7 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) { double xc, yc, w, h, a1, a2; double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; + int largeArc; if (i+3 > n) return; @@ -487,20 +484,7 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) a1 = poly[i+2].x, a2 = poly[i+2].y; - if (ctxcanvas->canvas->use_matrix) /* Transformation active */ - { - double temp = 360 - a1; - a1 = 360 - a2; - a2 = temp; - } - - arcStartX = (xc+(w/2)*cos(a1*CD_DEG2RAD)); - arcStartY = (yc-(h/2)*sin(a1*CD_DEG2RAD)); - arcEndX = (xc+(w/2)*cos(a2*CD_DEG2RAD)); - arcEndY = (yc-(h/2)*sin(a2*CD_DEG2RAD)); - - if ((a2-a1) > 180.0) - largeArc = 1; + sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc); fprintf(ctxcanvas->file, "M %g %g A %g %g 0 %d 0 %g %g ", arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY); @@ -647,8 +631,8 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) { int xc, yc, w, h; double a1, a2; - int arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; + double arcStartX, arcStartY, arcEndX, arcEndY; + int largeArc; if (i+3 > n) return; @@ -659,22 +643,9 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) a1 = poly[i+2].x/1000.0, a2 = poly[i+2].y/1000.0; - if (ctxcanvas->canvas->use_matrix) /* Transformation active */ - { - double temp = 360 - a1; - a1 = 360 - a2; - a2 = temp; - } - - arcStartX = (int)(xc+(w/2)*cos(a1*CD_DEG2RAD)); - arcStartY = (int)(yc-(h/2)*sin(a1*CD_DEG2RAD)); - arcEndX = (int)(xc+(w/2)*cos(a2*CD_DEG2RAD)); - arcEndY = (int)(yc-(h/2)*sin(a2*CD_DEG2RAD)); - - if ((a2-a1) > 180.0) - largeArc = 1; + sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc); - fprintf(ctxcanvas->file, "M %d %d A %d %d 0 %d 0 %d %d ", + fprintf(ctxcanvas->file, "M %g %g A %d %d 0 %d 0 %g %g ", arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY); i += 3; @@ -889,6 +860,7 @@ static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int ( { for (i = 0; i < n; i++) { + /* internal transform, affects also pattern orientation */ if (ctxcanvas->canvas->invert_yaxis) ret = data2rgb(ctxcanvas, n, i, m-1 - j, data, &r, &g, &b); else diff --git a/src/win32/cdwin.c b/src/win32/cdwin.c index baaff13..65c183a 100644 --- a/src/win32/cdwin.c +++ b/src/win32/cdwin.c @@ -643,10 +643,26 @@ static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style) return style; } +static void sUpdateFill(cdCtxCanvas* ctxcanvas, int fill) +{ + if (fill) + { + if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && + (ctxcanvas->canvas->interior_style != CD_PATTERN)) + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + } + else + { + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + } +} + +/*******************************************************************************/ + static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2) { - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); MoveToEx( ctxcanvas->hDC, x1, y1, NULL ); LineTo( ctxcanvas->hDC, x2, y2 ); @@ -657,8 +673,7 @@ static void cdrect (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ym { HBRUSH oldBrush; - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); oldBrush = SelectObject(ctxcanvas->hDC, GetStockObject(NULL_BRUSH)); /* tira o desenho do interior */ Rectangle(ctxcanvas->hDC, xmin, ymin, xmax+1, ymax+1); /* +1 porque nao inclue right/bottom */ @@ -667,9 +682,7 @@ static void cdrect (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ym static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) { - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN) ) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (ctxcanvas->canvas->new_region) { @@ -699,26 +712,30 @@ typedef struct _winArcParam static void sCalcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc) { + /* convert to radians */ + angle1 *= CD_DEG2RAD; + angle2 *= CD_DEG2RAD; + arc->LeftRect = xc - w/2; arc->RightRect = xc + w/2 + 1; - arc->XStartArc = xc + cdRound(w * cos(CD_DEG2RAD * angle1) / 2.0); - arc->XEndArc = xc + cdRound(w * cos(CD_DEG2RAD * angle2) / 2.0); + arc->XStartArc = xc + cdRound(w * cos(angle1) / 2.0); + arc->XEndArc = xc + cdRound(w * cos(angle2) / 2.0); if (ctxcanvas->canvas->invert_yaxis) { arc->TopRect = yc - h/2; arc->BottomRect = yc + h/2 + 1; - arc->YStartArc = yc - cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0); - arc->YEndArc = yc - cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0); + arc->YStartArc = yc - cdRound(h * sin(angle1) / 2.0); + arc->YEndArc = yc - cdRound(h * sin(angle2) / 2.0); } else { arc->BottomRect = yc - h/2; arc->TopRect = yc + h/2 + 1; - arc->YStartArc = yc + cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0); - arc->YEndArc = yc + cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0); + arc->YStartArc = yc + cdRound(h * sin(angle1) / 2.0); + arc->YEndArc = yc + cdRound(h * sin(angle2) / 2.0); - /* it is clock-wise when axis inverted */ + /* it is clock-wise when axis NOT inverted */ _cdSwapInt(arc->XStartArc, arc->XEndArc); _cdSwapInt(arc->YStartArc, arc->YEndArc); } @@ -729,8 +746,7 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a winArcParam arc; sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); } @@ -740,9 +756,7 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl winArcParam arc; sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN) ) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (angle1==0 && angle2==360) { @@ -784,9 +798,7 @@ static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double winArcParam arc; sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN) ) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (angle1==0 && angle2==360) { @@ -895,6 +907,7 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) break; case CD_PATH_FILLSTROKE: sUpdateFill(ctxcanvas, 1); + sUpdateFill(ctxcanvas, 0); SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); StrokeAndFillPath(ctxcanvas->hDC); break; @@ -915,13 +928,11 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) n++; /* continua */ case CD_OPEN_LINES: - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); Polyline(ctxcanvas->hDC, (POINT*)poly, n); break; case CD_BEZIER: - if (ctxcanvas->rebuild_pen) - sCreatePen(ctxcanvas); + sUpdateFill(ctxcanvas, 0); PolyBezier(ctxcanvas->hDC, (POINT*)poly, n); break; case CD_FILL: @@ -936,14 +947,10 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) } else { - if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && - (ctxcanvas->canvas->interior_style != CD_PATTERN)) - cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + sUpdateFill(ctxcanvas, 1); if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0') - { SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ - } else { Pen = CreatePen(PS_SOLID, 1, ctxcanvas->fg); @@ -954,9 +961,7 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) Polygon(ctxcanvas->hDC, (POINT*)poly, n); if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0') - { SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ - } else { SelectObject(ctxcanvas->hDC, oldPen); diff --git a/src/x11/cdx11.c b/src/x11/cdx11.c index 4a330f0..8c59d48 100644 --- a/src/x11/cdx11.c +++ b/src/x11/cdx11.c @@ -1141,6 +1141,8 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a return; } + /* angles in 1/64ths of degrees counterclockwise, similar to CD */ + cdxCheckSolidStyle(ctxcanvas, 1); XDrawArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); cdxCheckSolidStyle(ctxcanvas, 0); |