diff options
author | scuri <scuri> | 2010-06-01 22:31:45 +0000 |
---|---|---|
committer | scuri <scuri> | 2010-06-01 22:31:45 +0000 |
commit | 17be65cfea56a53dc3a9cb617895adf5300db099 (patch) | |
tree | 03362237b113b92157f433ce0e018c39821b1f84 | |
parent | 3e4bae27558fd3bcec4bc54928b0a5d3145cd7c3 (diff) |
*** empty log message ***
-rw-r--r-- | html/en/func/filled.html | 24 | ||||
-rw-r--r-- | html/en/func/lines.html | 22 | ||||
-rw-r--r-- | html/en/func/polygon.html | 31 | ||||
-rw-r--r-- | include/cd_private.h | 23 | ||||
-rw-r--r-- | src/cairo/cdcairo.c | 72 | ||||
-rw-r--r-- | src/cd.c | 4 | ||||
-rw-r--r-- | src/cd.def | 6 | ||||
-rw-r--r-- | src/cd_primitives.c | 169 | ||||
-rw-r--r-- | src/cd_util.c | 1 | ||||
-rw-r--r-- | src/drv/cdirgb.c | 186 | ||||
-rw-r--r-- | src/drv/cdpdf.c | 28 | ||||
-rw-r--r-- | src/drv/cdpicture.c | 12 | ||||
-rw-r--r-- | src/drv/cdps.c | 44 | ||||
-rw-r--r-- | src/gdiplus/cdwinp.cpp | 78 | ||||
-rw-r--r-- | src/gdk/cdgdk.c | 2 | ||||
-rw-r--r-- | src/sim/sim_primitives.c | 161 | ||||
-rw-r--r-- | src/svg/cdsvg.c | 57 | ||||
-rw-r--r-- | src/win32/cdwin.c | 84 | ||||
-rw-r--r-- | test/simple/simple.c | 20 |
19 files changed, 522 insertions, 502 deletions
diff --git a/html/en/func/filled.html b/html/en/func/filled.html index 2ae1083..97a2e84 100644 --- a/html/en/func/filled.html +++ b/html/en/func/filled.html @@ -63,25 +63,29 @@ canvas:fSector(xc, yc, w, h, angle1, angle2: number) [in Lua] canvas:wSector(xc, yc, w, h, angle1, angle2: number) (WC) [in Lua]</pre> <p>Fills the arc of an ellipse aligned with the axis, according to the current - interior style, in the shape of a pie. It is drawn counter-clockwise. The + interior style, in the shape of a pie. </p> +<p>The coordinate <b>(xc,yc)</b> defines the center of the ellipse. Dimensions <b>w</b> and <b>h</b> define the elliptic axes X and Y, respectively. </p> - <p>Angles <b>angle1</b> and <b>angle2</b>, in degrees, - define the arc's beginning and end, but they are not the angle relative to the + <p>Angles <b>angle1</b> and <b>angle2</b> are in degrees and oriented + counter-clockwise. They + define the arc start and end, but they are not the angle relative to the center, except when w==h and the ellipse is reduced to a circle. The arc - starts at the point <b>(xc+(w/2)*cos(angle1),yc+(h/2)*sin(angle1))</b> - and ends at <b>(xc+(w/2)*cos(angle2),yc+(h/2)*sin(angle2))</b>. A - complete ellipse can be drawn using 0 and 360 as the angles. </p> + starts at the point <b>(xc+(w/2)*cos(angle1), yc+(h/2)*sin(angle1))</b> + and ends at <b>(xc+(w/2)*cos(angle2), yc+(h/2)*sin(angle2))</b>. A + complete ellipse can be drawn using 0 and 360 as the angles. If <b>angle2</b> + is less than <b>angle1</b> it will be increased by 360 until it is greater + than <b>angle1</b>. </p> <p>The angles are specified so if the size of the ellipse (w x h) is changed, its shape is preserved. So the angles relative to the center are dependent - from the ellipse size. The actual angle can be obtained using <tt><b>rangle = - atan2((h/2</b></tt><b>)*sin(angle),(w/2)*cos(angle))</b>.</p> - <p>The angles are given in degrees. To specify the angle in radians, you can + from the ellipse size. The actual angle can be obtained using <b>rangle = + atan2((h/2)*sin(angle), (w/2)*cos(angle))</b>.</p> + <p>To specify the angle in radians, you can use the definition <font size="2"><strong>CD_RAD2DEG</strong></font> to multiply the value in radians before passing the angle to CD. </p> <p>When the interior style <font><strong>CD_HOLLOW</strong></font> is defined, - the function behaves like its equivalent <strong><font>cdArc</font></strong>, + the function behaves like its equivalent <strong><font>cdCanvasArc</font></strong>, plus two lines connecting to the center.</p> <p align="center"><font size="4">Sector Parameters</font><br> <img src="../../img/sector.gif" border="2" width="161" height="160"></p> diff --git a/html/en/func/lines.html b/html/en/func/lines.html index b748391..6ba78d7 100644 --- a/html/en/func/lines.html +++ b/html/en/func/lines.html @@ -1,5 +1,5 @@ <!doctype HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> +<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"> <head> <meta http-equiv="Content-Language" content="en-us"> @@ -64,21 +64,25 @@ canvas:fArc(xc, yc, w, h, angle1, angle2: <em>number</em>) [in Lua] canvas:wArc(xc, yc, w, h, angle1, angle2: <em>number</em>)<font><font> (WC) [in Lua]</font></font></pre> <p>Draws the arc of an ellipse aligned with the axis, using the current - foreground color and line width and style. It is drawn counter-clockwise. The + foreground color and line width and style.</p> +<p>The coordinate <b>(xc,yc)</b> defines the center of the ellipse. Dimensions <b>w</b> and <b>h</b> define the elliptic axes X and Y, respectively. </p> - <p>Angles <b>angle1</b> and <b>angle2</b>, in degrees define - the arc's beginning and end, but they are not the angle relative to the + <p>Angles <b>angle1</b> and <b>angle2</b> are in degrees and oriented + counter-clockwise. They define + the arc start and end, but they are not the angle relative to the center, except when w==h and the ellipse is reduced to a circle. The arc - starts at the point <b><b>(xc+(w/2)*cos(angle1),yc+(h/2)*sin(angle1))</b> - </b>and ends at <b>(xc+(w/2)*cos(angle2),yc+(h/2)*sin(angle2))</b>. A - complete ellipse can be drawn using 0 and 360 as the angles. </p> + starts at the point <b><b>(xc+(w/2)*cos(angle1), yc+(h/2)*sin(angle1))</b> + </b>and ends at <b>(xc+(w/2)*cos(angle2), yc+(h/2)*sin(angle2))</b>. A + complete ellipse can be drawn using 0 and 360 as the angles. If <b>angle2</b> + is less than <b>angle1</b> it will be increased by 360 until it is greater + than <b>angle1</b>. </p> <p>The angles are specified so if the size of the ellipse (w x h) is changed, its shape is preserved. So the angles relative to the center are dependent from the ellipse size. The actual angle can be obtained using <b>rangle = - atan2((h/2</b><b>)*sin(angle),(w/2)*cos(angle))</b>.</p> - <p>The angles are given in degrees. To specify the angle in radians, you can + atan2((h/2</b><b>)*sin(angle), (w/2)*cos(angle))</b>.</p> + <p>To specify the angle in radians, you can use the definition <font size="2"><strong>CD_RAD2DEG</strong></font> to multiply the value in radians before passing the angle to CD.</p> <p align="center"><font size="4">Arc Parameters<br> diff --git a/html/en/func/polygon.html b/html/en/func/polygon.html index 3a0b9c0..c2acb9a 100644 --- a/html/en/func/polygon.html +++ b/html/en/func/polygon.html @@ -93,42 +93,43 @@ canvas:PathSet(action: number) [in Lua]</pre> <p>Configures the action between sequences of <strong>cdCanvasVertex</strong>. <strong>action</strong> can be:</p> <ul> - <li> CD_PATH_NEW - creates a new empty path. Useful if more than one + <li> <strong>CD_PATH_NEW</strong> - creates a new empty path. Useful if more than one path is configured. <strong>cdCanvasBegin</strong>(CD_PATH) already creates a new path.</li> - <li>CD_PATH_MOVETO - moves the current position to the given coordinates. + <li><strong>CD_PATH_MOVETO</strong> - moves the current position to the given coordinates. Must be followed by 1 call to <strong>cdCanvasVertex</strong>, <strong> cdfCanvasVertex</strong>, or <strong>wdCanvasVertex</strong>.</li> - <li>CD_PATH_LINETO - adds a line to the path from the current position to + <li><strong>CD_PATH_LINETO</strong> - adds a line to the path from the current position to the given coordinates. The current position is updated to the given coordinates. If there is no current position, nothing is connected and only the current position is updated. Must be followed by 1 call to <strong> cdCanvasVertex</strong>, <strong>cdfCanvasVertex</strong>, or <strong> wdCanvasVertex</strong>.</li> - <li>CD_PATH_ARC - adds an arc to the path. If there is a current position + <li><strong>CD_PATH_ARC</strong> - adds an arc to the path. If there is a current position adds also a line from the current position to the start of the arc. The end of the arc becomes the current position. Must be followed by 3 calls to <strong>cdCanvasVertex</strong>, <strong>cdfCanvasVertex</strong>, or <strong>wdCanvasVertex</strong>. One for the center of the arc (xc,yc), one for the bounding rectangle size (w,h), and one for the start and end angles - (angle1,angle2). Angles are in degrees. When using integer coordinates + (angle1,angle2). Angles are in degrees and oriented counter-clockwise, but + angle2 can be smaller than angle1 to describe a clockwise arc. When using integer coordinates angles must be multiplied by 1000.</li> - <li>CD_PATH_CURVETO - adds a bezier curve to the path. If there is no + <li><strong>CD_PATH_CURVETO</strong> - adds a bezier curve to the path. If there is no current position, the first point will be used twice. The end point becomes the current position. Must be followed by 3 calls to <strong>cdCanvasVertex</strong>, <strong>cdfCanvasVertex</strong>, or <strong>wdCanvasVertex</strong>. Must be first control point (x1,y1) + second control point (x2,y2) + end point (x3,y3).</li> - <li>CD_PATH_CLOSE - adds a line to the path that connects the last point + <li><strong>CD_PATH_CLOSE</strong> - adds a line to the path that connects the last point with the first point of the path, closing it.</li> - <li>CD_PATH_FILL - fills the path with the current fill attributes, + <li><strong>CD_PATH_FILL</strong> - fills the path with the current fill attributes, then the path is discarded.</li> - <li>CD_PATH_STROKE - strokes the path with the current line attributes, then the + <li><strong>CD_PATH_STROKE</strong> - strokes the path with the current line attributes, then the path is discarded.</li> - <li>CD_PATH_FILLSTROKE - fills the path with the current fill + <li><strong>CD_PATH_FILLSTROKE</strong> - fills the path with the current fill attributes, strokes the path with the current line attributes, then the path is discarded.</li> - <li>CD_PATH_CLIP - use the path as a clipping area to be + <li><strong>CD_PATH_CLIP</strong> - use the path as a clipping area to be intersected with the current clipping area, then the path is discarded.</li> </ul> @@ -139,6 +140,14 @@ cdCanvasPathSet(canvas, CD_PATH_MOVETO); cdCanvasVertex(canvas, x1, y1); cdCanvasPathSet(canvas, CD_PATH_LINETO); cdCanvasVertex(canvas, x2, y2); +cdCanvasPathSet(canvas, CD_PATH_CURVETO); +cdCanvasVertex(canvas, x3, y3); /* control point for start point */ +cdCanvasVertex(canvas, x4, y4); /* control point for end point */ +cdCanvasVertex(canvas, x5, y5); /* end point */ +cdCanvasPathSet(canvas, CD_PATH_ARC); +cdCanvasVertex(canvas, x6, y6); /* center */ +cdCanvasVertex(canvas, x7, y7); /* width, height */ +cdCanvasVertex(canvas, x8, y8); /* start angle, end angle (degrees / 1000) */ cdCanvasPathSet(canvas, CD_PATH_STROKE); cdCanvasEnd(canvas);</pre> diff --git a/include/cd_private.h b/include/cd_private.h index 28b92d8..1410126 100644 --- a/include/cd_private.h +++ b/include/cd_private.h @@ -222,7 +222,6 @@ struct _cdCanvas /* simulation flags */ int sim_mode; - int sim_poly; /* WC */ double s, sx, tx, sy, ty; /* Transformacao Window -> Viewport (scale+translation)*/ @@ -269,7 +268,6 @@ enum{CD_CTX_NATIVEWINDOW, CD_CTX_IMAGE, CD_CTX_DBUFFER, CD_CTX_PRINTER, CD_CTX_E /* utilities */ /*************/ int cdRound(double x); -void cdCanvasGetEllipseBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax); int cdCheckBoxSize(int *xmin, int *xmax, int *ymin, int *ymax); int cdfCheckBoxSize(double *xmin, double *xmax, double *ymin, double *ymax); void cdNormalizeLimits(int w, int h, int *xmin, int *xmax, int *ymin, int *ymax); @@ -280,6 +278,14 @@ char* cdStrDup(const char* str); char* cdStrDupN(const char* str, int len); void cdSetPaperSize(int size, double *w_pt, double *h_pt); +void cdCanvasPoly(cdCanvas* canvas, int mode, cdPoint* points, int n); +void cdCanvasGetArcBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax); +int cdCanvasGetArcPathF(cdCanvas* canvas, const cdPoint* poly, double *xc, double *yc, double *w, double *h, double *a1, double *a2); +int cdfCanvasGetArcPath(cdCanvas* canvas, const cdfPoint* poly, double *xc, double *yc, double *w, double *h, double *a1, double *a2); +int cdCanvasGetArcPath(cdCanvas* canvas, const cdPoint* poly, int *xc, int *yc, int *w, int *h, double *a1, double *a2); +void cdCanvasGetArcStartEnd(int xc, int yc, int w, int h, double a1, double a2, int *x1, int *y1, int *x2, int *y2); +void cdfCanvasGetArcStartEnd(double xc, double yc, double w, double h, double a1, double a2, double *x1, double *y1, double *x2, double *y2); + #define _cdCheckCanvas(_canvas) (_canvas!=NULL && ((unsigned char*)_canvas)[0] == 'C' && ((unsigned char*)_canvas)[1] == 'D') #define _cdInvertYAxis(_canvas, _y) (_canvas->h - (_y) - 1) #define _cdSwapInt(_a,_b) {int _c=_a;_a=_b;_b=_c;} @@ -351,11 +357,6 @@ void cdSimGetTextSizeFT(cdCtxCanvas* ctxcanvas, const char *s, int len, int *wid /* sim_primitives.c */ -/* Simulation functions that depend on the simulation base driver. */ -void cdSimPolyFill(cdCanvas* canvas, cdPoint* poly, int n); -void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n); -void cdfSimPolyLine(cdCanvas* canvas, const cdfPoint* poly, int n); - /* Simulation functions that are >> independent << of the simulation base driver. */ void cdSimMark(cdCanvas* canvas, int x, int y); void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax); @@ -368,6 +369,8 @@ void cdSimBox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax); void cdSimArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2); void cdSimSector(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2); void cdSimChord(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2); +void cdSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* points, int n); + void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n); void cdSimPolyPath(cdCanvas* canvas, const cdPoint* points, int n); @@ -379,13 +382,11 @@ void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, do void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2); void cdfSimSector(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2); void cdfSimChord(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2); +void cdfSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* fpoly, int n); + void cdfSimPolyBezier(cdCanvas* canvas, const cdfPoint* points, int n); void cdfSimPolyPath(cdCanvas* canvas, const cdfPoint* points, int n); -/* Utilities */ -void cdSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* points, int n); -int cdSimCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height); - #ifdef __cplusplus } 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 */ } @@ -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; } @@ -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, ¤t); @@ -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, ¤t); @@ -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, ¤t); @@ -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: diff --git a/test/simple/simple.c b/test/simple/simple.c index eb7acab..891caef 100644 --- a/test/simple/simple.c +++ b/test/simple/simple.c @@ -705,18 +705,26 @@ int SimpleDrawAll(void) cdCanvasPathSet(canvas, CD_PATH_MOVETO); cdVertex(w/2 + 200, h/2); cdCanvasPathSet(canvas, CD_PATH_LINETO); + cdVertex(w/2 + 230, h/2 + 50); + cdCanvasPathSet(canvas, CD_PATH_LINETO); cdVertex(w/2 + 250, h/2 + 50); cdCanvasPathSet(canvas, CD_PATH_CURVETO); - cdVertex(w/2+150+150, h/2+200-50); - cdVertex(w/2+150+180, h/2+250-50); - cdVertex(w/2+150+180, h/2+200-50); + cdVertex(w/2+150+150, h/2+200-50); /* control point for start */ + cdVertex(w/2+150+180, h/2+250-50); /* control point for end */ + cdVertex(w/2+150+180, h/2+200-50); /* end point */ cdCanvasPathSet(canvas, CD_PATH_CURVETO); cdVertex(w/2+150+180, h/2+150-50); cdVertex(w/2+150+150, h/2+100-50); cdVertex(w/2+150+300, h/2+100-50); - cdCanvasPathSet(canvas, CD_PATH_CLOSE); -// cdCanvasPathSet(canvas, CD_PATH_STROKE); - cdCanvasPathSet(canvas, CD_PATH_FILL); + cdCanvasPathSet(canvas, CD_PATH_LINETO); + cdVertex(w/2+150+300, h/2-50); + cdCanvasPathSet(canvas, CD_PATH_ARC); + cdVertex(w/2+300, h/2); /* center */ + cdVertex(200, 100); /* width, height */ + cdVertex(-30*1000, -170*1000); /* start angle, end angle (degrees / 1000) */ +// cdCanvasPathSet(canvas, CD_PATH_CLOSE); + cdCanvasPathSet(canvas, CD_PATH_STROKE); +// cdCanvasPathSet(canvas, CD_PATH_FILL); // cdCanvasPathSet(canvas, CD_PATH_FILLSTROKE); cdEnd(); |