summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--html/en/drv/cairo.html42
-rw-r--r--html/en/drv/gdiplus.html6
-rw-r--r--html/en/drv/pdf.html5
-rw-r--r--html/en/drv/ps.html5
-rw-r--r--html/en/drv/svg.html3
-rw-r--r--html/en/drv/win32.html3
-rw-r--r--html/en/drv/xrender.html3
-rw-r--r--html/en/func/color.html5
-rw-r--r--html/en/func/init.html26
-rw-r--r--html/en/func/marks.html3
-rw-r--r--html/en/func/other.html2
-rw-r--r--html/en/func/polygon.html30
-rw-r--r--html/en/func/region.html2
-rw-r--r--html/en/func/server.html3
-rw-r--r--html/en/func/vectortext.html4
-rw-r--r--html/en/func/wd.html2
-rw-r--r--html/en/history.html9
-rw-r--r--html/en/home.html2
-rw-r--r--html/wb/wb_usr.lua39
-rw-r--r--html/wb_search.txt5
-rw-r--r--html/wb_title.html2
-rw-r--r--html/wb_tree.html31
-rw-r--r--include/cd.h17
-rw-r--r--include/cd_private.h5
-rw-r--r--mak.vc9/cdxrender.vcproj2
-rw-r--r--src/cairo/cdcairo.c249
-rw-r--r--src/cairo/cdcaironative_win32.c2
-rw-r--r--src/cd.def1
-rw-r--r--src/cd_primitives.c39
-rw-r--r--src/drv/cdpdf.c194
-rw-r--r--src/drv/cdps.c368
-rw-r--r--src/gdiplus/cdwdbufp.cpp2
-rw-r--r--src/gdiplus/cdwinp.cpp445
-rw-r--r--src/gdiplus/cdwinp.h5
-rw-r--r--src/svg/cdsvg.c313
-rw-r--r--src/win32/cdwin.c87
36 files changed, 1806 insertions, 155 deletions
diff --git a/html/en/drv/cairo.html b/html/en/drv/cairo.html
index 4977258..c0ad80f 100644
--- a/html/en/drv/cairo.html
+++ b/html/en/drv/cairo.html
@@ -6,6 +6,11 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>CAIRO</title>
<link rel="stylesheet" type="text/css" href="../../style.css">
+<style type="text/css">
+.style1 {
+ font-family: Courier;
+}
+</style>
</head>
<body>
@@ -15,8 +20,9 @@
<p>This driver represents a basic driver for all system-dependent drivers
implemented in the X-Windows and MS-Windows systems. The implementation uses the
<a href="http://library.gnome.org/devel/pango/">Cairo</a> API
- functions and some GTK functions to support Unicode text. This driver can be
- compiled and used in all systems Cairo is supported.</p>
+ functions and Pango functions to support Unicode text. This driver can be
+ compiled and used in all systems Cairo is supported. The drivers <b>Native Window</b>,
+ <b>Image</b>, <b>Printer</b> and <b>Double Buffer</b> were implemented.</p>
<p>The main motivation for the use of Cairo was transparency for all the
primitives. Beyond that we got other features like anti-aliasing, gradient
filling, transformations and back-ends (support to rendering: PDF, PS, SVG and
@@ -24,6 +30,25 @@ PNG surfaces).</p>
<p>This driver still does not completely replace the X-Windows and GDI Windows
base drivers, because Cairo does not have support for bitwise XOR operations and
for complex clipping regions.</p>
+ <p>So we let the programmer to choose what to use. We created the function <font face="Courier"><strong>
+ cdUseContextPlus</strong></font> that allows to activate or to deactivate the use of
+ Cairo for the available GDK, Win32 or X-Windows based drivers.
+ This function affects only the <font face="Courier"><strong>cdCreateCanvas</strong></font> function call, once created
+ the canvas will be always a Cairo canvas. In fact the function affects primary the definitions
+ <font face="Courier"><strong>CD_NATIVEWINDOW</strong></font>,
+ <strong><span style="font-family: Courier">CD_IMAGE</span></strong> and <strong>
+ <span style="font-family: Courier">CD_DBUFFER</span></strong>, because they are
+ function calls and not static defines.</p>
+ <p>Using Cairo it is allowed to create more that one canvas at the same time for the same Window. And they can co-exist
+ with a standard GD, Win32 or X-Windows canvas.</p>
+ <p>To enable the use of Cairo based drivers you must call the initialization function <font face="Courier"><strong>
+ cdInitContextPlus()</strong></font> once and link to the libraries &quot;<strong>cdcairo</strong>&quot; and &quot;<strong>cairo</strong>&quot;.
+ When using the GDK base driver you do not need to link with the &quot;<strong>cdcairo</strong>&quot;
+ library. Also the Cairo library must be installed in your system.</p>
+ <p>In CDLua it is not necessary any additional initialization, but the
+ application must still be linked with the <strong>cdcontextplus.lib</strong>
+ library or a <strong>require&quot;cdluacontextplus&quot;</strong> can be used when
+ using dynamic libraries.</p>
<h3>Behavior of Functions</h3>
<h4>Control&nbsp; </h4>
@@ -39,6 +64,13 @@ for complex clipping regions.</p>
<font face="Courier"><strong>UpdateYAxis</strong></font></a>: the
orientation of axis Y is the opposite to its orientation in the CD library.</li>
</ul>
+<h4>Primitives</h4>
+<ul>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>CD_PATH</tt></strong>
+ is supported.</li>
+ <li>Floating point primitives are supported.</li>
+</ul>
<h4>Attributes </h4>
<ul>
<li>
@@ -104,6 +136,12 @@ for complex clipping regions.</p>
</ul>
<ul>
+ <li>&quot;<span class="style1"><strong>PATTERNIMAGE</strong></span>&quot;:&nbsp;defines
+ a filled interior style using a server image as pattern. Data must be a server
+ image handle created with he Cairo base driver.</li>
+</ul>
+
+<ul>
<li>&quot;<b><font face="Courier">POLYHOLE</font></b>&quot;:&nbsp;defines the index of
the vertex where there is a hole in a closed polygon. It will affect the next
<strong>cdEnd</strong>. Can be called several times between <strong>cdBegin</strong>
diff --git a/html/en/drv/gdiplus.html b/html/en/drv/gdiplus.html
index f5b89f4..41e72dd 100644
--- a/html/en/drv/gdiplus.html
+++ b/html/en/drv/gdiplus.html
@@ -61,7 +61,8 @@
</ul>
<h4>Primitives</h4>
<ul>
- <li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
+ <li>Floating point primitives are supported.</li>
+ <li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
uses GDI. Excepting when the canvas is an image so it is done using GDI+.</li>
<li><font face="Courier"><a href="../func/filled.html#cdSector"><b>Sector</b></a></font>:
it also draws an arc in the same position to complete the size of the sector.</li>
@@ -77,7 +78,8 @@
<strong><tt>CD_FILLGRADIENT</tt></strong> defines the points of a filled polygon. It is filled with a gradient from
colors in each vertex to a color in its center. The colors are defined by the &quot;<strong><tt>GRADIENTCOLOR</tt></strong>&quot;
attribute, that must be set before each <strong><tt>cdVertex</tt></strong> call and before <strong><tt>cdEnd</tt></strong>
- for the center color. This will not affect the current interior style.</li>
+ for the center color. This will not affect the current interior style.<br>
+ <strong><tt>CD_PATH</tt></strong> is supported. </li>
</ul>
<h4>Attributes </h4>
<ul>
diff --git a/html/en/drv/pdf.html b/html/en/drv/pdf.html
index 979256b..2d9203d 100644
--- a/html/en/drv/pdf.html
+++ b/html/en/drv/pdf.html
@@ -166,7 +166,10 @@ ZapfDingbats</pre>
<li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
does not exist in PDF, is simulated using a circle with radius=1.</li>
<li>Floating point primitives are supported.</li>
- <li>Filled primitves do not include the line at the edges of the filled area.</li>
+ <li>Filled primitives do not include the line at the edges of the filled area.</li>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>CD_PATH</tt></strong>
+ is supported.</li>
</ul>
<h4>Server Images</h4>
<ul>
diff --git a/html/en/drv/ps.html b/html/en/drv/ps.html
index 7e8f0c2..9f4267a 100644
--- a/html/en/drv/ps.html
+++ b/html/en/drv/ps.html
@@ -179,7 +179,10 @@
<li><font face="Courier"><strong><a href="../func/marks.html#cdPixel">Pixel</a></strong></font>:
does not exist in PS, is simulated using a circle with radius=1.</li>
<li>Floating point primitives are supported.</li>
- <li>Filled primitves do not include the line at the edges of the filled area.</li>
+ <li>Filled primitives do not include the line at the edges of the filled area.</li>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>CD_PATH</tt></strong>
+ is supported.</li>
</ul>
<h4>Server Images</h4>
<ul>
diff --git a/html/en/drv/svg.html b/html/en/drv/svg.html
index 10a0952..af703a5 100644
--- a/html/en/drv/svg.html
+++ b/html/en/drv/svg.html
@@ -76,6 +76,9 @@
<a href="http://www.tecgraf.puc-rio.br/cd/en/func/marks.html#cdPixel">Pixel</a></strong></font>:
does not exist in SVG, is simulated using a circle with radius=0.1.</li>
<li>Floating point primitives are supported.</li>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>CD_PATH</tt></strong>
+ is supported.</li>
</dir>
<h4>Client Images</h4>
<dir>
diff --git a/html/en/drv/win32.html b/html/en/drv/win32.html
index df0d902..86a3f4e 100644
--- a/html/en/drv/win32.html
+++ b/html/en/drv/win32.html
@@ -37,6 +37,9 @@
using bitmaps.</li>
<li><font face="Courier"><strong><a href="../func/lines.html#cdLine">Line</a></strong></font>:
needs to draw an extra pixel in the final position.</li>
+ <li><a href="../func/lines.html#cdBegin">
+ <font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>CD_PATH</tt></strong>
+ is supported.</li>
</ul>
<h4>Attributes </h4>
<ul>
diff --git a/html/en/drv/xrender.html b/html/en/drv/xrender.html
index 381470f..be85b8e 100644
--- a/html/en/drv/xrender.html
+++ b/html/en/drv/xrender.html
@@ -69,7 +69,8 @@ IRIX.</p>
contain text regions.</li>
<li><a href="../func/lines.html#cdBegin">
<font face="Courier"><strong>Begin</strong></font></a>: <strong><tt>
- CD_BEZIER</tt></strong> is simulated with lines.</li>
+ CD_BEZIER</tt></strong> is simulated with lines.
+ <strong><tt>CD_PATH</tt></strong> is supported.</li>
<li><font face="Courier"><strong><a href="../func/lines.html#cdRect">Rect</a></strong></font>:
simulated using the client's <strong>Line</strong>.</li>
<li><font face="Courier"><a href="../func/lines.html#cdArc"><b>Arc</b></a></font>:
diff --git a/html/en/func/color.html b/html/en/func/color.html
index 8efd8a4..fbd4b52 100644
--- a/html/en/func/color.html
+++ b/html/en/func/color.html
@@ -52,8 +52,9 @@ cd.DecodeColor(color: lightuserdata) -&gt; (r, g, b: number) [in Lua]</pre>
cd.EncodeAlpha(color: lightuserdata, alpha: number) -&gt; (color: lightuserdata) [in Lua]</pre>
<p>Returns the given color coded with the alpha information. ATENTION: At the
- moment only the <a href="../drv/gdiplus.html">Win32 with GDI+</a>, the
- <a href="../drv/xrender.html">XRender</a> and the <a href="../drv/irgb.html">IMAGERGB</a>
+ moment only the <a href="../drv/cairo.html">Cairo</a>,
+ <a href="../drv/gdiplus.html">GDI+</a>, <a href="../drv/xrender.html">XRender</a>
+ and <a href="../drv/irgb.html">IMAGERGB</a>
drivers support alpha components in color coding. The
internal representation of the component is inverted, because the default value
must be 0 and opaque for backward compatibility, so you should use the <strong>cdDecodeAlpha</strong>
diff --git a/html/en/func/init.html b/html/en/func/init.html
index 9cdee9e..32a1ab6 100644
--- a/html/en/func/init.html
+++ b/html/en/func/init.html
@@ -41,7 +41,9 @@ cd.CreateCanvas(ctx: number, data: string or userdata) -&gt; (canvas: cdCanvas)
<ul>
<li><a href="../drv/clipbd.html"><b>CD_CLIPBOARD</b></a> = Clipboard (<b>cdclipbd.h</b>).</li>
- <li><a href="../drv/printer.html"><b>CD_PRINTER</b></a> = Printer (<b>cdprint.h</b>).</li>
+ <li><a href="../drv/printer.html"><b>CD_PRINTER</b></a> = Printer (<b>cdprint.h</b>).<br>
+ <a href="../drv/picture.html"><strong>CD_PICTURE</strong></a> = Picture in
+ memory (<strong>cdpicture.h</strong>).</li>
</ul>
<p><b>Image-Based Drivers</b>&nbsp; </p>
<ul>
@@ -51,22 +53,28 @@ cd.CreateCanvas(ctx: number, data: string or userdata) -&gt; (canvas: cdCanvas)
Drawing (<b>cdirgb.h</b>).</li>
<li><a href="../drv/dbuf.html"><b>CD_DBUFFER</b></a> = Offscreen Drawing
(<b>cddbuf.h</b>).</li>
+ <li><b><a href="../drv/dbufrgb.html">CD_DBUFFERRGB</a></b> = Client Offscreen Drawing
+ (<b>cddbuf.h</b>).</li>
</ul>
<p><b>File-Based Drivers</b>&nbsp; </p>
<ul>
- <li><a href="../drv/cgm.html"><b>CD_CGM</b></a> = Computer Graphics
+ <li><a href="../drv/pdf.html"><b>CD_PDF</b></a> = Adobe Portable Document Format (<b>cdpdf.h</b>).</li>
+ <li><a href="../drv/ps.html"><b>CD_PS</b></a> = PostScript File (<b>cdps.h</b>).</li>
+ <li><a href="../drv/svg.html"><b>CD_SVG</b></a> = Scalable Vector Graphics (<b>cdsvg.h</b>).</li>
+ <li><a href="../drv/mf.html"><b>CD_METAFILE</b></a> = Internal CD Metafile (<b>cdmf.h</b>).</li>
+ <li><a href="../drv/debug.html"><b>CD_DEBUG</b></a> = Internal CD Debug Log (<b>cddebug.h</b>).<br>
+ </li>
+ <li><a href="../drv/cgm.html"><b>CD_CGM</b></a> = Computer Graphics
Metafile ISO (<b>cdcgm.h</b>).</li>
<li><a href="../drv/dgn.html"><b>CD_DGN</b></a> = MicroStation Design
File (<b>cddgn.h</b>).</li>
<li><a href="../drv/dxf.html"><b>CD_DXF</b></a> = AutoCad Drawing
- Interchange File (<b>cddxf.h</b>).</li>
+ Interchange File (<b>cddxf.h</b>).<br>
+ </li>
<li><a href="../drv/emf.html"><b>CD_EMF</b></a> = Microsoft Windows
Enhanced Metafile (<b>cdemf.h</b>). Works only in MS Windows systems.</li>
- <li><a href="../drv/mf.html"><b>CD_METAFILE</b></a> = Metafile Canvas
- Draw (<b>cdmf.h</b>).</li>
- <li><a href="../drv/ps.html"><b>CD_PS</b></a> = PostScript File (<b>cdps.h</b>).</li>
<li><a href="../drv/wmf.html"><b>CD_WMF</b></a> = Microsoft Windows
- Metafile (<b>cdwmf.h</b>).</li>
+ Metafile (<b>cdwmf.h</b>). Works only in MS Windows systems.</li>
</ul>
<pre class="function"><span class="mainFunction">cdCanvas*&nbsp;<a name="cdCreateCanvasf">cdCreateCanvasf(cdContext *ctx, const char* format, ...)</a>; [in C]
@@ -115,8 +123,8 @@ cd.UseContextPlus(use: boolean) -&gt; (old_use: boolean) [in Lua]</pre>
cd.InitContextPlus() [in Lua]</pre>
<p>Initializes the context driver to use another context replacing the standard drivers.
This functions is only available when a library containing a &quot;ContextPlus&quot;
-context driver is used. See the <a href="../drv/gdiplus.html">GDI+</a> base
-driver and the <a href="../drv/xrender.html">XRender</a> base driver.</p>
+context driver is used. See the <a href="../drv/cairo.html">Cairo</a>,&nbsp; <a href="../drv/gdiplus.html">GDI+</a>
+and <a href="../drv/xrender.html">XRender</a> base drivers.</p>
<p>In Lua, when using require&quot;cdluacontextplus&quot; this function will be
automatically called.</p>
diff --git a/html/en/func/marks.html b/html/en/func/marks.html
index b68db35..e467c10 100644
--- a/html/en/func/marks.html
+++ b/html/en/func/marks.html
@@ -25,7 +25,8 @@ canvas:Pixel(x, y: number, color: lightuserdata) [in Lua]
canvas:wPixel(x, y: number, color: lightuserdata) (WC) [in Lua]</pre>
<p>Configures the pixel <b>(x,y)</b> with the color defined by <b>color</b>. It is the smallest element of the canvas. It depends only
- on global attributes of the canvas.</p>
+ on global attributes of the canvas. It can be very slow on some drivers.
+ Sometimes it is implemented as a rectangle with size 1x1.</p>
<pre class="function"><span class="mainFunction">void <a name="cdMark">cdCanvasMark</a>(cdCanvas* canvas, int x, int y); [in C]</span>
void wdCanvasMark(cdCanvas* canvas, double x, double y); (WC) [in C]
diff --git a/html/en/func/other.html b/html/en/func/other.html
index b493ae5..d334508 100644
--- a/html/en/func/other.html
+++ b/html/en/func/other.html
@@ -48,7 +48,7 @@ cd._VERSION
cd._VERSION_DATE
cd._VERSION_NUMBER</pre>
- <p>Usefull definitions. They have the same value returned by <b>cdVersion</b>*
+ <p>Useful definitions. They have the same value returned by <b>cdVersion</b>*
functions, except that they do not include the build number.</p>
<hr>
diff --git a/html/en/func/polygon.html b/html/en/func/polygon.html
index 4e18664..4ab5834 100644
--- a/html/en/func/polygon.html
+++ b/html/en/func/polygon.html
@@ -6,6 +6,11 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Polygons</title>
<link rel="stylesheet" type="text/css" href="../../style.css">
+<style type="text/css">
+.style1 {
+ font-family: Courier;
+}
+</style>
</head>
<body>
@@ -82,6 +87,31 @@ canvas:End() [in Lua]</pre>
<p>Ends the polygon's definition and draws it.</p>
+<p>&nbsp;</p>
+&quot;<span class="style1"><strong>PATH</strong></span>&quot;:&nbsp;allows to create
+ a complex path using CD primitives and then fill, stroke or clip using the
+ new path. Must be used with the following parameters:<ul>
+ <li>&quot;BEGIN&quot; - creates a new empty path, must be the first call</li>
+ <li>cdCanvasPixel, cdCanvasLine, cdCanvasArc - add elements to the path
+ instead of drawing to the canvas</li>
+ <li>&quot;FILL&quot; - closes the path, and fills it with the current fill attributes,
+ then the path is discarded</li>
+ <li>&quot;STROKE&quot; - strokes the path with the current line attributes, then the
+ path is discarded</li>
+ <li>&quot;CLOSESTROKE&quot; - closes the path, and strokes it with the current line
+ attributes, then the path is discarded</li>
+ <li>&quot;FILLSTROKE&quot; - closes the path, and fills it with the current fill
+ attributes, strokes the path with the current line attributes, then the path
+ is discarded</li>
+ <li>&quot;CLIP&quot; - closes the path, and use it as a clipping area to be
+ intersected with the current clipping area, then the path is discarded</li>
+ <li>&quot;NULL&quot; - discards the path and ends the process without any output.</li>
+ <li>ARC - If there is a current point an additional straight line is drawn
+ from the current point to the starting point of the arc. The endpoint of the
+ arc becomes the new current point. </li>
+ </ul>
+
+
</body>
</html>
diff --git a/html/en/func/region.html b/html/en/func/region.html
index 1581180..59874b8 100644
--- a/html/en/func/region.html
+++ b/html/en/func/region.html
@@ -67,7 +67,7 @@ canvas:wOffsetRegion(dx, dy: number) (WC) [in Lua]</pre>
<p>Moves the current region by the given offset. In X-Windows, if the region
moves to outside the canvas border, the part moved outside will be lost, the
- region will need to be reconstruted.</p>
+ region will need to be reconstructed.</p>
<pre class="function"><span class="mainFunction">void&nbsp;cdCanvasGetRegionBox(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax); [in C]</span>
void wdCanvasGetRegionBox(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax); (WC) [in C]
diff --git a/html/en/func/server.html b/html/en/func/server.html
index 6663de5..2a9142e 100644
--- a/html/en/func/server.html
+++ b/html/en/func/server.html
@@ -21,7 +21,8 @@
<p>It is called &quot;server&quot; images because the data is stored in a system private
format, that the application (or the client) does not have access.</p>
<p>To create a server image there must be an active canvas of a driver with
- server image support.</p>
+ server image support. Only the base drivers Win32, GDI+, X-Windows, XRender
+ and Cairo, support server images.</p>
<hr>
<pre class="function"><span class="mainFunction">cdImage* <a name="cdCreateImage">cdCanvasCreateImage</a>(cdCanvas* canvas, int w, int h); [in C]</span>
diff --git a/html/en/func/vectortext.html b/html/en/func/vectortext.html
index 84ca128..ec66aa2 100644
--- a/html/en/func/vectortext.html
+++ b/html/en/func/vectortext.html
@@ -14,8 +14,8 @@
left to right.</p>
<p align="center"><font size="4">Vector Text Parameters</font><br>
<img src="../../img/vector_text.gif" align="middle" border="2" width="101" height="91"></p>
- <p>All vector text drawing in all drivers are simulated using other CD
- primitives.</p>
+ <p>All vector text drawing in all drivers are simulated with other CD
+ primitives using polygons only.</p>
<hr>
<pre class="function"><span class="mainFunction">void <a name="cdVectorText">cdCanvasVectorText</a>(cdCanvas* canvas, int x, int y, const char* text); [in C]</span>
void wdCanvasVectorText(cdCanvas* canvas, double x, double y, const char* text); (WC) [in C]
diff --git a/html/en/func/wd.html b/html/en/func/wd.html
index 938d19d..02fda2e 100644
--- a/html/en/func/wd.html
+++ b/html/en/func/wd.html
@@ -24,7 +24,7 @@
if the canvas has a small size the picture quality will be poor. To increase
picture quality create a canvas with a larger size, if possible.</p>
<p>All World Coordinate drawing in all drivers are simulated using other CD
- primitives.</p>
+ primitives and do NOT depend or use the Transformation matrix.</p>
<hr>
<pre class="function"><span class="mainFunction">void <a name="wdWindow">wdCanvasWindow</a>(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax); [in C]</span>
diff --git a/html/en/history.html b/html/en/history.html
index 3029b31..7325ce8 100644
--- a/html/en/history.html
+++ b/html/en/history.html
@@ -19,13 +19,19 @@
<body>
<h2>History of Changes</h2>
-<h3>CVS (12/May/2010)</h3>
+<h3><a href="http://sourceforge.net/projects/canvasdraw/files/5.4/">Version 5.4</a> (XX/XX/2010)</h3>
<ul>
<li><span style="color: #0000FF">New:</span> context plus driver Cairo.</li>
<li><span style="color: #0000FF">New:</span> &quot;CMD&quot;, &quot;OPACITY&quot; and &quot;HATCHBOXSIZE&quot;
attributes in the SVG driver.</li>
+ <li><span style="color: #0000FF">New:</span> CD_PATH <strong>cdCanvasBegin</strong>
+ mode in the SVG, PS, PDF, Cairo, Win32 and GDI+ drivers.</li>
<li><span class="style1">Changed</span><span class="hist_changed">:</span>
CD_DXF now supports solid filled primitives for polygons and rectangles.</li>
+ <li><span class="style1">Changed</span><span class="hist_changed">:</span>
+ GDI+ base driver now supports floating point primitives. ATTENTION: check
+ for alignment and size problems in the application. Please report if
+ anything changed.</li>
<li><span style="color: #FF0000">Fixed:</span> PDF driver documentation,
<strong>CanvasBackOpacity</strong> and <strong>CanvasBackground</strong> are
supported.</li>
@@ -37,6 +43,7 @@
CanvasArc</strong> and Bezier polygon in the IMAGERGB driver.</li>
<li><span style="color: #FF0000">Fixed:</span> missed implementation for
CD_DEBUG, CD_PICTURE and CD_DBUFFERRGB in Lua.</li>
+ <li><span style="color: #FF0000">Fixed:</span> Chord in PDF driver.</li>
</ul>
<h3><a href="http://sourceforge.net/projects/canvasdraw/files/5.3/">Version 5.3</a> (26/Jan/2010)</h3>
<ul>
diff --git a/html/en/home.html b/html/en/home.html
index e5c2968..07f79ab 100644
--- a/html/en/home.html
+++ b/html/en/home.html
@@ -11,7 +11,7 @@
<div class="homeTitle">CD</div>
<div class="homeDescription">Canvas Draw, A 2D Graphics Library</div>
-<div class="homeVersion">Version 5.3</div>
+<div class="homeVersion">Version 5.4</div>
<hr>
<p><strong>CD</strong> (Canvas Draw) is a platform-independent graphics library. It is implemented in several
diff --git a/html/wb/wb_usr.lua b/html/wb/wb_usr.lua
index c7b3d4e..dc9ea95 100644
--- a/html/wb/wb_usr.lua
+++ b/html/wb/wb_usr.lua
@@ -12,7 +12,7 @@ wb_usr = {
wb_usr.messages = {
en = {
- bar_title = "CD - Version 5.3",
+ bar_title = "CD - Version 5.4",
title = "CD - Canvas Draw",
}
}
@@ -1007,6 +1007,10 @@ wb_usr.tree =
name= {nl= "MF"},
link= "drv/mf.html"
},
+ {
+ name= {nl= "DEBUG"},
+ link= "drv/debug.html"
+ },
{ link= "", name= {en= "" } },
{
name= {nl= "CGM"},
@@ -1029,10 +1033,6 @@ wb_usr.tree =
name= {nl= "WMF"},
link= "drv/wmf.html"
},
- {
- name= {nl= "DEBUG"},
- link= "drv/debug.html"
- }
}
},
{
@@ -1040,11 +1040,7 @@ wb_usr.tree =
folder=
{
{
- name= {en= "Simulation"},
- link= "drv/sim.html"
- },
- {
- name= {en= "GDK/Cairo"},
+ name= {en= "GDK"},
link= "drv/gdk.html"
},
{
@@ -1052,13 +1048,28 @@ wb_usr.tree =
link= "drv/win32.html"
},
{
- name= {nl= "Win32 GDI+"},
- link= "drv/gdiplus.html"
- },
- {
name= {nl= "X-Win"},
link= "drv/xwin.html"
},
+ { link= "", name= {en= "" } },
+ {
+ name= {en= "Simulation"},
+ link= "drv/sim.html"
+ },
+ }
+ },
+ {
+ name= {en= "Context Plus"},
+ folder=
+ {
+ {
+ name= {en= "Cairo"},
+ link= "drv/cairo.html"
+ },
+ {
+ name= {nl= "GDI+"},
+ link= "drv/gdiplus.html"
+ },
{
name= {nl= "XRender"},
link= "drv/xrender.html"
diff --git a/html/wb_search.txt b/html/wb_search.txt
index a8b5c89..c5755bf 100644
--- a/html/wb_search.txt
+++ b/html/wb_search.txt
@@ -5,11 +5,12 @@ en/func/wd.html
en/func/client.html
en/func/region.html
en/drv/sim.html
+en/drv/xrender.html
en/drv/native.html
en/func/control.html
-en/drv/xrender.html
-en/drv/irgb.html
en/drv/gdiplus.html
+en/drv/cairo.html
+en/drv/irgb.html
en/func/vectortext.html
en/cvs.html
en/func/init.html
diff --git a/html/wb_title.html b/html/wb_title.html
index 577b087..2c1fec0 100644
--- a/html/wb_title.html
+++ b/html/wb_title.html
@@ -35,7 +35,7 @@ a.contact:hover {
<table style="width: 100%" cellspacing="0" cellpadding="0">
<tr>
<td style="width: 50px;"><img src="logo.gif"></td>
- <td class="title">CD - Version 5.3</td>
+ <td class="title">CD - Version 5.4</td>
<td style="width: 3.5em">
<a class="contact" href="ssSearch.html">SimpleSearch</a>
</td>
diff --git a/html/wb_tree.html b/html/wb_tree.html
index ed2fbb6..8de3575 100644
--- a/html/wb_tree.html
+++ b/html/wb_tree.html
@@ -526,23 +526,28 @@
<p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link196folder.6.4" href="en/drv/ps.html">PS</a></p>
<p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link197folder.6.4" href="en/drv/svg.html">SVG</a></p>
<p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link198folder.6.4" href="en/drv/mf.html">MF</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link199folder.6.4" href="en/drv/debug.html">DEBUG</a></p>
<p class="sep"><img src="wb_img/sepblank.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link199folder.6.4" href="en/drv/cgm.html">CGM</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link200folder.6.4" href="en/drv/dgn.html">DGN</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link201folder.6.4" href="en/drv/dxf.html">DXF</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link200folder.6.4" href="en/drv/cgm.html">CGM</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link201folder.6.4" href="en/drv/dgn.html">DGN</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link202folder.6.4" href="en/drv/dxf.html">DXF</a></p>
<p class="sep"><img src="wb_img/sepblank.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link202folder.6.4" href="en/drv/emf.html">EMF</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link203folder.6.4" href="en/drv/wmf.html">WMF</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link204folder.6.4" href="en/drv/debug.html">DEBUG</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link203folder.6.4" href="en/drv/emf.html">EMF</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link204folder.6.4" href="en/drv/wmf.html">WMF</a></p>
</div>
- <p><img src="wb_img/blank.png"><img name="imgfolder.6.5" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.6.5')"> Base Drivers</p>
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.5" src="wb_img/plusnode.png" onclick="toggleFolder('folder.6.5')"> Base Drivers</p>
<div id="folder.6.5">
- <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link205folder.6.5" href="en/drv/sim.html">Simulation</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link206folder.6.5" href="en/drv/gdk.html">GDK/Cairo</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link207folder.6.5" href="en/drv/win32.html">Win32</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link208folder.6.5" href="en/drv/gdiplus.html">Win32 GDI+</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link209folder.6.5" href="en/drv/xwin.html">X-Win</a></p>
- <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link210folder.6.5" href="en/drv/xrender.html">XRender</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link205folder.6.5" href="en/drv/gdk.html">GDK</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link206folder.6.5" href="en/drv/win32.html">Win32</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/node.png"><a class="el" name="link207folder.6.5" href="en/drv/xwin.html">X-Win</a></p>
+ <p class="sep"><img src="wb_img/sepblank.png"><img src="wb_img/sepvertline.png"><img src="wb_img/sepnode.png"></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/vertline.png"><img src="wb_img/nodelast.png"><a class="el" name="link208folder.6.5" href="en/drv/sim.html">Simulation</a></p>
+ </div>
+ <p><img src="wb_img/blank.png"><img name="imgfolder.6.6" src="wb_img/plusnodelast.png" onclick="toggleFolder('folder.6.6')"> Context Plus</p>
+ <div id="folder.6.6">
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link209folder.6.6" href="en/drv/cairo.html">Cairo</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/node.png"><a class="el" name="link210folder.6.6" href="en/drv/gdiplus.html">GDI+</a></p>
+ <p><img src="wb_img/blank.png"><img src="wb_img/blank.png"><img src="wb_img/nodelast.png"><a class="el" name="link211folder.6.6" href="en/drv/xrender.html">XRender</a></p>
</div>
</div>
</div>
diff --git a/include/cd.h b/include/cd.h
index 8d3826c..1dc90c0 100644
--- a/include/cd.h
+++ b/include/cd.h
@@ -116,6 +116,7 @@ void cdCanvasMark(cdCanvas* canvas, int x, int y);
void cdCanvasLine(cdCanvas* canvas, int x1, int y1, int x2, int y2);
void cdCanvasBegin(cdCanvas* canvas, int mode);
void cdCanvasVertex(cdCanvas* canvas, int x, int y);
+void cdCanvasPathSet(cdCanvas* canvas, int action);
void cdCanvasEnd(cdCanvas* canvas);
void cdCanvasRect(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax);
void cdCanvasBox(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax);
@@ -271,11 +272,25 @@ enum { /* polygon mode (begin...end) */
CD_CLOSED_LINES,
CD_CLIP,
CD_BEZIER,
- CD_REGION
+ CD_REGION,
+ CD_PATH
};
#define CD_POLYCUSTOM 10
+enum { /* path actions */
+ CD_PATH_NEW,
+ CD_PATH_MOVETO,
+ CD_PATH_LINETO,
+ CD_PATH_ARC,
+ CD_PATH_CURVETO,
+ CD_PATH_CLOSE,
+ CD_PATH_FILL,
+ CD_PATH_STROKE,
+ CD_PATH_FILLSTROKE,
+ CD_PATH_CLIP
+};
+
enum { /* fill mode */
CD_EVENODD,
CD_WINDING
diff --git a/include/cd_private.h b/include/cd_private.h
index a70469c..742750e 100644
--- a/include/cd_private.h
+++ b/include/cd_private.h
@@ -215,6 +215,11 @@ struct _cdCanvas
cdfPoint* fpoly; /* used during an real poligon creation, only if ->fPoly exists */
int use_fpoly;
+ /* last path */
+ int path_n, /* current number of actions */
+ path_size; /* allocated number of actions, only increases */
+ int* path; /* used during path creation */
+
/* simulation flags */
int sim_mode;
int sim_poly;
diff --git a/mak.vc9/cdxrender.vcproj b/mak.vc9/cdxrender.vcproj
index c69927d..e5b9a40 100644
--- a/mak.vc9/cdxrender.vcproj
+++ b/mak.vc9/cdxrender.vcproj
@@ -41,7 +41,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\xrender;..\src\sim;C:\cygwin\usr\X11R6\include\;C:\LNG\x11inc;..\..\iup\include;..\src\freetype2"
+ AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\xrender;..\src\sim;C:\cygwin17\usr\X11R6\include\;D:\LNG\x11inc;..\..\iup\include;..\src\freetype2"
PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,CD_NO_OLD_INTERFACE,_CRT_SECURE_NO_DEPRECATE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
diff --git a/src/cairo/cdcairo.c b/src/cairo/cdcairo.c
index 6b536a4..286d5ad 100644
--- a/src/cairo/cdcairo.c
+++ b/src/cairo/cdcairo.c
@@ -79,7 +79,7 @@ char* StrConvertToUTF8(cdCtxCanvas *ctxcanvas, const char* str, int length)
return (char*)str;
}
-static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill)
{
if (fill == 0 || ctxcanvas->canvas->interior_style == CD_SOLID)
{
@@ -320,7 +320,6 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
cairo_t* cr;
hatch_surface = cairo_surface_create_similar(cairo_get_target(ctxcanvas->cr), CAIRO_CONTENT_COLOR_ALPHA, hsize, hsize);
-
cr = cairo_create(hatch_surface);
if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
@@ -576,7 +575,7 @@ static void cdclear(cdCtxCanvas* ctxcanvas)
static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, x1, y1);
cairo_line_to(ctxcanvas->cr, x2, y2);
@@ -608,7 +607,7 @@ static void sFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
sFixAngles(ctxcanvas, &a1, &a2);
@@ -639,7 +638,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
sFixAngles(ctxcanvas, &a1, &a2);
@@ -673,15 +672,14 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
sFixAngles(ctxcanvas, &a1, &a2);
if (w == h)
{
cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
- cairo_fill_preserve(ctxcanvas->cr);
- cairo_stroke(ctxcanvas->cr);
+ cairo_fill(ctxcanvas->cr);
}
else /* Ellipse: change the scale to create from the circle */
{
@@ -693,8 +691,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
cairo_translate(ctxcanvas->cr, -xc, -yc);
cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
- cairo_fill_preserve(ctxcanvas->cr);
- cairo_stroke(ctxcanvas->cr);
+ cairo_fill(ctxcanvas->cr);
cairo_restore(ctxcanvas->cr); /* restore from local */
}
@@ -707,7 +704,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double
static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
cairo_stroke(ctxcanvas->cr);
}
@@ -719,7 +716,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma
static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
cairo_fill(ctxcanvas->cr);
}
@@ -806,7 +803,7 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i
cairo_set_font_matrix(ctxcanvas->cr, &matrix);
}
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, x, y);
cairo_show_text(ctxcanvas->cr, s);
@@ -844,9 +841,102 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ cairo_new_path(ctxcanvas->cr);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ cairo_new_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ 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;
+
+ sFixAngles(ctxcanvas, &a1, &a2);
+
+ if (w == h)
+ {
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Ellipse: change the scale to create from the circle */
+ {
+ cairo_save(ctxcanvas->cr); /* save to use the local transform */
+
+ cairo_translate(ctxcanvas->cr, xc, yc);
+ 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);
+
+ cairo_restore(ctxcanvas->cr); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ cairo_curve_to(ctxcanvas->cr, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ cairo_close_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill(ctxcanvas->cr);
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill_preserve(ctxcanvas->cr);
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_CLIP:
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_clip(ctxcanvas->cr);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_EVEN_ODD);
@@ -854,7 +944,7 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_WINDING);
}
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y);
@@ -904,9 +994,102 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ cairo_new_path(ctxcanvas->cr);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ cairo_new_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ 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;
+
+ sFixAngles(ctxcanvas, &a1, &a2);
+
+ if (w == h)
+ {
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Ellipse: change the scale to create from the circle */
+ {
+ cairo_save(ctxcanvas->cr); /* save to use the local transform */
+
+ cairo_translate(ctxcanvas->cr, xc, yc);
+ 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);
+
+ cairo_restore(ctxcanvas->cr); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ cairo_curve_to(ctxcanvas->cr, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ cairo_close_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill(ctxcanvas->cr);
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill_preserve(ctxcanvas->cr);
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_CLIP:
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_clip(ctxcanvas->cr);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_EVEN_ODD);
@@ -914,7 +1097,7 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_WINDING);
}
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y);
@@ -1476,6 +1659,31 @@ static cdAttribute aa_attrib =
get_aa_attrib
};
+static void set_pattern_image_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ if (data)
+ {
+ cdCtxImage *ctximage = (cdCtxImage *)data;
+
+ if (ctxcanvas->pattern)
+ cairo_pattern_destroy(ctxcanvas->pattern);
+
+ ctxcanvas->pattern = cairo_pattern_create_for_surface(cairo_get_target(ctximage->cr));
+ cairo_pattern_reference(ctxcanvas->pattern);
+ cairo_pattern_set_extend(ctxcanvas->pattern, CAIRO_EXTEND_REPEAT);
+
+ cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern);
+ ctxcanvas->last_source = 1;
+ }
+}
+
+static cdAttribute pattern_image_attrib =
+{
+ "PATTERNIMAGE",
+ set_pattern_image_attrib,
+ NULL
+};
+
static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data)
{
if (data)
@@ -1698,6 +1906,7 @@ cdCtxCanvas *cdcairoCreateCanvas(cdCanvas* canvas, cairo_t* cr)
cdRegisterAttribute(canvas, &interp_attrib);
cdRegisterAttribute(canvas, &cairodc_attrib);
cdRegisterAttribute(canvas, &hatchboxsize_attrib);
+ cdRegisterAttribute(canvas, &pattern_image_attrib);
cairo_save(ctxcanvas->cr);
cairo_set_operator(ctxcanvas->cr, CAIRO_OPERATOR_OVER);
@@ -1759,9 +1968,3 @@ void cdcairoInitTable(cdCanvas* canvas)
canvas->cxPutImageRectMap = cdputimagerectmap;
canvas->cxPutImageRectRGBA = cdputimagerectrgba;
}
-
-/*
-cairo_arc (cr, 128.0, 128.0, 76.8, 0, 2*M_PI);
-cairo_clip (cr);
-cairo_new_path (cr); // path not consumed by clip()
-*/
diff --git a/src/cairo/cdcaironative_win32.c b/src/cairo/cdcaironative_win32.c
index b685d12..e0b860e 100644
--- a/src/cairo/cdcaironative_win32.c
+++ b/src/cairo/cdcaironative_win32.c
@@ -143,7 +143,7 @@ static void cdinittable(cdCanvas* canvas)
static cdContext cdNativeWindowContext =
{
- CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE | CD_CAP_FPRIMTIVES),
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE),
1,
cdcreatecanvas,
cdinittable,
diff --git a/src/cd.def b/src/cd.def
index f5ae417..eda5beb 100644
--- a/src/cd.def
+++ b/src/cd.def
@@ -361,6 +361,7 @@ EXPORTS
cdCanvasVectorTextDirection
cdCanvasVectorTextSize
cdCanvasVertex
+ cdCanvasPathSet
cdfCanvasGetClipArea
cdfCanvasArc
diff --git a/src/cd_primitives.c b/src/cd_primitives.c
index b1a19ba..71e0fcd 100644
--- a/src/cd_primitives.c
+++ b/src/cd_primitives.c
@@ -123,12 +123,15 @@ void cdCanvasBegin(cdCanvas* canvas, int mode)
assert(mode>=CD_FILL);
if (!_cdCheckCanvas(canvas)) return;
+ canvas->use_fpoly = -1;
+ canvas->poly_n = 0;
+ canvas->path_n = 0;
+
if (mode == CD_REGION)
{
if (!canvas->cxNewRegion) return;
canvas->new_region = 1;
- canvas->poly_n = 0;
canvas->cxNewRegion(canvas->ctxcanvas);
return;
}
@@ -147,8 +150,6 @@ void cdCanvasBegin(cdCanvas* canvas, int mode)
if (mode == CD_FILL && canvas->sim_mode & CD_SIM_POLYGON)
canvas->sim_poly = 1;
- canvas->use_fpoly = -1;
- canvas->poly_n = 0;
canvas->poly_mode = mode;
}
@@ -233,6 +234,30 @@ void cdfCanvasVertex(cdCanvas* canvas, double x, double y)
canvas->poly_n++;
}
+void cdCanvasPathSet(cdCanvas* canvas, int action)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->poly_mode!=CD_PATH)
+ return;
+
+ if (!canvas->path)
+ {
+ canvas->path = (int*)malloc(sizeof(int)*(_CD_POLY_BLOCK+1));
+ canvas->path_size = _CD_POLY_BLOCK;
+ }
+
+ if (canvas->path_n == canvas->path_size)
+ {
+ canvas->path_size += _CD_POLY_BLOCK;
+ canvas->path = (int*)realloc(canvas->path, sizeof(int) * (canvas->path_size+1));
+ }
+
+ canvas->path[canvas->path_n] = action;
+ canvas->path_n++;
+}
+
void cdCanvasEnd(cdCanvas* canvas)
{
assert(canvas);
@@ -245,6 +270,13 @@ void cdCanvasEnd(cdCanvas* canvas)
return;
}
+ if (canvas->poly_mode==CD_PATH && canvas->poly_n < 2)
+ {
+ canvas->poly_n = 0;
+ canvas->path_n = 0;
+ return;
+ }
+
if (canvas->poly_mode==CD_OPEN_LINES && canvas->poly_n < 2)
{
canvas->poly_n = 0;
@@ -303,6 +335,7 @@ void cdCanvasEnd(cdCanvas* canvas)
}
}
+ canvas->path_n = 0;
canvas->poly_n = 0;
canvas->use_fpoly = -1;
}
diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c
index e6f3f73..eb9371f 100644
--- a/src/drv/cdpdf.c
+++ b/src/drv/cdpdf.c
@@ -138,7 +138,7 @@ static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
free(ctxcanvas);
}
-static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill)
{
if (fill == 0)
{
@@ -283,7 +283,7 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
PDF_moveto(ctxcanvas->pdf, x1, y1);
PDF_lineto(ctxcanvas->pdf, x2, y2);
@@ -297,7 +297,7 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
PDF_rect(ctxcanvas->pdf, xmin, ymin, xmax-xmin, ymax-ymin);
PDF_stroke(ctxcanvas->pdf);
@@ -310,7 +310,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma
static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
PDF_moveto(ctxcanvas->pdf, xmin, ymin);
PDF_lineto(ctxcanvas->pdf, xmax, ymin);
@@ -326,7 +326,7 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax
static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (w==h)
{
@@ -355,7 +355,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h)
{
@@ -386,12 +386,12 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h)
{
PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
- PDF_fill_stroke(ctxcanvas->pdf);
+ PDF_fill(ctxcanvas->pdf);
}
else /* Elipse: mudar a escala p/ criar a partir do circulo */
{
@@ -403,7 +403,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
PDF_translate(ctxcanvas->pdf, -xc, -yc);
PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
- PDF_fill_stroke(ctxcanvas->pdf);
+ PDF_fill(ctxcanvas->pdf);
PDF_restore(ctxcanvas->pdf); /* restore from local */
}
@@ -537,10 +537,94 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ PDF_endpath(ctxcanvas->pdf);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ PDF_endpath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ 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 (w==h)
+ 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 */
+
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, w/h, 1);
+ PDF_translate(ctxcanvas->pdf, -xc, -yc);
+
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ PDF_closepath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILL:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill(ctxcanvas->pdf);
+ break;
+ case CD_PATH_STROKE:
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILLSTROKE:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_CLIP:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_clip(ctxcanvas->pdf);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (mode==CD_FILL)
{
@@ -599,10 +683,94 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ PDF_endpath(ctxcanvas->pdf);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ PDF_endpath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ 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 (w==h)
+ 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 */
+
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, w/h, 1);
+ PDF_translate(ctxcanvas->pdf, -xc, -yc);
+
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ PDF_closepath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILL:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill(ctxcanvas->pdf);
+ break;
+ case CD_PATH_STROKE:
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILLSTROKE:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_CLIP:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_clip(ctxcanvas->pdf);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (mode==CD_FILL)
{
diff --git a/src/drv/cdps.c b/src/drv/cdps.c
index c54c95a..ce45397 100644
--- a/src/drv/cdps.c
+++ b/src/drv/cdps.c
@@ -64,6 +64,7 @@ struct _cdCtxCanvas
int level1; /* if true generates level 1 only function calls */
int landscape; /* page orientation */
int debug; /* print debug strings in the file */
+
float rotate_angle;
int rotate_center_x,
rotate_center_y;
@@ -73,7 +74,6 @@ struct _cdCtxCanvas
int poly_holes[500];
int holes;
-
};
/*
@@ -396,7 +396,7 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style);
static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple);
static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern);
-static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill)
{
if (fill == 0)
{
@@ -504,7 +504,7 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
fprintf(ctxcanvas->file, "N %d %d %d %d LL\n", x1, y1, x2, y2);
@@ -517,7 +517,7 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
fprintf(ctxcanvas->file, "N %g %g %g %g LL\n", x1, y1, x2, y2);
@@ -530,7 +530,7 @@ static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, dou
static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (ctxcanvas->level1)
{
@@ -553,7 +553,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma
static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (ctxcanvas->level1)
{
@@ -576,7 +576,7 @@ static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymi
static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->level1)
{
@@ -599,7 +599,7 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax
static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->level1)
{
@@ -622,7 +622,7 @@ static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin
static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -654,7 +654,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -686,7 +686,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl
static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -727,7 +727,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -768,7 +768,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do
static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -806,7 +806,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -849,7 +849,7 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len)
int i;
int ascent, height, baseline;
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL);
baseline = height - ascent;
@@ -960,30 +960,242 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len)
if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n");
}
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len)
+{
+ int i;
+ int ascent, height, baseline;
+
+ sUpdateFill(ctxcanvas, 0);
+
+ cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdText Begin\n");
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ set_default_matrix(ctxcanvas);
+
+ fprintf(ctxcanvas->file, "N 0 0 M\n");
+ putc('(', ctxcanvas->file);
+
+ for (i=0; i<len; i++)
+ {
+ if (s[i]=='(' || s[i]==')')
+ putc('\\', ctxcanvas->file);
+ putc(s[i], ctxcanvas->file);
+ }
+
+ fprintf(ctxcanvas->file, ")\n");
+ fprintf(ctxcanvas->file, "dup true charpath\n");
+ fprintf(ctxcanvas->file, "flattenpath\n");
+ fprintf(ctxcanvas->file, "pathbbox\n"); /* bbox na pilha: llx lly urx ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: llx lly ury urx */
+ fprintf(ctxcanvas->file, "4 1 roll\n"); /* roda: urx llx lly ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: urx llx ury lly */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: urx llx h */
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: h urx llx */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: h w */
+ fprintf(ctxcanvas->file, "0 0\n"); /* empilha: h w 0 0 */
+ fprintf(ctxcanvas->file, "4 -1 roll\n"); /* roda: w 0 0 h */
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ cdtransform(ctxcanvas, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL);
+
+ fprintf(ctxcanvas->file, "gsave\n"); /* save to use local transform */
+ fprintf(ctxcanvas->file, "%g %g translate\n", x, y);
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ fprintf(ctxcanvas->file, "%g rotate\n", ctxcanvas->canvas->text_orientation);
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em Y. topo da pilha: w x y h */
+ {
+ case CD_NORTH:
+ case CD_NORTH_EAST:
+ case CD_NORTH_WEST:
+ fprintf(ctxcanvas->file, "%d sub sub\n", baseline); /* empilha, subtrai, subtrai: w x y-(h-baseline) */
+ break;
+ case CD_EAST:
+ case CD_WEST:
+ case CD_CENTER:
+ fprintf(ctxcanvas->file, "2 div %d sub sub\n", baseline); /* empilha, divide, empilha, subtrai, subtrai: w x y-(h/2-baseline) */
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH:
+ case CD_SOUTH_WEST:
+ fprintf(ctxcanvas->file, "pop %d add\n", baseline); /* desempilha, empilha, adiciona: w x y+baseline */
+ break;
+ case CD_BASE_RIGHT:
+ case CD_BASE_CENTER:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha h: w x y */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: y' w x */
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: y' x w */
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em X, topo da pilha: x w */
+ {
+ case CD_NORTH:
+ case CD_SOUTH:
+ case CD_CENTER:
+ case CD_BASE_CENTER:
+ fprintf(ctxcanvas->file, "2 div sub\n"); /* empilha, divide, subtrai: y' x-w/2 */
+ break;
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ case CD_BASE_RIGHT:
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: y' x-w */
+ break;
+ case CD_SOUTH_WEST:
+ case CD_WEST:
+ case CD_NORTH_WEST:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha: y' x */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: x' y' */
+ fprintf(ctxcanvas->file, "M\n"); /* moveto */
+
+ fprintf(ctxcanvas->file, "show\n");
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ s = cdStrDupN(s, len);
+ cdCanvasGetTextBox(ctxcanvas->canvas, (int)x, (int)y, s, &xmin, &xmax, &ymin, &ymax);
+ free((char*)s);
+ fbbox(ctxcanvas, (double)xmin, (double)ymin);
+ fbbox(ctxcanvas, (double)xmax, (double)ymax);
+ }
+
+ fprintf(ctxcanvas->file, "grestore\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n");
+}
+
static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
{
int i;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ fprintf(ctxcanvas->file, "newpath\n");
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ fprintf(ctxcanvas->file, "newpath\n");
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%d %d M\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%d %d L\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ 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 (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */
+ 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, "setmatrix\n"); /* back to CTM */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d B\n", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "closepath\n");
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ fprintf(ctxcanvas->file, "gsave\n");
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ fprintf(ctxcanvas->file, "grestore\n");
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_CLIP:
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_CLIP)
{
if (ctxcanvas->eps) /* initclip not allowed in EPS */
return;
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
-
fprintf(ctxcanvas->file, "/clip_polygon {\n");
fprintf(ctxcanvas->file, "initclip\n");
}
else
{
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
-
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+ sUpdateFill(ctxcanvas, 0);
}
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+
fprintf(ctxcanvas->file, "N\n");
fprintf(ctxcanvas->file, "%d %d M\n", poly[0].x, poly[0].y);
@@ -1061,26 +1273,122 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
{
int i, hole_index = 0;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ fprintf(ctxcanvas->file, "newpath\n");
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ fprintf(ctxcanvas->file, "newpath\n");
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%g %g M\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%g %g L\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ 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 (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */
+ 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, "setmatrix\n"); /* back to CTM */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "%g %g %g %g %g %g B\n", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "closepath\n");
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ fprintf(ctxcanvas->file, "gsave\n");
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ fprintf(ctxcanvas->file, "grestore\n");
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_CLIP:
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_CLIP)
{
if (ctxcanvas->eps) /* initclip not allowed in EPS */
return;
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
-
fprintf(ctxcanvas->file, "/clip_polygon {\n");
fprintf(ctxcanvas->file, "initclip\n");
}
else
{
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
-
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+ sUpdateFill(ctxcanvas, 0);
}
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+
fprintf(ctxcanvas->file, "N\n");
fprintf(ctxcanvas->file, "%g %g M\n", poly[0].x, poly[0].y);
@@ -1752,7 +2060,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)
static void cdinittable(cdCanvas* canvas)
{
canvas->cxFlush = cdflush;
+
canvas->cxPixel = cdpixel;
+
canvas->cxLine = cdline;
canvas->cxPoly = cdpoly;
canvas->cxRect = cdrect;
@@ -1761,8 +2071,10 @@ static void cdinittable(cdCanvas* canvas)
canvas->cxSector = cdsector;
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+
canvas->cxPutImageRectRGB = cdputimagerectrgb;
canvas->cxPutImageRectMap = cdputimagerectmap;
+
canvas->cxFLine = cdfline;
canvas->cxFPoly = cdfpoly;
canvas->cxFRect = cdfrect;
@@ -1770,6 +2082,8 @@ static void cdinittable(cdCanvas* canvas)
canvas->cxFArc = cdfarc;
canvas->cxFSector = cdfsector;
canvas->cxFChord = cdfchord;
+ canvas->cxFText = cdftext;
+
canvas->cxClip = cdclip;
canvas->cxFClipArea = cdfcliparea;
canvas->cxLineStyle = cdlinestyle;
diff --git a/src/gdiplus/cdwdbufp.cpp b/src/gdiplus/cdwdbufp.cpp
index 95cfe2e..87957fb 100644
--- a/src/gdiplus/cdwdbufp.cpp
+++ b/src/gdiplus/cdwdbufp.cpp
@@ -120,7 +120,7 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)
bitmap->SetResolution((REAL)(canvas_dbuffer->xres*25.4), (REAL)(canvas_dbuffer->yres*25.4));
Graphics imggraphics(bitmap);
- imggraphics.Clear(Color::White);
+ imggraphics.Clear(Color((ARGB)Color::White));
Graphics* graphics = new Graphics(bitmap);
diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp
index ea14628..a8d3f9c 100644
--- a/src/gdiplus/cdwinp.cpp
+++ b/src/gdiplus/cdwinp.cpp
@@ -51,10 +51,10 @@ void cdwpShowStatus(const char* title, Status status)
void cdwpKillCanvas(cdCtxCanvas* ctxcanvas)
{
if (ctxcanvas->clip_poly) delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_fpoly) delete[] ctxcanvas->clip_fpoly;
if (ctxcanvas->clip_region) delete ctxcanvas->clip_region;
if (ctxcanvas->new_region) delete ctxcanvas->new_region;
if (ctxcanvas->font) delete ctxcanvas->font;
- if (ctxcanvas->wdpoly) delete ctxcanvas->wdpoly;
delete ctxcanvas->fillBrush;
delete ctxcanvas->lineBrush;
@@ -245,7 +245,10 @@ static void sClipPoly(cdCtxCanvas* ctxcanvas)
GraphicsPath path;
path.SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
- path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
+ if (ctxcanvas->clip_fpoly)
+ path.AddPolygon(ctxcanvas->clip_fpoly, ctxcanvas->clip_poly_n);
+ else
+ path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
ctxcanvas->clip_region = new Region(&path);
ctxcanvas->graphics->SetClip(ctxcanvas->clip_region);
@@ -572,6 +575,12 @@ static void cdline(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
ctxcanvas->dirty = 1;
}
+static void cdfline(cdCtxCanvas* ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ ctxcanvas->graphics->DrawLine(ctxcanvas->linePen, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
+ ctxcanvas->dirty = 1;
+}
+
static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
Rect rect(xmin, ymin, xmax-xmin, ymax-ymin); // in this case Size = Max - Min
@@ -579,6 +588,13 @@ static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int yma
ctxcanvas->dirty = 1;
}
+static void cdfrect(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ RectF rect((REAL)xmin, (REAL)ymin, (REAL)(xmax-xmin), (REAL)(ymax-ymin)); // in this case Size = Max - Min
+ ctxcanvas->graphics->DrawRectangle(ctxcanvas->linePen, rect);
+ ctxcanvas->dirty = 1;
+}
+
static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1);
@@ -594,6 +610,21 @@ static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax
}
}
+static void cdfbox(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ RectF rect((REAL)xmin, (REAL)ymin, (REAL)(xmax-xmin+1), (REAL)(ymax-ymin+1));
+ if (ctxcanvas->canvas->new_region)
+ {
+ Region region(rect);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ ctxcanvas->graphics->FillRectangle(ctxcanvas->fillBrush, rect);
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
{
if (ctxcanvas->canvas->invert_yaxis)
@@ -617,6 +648,19 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a
ctxcanvas->dirty = 1;
}
+static void cdfarc(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (angle1 == 0 && angle2 == 360)
+ ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+}
+
static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
Rect rect(xc - w/2, yc - h/2, w, h);
@@ -653,6 +697,42 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
}
}
+static void cdfsector(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ // complete the remaining pixels using an Arc
+ Pen pen(ctxcanvas->fillBrush);
+
+ if (angle1==0 && angle2==360)
+ {
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ ctxcanvas->graphics->DrawEllipse(&pen, rect);
+ }
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
Rect rect(xc - w/2, yc - h/2, w, h);
@@ -687,10 +767,135 @@ static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
}
}
+static void cdfchord(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ path.CloseFigure();
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ if (angle1==0 && angle2==360)
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ else
+ {
+ GraphicsPath path;
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path);
+ }
+ Pen pen(ctxcanvas->fillBrush); // complete the remaining pixels using an Arc
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
{
- switch( mode )
+ switch (mode)
{
+ case CD_PATH:
+ {
+ int p, i, current_x = 0, current_y = 0;
+ GraphicsPath* graphics_path;
+ PointF lastPoint;
+
+ /* starts a new path */
+ graphics_path = new GraphicsPath(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ graphics_path->Reset();
+ graphics_path->SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ graphics_path->AddLine(current_x, current_y, poly[i].x, poly[i].y);
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ Rect rect(xc - w/2, yc - h/2, w, h);
+ if (a1 == 0 && a2 == 360)
+ graphics_path->AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &a1, &a2);
+ graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
+ }
+
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = (int)lastPoint.X;
+ current_y = (int)lastPoint.Y;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ graphics_path->AddBezier(current_x, current_y, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = (int)lastPoint.X;
+ current_y = (int)lastPoint.Y;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ graphics_path->CloseFigure();
+ break;
+ case CD_PATH_FILL:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ break;
+ case CD_PATH_STROKE:
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_FILLSTROKE:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_CLIP:
+ ctxcanvas->graphics->SetClip(graphics_path, CombineModeIntersect);
+ break;
+ }
+ }
+
+ delete graphics_path;
+ break;
+ }
case CD_BEZIER:
if (n < 4) return;
ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (Point*)poly, n);
@@ -749,6 +954,11 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
if (ctxcanvas->clip_poly)
delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_fpoly)
+ {
+ delete[] ctxcanvas->clip_fpoly;
+ ctxcanvas->clip_fpoly = NULL;
+ }
ctxcanvas->clip_poly = new Point [n];
@@ -780,6 +990,223 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
ctxcanvas->dirty = 1;
}
+static PointF* sPolyToFloat(cdfPoint* poly, int n)
+{
+ PointF* fpoly = new PointF[n+1];
+
+ for (int i = 0; i < n; i++)
+ {
+ fpoly[i].X = (REAL)poly[i].x;
+ fpoly[i].Y = (REAL)poly[i].y;
+ }
+
+ return fpoly;
+}
+
+static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ PointF* fpoly = NULL;
+
+ switch (mode)
+ {
+ case CD_PATH:
+ {
+ int p, i;
+ double current_x = 0, current_y = 0;
+ GraphicsPath* graphics_path;
+ PointF lastPoint;
+
+ /* starts a new path */
+ graphics_path = new GraphicsPath(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ graphics_path->Reset();
+ graphics_path->SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ graphics_path->AddLine((REAL)current_x, (REAL)current_y, (REAL)poly[i].x, (REAL)poly[i].y);
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (a1 == 0 && a2 == 360)
+ graphics_path->AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &a1, &a2);
+ graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
+ }
+
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = lastPoint.X;
+ current_y = lastPoint.Y;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ graphics_path->AddBezier((REAL)current_x, (REAL)current_y, (REAL)poly[i].x, (REAL)poly[i].y, (REAL)poly[i+1].x, (REAL)poly[i+1].y, (REAL)poly[i+2].x, (REAL)poly[i+2].y);
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = lastPoint.X;
+ current_y = lastPoint.Y;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ graphics_path->CloseFigure();
+ break;
+ case CD_PATH_FILL:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ break;
+ case CD_PATH_STROKE:
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_FILLSTROKE:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_CLIP:
+ ctxcanvas->graphics->SetClip(graphics_path, CombineModeIntersect);
+ break;
+ }
+ }
+
+ delete graphics_path;
+ break;
+ }
+ case CD_BEZIER:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_FILLSPLINE:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddClosedCurve((PointF*)fpoly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillClosedCurve(ctxcanvas->fillBrush, (PointF*)fpoly, n);
+ break;
+ case CD_SPLINE:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawClosedCurve(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_CLOSED_LINES:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawLines(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_FILLGRADIENT:
+ {
+ int count = n;
+ PathGradientBrush* brush = new PathGradientBrush((PointF*)fpoly, n);
+ fpoly = sPolyToFloat(poly, n);
+ brush->SetSurroundColors(ctxcanvas->pathGradient, &count);
+ brush->SetCenterColor(ctxcanvas->pathGradient[n]);
+ ctxcanvas->graphics->FillPolygon(brush, (PointF*)fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ delete brush;
+ }
+ break;
+ case CD_FILL:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ fpoly = sPolyToFloat(poly, n);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddPolygon((PointF*)fpoly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillPolygon(ctxcanvas->fillBrush, (PointF*)fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_CLIP:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+
+ if (ctxcanvas->clip_fpoly)
+ delete[] ctxcanvas->clip_fpoly;
+ if (ctxcanvas->clip_poly)
+ {
+ delete[] ctxcanvas->clip_poly;
+ ctxcanvas->clip_poly = NULL;
+ }
+
+ ctxcanvas->clip_fpoly = new PointF [n];
+
+ cdfPoint* pnt = poly;
+ int t = n;
+ int nc = 1;
+
+ ctxcanvas->clip_fpoly[0].X = (REAL)pnt->x;
+ ctxcanvas->clip_fpoly[0].Y = (REAL)pnt->y;
+ pnt++;
+
+ for (int i = 1; i < t-1; i++, pnt++)
+ {
+ if (!(((REAL)pnt->x == ctxcanvas->clip_fpoly[nc-1].X && pnt->x == (pnt + 1)->x) ||
+ ((REAL)pnt->y == ctxcanvas->clip_fpoly[nc-1].Y && pnt->y == (pnt + 1)->y)))
+ {
+ ctxcanvas->clip_fpoly[nc].X = (REAL)pnt->x;
+ ctxcanvas->clip_fpoly[nc].Y = (REAL)pnt->y;
+ nc++;
+ }
+ }
+
+ ctxcanvas->clip_poly_n = nc;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ sClipPoly(ctxcanvas);
+
+ break;
+ }
+
+ if (fpoly)
+ delete[] fpoly;
+
+ ctxcanvas->dirty = 1;
+}
+
WCHAR* cdwpString2Unicode(const char* s, int len)
{
static WCHAR wstr[10240] = L"";
@@ -1654,7 +2081,7 @@ static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height)
ctximage->h_mm = ctximage->h / ctximage->yres;
Graphics imggraphics(ctximage->bitmap);
- imggraphics.Clear(Color::White);
+ imggraphics.Clear(Color((ARGB)Color::White));
return ctximage;
}
@@ -2248,6 +2675,7 @@ cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype)
canvas->invert_yaxis = 1;
ctxcanvas->clip_poly = NULL;
+ ctxcanvas->clip_fpoly = NULL;
ctxcanvas->clip_poly_n = 0;
ctxcanvas->clip_region = NULL;
ctxcanvas->new_region = NULL;
@@ -2303,6 +2731,7 @@ void cdwpInitTable(cdCanvas* canvas)
canvas->cxFlush = cdflush;
canvas->cxPixel = cdpixel;
+
canvas->cxLine = cdline;
canvas->cxPoly = cdpoly;
canvas->cxRect = cdrect;
@@ -2312,6 +2741,14 @@ void cdwpInitTable(cdCanvas* canvas)
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+
canvas->cxNewRegion = cdnewregion;
canvas->cxIsPointInRegion = cdispointinregion;
canvas->cxOffsetRegion = cdoffsetregion;
diff --git a/src/gdiplus/cdwinp.h b/src/gdiplus/cdwinp.h
index 0c4ae55..b42dc9a 100644
--- a/src/gdiplus/cdwinp.h
+++ b/src/gdiplus/cdwinp.h
@@ -48,15 +48,12 @@ struct _cdCtxCanvas
} fontinfo;
Point *clip_poly; /* coordenadas do pixel no X,Y */
+ PointF *clip_fpoly; /* coordenadas do pixel no X,Y */
int clip_poly_n; /* numero de pontos correntes */
Region *clip_region;
Region *new_region;
- int max_points;
- PointF *wdpoly; // cache buffer for wdpoly
- Point *cdpoly; // alias to cache buffer (float=int)
-
int antialias;
Point gradient[2];
diff --git a/src/svg/cdsvg.c b/src/svg/cdsvg.c
index 2441523..fd48559 100644
--- a/src/svg/cdsvg.c
+++ b/src/svg/cdsvg.c
@@ -101,11 +101,12 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode)
if (ctxcanvas->clip_polygon)
{
/* open clipping container */
- fprintf(ctxcanvas->file, "<g clip-path=\"url(#clippoly%d)\">\n", ctxcanvas->last_clip_poly);
+ fprintf(ctxcanvas->file, "<g clip-path=\"url(#clippoly%d)\" clip-rule:%s >\n", ctxcanvas->last_clip_poly, (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero");
ctxcanvas->clip_control = 1;
}
break;
}
+
return clip_mode;
}
@@ -407,7 +408,7 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int l
cdftext(ctxcanvas, (double)x, (double)y, text, len);
}
-static void write_points(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int close)
+static void sWritePointsF(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int close)
{
int i;
for(i = 0; i<n; i++)
@@ -416,27 +417,153 @@ static void write_points(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int clos
fprintf(ctxcanvas->file, "%g,%g ", poly[0].x, poly[0].y);
}
+static void sWritePoints(cdCtxCanvas *ctxcanvas, cdPoint* poly, int n, int close)
+{
+ int i;
+ for(i = 0; i<n; i++)
+ fprintf(ctxcanvas->file, "%d,%d ", poly[i].x, poly[i].y);
+ if (close)
+ fprintf(ctxcanvas->file, "%d,%d ", poly[0].x, poly[0].y);
+}
+
static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
{
char* rule;
+ if (mode == CD_PATH)
+ {
+ int i, p, clip_path = 0, end_path;
+
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP)
+ {
+ clip_path = 1;
+ break;
+ }
+ }
+
+ if (clip_path)
+ fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
+
+ /* starts a new path */
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ if (!end_path)
+ fprintf(ctxcanvas->file, "\" />\n");
+
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "M %g %g ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "L %g %g ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+ double arcStartX, arcStartY, arcEndX, arcEndY;
+ int largeArc = 0;
+
+ 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 (ctxcanvas->canvas->use_matrix) /* Transformation active */
+ {
+ double temp = 360 - a1;
+ a1 = 360 - a2;
+ a2 = temp;
+ }
+
+ arcStartX = (xc+(w/2)*cos(a1*CD_DEG2RAD));
+ arcStartY = (yc-(h/2)*sin(a1*CD_DEG2RAD));
+ arcEndX = (xc+(w/2)*cos(a2*CD_DEG2RAD));
+ arcEndY = (yc-(h/2)*sin(a2*CD_DEG2RAD));
+
+ if ((a2-a1) > 180.0)
+ largeArc = 1;
+
+ fprintf(ctxcanvas->file, "M %g %g A %g %g 0 %d 0 %g %g ",
+ arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY);
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "C %g %g %g %g %g %g ", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "Z ");
+ break;
+ case CD_PATH_FILL:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_STROKE:
+ fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_FILLSTROKE:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_CLIP:
+ fprintf(ctxcanvas->file, "\" />\n");
+ fprintf(ctxcanvas->file, "</clipPath>\n");
+ ctxcanvas->clip_polygon = 1;
+ cdclip(ctxcanvas, CD_CLIPPOLYGON);
+ end_path = 1;
+ break;
+ }
+ }
+ return;
+ }
+
switch (mode)
{
case CD_CLOSED_LINES:
fprintf(ctxcanvas->file, "<polygon style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
- write_points(ctxcanvas, poly, n, 1);
+ sWritePointsF(ctxcanvas, poly, n, 1);
fprintf(ctxcanvas->file, "\" />\n");
break;
case CD_OPEN_LINES:
fprintf(ctxcanvas->file, "<polyline style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
- write_points(ctxcanvas, poly, n, 0);
+ sWritePointsF(ctxcanvas, poly, n, 0);
fprintf(ctxcanvas->file, "\" />\n");
break;
case CD_BEZIER:
fprintf(ctxcanvas->file, "<path d=\"M%g,%g C", poly[0].x, poly[0].y);
- write_points(ctxcanvas, poly+1, n-1, 0);
+ sWritePointsF(ctxcanvas, poly+1, n-1, 0);
fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
break;
@@ -448,14 +575,14 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
fprintf(ctxcanvas->file, "<polygon style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" points=\"",
(ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
- write_points(ctxcanvas, poly, n, 0);
+ sWritePointsF(ctxcanvas, poly, n, 0);
fprintf(ctxcanvas->file, "\" />\n");
break;
case CD_CLIP:
fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
fprintf(ctxcanvas->file, "<polygon points=\"");
- write_points(ctxcanvas, poly, n, 0);
+ sWritePointsF(ctxcanvas, poly, n, 0);
fprintf(ctxcanvas->file, "\" />\n");
fprintf(ctxcanvas->file, "</clipPath>\n");
@@ -472,20 +599,174 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
{
- int i;
- cdfPoint* newPoly = NULL;
-
- newPoly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+1));
+ char* rule;
- for(i = 0; i < n; i++)
+ if (mode == CD_PATH)
{
- newPoly[i].x = (double)poly[i].x;
- newPoly[i].y = (double)poly[i].y;
+ int i, p, clip_path = 0, end_path;
+
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP)
+ {
+ clip_path = 1;
+ break;
+ }
+ }
+
+ if (clip_path)
+ fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
+
+ /* starts a new path */
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ if (!end_path)
+ fprintf(ctxcanvas->file, "\" />\n");
+
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "M %d %d ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "L %d %d ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+ int arcStartX, arcStartY, arcEndX, arcEndY;
+ int largeArc = 0;
+
+ 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 (ctxcanvas->canvas->use_matrix) /* Transformation active */
+ {
+ double temp = 360 - a1;
+ a1 = 360 - a2;
+ a2 = temp;
+ }
+
+ arcStartX = (int)(xc+(w/2)*cos(a1*CD_DEG2RAD));
+ arcStartY = (int)(yc-(h/2)*sin(a1*CD_DEG2RAD));
+ arcEndX = (int)(xc+(w/2)*cos(a2*CD_DEG2RAD));
+ arcEndY = (int)(yc-(h/2)*sin(a2*CD_DEG2RAD));
+
+ if ((a2-a1) > 180.0)
+ largeArc = 1;
+
+ fprintf(ctxcanvas->file, "M %d %d A %d %d 0 %d 0 %d %d ",
+ arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY);
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "C %d %d %d %d %d %d ", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "Z ");
+ break;
+ case CD_PATH_FILL:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_STROKE:
+ fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_FILLSTROKE:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_CLIP:
+ fprintf(ctxcanvas->file, "\" />\n");
+ fprintf(ctxcanvas->file, "</clipPath>\n");
+ ctxcanvas->clip_polygon = 1;
+ cdclip(ctxcanvas, CD_CLIPPOLYGON);
+ end_path = 1;
+ break;
+ }
+ }
+ return;
}
- cdfpoly(ctxcanvas, mode, (cdfPoint*)newPoly, n);
+ switch (mode)
+ {
+ case CD_CLOSED_LINES:
+ fprintf(ctxcanvas->file, "<polygon style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ sWritePoints(ctxcanvas, poly, n, 1);
+ fprintf(ctxcanvas->file, "\" />\n");
+ break;
+ case CD_OPEN_LINES:
+ fprintf(ctxcanvas->file, "<polyline style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ sWritePoints(ctxcanvas, poly, n, 0);
+ fprintf(ctxcanvas->file, "\" />\n");
+ break;
+ case CD_BEZIER:
+ fprintf(ctxcanvas->file, "<path d=\"M%g,%g C", poly[0].x, poly[0].y);
+ sWritePoints(ctxcanvas, poly+1, n-1, 0);
+ fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ break;
+ case CD_FILL:
+ if(ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ rule = "evenodd";
+ else
+ rule = "nonzero";
- free(newPoly);
+ fprintf(ctxcanvas->file, "<polygon style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" points=\"",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
+ sWritePoints(ctxcanvas, poly, n, 0);
+ fprintf(ctxcanvas->file, "\" />\n");
+ break;
+ case CD_CLIP:
+ fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
+
+ fprintf(ctxcanvas->file, "<polygon points=\"");
+ sWritePoints(ctxcanvas, poly, n, 0);
+ fprintf(ctxcanvas->file, "\" />\n");
+
+ fprintf(ctxcanvas->file, "</clipPath>\n");
+
+ ctxcanvas->clip_polygon = 1;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ cdclip(ctxcanvas, CD_CLIPPOLYGON);
+
+ break;
+
+ }
}
static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
diff --git a/src/win32/cdwin.c b/src/win32/cdwin.c
index da9bf9d..baaff13 100644
--- a/src/win32/cdwin.c
+++ b/src/win32/cdwin.c
@@ -697,7 +697,7 @@ typedef struct _winArcParam
YEndArc; /* second radial ending point */
} winArcParam;
-static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc)
+static void sCalcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc)
{
arc->LeftRect = xc - w/2;
arc->RightRect = xc + w/2 + 1;
@@ -727,7 +727,7 @@ static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
if (ctxcanvas->rebuild_pen)
sCreatePen(ctxcanvas);
@@ -738,7 +738,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;
- calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
(ctxcanvas->canvas->interior_style != CD_PATTERN) )
@@ -782,7 +782,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;
- calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
(ctxcanvas->canvas->interior_style != CD_PATTERN) )
@@ -829,6 +829,84 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
POINT* pnt;
HPEN oldPen = NULL, Pen = NULL;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ BeginPath(ctxcanvas->hDC);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ BeginPath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ MoveToEx(ctxcanvas->hDC, poly[i].x, poly[i].y, NULL);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ LineTo(ctxcanvas->hDC, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ 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;
+
+ sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arc);
+
+ Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc);
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ PolyBezierTo(ctxcanvas->hDC, (POINT*)(poly + i), 3);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ CloseFigure(ctxcanvas->hDC);
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ FillPath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ StrokePath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ StrokeAndFillPath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_CLIP:
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ SelectClipPath(ctxcanvas->hDC, RGN_AND);
+ break;
+ }
+ }
+ return;
+ }
+
switch( mode )
{
case CD_CLOSED_LINES:
@@ -2337,6 +2415,7 @@ void cdwInitTable(cdCanvas* canvas)
canvas->cxSector = cdsector;
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+
canvas->cxGetFontDim = cdgetfontdim;
canvas->cxGetTextSize = cdgettextsize;
canvas->cxPutImageRectRGB = cdputimagerectrgb;