diff options
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 "<strong>cdcairo</strong>" and "<strong>cairo</strong>". + When using the GDK base driver you do not need to link with the "<strong>cdcairo</strong>" + 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"cdluacontextplus"</strong> can be used when + using dynamic libraries.</p> <h3>Behavior of Functions</h3> <h4>Control </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>"<span class="style1"><strong>PATTERNIMAGE</strong></span>": 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>"<b><font face="Courier">POLYHOLE</font></b>": 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 "<strong><tt>GRADIENTCOLOR</tt></strong>" 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) -> (r, g, b: number) [in Lua]</pre> cd.EncodeAlpha(color: lightuserdata, alpha: number) -> (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) -> (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> </p> <ul> @@ -51,22 +53,28 @@ cd.CreateCanvas(ctx: number, data: string or userdata) -> (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> </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* <a name="cdCreateCanvasf">cdCreateCanvasf(cdContext *ctx, const char* format, ...)</a>; [in C] @@ -115,8 +123,8 @@ cd.UseContextPlus(use: boolean) -> (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 "ContextPlus" -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>, <a href="../drv/gdiplus.html">GDI+</a> +and <a href="../drv/xrender.html">XRender</a> base drivers.</p> <p>In Lua, when using require"cdluacontextplus" 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> </p> +"<span class="style1"><strong>PATH</strong></span>": 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>"BEGIN" - 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>"FILL" - closes the path, and fills it with the current fill attributes, + then the path is discarded</li> + <li>"STROKE" - strokes the path with the current line attributes, then the + path is discarded</li> + <li>"CLOSESTROKE" - closes the path, and strokes it with the current line + attributes, then the path is discarded</li> + <li>"FILLSTROKE" - 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>"CLIP" - 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>"NULL" - 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 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 "server" 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> "CMD", "OPACITY" and "HATCHBOXSIZE" 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, @@ -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; |