summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cairo/cdcairo.c37
-rw-r--r--src/drv/cddxf.c4
-rw-r--r--src/drv/cdpdf.c2
-rw-r--r--src/drv/cdps.c2
-rw-r--r--src/gdiplus/cdwinp.cpp5
-rw-r--r--src/gdk/cdgdk.c2
-rw-r--r--src/sim/sim_primitives.c281
-rw-r--r--src/svg/cdsvg.c126
-rw-r--r--src/win32/cdwin.c71
-rw-r--r--src/x11/cdx11.c2
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, &current);
+ 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, &current);
+ 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, &current);
+ 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);