From 17be65cfea56a53dc3a9cb617895adf5300db099 Mon Sep 17 00:00:00 2001
From: scuri <scuri>
Date: Tue, 1 Jun 2010 22:31:45 +0000
Subject: *** empty log message ***

---
 html/en/func/filled.html  |  24 +++---
 html/en/func/lines.html   |  22 +++---
 html/en/func/polygon.html |  31 +++++---
 include/cd_private.h      |  23 +++---
 src/cairo/cdcairo.c       |  72 ++++++++++--------
 src/cd.c                  |   4 +
 src/cd.def                |   6 ++
 src/cd_primitives.c       | 169 ++++++++++++++++++++++++++++++++---------
 src/cd_util.c             |   1 +
 src/drv/cdirgb.c          | 186 ++--------------------------------------------
 src/drv/cdpdf.c           |  28 +++----
 src/drv/cdpicture.c       |  12 +--
 src/drv/cdps.c            |  44 +++++------
 src/gdiplus/cdwinp.cpp    |  78 ++++++++-----------
 src/gdk/cdgdk.c           |   2 +-
 src/sim/sim_primitives.c  | 161 ++++++++++++++++++++++-----------------
 src/svg/cdsvg.c           |  57 +++++++++-----
 src/win32/cdwin.c         |  84 +++++++++++++--------
 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.&nbsp; 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>.&nbsp;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>.&nbsp;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>&nbsp;CD_PATH_NEW - creates a new empty path. Useful if more than one 
+	<li>&nbsp;<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&nbsp; 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 */
           }
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:
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();
 
-- 
cgit v1.2.3