summaryrefslogtreecommitdiff
path: root/cd/src/cd_primitives.c
diff options
context:
space:
mode:
Diffstat (limited to 'cd/src/cd_primitives.c')
-rwxr-xr-xcd/src/cd_primitives.c208
1 files changed, 170 insertions, 38 deletions
diff --git a/cd/src/cd_primitives.c b/cd/src/cd_primitives.c
index b1a19ba..8714e70 100755
--- a/cd/src/cd_primitives.c
+++ b/cd/src/cd_primitives.c
@@ -123,32 +123,22 @@ void cdCanvasBegin(cdCanvas* canvas, int mode)
assert(mode>=CD_FILL);
if (!_cdCheckCanvas(canvas)) return;
+ canvas->use_fpoly = -1;
+ canvas->poly_n = 0;
+ canvas->path_n = 0;
+
if (mode == CD_REGION)
{
if (!canvas->cxNewRegion) return;
canvas->new_region = 1;
- canvas->poly_n = 0;
canvas->cxNewRegion(canvas->ctxcanvas);
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->use_fpoly = -1;
- canvas->poly_n = 0;
canvas->poly_mode = mode;
}
@@ -181,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)
@@ -233,6 +223,51 @@ void cdfCanvasVertex(cdCanvas* canvas, double x, double y)
canvas->poly_n++;
}
+void cdCanvasPathSet(cdCanvas* canvas, int action)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->poly_mode!=CD_PATH)
+ return;
+
+ if (!canvas->path)
+ {
+ canvas->path = (int*)malloc(sizeof(int)*(_CD_POLY_BLOCK+1));
+ canvas->path_size = _CD_POLY_BLOCK;
+ }
+
+ if (canvas->path_n == canvas->path_size)
+ {
+ canvas->path_size += _CD_POLY_BLOCK;
+ canvas->path = (int*)realloc(canvas->path, sizeof(int) * (canvas->path_size+1));
+ }
+
+ canvas->path[canvas->path_n] = 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);
@@ -245,6 +280,13 @@ void cdCanvasEnd(cdCanvas* canvas)
return;
}
+ if (canvas->poly_mode==CD_PATH && canvas->poly_n < 2)
+ {
+ canvas->poly_n = 0;
+ canvas->path_n = 0;
+ return;
+ }
+
if (canvas->poly_mode==CD_OPEN_LINES && canvas->poly_n < 2)
{
canvas->poly_n = 0;
@@ -265,15 +307,10 @@ void cdCanvasEnd(cdCanvas* canvas)
return;
}
- if (canvas->sim_poly)
- cdpolySIM(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)
{
@@ -303,6 +340,7 @@ void cdCanvasEnd(cdCanvas* canvas)
}
}
+ canvas->path_n = 0;
canvas->poly_n = 0;
canvas->use_fpoly = -1;
}
@@ -429,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);
@@ -444,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)
{
@@ -466,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)
{
@@ -492,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)
{
@@ -535,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)
{
@@ -581,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)
{
@@ -621,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)
{
@@ -656,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)
@@ -700,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;
+}