summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cairo/cdcairo.c72
-rw-r--r--src/cd.c4
-rw-r--r--src/cd.def6
-rw-r--r--src/cd_primitives.c169
-rw-r--r--src/cd_util.c1
-rw-r--r--src/drv/cdirgb.c186
-rw-r--r--src/drv/cdpdf.c28
-rw-r--r--src/drv/cdpicture.c12
-rw-r--r--src/drv/cdps.c44
-rw-r--r--src/gdiplus/cdwinp.cpp78
-rw-r--r--src/gdk/cdgdk.c2
-rw-r--r--src/sim/sim_primitives.c161
-rw-r--r--src/svg/cdsvg.c57
-rw-r--r--src/win32/cdwin.c84
14 files changed, 449 insertions, 455 deletions
diff --git a/src/cairo/cdcairo.c b/src/cairo/cdcairo.c
index 55f8b51..9589d74 100644
--- a/src/cairo/cdcairo.c
+++ b/src/cairo/cdcairo.c
@@ -592,24 +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 *a1, double *a2)
+static void sFixAngles(cdCanvas* canvas, double *a1, double *a2, int swap)
{
- if (ctxcanvas->canvas->invert_yaxis)
- {
- double t;
+ /* Cairo angles are clock-wise by default, in radians */
+
+ /* if NOT inverted means a transformation is set,
+ so the angle will follow the transformation that includes the axis invertion,
+ then it is already counter-clockwise */
- /* Cairo angles are clock-wise by default */
+ if (canvas->invert_yaxis)
+ {
+ /* change orientation */
*a1 *= -1;
*a2 *= -1;
/* swap, so the start angle is the smaller */
- t = *a1;
- *a1 = *a2;
- *a2 = t;
+ if (swap)
+ {
+ double 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;
@@ -620,7 +624,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl
{
sUpdateFill(ctxcanvas, 0);
- sFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2, 1);
if (w == h)
{
@@ -651,7 +655,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do
{
sUpdateFill(ctxcanvas, 1);
- sFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2, 1);
if (w == h)
{
@@ -685,7 +689,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
{
sUpdateFill(ctxcanvas, 1);
- sFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2, 1);
if (w == h)
{
@@ -883,18 +887,17 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (i+3 > n) return;
- 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 (!cdCanvasGetArcPathF(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
- sFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2, 0); /* do not swap because we handle negative arcs here */
if (w == h)
{
- cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ if ((a2-a1)<0)
+ cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ else
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
}
else /* Ellipse: change the scale to create from the circle */
{
@@ -904,7 +907,10 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
cairo_scale(ctxcanvas->cr, w/h, 1.0);
cairo_translate(ctxcanvas->cr, -xc, -yc);
- cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
+ if ((a2-a1)<0)
+ cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
+ else
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
cairo_restore(ctxcanvas->cr); /* restore from local */
}
@@ -1036,18 +1042,17 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (i+3 > n) return;
- xc = poly[i].x,
- yc = poly[i].y,
- w = poly[i+1].x,
- h = poly[i+1].y,
- a1 = poly[i+2].x,
- a2 = poly[i+2].y;
+ if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
- sFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2, 0); /* do not swap because we handle negative arcs here */
if (w == h)
{
- cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ if ((a2-a1)<0)
+ cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ else
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
}
else /* Ellipse: change the scale to create from the circle */
{
@@ -1057,7 +1062,10 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
cairo_scale(ctxcanvas->cr, w/h, 1.0);
cairo_translate(ctxcanvas->cr, -xc, -yc);
- cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
+ if ((a2-a1)<0)
+ cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
+ else
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
cairo_restore(ctxcanvas->cr); /* restore from local */
}
diff --git a/src/cd.c b/src/cd.c
index 1c64def..13d2541 100644
--- a/src/cd.c
+++ b/src/cd.c
@@ -327,7 +327,11 @@ int cdCanvasSimulate(cdCanvas* canvas, int mode)
canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size);
if (mode & CD_SIM_POLYLINE || mode & CD_SIM_POLYGON)
+ {
+ /* can NOT replace canvas->cxPoly because it will be used by the simulation,
+ handle polygon simulation in Begin/End */
canvas->cxFPoly = NULL;
+ }
return sim_mode;
}
diff --git a/src/cd.def b/src/cd.def
index eda5beb..da6938c 100644
--- a/src/cd.def
+++ b/src/cd.def
@@ -220,6 +220,12 @@ EXPORTS
cdGetFontSizePoints
cdStrEqualNoCase
cdSetPaperSize
+ cdCanvasGetArcPath
+ cdfCanvasGetArcPath
+ cdCanvasGetArcPathF
+ cdCanvasGetArcBox
+ cdCanvasGetArcStartEnd
+ cdfCanvasGetArcStartEnd
wdCanvasLineWidth
wdCanvasMarkSize
diff --git a/src/cd_primitives.c b/src/cd_primitives.c
index ca6ad6d..8714e70 100644
--- a/src/cd_primitives.c
+++ b/src/cd_primitives.c
@@ -136,20 +136,9 @@ void cdCanvasBegin(cdCanvas* canvas, int mode)
return;
}
- canvas->sim_poly = 0;
-
if (canvas->interior_style == CD_HOLLOW && mode == CD_FILL)
mode = CD_CLOSED_LINES;
- /* simulacao de linhas */
- if ((mode == CD_CLOSED_LINES || mode == CD_OPEN_LINES || mode == CD_BEZIER) &&
- canvas->sim_mode & CD_SIM_POLYLINE)
- canvas->sim_poly = 1;
-
- /* simulacao de poligonos preenchidos */
- if (mode == CD_FILL && canvas->sim_mode & CD_SIM_POLYGON)
- canvas->sim_poly = 1;
-
canvas->poly_mode = mode;
}
@@ -182,7 +171,7 @@ void cdCanvasVertex(cdCanvas* canvas, int x, int y)
canvas->poly = (cdPoint*)realloc(canvas->poly, sizeof(cdPoint) * (canvas->poly_size+1));
}
- if (canvas->poly_mode != CD_BEZIER &&
+ if (canvas->poly_mode != CD_BEZIER && canvas->poly_mode != CD_PATH &&
canvas->poly_n > 0 &&
canvas->poly[canvas->poly_n-1].x == x &&
canvas->poly[canvas->poly_n-1].y == y)
@@ -258,6 +247,27 @@ void cdCanvasPathSet(cdCanvas* canvas, int action)
canvas->path_n++;
}
+void cdCanvasPoly(cdCanvas* canvas, int mode, cdPoint* points, int n)
+{
+ int sim_poly = 0;
+
+ /* simulacao de linhas */
+ if ((mode == CD_CLOSED_LINES || mode == CD_OPEN_LINES ||
+ mode == CD_BEZIER || mode == CD_PATH) &&
+ canvas->sim_mode & CD_SIM_POLYLINE)
+ sim_poly = 1;
+
+ /* simulacao de poligonos preenchidos */
+ if ((mode == CD_FILL || mode == CD_PATH) &&
+ canvas->sim_mode & CD_SIM_POLYGON)
+ sim_poly = 1;
+
+ if (sim_poly)
+ cdSimPoly(canvas->ctxcanvas, mode, points, n);
+ else
+ canvas->cxPoly(canvas->ctxcanvas, mode, points, n);
+}
+
void cdCanvasEnd(cdCanvas* canvas)
{
assert(canvas);
@@ -297,15 +307,10 @@ void cdCanvasEnd(cdCanvas* canvas)
return;
}
- if (canvas->sim_poly)
- cdSimPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->poly, canvas->poly_n);
+ if (canvas->use_fpoly)
+ canvas->cxFPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->fpoly, canvas->poly_n);
else
- {
- if (canvas->use_fpoly)
- canvas->cxFPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->fpoly, canvas->poly_n);
- else
- canvas->cxPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->poly, canvas->poly_n);
- }
+ cdCanvasPoly(canvas, canvas->poly_mode, canvas->poly, canvas->poly_n);
if (canvas->poly_mode == CD_CLIP)
{
@@ -462,7 +467,7 @@ void cdfCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, doubl
canvas->cxBox(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax));
}
-static void normAngles(double *angle1, double *angle2)
+static void sNormAngles(double *angle1, double *angle2)
{
*angle1 = fmod(*angle1,360);
*angle2 = fmod(*angle2,360);
@@ -477,7 +482,7 @@ void cdCanvasArc(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1,
if (angle1 == angle2 || w == 0 || h == 0)
return;
- normAngles(&angle1, &angle2);
+ sNormAngles(&angle1, &angle2);
if (canvas->use_origin)
{
@@ -499,7 +504,7 @@ void cdfCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, do
if (angle1 == angle2 || w == 0 || h == 0)
return;
- normAngles(&angle1, &angle2);
+ sNormAngles(&angle1, &angle2);
if (canvas->use_origin)
{
@@ -525,7 +530,7 @@ void cdCanvasSector(cdCanvas* canvas, int xc, int yc, int w, int h, double angle
if (angle1 == angle2 || w == 0 || h == 0)
return;
- normAngles(&angle1, &angle2);
+ sNormAngles(&angle1, &angle2);
if (canvas->interior_style == CD_HOLLOW)
{
@@ -568,7 +573,7 @@ void cdfCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h,
if (angle1 == angle2 || w == 0 || h == 0)
return;
- normAngles(&angle1, &angle2);
+ sNormAngles(&angle1, &angle2);
if (canvas->interior_style == CD_HOLLOW)
{
@@ -614,7 +619,7 @@ void cdCanvasChord(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1
if (angle1 == angle2 || w == 0 || h == 0)
return;
- normAngles(&angle1, &angle2);
+ sNormAngles(&angle1, &angle2);
if (canvas->interior_style == CD_HOLLOW)
{
@@ -654,7 +659,7 @@ void cdfCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h,
if (angle1 == angle2 || w == 0 || h == 0)
return;
- normAngles(&angle1, &angle2);
+ sNormAngles(&angle1, &angle2);
if (canvas->interior_style == CD_HOLLOW)
{
@@ -689,23 +694,43 @@ void cdfCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h,
canvas->cxChord(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2);
}
-void cdCanvasGetEllipseBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax)
+void cdCanvasGetArcStartEnd(int xc, int yc, int w, int h, double a1, double a2, int *x1, int *y1, int *x2, int *y2)
{
+ /* computation is done as if the angles are counterclockwise,
+ and yaxis is NOT inverted. */
+
+ /* leave xc and yc outside the round, so the center will be always the same */
+
+ if (x1) *x1 = xc + cdRound((w/2.0)*cos(a1*CD_DEG2RAD));
+ if (y1) *y1 = yc + cdRound((h/2.0)*sin(a1*CD_DEG2RAD));
+ if (x2) *x2 = xc + cdRound((w/2.0)*cos(a2*CD_DEG2RAD));
+ if (y2) *y2 = yc + cdRound((h/2.0)*sin(a2*CD_DEG2RAD));
+}
+
+void cdfCanvasGetArcStartEnd(double xc, double yc, double w, double h, double a1, double a2, double *x1, double *y1, double *x2, double *y2)
+{
+ if (x1) *x1 = xc + (w/2.0)*cos(a1*CD_DEG2RAD);
+ if (y1) *y1 = yc + (h/2.0)*sin(a1*CD_DEG2RAD);
+ if (x2) *x2 = xc + (w/2.0)*cos(a2*CD_DEG2RAD);
+ if (y2) *y2 = yc + (h/2.0)*sin(a2*CD_DEG2RAD);
+}
+
+void cdCanvasGetArcBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ int x, y;
+
+ /* computation is done as if the angles are counterclockwise,
+ and yaxis is NOT inverted. */
+
#define _BBOX() \
if (x > *xmax) *xmax = x; \
if (y > *ymax) *ymax = y; \
if (x < *xmin) *xmin = x; \
if (y < *ymin) *ymin = y;
- int x, y;
-
- *xmin = (int)(xc+w/2*cos(a1*CD_DEG2RAD));
- *ymin = (int)(yc+h/2*sin(a1*CD_DEG2RAD));
+ cdCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, xmin, ymin, &x, &y);
*xmax = *xmin;
*ymax = *ymin;
-
- x = (int)(xc+w/2*cos(a2*CD_DEG2RAD));
- y = (int)(yc+h/2*sin(a2*CD_DEG2RAD));
_BBOX()
if (a1 > a2)
@@ -733,3 +758,77 @@ void cdCanvasGetEllipseBox(int xc, int yc, int w, int h, double a1, double a2, i
_BBOX()
}
}
+
+int cdCanvasGetArcPath(cdCanvas* canvas, const cdPoint* poly, int *xc, int *yc, int *w, int *h, double *a1, double *a2)
+{
+ *xc = poly[0].x;
+ *yc = poly[0].y;
+ *w = poly[1].x;
+ *h = poly[1].y;
+ *a1 = poly[2].x;
+ *a2 = poly[2].y;
+
+ if (canvas->invert_yaxis) /* undo axis invertion */
+ {
+ *h = _cdInvertYAxis(canvas, *h);
+ *a2 = _cdInvertYAxis(canvas, *a2);
+ }
+
+ /* fix integer scale */
+ *a1 /= 1000.0;
+ *a2 /= 1000.0;
+
+ if (*a1 == *a2 || *w == 0 || *h == 0)
+ return 0;
+
+ /* path angles can be counter-clockwise (a1<a2) or clockwise (a1>a2) */
+ return 1;
+}
+
+int cdfCanvasGetArcPath(cdCanvas* canvas, const cdfPoint* poly, double *xc, double *yc, double *w, double *h, double *a1, double *a2)
+{
+ *xc = poly[0].x;
+ *yc = poly[0].y;
+ *w = poly[1].x;
+ *h = poly[1].y;
+ *a1 = poly[2].x;
+ *a2 = poly[2].y;
+
+ if (canvas->invert_yaxis) /* undo axis invertion */
+ {
+ *h = _cdInvertYAxis(canvas, *h);
+ *a2 = _cdInvertYAxis(canvas, *a2);
+ }
+
+ if (*a1 == *a2 || *w == 0 || *h == 0)
+ return 0;
+
+ /* path angles can be counter-clockwise (a1<a2) or clockwise (a1>a2) */
+ return 1;
+}
+
+int cdCanvasGetArcPathF(cdCanvas* canvas, const cdPoint* poly, double *xc, double *yc, double *w, double *h, double *a1, double *a2)
+{
+ *xc = poly[0].x;
+ *yc = poly[0].y;
+ *w = poly[1].x;
+ *h = poly[1].y;
+ *a1 = poly[2].x;
+ *a2 = poly[2].y;
+
+ if (canvas->invert_yaxis) /* undo axis invertion */
+ {
+ *h = _cdInvertYAxis(canvas, *h);
+ *a2 = _cdInvertYAxis(canvas, *a2);
+ }
+
+ /* fix integer scale */
+ *a1 /= 1000.0;
+ *a2 /= 1000.0;
+
+ if (*a1 == *a2 || *w == 0 || *h == 0)
+ return 0;
+
+ /* path angles can be counter-clockwise (a1<a2) or clockwise (a1>a2) */
+ return 1;
+}
diff --git a/src/cd_util.c b/src/cd_util.c
index 39d491d..b278dfc 100644
--- a/src/cd_util.c
+++ b/src/cd_util.c
@@ -397,3 +397,4 @@ void cdSetPaperSize(int size, double *w_pt, double *h_pt)
*w_pt = (double)paper[size].w_pt;
*h_pt = (double)paper[size].h_pt;
}
+
diff --git a/src/drv/cdirgb.c b/src/drv/cdirgb.c
index e6cb4b5..9f367e0 100644
--- a/src/drv/cdirgb.c
+++ b/src/drv/cdirgb.c
@@ -580,7 +580,7 @@ static void irgbClipPoly(cdCtxCanvas* ctxcanvas, unsigned char* clip_region, cdP
memcpy(t_poly, poly, sizeof(cdPoint)*n);
poly = t_poly;
- for(i = 0; i < n; i++)
+ for(i = 0; i < n; i++) /* must duplicate because clip poly is stored */
cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
}
@@ -642,79 +642,6 @@ static void irgbClipPoly(cdCtxCanvas* ctxcanvas, unsigned char* clip_region, cdP
irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h);
}
-static void irgbClipElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector)
-{
- float c, s, sx, sy, x, y, prev_x, prev_y;
- double da;
- int i, p;
- cdPoint* poly;
-
- /* number of segments of equivalent poligonal for a full ellipse */
- int n = cdSimCalcEllipseNumSegments(ctxcanvas->canvas, xc, yc, width, height);
-
- /* number of segments for the arc */
- n = cdRound((fabs(angle2-angle1)*n)/360);
- if (n < 1) n = 1;
-
- poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */
-
- /* converts degrees into radians */
- angle1 *= CD_DEG2RAD;
- angle2 *= CD_DEG2RAD;
-
- /* generates arc points at origin with axis x and y */
-
- da = (angle2-angle1)/n;
- c = (float)cos(da);
- s = (float)sin(da);
- sx = -(width*s)/height;
- sy = (height*s)/width;
-
- x = xc + (width/2.0f)*(float)cos(angle1);
- y = yc + (height/2.0f)*(float)sin(angle1);
- poly[0].x = _cdRound(x);
- poly[0].y = _cdRound(y);
- prev_x = x;
- prev_y = y;
- p = 1;
-
- for (i = 1; i < n+1; i++) /* n+1 points */
- {
- x = xc + c*(prev_x-xc) + sx*(prev_y-yc);
- y = yc + sy*(prev_x-xc) + c*(prev_y-yc);
-
- poly[p].x = _cdRound(x);
- poly[p].y = _cdRound(y);
-
- if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
- p++;
-
- prev_x = x;
- prev_y = y;
- }
-
- if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y)
- {
- if (sector) /* cdSector */
- {
- /* add center */
- poly[p].x = xc;
- poly[p].y = yc;
- }
- else /* cdChord */
- {
- /* add initial point */
- poly[p].x = poly[0].x;
- poly[p].y = poly[0].y;
- }
- p++;
- }
-
- irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, p, ctxcanvas->canvas->combine_mode);
-
- free(poly);
-}
-
static void irgbClipBox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
int combine_mode = ctxcanvas->canvas->combine_mode;
@@ -952,54 +879,6 @@ static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin
cdfSimBox(ctxcanvas, xmin, xmax, ymin, ymax);
}
-static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
-{
- if (ctxcanvas->canvas->new_region)
- {
- /* matrix transformation is done inside irgbClip* if necessary */
- irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1);
- return;
- }
-
- cdSimSector(ctxcanvas, xc, yc, w, h, a1, a2);
-}
-
-static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
-{
- if (ctxcanvas->canvas->new_region)
- {
- /* matrix transformation is done inside irgbClip* if necessary */
- irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0);
- return;
- }
-
- cdSimChord(ctxcanvas, xc, yc, w, h, a1, a2);
-}
-
-static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
-{
- if (ctxcanvas->canvas->new_region)
- {
- /* matrix transformation is done inside irgbClip* if necessary */
- irgbClipElipse(ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, 1);
- return;
- }
-
- cdfSimSector(ctxcanvas, xc, yc, w, h, a1, a2);
-}
-
-static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
-{
- if (ctxcanvas->canvas->new_region)
- {
- /* matrix transformation is done inside irgbClip* if necessary */
- irgbClipElipse(ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, 0);
- return;
- }
-
- cdfSimChord(ctxcanvas, xc, yc, w, h, a1, a2);
-}
-
static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len)
{
if (ctxcanvas->canvas->new_region)
@@ -1035,59 +914,6 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
cdSimPoly(ctxcanvas, mode, poly, n);
}
-static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* fpoly, int n)
-{
- int i;
-
- switch(mode)
- {
- case CD_CLOSED_LINES:
- fpoly[n] = fpoly[0];
- n++;
- /* continue */
- case CD_OPEN_LINES:
- cdfSimPolyLine(ctxcanvas->canvas, fpoly, n);
- break;
- case CD_BEZIER:
- cdfSimPolyBezier(ctxcanvas->canvas, fpoly, n);
- break;
- case CD_PATH:
- cdfSimPolyPath(ctxcanvas->canvas, fpoly, n);
- break;
- case CD_FILL:
- {
- cdPoint* poly = malloc(sizeof(cdPoint)*n);
-
- for (i = 0; i<n; i++)
- {
- poly[i].x = _cdRound(fpoly[i].x);
- poly[i].y = _cdRound(fpoly[i].y);
- }
-
- cdpoly(ctxcanvas, CD_FILL, poly, n);
-
- free(poly);
- }
- break;
- case CD_CLIP:
- {
- cdPoint* poly = malloc(sizeof(cdPoint)*n);
-
- for (i = 0; i<n; i++)
- {
- poly[i].x = _cdRound(fpoly[i].x);
- poly[i].y = _cdRound(fpoly[i].y);
- }
-
- cdpoly(ctxcanvas, CD_CLIP, poly, n);
-
- free(poly);
- if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) cdclip(ctxcanvas, CD_CLIPPOLYGON);
- }
- break;
- }
-}
-
static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h)
{
int dst_offset, src_offset, l, xsize, ysize, xpos, ypos;
@@ -2031,8 +1857,8 @@ static void cdinittable(cdCanvas* canvas)
canvas->cxRect = cdSimRect;
canvas->cxBox = cdbox;
canvas->cxArc = cdSimArc;
- canvas->cxSector = cdsector;
- canvas->cxChord = cdchord;
+ canvas->cxSector = cdSimSector;
+ canvas->cxChord = cdSimChord;
canvas->cxPoly = cdpoly;
canvas->cxText = cdtext;
@@ -2040,9 +1866,9 @@ static void cdinittable(cdCanvas* canvas)
canvas->cxFRect = cdfSimRect;
canvas->cxFBox = cdfbox;
canvas->cxFArc = cdfSimArc;
- canvas->cxFSector = cdfsector;
- canvas->cxFChord = cdfchord;
- canvas->cxFPoly = cdfpoly;
+ canvas->cxFSector = cdfSimSector;
+ canvas->cxFChord = cdfSimChord;
+ canvas->cxFPoly = cdfSimPoly;
canvas->cxKillCanvas = cdkillcanvas;
diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c
index 2c48d50..f6621d3 100644
--- a/src/drv/cdpdf.c
+++ b/src/drv/cdpdf.c
@@ -570,15 +570,16 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (i+3 > n) return;
- 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 (!cdCanvasGetArcPathF(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (w==h)
- PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ {
+ if ((a2-a1)<0)
+ PDF_arcn(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ else
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ }
else /* Ellipse: change the scale to create from the circle */
{
PDF_save(ctxcanvas->pdf); /* save to use the local transform */
@@ -587,7 +588,10 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
PDF_scale(ctxcanvas->pdf, w/h, 1);
PDF_translate(ctxcanvas->pdf, -xc, -yc);
- PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+ if ((a2-a1)<0)
+ PDF_arcn(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+ else
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
PDF_restore(ctxcanvas->pdf); /* restore from local */
}
@@ -716,12 +720,8 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (i+3 > n) return;
- xc = poly[i].x,
- yc = poly[i].y,
- w = poly[i+1].x,
- h = poly[i+1].y,
- a1 = poly[i+2].x,
- a2 = poly[i+2].y;
+ if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (w==h)
PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
diff --git a/src/drv/cdpicture.c b/src/drv/cdpicture.c
index f1d089a..4cbc5d5 100644
--- a/src/drv/cdpicture.c
+++ b/src/drv/cdpicture.c
@@ -508,7 +508,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
prim->param.arcsectorchord.angle1 = a1;
prim->param.arcsectorchord.angle2 = a2;
picAddPrim(ctxcanvas, prim);
- cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width);
picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width);
}
@@ -525,7 +525,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl
prim->param.arcsectorchordf.angle1 = a1;
prim->param.arcsectorchordf.angle2 = a2;
picAddPrim(ctxcanvas, prim);
- cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width);
picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width);
}
@@ -542,7 +542,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
prim->param.arcsectorchord.angle1 = a1;
prim->param.arcsectorchord.angle2 = a2;
picAddPrim(ctxcanvas, prim);
- cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
picUpdateBBox(ctxcanvas, xmin, ymin, 0);
picUpdateBBox(ctxcanvas, xmax, ymax, 0);
picUpdateBBox(ctxcanvas, xc, yc, 0);
@@ -560,7 +560,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do
prim->param.arcsectorchordf.angle1 = a1;
prim->param.arcsectorchordf.angle2 = a2;
picAddPrim(ctxcanvas, prim);
- cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
picUpdateBBox(ctxcanvas, xmin, ymin, 0);
picUpdateBBox(ctxcanvas, xmax, ymax, 0);
picUpdateBBox(ctxcanvas, _cdRound(xc), _cdRound(yc), 0);
@@ -578,7 +578,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double
prim->param.arcsectorchord.angle1 = a1;
prim->param.arcsectorchord.angle2 = a2;
picAddPrim(ctxcanvas, prim);
- cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
picUpdateBBox(ctxcanvas, xmin, ymin, 0);
picUpdateBBox(ctxcanvas, xmax, ymax, 0);
}
@@ -595,7 +595,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
prim->param.arcsectorchordf.angle1 = a1;
prim->param.arcsectorchordf.angle2 = a2;
picAddPrim(ctxcanvas, prim);
- cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
picUpdateBBox(ctxcanvas, xmin, ymin, 0);
picUpdateBBox(ctxcanvas, xmax, ymax, 0);
}
diff --git a/src/drv/cdps.c b/src/drv/cdps.c
index b651994..357abf4 100644
--- a/src/drv/cdps.c
+++ b/src/drv/cdps.c
@@ -648,7 +648,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
if (ctxcanvas->eps)
{
int xmin, xmax, ymin, ymax;
- cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
bbox(ctxcanvas, xmin, ymin);
bbox(ctxcanvas, xmax, ymax);
}
@@ -680,7 +680,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl
if (ctxcanvas->eps)
{
int xmin, xmax, ymin, ymax;
- cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
bbox(ctxcanvas, xmin, ymin);
bbox(ctxcanvas, xmax, ymax);
}
@@ -720,7 +720,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
if (ctxcanvas->eps)
{
int xmin, xmax, ymin, ymax;
- cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
bbox(ctxcanvas, xmin, ymin);
bbox(ctxcanvas, xmax, ymax);
bbox(ctxcanvas, xc, yc);
@@ -761,7 +761,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do
if (ctxcanvas->eps)
{
int xmin, xmax, ymin, ymax;
- cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
bbox(ctxcanvas, xmin, ymin);
bbox(ctxcanvas, xmax, ymax);
fbbox(ctxcanvas, xc, yc);
@@ -800,7 +800,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double
if (ctxcanvas->eps)
{
int xmin, xmax, ymin, ymax;
- cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax);
bbox(ctxcanvas, xmin, ymin);
bbox(ctxcanvas, xmax, ymax);
}
@@ -838,7 +838,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
if (ctxcanvas->eps)
{
int xmin, xmax, ymin, ymax;
- cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
+ cdCanvasGetArcBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax);
bbox(ctxcanvas, xmin, ymin);
bbox(ctxcanvas, xmax, ymax);
}
@@ -1110,19 +1110,19 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
case CD_PATH_ARC:
{
double xc, yc, w, h, a1, a2;
+ char* arc = "arc";
if (i+3 > n) return;
- 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 (!cdCanvasGetArcPathF(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
+
+ if ((a2-a1)<0)
+ arc = "arcn";
if (w==h) /* Circulo: PS implementa direto */
{
- fprintf(ctxcanvas->file, "N %d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "N %d %d %g %g %g %s\n", xc, yc, 0.5*w, a1, a2, arc);
}
else /* Elipse: mudar a escala p/ criar a partir do circulo */
{
@@ -1130,7 +1130,7 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
fprintf(ctxcanvas->file, "N\n");
- fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "0 0 %g %g %g %s\n", 0.5*w, a1, a2, arc);
fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */
}
@@ -1303,19 +1303,19 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
case CD_PATH_ARC:
{
double xc, yc, w, h, a1, a2;
+ char* arc = "arc";
if (i+3 > n) return;
- xc = poly[i].x,
- yc = poly[i].y,
- w = poly[i+1].x,
- h = poly[i+1].y,
- a1 = poly[i+2].x,
- a2 = poly[i+2].y;
+ if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
+
+ if ((a2-a1)<0)
+ arc = "arcn";
if (w==h) /* Circulo: PS implementa direto */
{
- fprintf(ctxcanvas->file, "N %g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "N %g %g %g %g %g %s\n", xc, yc, 0.5*w, a1, a2, arc);
}
else /* Elipse: mudar a escala p/ criar a partir do circulo */
{
@@ -1323,7 +1323,7 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
fprintf(ctxcanvas->file, "N\n");
- fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "0 0 %g %g %g %s\n", 0.5*w, a1, a2, arc);
fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */
}
diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp
index a2eec55..52c19a1 100644
--- a/src/gdiplus/cdwinp.cpp
+++ b/src/gdiplus/cdwinp.cpp
@@ -626,15 +626,21 @@ static void cdfbox(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin
}
}
-static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
+static void sFixAngles(cdCanvas* canvas, double *a1, double *a2)
{
- if (ctxcanvas->canvas->invert_yaxis)
+ // GDI+ angles are clock-wise by default, in degrees
+
+ /* if NOT inverted means a transformation is set,
+ so the angle will follow the transformation that includes the axis invertion,
+ then it is already counter-clockwise */
+
+ if (canvas->invert_yaxis)
{
- // GDI+ angles are clock-wise by default, in degrees
- *angle1 *= -1;
- *angle2 *= -1;
+ /* change orientation */
+ *a1 *= -1;
+ *a2 *= -1;
- // no need to swap, because we will use (angle2-angle1)
+ /* no need to swap, because we will use (angle2-angle1) */
}
}
@@ -645,7 +651,7 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a
ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect);
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1));
}
ctxcanvas->dirty = 1;
@@ -658,7 +664,7 @@ static void cdfarc(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, doubl
ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect);
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1));
}
ctxcanvas->dirty = 1;
@@ -674,7 +680,7 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
path.AddEllipse(rect);
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1));
}
Region region(&path);
@@ -692,7 +698,7 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
}
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1));
ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
}
@@ -710,7 +716,7 @@ static void cdfsector(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, do
path.AddEllipse(rect);
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1));
}
Region region(&path);
@@ -728,7 +734,7 @@ static void cdfsector(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, do
}
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1));
ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
}
@@ -746,7 +752,7 @@ static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
path.AddEllipse(rect);
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
path.CloseFigure();
}
@@ -760,7 +766,7 @@ static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
else
{
GraphicsPath path;
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path);
}
@@ -780,7 +786,7 @@ static void cdfchord(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, dou
path.AddEllipse(rect);
else
{
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
path.CloseFigure();
}
@@ -794,7 +800,7 @@ static void cdfchord(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, dou
else
{
GraphicsPath path;
- cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ sFixAngles(ctxcanvas->canvas, &angle1, &angle2);
path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path);
}
@@ -850,27 +856,17 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
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 (!cdCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (current_set)
{
int StartX, StartY;
if (ctxcanvas->canvas->invert_yaxis)
- {
- StartX = xc + cdRound(w * cos(CD_DEG2RAD * a1) / 2.0);
- StartY = yc - cdRound(h * sin(CD_DEG2RAD * a1) / 2.0);
- }
+ cdCanvasGetArcStartEnd(xc, yc, w, h, -a1, -a2, &StartX, &StartY, NULL, NULL);
else
- {
- StartX = xc + cdRound(w * cos(CD_DEG2RAD * a2) / 2.0);
- StartY = yc + cdRound(h * sin(CD_DEG2RAD * a2) / 2.0);
- }
+ cdCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, &StartX, &StartY, NULL, NULL);
graphics_path->AddLine(current_x, current_y, StartX, StartY);
}
@@ -880,7 +876,7 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
graphics_path->AddEllipse(rect);
else
{
- cdwpFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2);
graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
}
@@ -1084,27 +1080,17 @@ static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* poly, int n)
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,
- a2 = poly[i+2].y;
+ if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (current_set)
{
double StartX, StartY;
if (ctxcanvas->canvas->invert_yaxis)
- {
- StartX = xc + w * cos(CD_DEG2RAD * a1) / 2.0;
- StartY = yc - h * sin(CD_DEG2RAD * a1) / 2.0;
- }
+ cdfCanvasGetArcStartEnd(xc, yc, w, h, -a1, -a2, &StartX, &StartY, NULL, NULL);
else
- {
- StartX = xc + w * cos(CD_DEG2RAD * a2) / 2.0;
- StartY = yc + h * sin(CD_DEG2RAD * a2) / 2.0;
- }
+ cdfCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, &StartX, &StartY, NULL, NULL);
graphics_path->AddLine((REAL)current_x, (REAL)current_y, (REAL)StartX, (REAL)StartY);
}
@@ -1114,7 +1100,7 @@ static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* poly, int n)
graphics_path->AddEllipse(rect);
else
{
- cdwpFixAngles(ctxcanvas, &a1, &a2);
+ sFixAngles(ctxcanvas->canvas, &a1, &a2);
graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
}
diff --git a/src/gdk/cdgdk.c b/src/gdk/cdgdk.c
index 56055a7..d5236c7 100644
--- a/src/gdk/cdgdk.c
+++ b/src/gdk/cdgdk.c
@@ -890,7 +890,7 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
{
int i;
- if (mode != CD_BEZIER)
+ if (mode != CD_BEZIER && mode != CD_PATH)
{
for (i = 0; i < n; i++)
{
diff --git a/src/sim/sim_primitives.c b/src/sim/sim_primitives.c
index 9470b21..4b3ebf3 100644
--- a/src/sim/sim_primitives.c
+++ b/src/sim/sim_primitives.c
@@ -19,7 +19,7 @@ void cdSimLine(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
cdPoint poly[2];
poly[0].x = x1; poly[0].y = y1;
poly[1].x = x2; poly[1].y = y2;
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, 2);
+ cdCanvasPoly(canvas, CD_OPEN_LINES, poly, 2);
}
void cdfSimLine(cdCtxCanvas* ctxcanvas, double x1, double y1, double x2, double y2)
@@ -39,7 +39,7 @@ void cdSimRect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
poly[1].x = xmin; poly[1].y = ymax;
poly[2].x = xmax; poly[2].y = ymax;
poly[3].x = xmax; poly[3].y = ymin;
- canvas->cxPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
+ cdCanvasPoly(canvas, CD_CLOSED_LINES, poly, 4);
}
void cdfSimRect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
@@ -62,7 +62,7 @@ void cdSimBox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
poly[1].x = xmin; poly[1].y = ymax;
poly[2].x = xmax; poly[2].y = ymax;
poly[3].x = xmax; poly[3].y = ymin;
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
+ cdCanvasPoly(canvas, CD_FILL, poly, 4);
}
void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
@@ -77,9 +77,9 @@ void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, do
canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
}
-int cdSimCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height)
+static int sCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height, double angle1, double angle2)
{
- int n, dx, dy, hd;
+ int K, dx, dy, hd;
int w2 = width/2;
int h2 = height/2;
int x1 = xc-w2,
@@ -93,6 +93,8 @@ int cdSimCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int
cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
}
+ /* first calculate the number of segments of equivalent poligonal for a full ellipse */
+
dx = (x1-x2);
dy = (y1-y2);
hd = (int)(sqrt(dx*dx + dy*dy)/2);
@@ -104,40 +106,39 @@ int cdSimCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int
The number of segments will be 360 / min_angle.
*/
- n = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */
+ K = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */
/* multiple of 4 */
- n = ((n + 3)/4)*4;
+ K = ((K + 3)/4)*4;
/* minimum number is 4 */
- if (n < 4) n = 4;
+ if (K < 4) K = 4;
+
+
+ /* finally, calculate the number of segments for the arc */
+ K = cdRound((fabs(angle2-angle1)*K)/(360*CD_DEG2RAD));
+ if (K < 1) K = 1;
- return n;
+ return K;
}
-static void sFixAngles(cdCanvas* canvas, double *angle1, double *angle2)
+static void sFixAngles(cdCanvas* canvas, double *a1, double *a2)
{
+ /* computation in PolyAddArc is done as if the angles are counterclockwise,
+ and yaxis is NOT inverted. */
+
if (canvas->invert_yaxis)
{
- double t;
-
- /* 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;
+ /* change orientation */
+ *a1 *= -1;
+ *a2 *= -1;
- /* swap, so the start angle is the smaller */
- t = *angle1;
- *angle1 = *angle2;
- *angle2 = t;
+ /* no need to swap, because we will use (angle2-angle1) */
}
/* convert to radians */
- *angle1 *= CD_DEG2RAD;
- *angle2 *= CD_DEG2RAD;
+ *a1 *= CD_DEG2RAD;
+ *a2 *= CD_DEG2RAD;
}
static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int yc, int width, int height, double angle1, double angle2, cdPoint* current)
@@ -147,14 +148,10 @@ static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int
int i, K, k, p, new_n;
cdPoint* old_poly = poly;
- /* number of segments of equivalent poligonal for a full ellipse */
- K = cdSimCalcEllipseNumSegments(canvas, xc, yc, width, height);
-
sFixAngles(canvas, &angle1, &angle2);
/* number of segments for the arc */
- K = cdRound((fabs(angle2-angle1)*K)/(360*CD_DEG2RAD));
- if (K < 1) K = 1;
+ K = sCalcEllipseNumSegments(canvas, xc, yc, width, height, angle1, angle2);
new_n = *n + K+1; /* add room for K+1 samples */
poly = (cdPoint*)realloc(poly, sizeof(cdPoint)*(new_n+2)); /* add room also for points at start and end */
@@ -208,17 +205,13 @@ static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int
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;
+ int i, k, K, p, new_n;
cdfPoint* old_poly = poly;
- /* number of segments of equivalent poligonal for a full ellipse */
- int K = cdSimCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height);
-
sFixAngles(canvas, &angle1, &angle2);
/* number of segments for the arc */
- K = cdRound((fabs(angle2-angle1)*K)/(360*CD_DEG2RAD));
- if (K < 1) K = 1;
+ K = sCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height, angle1, angle2);
new_n = *n + K+1; /* add room for K+1 samples */
poly = (cdfPoint*)realloc(poly, sizeof(cdfPoint)*(new_n+2)); /* add room also for points at start and end */
@@ -284,7 +277,7 @@ void cdSimArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, dou
if (poly)
{
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, n);
+ cdCanvasPoly(canvas, CD_OPEN_LINES, poly, n);
free(poly);
}
}
@@ -336,7 +329,7 @@ static void sElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int heigh
if (poly)
{
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, n);
+ cdCanvasPoly(canvas, CD_FILL, poly, n);
free(poly);
}
}
@@ -684,7 +677,7 @@ void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n)
if (poly)
{
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, poly_n);
+ cdCanvasPoly(canvas, CD_OPEN_LINES, poly, poly_n);
free(poly);
}
}
@@ -789,12 +782,8 @@ void cdfSimPolyPath(cdCanvas* canvas, const cdfPoint* poly, int n)
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,
- a2 = poly[i+2].y;
+ if (!cdfCanvasGetArcPath(canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (current_set)
path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, &current);
@@ -909,12 +898,8 @@ static void sSimPolyFPath(cdCanvas* canvas, const cdPoint* poly, int n)
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 (!cdCanvasGetArcPathF(canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (current_set)
path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, &current);
@@ -1043,12 +1028,8 @@ void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n)
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 (!cdCanvasGetArcPath(canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
if (current_set)
path_poly = sPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, &current);
@@ -1091,22 +1072,22 @@ void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n)
break;
case CD_PATH_FILL:
if (poly)
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n);
+ cdCanvasPoly(canvas, CD_FILL, path_poly, path_poly_n);
break;
case CD_PATH_STROKE:
if (poly)
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ cdCanvasPoly(canvas, CD_OPEN_LINES, path_poly, path_poly_n);
break;
case CD_PATH_FILLSTROKE:
if (poly)
{
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n);
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ cdCanvasPoly(canvas, CD_FILL, path_poly, path_poly_n);
+ cdCanvasPoly(canvas, CD_OPEN_LINES, path_poly, path_poly_n);
}
break;
case CD_PATH_CLIP:
if (poly)
- canvas->cxPoly(canvas->ctxcanvas, CD_CLIP, path_poly, path_poly_n);
+ cdCanvasPoly(canvas, CD_CLIP, path_poly, path_poly_n);
break;
}
}
@@ -1117,6 +1098,11 @@ void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n)
/************************************************************************/
+/* Simulation functions that depend on the simulation base driver. */
+static void cdSimPolyFill(cdCanvas* canvas, cdPoint* poly, int n);
+static void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n);
+static void cdfSimPolyLine(cdCanvas* canvas, const cdfPoint* poly, int n);
+
void cdSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
@@ -1142,6 +1128,45 @@ void cdSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
}
}
+void cdfSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* fpoly, int n)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+
+ switch(mode)
+ {
+ case CD_CLOSED_LINES:
+ fpoly[n] = fpoly[0];
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ cdfSimPolyLine(canvas, fpoly, n);
+ break;
+ case CD_BEZIER:
+ cdfSimPolyBezier(canvas, fpoly, n);
+ break;
+ case CD_PATH:
+ cdfSimPolyPath(canvas, fpoly, n);
+ break;
+ case CD_CLIP:
+ case CD_FILL:
+ {
+ cdPoint* poly = malloc(sizeof(cdPoint)*n);
+ int i;
+
+ for (i = 0; i<n; i++)
+ {
+ poly[i].x = _cdRound(fpoly[i].x);
+ poly[i].y = _cdRound(fpoly[i].y);
+ }
+
+ cdCanvasPoly(canvas, mode, poly, n);
+
+ free(poly);
+ }
+ break;
+ }
+}
+
void cdSimMark(cdCanvas* canvas, int x, int y)
{
int oldinteriorstyle = canvas->interior_style;
@@ -1218,9 +1243,9 @@ void cdSimMark(cdCanvas* canvas, int x, int y)
poly[3].y = bottom;
if (canvas->mark_type == CD_DIAMOND)
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
+ cdCanvasPoly(canvas, CD_FILL, poly, 4);
else
- canvas->cxPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
+ cdCanvasPoly(canvas, CD_CLOSED_LINES, poly, 4);
}
break;
}
@@ -1296,7 +1321,7 @@ void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char
#include "cd_truetype.h"
#include "sim.h"
-void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n)
+static void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n)
{
int i, reset = 1, transform = 0;
int old_use_matrix = canvas->use_matrix;
@@ -1342,7 +1367,7 @@ void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n)
canvas->use_matrix = old_use_matrix;
}
-void cdfSimPolyLine(cdCanvas* canvas, const cdfPoint* poly, int n)
+static void cdfSimPolyLine(cdCanvas* canvas, const cdfPoint* poly, int n)
{
int i, reset = 1, transform = 0;
int old_use_matrix = canvas->use_matrix;
@@ -1429,14 +1454,14 @@ static void sGetBox(cdPoint* poly, int *xmin, int *xmax, int *ymin, int *ymax)
}
}
-void cdSimPolyFill(cdCanvas* canvas, cdPoint* poly, int n)
+static void cdSimPolyFill(cdCanvas* canvas, cdPoint* poly, int n)
{
int old_use_matrix = canvas->use_matrix;
if (canvas->use_matrix)
{
int i;
- for(i = 0; i < n; i++) /* can do that because poly is internal of the CD */
+ for(i = 0; i < n; i++) /* can do that because poly is internal of the CD, and it will NOT be stored */
cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
}
diff --git a/src/svg/cdsvg.c b/src/svg/cdsvg.c
index f84e4b5..789ece3 100644
--- a/src/svg/cdsvg.c
+++ b/src/svg/cdsvg.c
@@ -215,9 +215,36 @@ 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)
+static void sCalcArc(cdCanvas* canvas, 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)
+ /* computation is done as if the angles are counterclockwise,
+ and yaxis is NOT inverted. */
+
+ if (canvas->invert_yaxis)
+ {
+ double t;
+
+ /* change orientation */
+ a1 *= -1;
+ a2 *= -1;
+
+ /* swap, so the start angle is the smaller */
+ t = a1;
+ a1 = a2;
+ a2 = t;
+ }
+
+ cdfCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, arcStartX, arcStartY, arcEndX, arcEndY);
+
+ if (fabs(a2-a1) > 180.0)
+ *largeArc = 1;
+ else
+ *largeArc = 0;
+}
+
+static void sCalcArc_OLD(cdCanvas* canvas, double xc, double yc, double w, double h, double a1, double a2, double *arcStartX, double *arcStartY, double *arcEndX, double *arcEndY, int *largeArc)
+{
+ if (canvas->invert_yaxis==0)
{
double t;
@@ -263,7 +290,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl
return;
}
- sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc);
+ sCalcArc(ctxcanvas->canvas, 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);
@@ -286,7 +313,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do
return;
}
- sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc);
+ sCalcArc(ctxcanvas->canvas, 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);
@@ -302,7 +329,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
double arcStartX, arcStartY, arcEndX, arcEndY;
int largeArc;
- sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc);
+ sCalcArc(ctxcanvas->canvas, 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);
@@ -477,14 +504,10 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (i+3 > n) return;
- xc = poly[i].x,
- yc = poly[i].y,
- w = poly[i+1].x,
- h = poly[i+1].y,
- a1 = poly[i+2].x,
- a2 = poly[i+2].y;
+ if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
- sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc);
+ sCalcArc(ctxcanvas->canvas, 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);
@@ -636,14 +659,10 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (i+3 > n) return;
- 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 (!cdCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
- sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc);
+ sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc);
fprintf(ctxcanvas->file, "M %g %g A %d %d 0 %d 0 %g %g ",
arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY);
diff --git a/src/win32/cdwin.c b/src/win32/cdwin.c
index 37c4c0d..246ea5e 100644
--- a/src/win32/cdwin.c
+++ b/src/win32/cdwin.c
@@ -710,41 +710,45 @@ typedef struct _winArcParam
YEndArc; /* second radial ending point */
} winArcParam;
-static void sCalcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc)
+static void sCalcArc(cdCanvas* canvas, int xc, int yc, int w, int h, double a1, double a2, winArcParam* arc, int swap)
{
- /* convert to radians */
- angle1 *= CD_DEG2RAD;
- angle2 *= CD_DEG2RAD;
+ /* computation is done as if the angles are counter-clockwise,
+ and yaxis is NOT inverted. */
- arc->LeftRect = xc - w/2;
- arc->RightRect = xc + w/2 + 1;
- arc->XStartArc = xc + cdRound(w * cos(angle1) / 2.0);
- arc->XEndArc = xc + cdRound(w * cos(angle2) / 2.0);
+ arc->LeftRect = xc - w/2;
+ arc->TopRect = yc - h/2;
+ arc->RightRect = xc + w/2 + 1;
+ arc->BottomRect = yc + h/2 + 1;
- if (ctxcanvas->canvas->invert_yaxis)
+ /* GDI orientation is the same as CD */
+
+ if (!canvas->invert_yaxis)
+ _cdSwapInt(arc->BottomRect, arc->TopRect); /* not necessary, but done for clarity */
+
+ cdCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, &(arc->XStartArc), &(arc->YStartArc), &(arc->XEndArc), &(arc->YEndArc));
+
+ if (canvas->invert_yaxis)
{
- arc->TopRect = yc - h/2;
- arc->BottomRect = yc + h/2 + 1;
- arc->YStartArc = yc - cdRound(h * sin(angle1) / 2.0);
- arc->YEndArc = yc - cdRound(h * sin(angle2) / 2.0);
+ /* fix axis orientation only, because angle orientation is the same */
+ arc->YStartArc = 2*yc - arc->YStartArc;
+ arc->YEndArc = 2*yc - arc->YEndArc;
}
else
{
- arc->BottomRect = yc - h/2;
- arc->TopRect = yc + h/2 + 1;
- arc->YStartArc = yc + cdRound(h * sin(angle1) / 2.0);
- arc->YEndArc = yc + cdRound(h * sin(angle2) / 2.0);
-
+ /* Arc behave diferent when GM_ADVANCED is set */
/* it is clock-wise when axis NOT inverted */
- _cdSwapInt(arc->XStartArc, arc->XEndArc);
- _cdSwapInt(arc->YStartArc, arc->YEndArc);
+ if (swap)
+ {
+ _cdSwapInt(arc->XStartArc, arc->XEndArc);
+ _cdSwapInt(arc->YStartArc, arc->YEndArc);
+ }
}
}
static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas->canvas, xc, yc, w, h, angle1, angle2, &arc, 1);
sUpdateFill(ctxcanvas, 0);
@@ -754,7 +758,7 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a
static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas->canvas, xc, yc, w, h, angle1, angle2, &arc, 1);
sUpdateFill(ctxcanvas, 1);
@@ -796,7 +800,7 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas->canvas, xc, yc, w, h, angle1, angle2, &arc, 1);
sUpdateFill(ctxcanvas, 1);
@@ -843,10 +847,11 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
if (mode == CD_PATH)
{
- int p;
+ int p, current_set;
/* if there is any current path, remove it */
BeginPath(ctxcanvas->hDC);
+ current_set = 0;
i = 0;
for (p=0; p<ctxcanvas->canvas->path_n; p++)
@@ -856,42 +861,57 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
case CD_PATH_NEW:
EndPath(ctxcanvas->hDC);
BeginPath(ctxcanvas->hDC);
+ current_set = 0;
break;
case CD_PATH_MOVETO:
if (i+1 > n) return;
MoveToEx(ctxcanvas->hDC, poly[i].x, poly[i].y, NULL);
+ current_set = 1;
i++;
break;
case CD_PATH_LINETO:
if (i+1 > n) return;
LineTo(ctxcanvas->hDC, poly[i].x, poly[i].y);
+ current_set = 1;
i++;
break;
case CD_PATH_ARC:
{
- int xc, yc, w, h;
+ int xc, yc, w, h, old_arcmode = 0;
double a1, a2;
winArcParam arc;
if (i+3 > n) return;
- 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 (!cdCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
+
+ sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arc, 0);
- sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arc);
+ if (current_set)
+ LineTo(ctxcanvas->hDC, arc.XStartArc, arc.YStartArc);
+ if ((a2-a1)<0) /* can be clockwise */
+ {
+ /* Arc behave diferent when GM_ADVANCED is set */
+ old_arcmode = SetArcDirection(ctxcanvas->hDC, ctxcanvas->canvas->invert_yaxis? AD_CLOCKWISE: AD_COUNTERCLOCKWISE);
+ }
+
Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc);
+ if (old_arcmode) /* restore */
+ SetArcDirection(ctxcanvas->hDC, old_arcmode);
+
+ MoveToEx(ctxcanvas->hDC, arc.XEndArc, arc.YEndArc, NULL);
+ current_set = 1;
+
i += 3;
}
break;
case CD_PATH_CURVETO:
if (i+3 > n) return;
PolyBezierTo(ctxcanvas->hDC, (POINT*)(poly + i), 3);
+ current_set = 1;
i += 3;
break;
case CD_PATH_CLOSE: