diff options
| author | scuri <scuri> | 2010-05-12 20:38:46 +0000 | 
|---|---|---|
| committer | scuri <scuri> | 2010-05-12 20:38:46 +0000 | 
| commit | b7d97c7ed82f0d0472cf0c2ae5d61e99a73b33a8 (patch) | |
| tree | 0da03500210df1ac835203e2bb83748564e67423 | |
| parent | afaff9e085b51c822f0ce31ac91cc8196bfa5113 (diff) | |
New Cairo driver
42 files changed, 3707 insertions, 255 deletions
diff --git a/html/en/drv/cairo.html b/html/en/drv/cairo.html new file mode 100644 index 0000000..4977258 --- /dev/null +++ b/html/en/drv/cairo.html @@ -0,0 +1,134 @@ +<!doctype HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + +<head> +<meta http-equiv="Content-Language" content="en-us"> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<title>CAIRO</title> +<link rel="stylesheet" type="text/css" href="../../style.css"> +</head> + +<body> + +<h2>CAIRO Base Driver</h2> + +  <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> +<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  +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> + +<h3>Behavior of Functions</h3> +<h4>Control  </h4> +<ul> +  <li><a href="../func/other.html#cdPlay"> +  <font face="Courier"><strong>Play</strong></font></a>: does nothing, returns +  <font face="Courier">CD_ERROR</font>. </li> +</ul> +<h4>Coordinate System and Clipping </h4> +<ul> +  <li> +  <a href="../func/coordinates.html#cdUpdateYAxis"> +  <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>Attributes </h4> +<ul> +  <li> +  <a href="http://www.tecgraf.puc-rio.br/cd/en/func/attributes.html#cdWriteMode"> +  <font face="Courier"><strong>WriteMode</strong></font></a>: does nothing.  +  There is no support for XOR or NOT_XOR.</li> +  <li> +  <a href="../func/text.html#cdNativeFont"> +  <font face="Courier"><strong>NativeFont</strong></font></a>: also accepts the  +  X-Windows font string format.</li> +    <li><a href="../func/text.html#cdFont"> +  <font face="Courier"><strong>Font</strong></font></a>: "Courier" is mapped to  +	"Courier New", "Helvetica" is mapped to "Arial", and "Times" is mapped to  +	"Times New Roman". Underline and Strikeout are NOT supported.</li> +</ul> +<h4>Colors </h4> +<ul> +  <li> +  <a href="../func/color.html#cdPalette"> +  <font face="Courier"><strong>Palette</strong></font></a>: NOT supported.</li> +</ul> +<h4>Exclusive Attributes</h4> + +<ul> +  <li>"<b><font face="Courier">ANTIALIAS</font></b>": controls  +  the use of anti-aliasing for the text and drawing shapes. Assumes values "1"  +  (active) and "0" (inactive). Default value: "1".</li> +</ul> + +<ul> +  <li>"<b><font face="Courier">CAIRODC</font></b>": returns the  +  Cairo drawing context (get only). In Lua is returned as a user data.</li> +</ul> + +<ul> +    <li><b><font face="Courier">"CAIROVERSION": </font></b>returns a string with  +  the Cairo version number. It is empty if the Cairo is not available.</li> +</ul> + +<ul> +  <li><strong><span style="font-family: Courier">"HATCHBOXSIZE"</span></strong>:  +  defines the size of smallest hatch box pattern. This affects the spacing  +  between the hatch lines. The value passed must be a string containing an  +  integer ("%d"). If the value of the attribute passed is NULL, the value is  +  rest to the default. When consulted returns the current value ("%d"). Default:  +  "8".</li> +</ul> + +<ul> +  <li>"<b><font face="Courier">IMGINTERP</font></b>": changes how  +  interpolation is used in image scale. Can be "BEST" (highest-quality),  +  "BILINEAR" (linear interpolation), "GOOD" (quality similar to BILINEAR),  +  "NEAREST" (nearest-neighbor filtering) or "FAST" (quality similar to NEAREST).  +  Default: "GOOD".</li> +</ul> + +<ul> +  <li>"<b><font face="Courier">LINEGRADIENT</font></b>": defines  +  a filled interior style that uses a line gradient between two colors. It uses  +  2 points ("%d %d %d %d" = x1 y1 x2 y2), one for the starting point using  +  (using the foreground color), and another one for the end point (using the  +  background color).</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>  +  and <strong>cdEnd</strong> to define holes. The value passed must be a string  +  containing an integer ("%d"). If the value of the attribute passed is NULL,  +  all holes will no longer be considered. When consulted returns the current  +  number of holes ("%d"). It can have a maximum of 500 holes. Default: NULL.</li> +</ul> + +<ul> +  <li>"<b><font face="Courier">RADIALGRADIENT</font></b>": defines  +  a filled interior style that uses a radial gradient between two colors. It  +  uses 2 points and 2 radius ("%d %d %g %d %d %g" = x1 y1 rad1 x2 y2 rad2), one  +  for the starting point using (using the foreground color), and another one for  +  the end point (using the background color).</li> +</ul> + +<ul> +  <li>"<b><font face="Courier">ROTATE</font></b>":  allows the usage of 1  +	angle and 1 coordinate (x, y), that define a global rotation transformation  +	centered in the specified coordinate. Use 1 real and 2 integer values inside  +	a string ("%g %d %d" = angle x y). Can not be set if a transformation is  +	already set.</li> +</ul> + +</body> + +</html> diff --git a/html/en/drv/gdiplus.html b/html/en/drv/gdiplus.html index e4a2810..f5b89f4 100644 --- a/html/en/drv/gdiplus.html +++ b/html/en/drv/gdiplus.html @@ -182,7 +182,8 @@  <ul>    <li>"<b><font face="Courier">ROTATE</font></b>":  allows the usage of 1 angle and 1 coordinate (x, y), that     define a global rotation transformation centered in the specified coordinate. Use 1 real and 2 integer values inside a  -  string ("%g %d %d" = angle x y).</li> +  string ("%g %d %d" = angle x y). Can not be set if a transformation  +	is already set.</li>  </ul>  <ul>    <li><b><font face="Courier">"LINEGRADIENT": </font></b>defines a filled interior style that uses a line gradient  diff --git a/html/en/drv/pdf.html b/html/en/drv/pdf.html index 4fba6b8..979256b 100644 --- a/html/en/drv/pdf.html +++ b/html/en/drv/pdf.html @@ -193,7 +193,8 @@ the vertex where there is a hole in a  <ul>    <li>"<b><font face="Courier">ROTATE</font></b>":  allows the usage of 1 angle and 1 coordinate (x, y), that     define a global rotation transformation centered in the specified coordinate. Use 1 real and 2 integer values inside a  -  string ("%g %d %d" = angle x y).</li> +  string ("%g %d %d" = angle x y). Can not be set if a transformation  +	is already set.</li>  </ul>  <ul>    <li>"<b><font face="Courier">OPACITY</font></b>":  allows the usage of a global  diff --git a/html/en/drv/ps.html b/html/en/drv/ps.html index f27efb7..7e8f0c2 100644 --- a/html/en/drv/ps.html +++ b/html/en/drv/ps.html @@ -204,7 +204,8 @@    <li>"<b><font face="Courier">ROTATE</font></b>":  allows the usage of 1 angle   	and 1 coordinate (x, y), that define a global rotation transformation   	centered in the specified coordinate. Use 1 real and 2 integer values inside  -	a string ("%g %d %d" = angle x y).</li> +	a string ("%g %d %d" = angle x y). Can not be set if a  +	transformation is already set.</li>  </ul>  </body> diff --git a/html/en/drv/win32.html b/html/en/drv/win32.html index 53ac2a5..df0d902 100644 --- a/html/en/drv/win32.html +++ b/html/en/drv/win32.html @@ -129,7 +129,8 @@    <li>"<b><font face="Courier">ROTATE</font></b>":  allows the usage of 1     angle and 1 coordinate (x, y), that define a global rotation transformation     centered in the specified coordinate. Use 1 real and 2 integer values inside a  -  string ("%g %d %d" = angle x y).</li> +  string ("%g %d %d" = angle x y).  Can not be set if a  +	transformation is already set.</li>  </ul>  </body> diff --git a/include/cd.h b/include/cd.h index b3a8784..8d3826c 100644 --- a/include/cd.h +++ b/include/cd.h @@ -21,7 +21,7 @@ extern "C" {  #define CD_COPYRIGHT    "Copyright (C) 1994-2010 Tecgraf, PUC-Rio."  #define CD_VERSION "5.3"              /* bug fixes are reported only by cdVersion functions */  #define CD_VERSION_NUMBER 503000 -#define CD_VERSION_DATE "2010/01/26" +#define CD_VERSION_DATE "2010/01/26"  /* does not include bug fix releases */  typedef struct _cdContext cdContext;  typedef struct _cdCanvas cdCanvas; @@ -460,6 +460,18 @@ typedef int(*cdSizeCB)(cdCanvas *canvas, int w, int h, double w_mm, double h_mm)  #define CD_RAD2DEG  57.295779513   /* radians to degrees (deg = CD_RAD2DEG * rad) */  #define CD_DEG2RAD  0.01745329252  /* degrees to radians (rad = CD_DEG2RAD * deg) */ +/* paper sizes */ +enum { +  CD_A0, +  CD_A1, +  CD_A2, +  CD_A3, +  CD_A4, +  CD_A5, +  CD_LETTER, +  CD_LEGAL +}; +  #ifdef __cplusplus  } diff --git a/include/cd_private.h b/include/cd_private.h index af216c5..a70469c 100644 --- a/include/cd_private.h +++ b/include/cd_private.h @@ -273,6 +273,7 @@ int cdStrEqualNoCase(const char* str1, const char* str2);  int cdStrLineCount(const char* str);  char* cdStrDup(const char* str);  char* cdStrDupN(const char* str, int len); +void cdSetPaperSize(int size, double *w_pt, double *h_pt);  #define _cdCheckCanvas(_canvas) (_canvas!=NULL && ((unsigned char*)_canvas)[0] == 'C' && ((unsigned char*)_canvas)[1] == 'D')  #define _cdInvertYAxis(_canvas, _y) (_canvas->h - (_y) - 1) @@ -288,6 +289,7 @@ void cdMatrixTransformPoint(double* matrix, int x, int y, int *rx, int *ry);  void cdfMatrixTransformPoint(double* matrix, double x, double y, double *rx, double *ry);  void cdMatrixMultiply(const double* matrix, double* mul_matrix);  void cdMatrixInverse(const double* matrix, double* inv_matrix); +void cdfRotatePoint(cdCanvas* canvas, double x, double y, double cx, double cy, double *rx, double *ry, double sin_theta, double cos_theta);  void cdRotatePoint(cdCanvas* canvas, int x, int y, int cx, int cy, int *rx, int *ry, double sin_teta, double cos_teta);  void cdRotatePointY(cdCanvas* canvas, int x, int y, int cx, int cy, int *ry, double sin_theta, double cos_theta);  void cdTextTranslatePoint(cdCanvas* canvas, int x, int y, int w, int h, int baseline, int *rx, int *ry); diff --git a/include/cdcairo.h b/include/cdcairo.h new file mode 100644 index 0000000..2d01f2e --- /dev/null +++ b/include/cdcairo.h @@ -0,0 +1,41 @@ +/** \file + * \brief Cairo extra drivers. + *        Rendering PDF, PS, SVG and IMAGERGB. + * + * See Copyright Notice in cd.h + */ + +#ifndef __CD_CAIRO_H +#define __CD_CAIRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Some of these context can be used directly or by cdInitContextPlus, +   as  CD_NATIVEWINDOW, CD_IMAGE and CD_DBUFFER. +   The other only directly.  +*/ + +cdContext* cdContextCairoPS(void); +cdContext* cdContextCairoPDF(void); +cdContext* cdContextCairoSVG(void); +cdContext* cdContextCairoImageRGB(void); +cdContext* cdContextCairoDBuffer(void); +cdContext* cdContextCairoImage(void); +cdContext* cdContextCairoNativeWindow(void); + +#define CD_CAIRO_NATIVEWINDOW cdContextCairoNativeWindow() +#define CD_CAIRO_IMAGE cdContextCairoImage() +#define CD_CAIRO_DBUFFER cdContextCairoDBuffer() +#define CD_CAIRO_PS cdContextCairoPS() +#define CD_CAIRO_PDF cdContextCairoPDF() +#define CD_CAIRO_SVG cdContextCairoSVG() +#define CD_CAIRO_IMAGERGB cdContextCairoImageRGB() + + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef __CD_CAIRO_ */ diff --git a/include/cdpdf.h b/include/cdpdf.h index 70d6df5..89486fc 100644 --- a/include/cdpdf.h +++ b/include/cdpdf.h @@ -15,21 +15,6 @@ cdContext* cdContextPDF(void);  #define CD_PDF cdContextPDF() -#ifndef CD_PAPERSIZE -#define CD_PAPERSIZE -enum {                          /* paper sizes */ -  CD_A0, -  CD_A1, -  CD_A2, -  CD_A3, -  CD_A4, -  CD_A5, -  CD_LETTER, -  CD_LEGAL -}; -#endif - -  #ifdef __cplusplus  }  #endif diff --git a/include/cdps.h b/include/cdps.h index 180ebad..0f4bdd8 100644 --- a/include/cdps.h +++ b/include/cdps.h @@ -15,20 +15,6 @@ cdContext* cdContextPS(void);  #define CD_PS cdContextPS() -#ifndef CD_PAPERSIZE -#define CD_PAPERSIZE -enum {                          /* paper sizes */ -  CD_A0, -  CD_A1, -  CD_A2, -  CD_A3, -  CD_A4, -  CD_A5, -  CD_LETTER, -  CD_LEGAL -}; -#endif -  #ifdef __cplusplus  }  #endif diff --git a/mak.vc9/cd.sln b/mak.vc9/cd.sln index 165a240..7def44e 100644 --- a/mak.vc9/cd.sln +++ b/mak.vc9/cd.sln @@ -89,6 +89,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdgdk", "cdgdk.vcproj", "{0  EndProject  Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdsimplegdk", "cdsimplegdk.vcproj", "{82BC36B1-DDDD-41D4-ABCD-A12312378CE6}"  	ProjectSection(ProjectDependencies) = postProject +		{01818D2C-AAAA-DD23-00AA-5678401C6461} = {01818D2C-AAAA-DD23-00AA-5678401C6461}  		{01818D2C-AAAA-4D5C-ABCD-1234401C6461} = {01818D2C-AAAA-4D5C-ABCD-1234401C6461}  		{8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}  	EndProjectSection @@ -107,6 +108,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdtestplus", "cdtestplus.vc  		{8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467}  	EndProjectSection  EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{1EE89DAC-3D3A-450C-9CF8-E200DF5E12E8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdcairo", "cdcairo.vcproj", "{01818D2C-AAAA-DD23-00AA-5678401C6461}" +	ProjectSection(ProjectDependencies) = postProject +		{01818D2C-1234-4D5C-ABCD-4DFF401C6461} = {01818D2C-1234-4D5C-ABCD-4DFF401C6461} +	EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdtestcairo", "cdtestcairo.vcproj", "{A7E49FB8-0022-15EC-AB17-FFCDC7E83C00}" +	ProjectSection(ProjectDependencies) = postProject +		{01818D2C-AAAA-DD23-00AA-5678401C6461} = {01818D2C-AAAA-DD23-00AA-5678401C6461} +		{01818D2C-AAAA-4D5C-ABCD-1234401C6461} = {01818D2C-AAAA-4D5C-ABCD-1234401C6461} +		{8441F69D-7135-43B2-974F-45C6123C8467} = {8441F69D-7135-43B2-974F-45C6123C8467} +	EndProjectSection +EndProject  Global  	GlobalSection(SolutionConfigurationPlatforms) = preSolution  		Debug|Win32 = Debug|Win32 @@ -150,11 +165,20 @@ Global  		{A7E49FB8-0000-45EC-1234-ABCDC7E83C00}.Debug|Win32.Build.0 = Debug|Win32  		{A7E49FB8-5467-45EC-2211-FFAB7E83C100}.Debug|Win32.ActiveCfg = Debug|Win32  		{A7E49FB8-5467-45EC-2211-FFAB7E83C100}.Debug|Win32.Build.0 = Debug|Win32 +		{01818D2C-AAAA-DD23-00AA-5678401C6461}.Debug|Win32.ActiveCfg = Debug|Win32 +		{01818D2C-AAAA-DD23-00AA-5678401C6461}.Debug|Win32.Build.0 = Debug|Win32 +		{A7E49FB8-0022-15EC-AB17-FFCDC7E83C00}.Debug|Win32.ActiveCfg = Debug|Win32 +		{A7E49FB8-0022-15EC-AB17-FFCDC7E83C00}.Debug|Win32.Build.0 = Debug|Win32  	EndGlobalSection  	GlobalSection(SolutionProperties) = preSolution  		HideSolutionNode = FALSE  	EndGlobalSection  	GlobalSection(NestedProjects) = preSolution +		{01818D2C-7689-4D5C-1234-4DFF401C6461} = {1EE89DAC-3D3A-450C-9CF8-E200DF5E12E8} +		{01818D2C-AAAA-4D5C-ABCD-1234401C6461} = {1EE89DAC-3D3A-450C-9CF8-E200DF5E12E8} +		{01818D2C-1234-4D5C-ABCD-4DFF401C6461} = {1EE89DAC-3D3A-450C-9CF8-E200DF5E12E8} +		{01818D2C-65AF-4D5C-9452-4DFF401C6461} = {1EE89DAC-3D3A-450C-9CF8-E200DF5E12E8} +		{01818D2C-AAAA-DD23-00AA-5678401C6461} = {1EE89DAC-3D3A-450C-9CF8-E200DF5E12E8}  		{B4823266-DF8C-AAAA-9999-C7E78C234EAC} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}  		{53FC9752-81C1-4AA6-B366-AF6D0A2B81F6} = {E92DB6FF-5501-4FC0-81D2-00DB8EFA2434}  		{B4823266-DF8C-1224-EE00-C7688C234EAC} = {EFB1BE3C-2981-456B-8E32-928CBDFF7822} @@ -166,6 +190,7 @@ Global  		{82BC36B1-DDDD-41D4-ABCD-A12312378CE6} = {162715BD-4DB3-4007-8B50-725C0BD11878}  		{A7E49FB8-0000-45EC-1234-ABCDC7E83C00} = {162715BD-4DB3-4007-8B50-725C0BD11878}  		{A7E49FB8-5467-45EC-2211-FFAB7E83C100} = {162715BD-4DB3-4007-8B50-725C0BD11878} +		{A7E49FB8-0022-15EC-AB17-FFCDC7E83C00} = {162715BD-4DB3-4007-8B50-725C0BD11878}  	EndGlobalSection  	GlobalSection(DevPartner Solution Properties) = postSolution  	EndGlobalSection diff --git a/mak.vc9/cdcairo.vcproj b/mak.vc9/cdcairo.vcproj new file mode 100644 index 0000000..ec7c1e5 --- /dev/null +++ b/mak.vc9/cdcairo.vcproj @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject +	ProjectType="Visual C++" +	Version="9,00" +	Name="cdcairo" +	ProjectGUID="{01818D2C-AAAA-DD23-00AA-5678401C6461}" +	TargetFrameworkVersion="0" +	> +	<Platforms> +		<Platform +			Name="Win32" +		/> +	</Platforms> +	<ToolFiles> +	</ToolFiles> +	<Configurations> +		<Configuration +			Name="Debug|Win32" +			OutputDirectory="..\lib" +			IntermediateDirectory="..\obj\Debug\$(ProjectName)" +			ConfigurationType="4" +			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" +			UseOfMFC="0" +			ATLMinimizesCRunTimeLibraryUsage="false" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +			/> +			<Tool +				Name="VCCLCompilerTool" +				Optimization="0" +				AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\freetype2;..\src\intcgm;..\src\iup;..\src\sim;"d:\lng\gtk\include\atk-1.0";d:\lng\gtk\include\cairo;"d:\lng\gtk\include\glib-2.0";"d:\lng\gtk\include\pango-1.0";"d:\lng\gtk\include\gtk-2.0";"d:\lng\gtk\lib\glib-2.0\include";"d:\lng\gtk\lib\gtk-2.0\include";D:\LNG\x11inc" +				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CD_NO_OLD_INTERFACE;FT2_BUILD_LIBRARY;_CRT_SECURE_NO_DEPRECATE" +				BasicRuntimeChecks="3" +				RuntimeLibrary="1" +				PrecompiledHeaderFile=".\..\obj\cdcairo/cd.pch" +				AssemblerListingLocation="" +				ObjectFile="$(IntDir)\" +				ProgramDataBaseFileName="$(IntDir)\vc90.pdb" +				WarningLevel="4" +				SuppressStartupBanner="true" +				DebugInformationFormat="1" +				CompileAs="0" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +				Culture="1046" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCLibrarianTool" +				AdditionalDependencies="cdcore.lib" +				OutputFile="$(OutDir)/$(ProjectName).lib" +				AdditionalLibraryDirectories="$(OutDir)" +				SuppressStartupBanner="true" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +		</Configuration> +	</Configurations> +	<References> +	</References> +	<Files> +		<Filter +			Name="inc" +			> +			<File +				RelativePath="..\src\cairo\cdcairoctx.h" +				> +			</File> +		</Filter> +		<Filter +			Name="include" +			> +			<File +				RelativePath="..\include\cdcairo.h" +				> +			</File> +		</Filter> +		<File +			RelativePath="..\src\cairo\cdcairo.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairodbuf.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairoimg.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairoirgb.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcaironative_gdk.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcaironative_win32.c" +			> +			<FileConfiguration +				Name="Debug|Win32" +				ExcludedFromBuild="true" +				> +				<Tool +					Name="VCCLCompilerTool" +				/> +			</FileConfiguration> +		</File> +		<File +			RelativePath="..\src\cairo\cdcaironative_x11.c" +			> +			<FileConfiguration +				Name="Debug|Win32" +				ExcludedFromBuild="true" +				> +				<Tool +					Name="VCCLCompilerTool" +				/> +			</FileConfiguration> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairopdf.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairoplus.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairops.c" +			> +		</File> +		<File +			RelativePath="..\src\cairo\cdcairosvg.c" +			> +		</File> +	</Files> +	<Globals> +	</Globals> +</VisualStudioProject> diff --git a/mak.vc9/cdsimplegdk.vcproj b/mak.vc9/cdsimplegdk.vcproj index 57fe233..51310a6 100644 --- a/mak.vc9/cdsimplegdk.vcproj +++ b/mak.vc9/cdsimplegdk.vcproj @@ -44,7 +44,7 @@  				Name="VCCLCompilerTool"  				Optimization="0"  				AdditionalIncludeDirectories="..\include,..\..\iup\include" -				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__CD__;simple;_CRT_SECURE_NO_DEPRECATE;USE_GDK" +				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__CD__;simple;_CRT_SECURE_NO_DEPRECATE;USE_GDK;USE_CONTEXTPLUS"  				BasicRuntimeChecks="3"  				RuntimeLibrary="1"  				PrecompiledHeaderFile=".\..\obj\cdsimplegdk/cdsimplegdk.pch" @@ -70,7 +70,7 @@  			<Tool  				Name="VCLinkerTool"  				AdditionalOptions="/MACHINE:I386" -				AdditionalDependencies="gtk-win32-2.0.lib gdk-win32-2.0.lib gdk_pixbuf-2.0.lib cairo.lib pango-1.0.lib pangowin32-1.0.lib gobject-2.0.lib gmodule-2.0.lib glib-2.0.lib freetype6.lib cdgdk.lib iupcd.lib iupgtk.lib comctl32.lib cdpdf.lib pdflib.lib iupcontrols.lib" +				AdditionalDependencies="gtk-win32-2.0.lib gdk-win32-2.0.lib gdk_pixbuf-2.0.lib cairo.lib pango-1.0.lib pangowin32-1.0.lib gobject-2.0.lib gmodule-2.0.lib glib-2.0.lib freetype6.lib cdgdk.lib cdcairo.lib iupcd.lib iupgtk.lib comctl32.lib cdpdf.lib pdflib.lib iupcontrols.lib"  				OutputFile="$(OutDir)\$(ProjectName).exe"  				LinkIncremental="1"  				SuppressStartupBanner="true" diff --git a/mak.vc9/cdtestcairo.vcproj b/mak.vc9/cdtestcairo.vcproj new file mode 100644 index 0000000..bc63e14 --- /dev/null +++ b/mak.vc9/cdtestcairo.vcproj @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject +	ProjectType="Visual C++" +	Version="9,00" +	Name="cdtestcairo" +	ProjectGUID="{A7E49FB8-0022-15EC-AB17-FFCDC7E83C00}" +	TargetFrameworkVersion="0" +	> +	<Platforms> +		<Platform +			Name="Win32" +		/> +	</Platforms> +	<ToolFiles> +	</ToolFiles> +	<Configurations> +		<Configuration +			Name="Debug|Win32" +			OutputDirectory="..\bin" +			IntermediateDirectory="..\obj\Debug\$(ProjectName)" +			ConfigurationType="1" +			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" +			UseOfMFC="0" +			ATLMinimizesCRunTimeLibraryUsage="false" +			CharacterSet="2" +			> +			<Tool +				Name="VCPreBuildEventTool" +			/> +			<Tool +				Name="VCCustomBuildTool" +			/> +			<Tool +				Name="VCXMLDataGeneratorTool" +			/> +			<Tool +				Name="VCWebServiceProxyGeneratorTool" +			/> +			<Tool +				Name="VCMIDLTool" +				PreprocessorDefinitions="_DEBUG" +				MkTypLibCompatible="true" +				SuppressStartupBanner="true" +				TargetEnvironment="1" +			/> +			<Tool +				Name="VCCLCompilerTool" +				Optimization="0" +				AdditionalIncludeDirectories="..\include,..\..\iup\include" +				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CDTEST_WIN32;_CRT_SECURE_NO_DEPRECATE;USE_CONTEXTPLUS" +				BasicRuntimeChecks="3" +				RuntimeLibrary="1" +				AssemblerListingLocation="" +				ObjectFile="$(IntDir)\" +				ProgramDataBaseFileName="$(IntDir)\vc90.pdb" +				WarningLevel="4" +				SuppressStartupBanner="true" +				DebugInformationFormat="1" +				CompileAs="0" +			/> +			<Tool +				Name="VCManagedResourceCompilerTool" +			/> +			<Tool +				Name="VCResourceCompilerTool" +				PreprocessorDefinitions="_DEBUG" +				Culture="1046" +			/> +			<Tool +				Name="VCPreLinkEventTool" +			/> +			<Tool +				Name="VCLinkerTool" +				AdditionalOptions="/MACHINE:I386" +				AdditionalDependencies="gtk-win32-2.0.lib gdk-win32-2.0.lib gdk_pixbuf-2.0.lib cairo.lib pango-1.0.lib pangowin32-1.0.lib gobject-2.0.lib gmodule-2.0.lib glib-2.0.lib freetype6.lib comctl32.lib cdgdk.lib cdcairo.lib iupcd.lib iupgtk.lib cdpdf.lib pdflib.lib" +				OutputFile="$(OutDir)\$(ProjectName).exe" +				LinkIncremental="1" +				SuppressStartupBanner="true" +				AdditionalLibraryDirectories="..\lib,..\..\iup\lib;d:\lng\gtk\lib" +				GenerateManifest="false" +				GenerateDebugInformation="true" +				ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb" +				SubSystem="1" +			/> +			<Tool +				Name="VCALinkTool" +			/> +			<Tool +				Name="VCManifestTool" +			/> +			<Tool +				Name="VCXDCMakeTool" +			/> +			<Tool +				Name="VCBscMakeTool" +			/> +			<Tool +				Name="VCFxCopTool" +			/> +			<Tool +				Name="VCAppVerifierTool" +			/> +			<Tool +				Name="VCPostBuildEventTool" +			/> +		</Configuration> +	</Configurations> +	<References> +	</References> +	<Files> +		<Filter +			Name="Source Files" +			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +			> +			<File +				RelativePath="..\test\cdtest\cdtest.c" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\cdtest.led" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\cdtest.rc" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\cdtest_led.c" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\colorbar.c" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\drivers.c" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\list.c" +				> +			</File> +			<File +				RelativePath="..\test\cdtest\rubber.c" +				> +			</File> +		</Filter> +		<Filter +			Name="Header Files" +			Filter="h;hpp;hxx;hm;inl" +			> +			<File +				RelativePath="..\test\cdtest\cdtest.h" +				> +			</File> +		</Filter> +	</Files> +	<Globals> +	</Globals> +</VisualStudioProject> diff --git a/mak.vc9/cdx11.vcproj b/mak.vc9/cdx11.vcproj index 8336785..5d6398c 100644 --- a/mak.vc9/cdx11.vcproj +++ b/mak.vc9/cdx11.vcproj @@ -41,7 +41,7 @@  			<Tool  				Name="VCCLCompilerTool"  				Optimization="0" -				AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\sim;D:\LNG\x11inc;..\..\iup\include" +				AdditionalIncludeDirectories="..\include;..\src;..\src\drv;..\src\iup;..\src\x11;..\src\sim;D:\LNG\x11inc"  				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 new file mode 100644 index 0000000..34fdef7 --- /dev/null +++ b/src/cairo/cdcairo.c @@ -0,0 +1,1758 @@ +/** \file +* \brief Cairo Base Driver +* +* See Copyright Notice in cd.h +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <math.h> + +#include <glib.h> + +#include "cdcairoctx.h" + +#define HATCH_WIDTH  8 +#define HATCH_HEIGHT 8 + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + + +static int StrIsAscii(const char* str) +{ +  while(*str) +  { +    int c = *str; +    if (c < 0) +      return 0; +    str++; +  } +  return 1; +} + +static char* StrToUTF8(const char *str, const char* charset, int length) +{ +  return g_convert(str, length, "UTF-8", charset, NULL, NULL, NULL); +} + +char* StrConvertToUTF8(cdCtxCanvas *ctxcanvas, const char* str, int length) +{ +  const char *charset = NULL; + +  if (!str || *str == 0) +    return (char*)str; + +  if (g_get_charset(&charset))  /* current locale is already UTF-8 */ +  { +    if (g_utf8_validate(str, -1, NULL)) +    { +      return (char*)str; +    } +    else +    { +      ctxcanvas->cairoLastConvertUTF8 = StrToUTF8(str, "ISO8859-1", length);   /* if string is not UTF-8, assume ISO8859-1 */ + +      if (!ctxcanvas->cairoLastConvertUTF8) +        return (char*)str; + +      return ctxcanvas->cairoLastConvertUTF8; +    } +  } +  else +  { +    if (StrIsAscii(str) || !charset) +    { +      return (char*)str; +    } +    else if (charset) +    {     +      ctxcanvas->cairoLastConvertUTF8 = StrToUTF8(str, charset, length); + +      if (!ctxcanvas->cairoLastConvertUTF8) +        return (char*)str; + +      return ctxcanvas->cairoLastConvertUTF8; +    } +  } + +  return (char*)str; +} + +static void update_fill(cdCtxCanvas *ctxcanvas, int fill) +{ +  if (fill == 0 || ctxcanvas->canvas->interior_style == CD_SOLID) +  { +    if (ctxcanvas->last_source == 0) +      return; + +    cairo_set_source(ctxcanvas->cr, ctxcanvas->solid); +    ctxcanvas->last_source = 0; +  } +  else +  { +    if (ctxcanvas->last_source == 1) +      return; + +    cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern); +    ctxcanvas->last_source = 1; +  } +} + +/******************************************************/ + +void cdcairoKillCanvas(cdCtxCanvas *ctxcanvas) +{ +  if (ctxcanvas->solid) +    cairo_pattern_destroy(ctxcanvas->solid); + +  if (ctxcanvas->pattern) +    cairo_pattern_destroy(ctxcanvas->pattern); + +  if (ctxcanvas->font) +    cairo_scaled_font_destroy(ctxcanvas->font); + +  if (ctxcanvas->cairoLastConvertUTF8) +    g_free(ctxcanvas->cairoLastConvertUTF8); + +  cairo_destroy(ctxcanvas->cr); + +  memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); +  free(ctxcanvas); +} + +/******************************************************/ + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ +  cairo_show_page(ctxcanvas->cr); +} + +/******************************************************/ + +static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax) +{ +  cairo_reset_clip(ctxcanvas->cr); +  cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1); +  cairo_clip(ctxcanvas->cr); +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ +  if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA) +    return; + +  setcliprect(ctxcanvas, (double)xmin, (double)ymin, (double)xmax, (double)ymax); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ +  switch (mode) +  { +  case CD_CLIPOFF: +    cairo_reset_clip(ctxcanvas->cr); +    break; +  case CD_CLIPAREA: +      ctxcanvas->canvas->clip_mode = CD_CLIPAREA; +      setcliprect(ctxcanvas, (double)ctxcanvas->canvas->clip_rect.xmin,  +        (double)ctxcanvas->canvas->clip_rect.ymin,  +        (double)ctxcanvas->canvas->clip_rect.xmax,  +        (double)ctxcanvas->canvas->clip_rect.ymax); +      break; +  case CD_CLIPPOLYGON: +    { +      int hole_index = 0; +      int i; +      cairo_reset_clip(ctxcanvas->cr); + +      if (ctxcanvas->canvas->clip_poly) +      { +        cdPoint *poly = ctxcanvas->canvas->clip_poly;  +        cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y); +        for (i=1; i<ctxcanvas->canvas->clip_poly_n; i++) +        { +          if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) +          { +            cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y); +            hole_index++; +          } +          else +            cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y); +        } +      } +      else if (ctxcanvas->canvas->clip_fpoly) +      { +        cdfPoint *poly = ctxcanvas->canvas->clip_fpoly;  +        cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y); +        for (i=1; i<ctxcanvas->canvas->clip_poly_n; i++) +        { +          if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) +          { +            cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y); +            hole_index++; +          } +          else +            cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y); +        } +      } +      cairo_clip(ctxcanvas->cr); +      break; +    } +  case CD_CLIPREGION: +    break; +  } + +  return mode; +} + +/******************************************************/ + +static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b, unsigned char*a)) +{ +  int i, j; +  unsigned char r, g, b, a; +  cairo_surface_t* pattern_surface; +  cairo_t* cr; + +  pattern_surface = cairo_surface_create_similar(cairo_get_target(ctxcanvas->cr), CAIRO_CONTENT_COLOR_ALPHA, n, m); + +  cr = cairo_create(pattern_surface); + +  for (j = 0; j < m; j++) +  { +    for (i = 0; i < n; i++) +    { +      int ret = data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b, &a); +      if (ret == -1) +        continue; + +      cairo_set_source_rgba(cr, (double)r/255.0, (double)g/255.0, (double)b/255.0, (double)a/255.0); + +      cairo_rectangle(cr, i, m-1-j, 1.0, 1.0); +      cairo_fill(cr); +    } +  } + +  if (ctxcanvas->pattern) +    cairo_pattern_destroy(ctxcanvas->pattern); + +  ctxcanvas->pattern = cairo_pattern_create_for_surface(pattern_surface); +  cairo_pattern_set_extend(ctxcanvas->pattern, CAIRO_EXTEND_REPEAT); + +  cairo_surface_destroy(pattern_surface); +  cairo_destroy(cr); +} + +static int long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b, unsigned char*a) +{ +  long* long_data = (long*)data; +  long c = long_data[j*n+i]; +  (void)ctxcanvas; +  cdDecodeColor(c, r, g, b); +  *a = cdDecodeAlpha(c); +  return 1; +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) +{ +  make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb); +  cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern); +  ctxcanvas->last_source = 1; +} + +static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b, unsigned char*a) +{ +  unsigned char* uchar_data = (unsigned char*)data; +  if (uchar_data[j*n+i]) +  { +    cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); +    *a = cdDecodeAlpha(ctxcanvas->canvas->foreground); +  } +  else +  { +    if (ctxcanvas->canvas->back_opacity == CD_TRANSPARENT) +      return -1; +    else +    { +      cdDecodeColor(ctxcanvas->canvas->background, r, g, b); +      *a = cdDecodeAlpha(ctxcanvas->canvas->background); +    } +  } + +  return 1; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) +{ +  make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb); +  cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern); +  ctxcanvas->last_source = 1; +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ +  int hsize = HATCH_WIDTH - 1; +  int hhalf = hsize / 2; +  cairo_surface_t* hatch_surface; +  cairo_t* cr; + +  hatch_surface = cairo_surface_create_similar(cairo_get_target(ctxcanvas->cr), CAIRO_CONTENT_COLOR_ALPHA, HATCH_WIDTH, HATCH_HEIGHT); + +  cr = cairo_create(hatch_surface); + +  if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) +  { +    cairo_set_source_rgba(cr, cdCairoGetRed(ctxcanvas->canvas->background), cdCairoGetGreen(ctxcanvas->canvas->background), cdCairoGetBlue(ctxcanvas->canvas->background), cdCairoGetAlpha(ctxcanvas->canvas->background)); +    cairo_rectangle(cr, 0, 0, hsize, hsize); +    cairo_fill(cr); +  } + +  cairo_set_source_rgba(cr, cdCairoGetRed(ctxcanvas->canvas->foreground), cdCairoGetGreen(ctxcanvas->canvas->foreground), cdCairoGetBlue(ctxcanvas->canvas->foreground), cdCairoGetAlpha(ctxcanvas->canvas->foreground)); + +  switch(style) +  { +  case CD_HORIZONTAL: +    cairo_move_to(cr, 0.0, (double)hhalf); +    cairo_line_to(cr, (double)hsize, (double)hhalf); +    break; +  case CD_VERTICAL: +    cairo_move_to(cr, (double)hhalf, 0.0); +    cairo_line_to(cr, (double)hhalf, (double)hsize); +    break; +  case CD_BDIAGONAL: +    cairo_move_to(cr, 0.0, (double)hsize); +    cairo_line_to(cr, (double)hsize, 0.0); +    break; +  case CD_FDIAGONAL: +    cairo_move_to(cr, 0.0, 0.0); +    cairo_line_to(cr, (double)hsize, (double)hsize); +    break; +  case CD_CROSS: +    cairo_move_to(cr, (double)hsize, 0.0); +    cairo_line_to(cr, (double)hsize, (double)hsize); +    cairo_move_to(cr, 0.0, (double)hhalf); +    cairo_line_to(cr, (double)hsize, (double)hhalf); +    break; +  case CD_DIAGCROSS: +    cairo_move_to(cr, 0.0, 0.0); +    cairo_line_to(cr, (double)hsize, (double)hsize); +    cairo_move_to(cr, (double)hsize, 0.0); +    cairo_line_to(cr, 0.0, (double)hsize); +    break; +  } + +  cairo_stroke(cr); + +  if (ctxcanvas->pattern) +    cairo_pattern_destroy(ctxcanvas->pattern); + +  ctxcanvas->pattern = cairo_pattern_create_for_surface(hatch_surface); +  cairo_pattern_reference(ctxcanvas->pattern); +  cairo_pattern_set_extend(ctxcanvas->pattern, CAIRO_EXTEND_REPEAT); + +  cairo_surface_destroy(hatch_surface); +  cairo_destroy(cr); + +  cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern); +  ctxcanvas->last_source = 1; + +  return style; +} + +/******************************************************/ +/* attributes                                         */ +/******************************************************/ + +static int cdwritemode(cdCtxCanvas *ctxcanvas, int write_mode) +{ +  switch (write_mode) +  { +  case CD_REPLACE: +    cairo_set_operator (ctxcanvas->cr, CAIRO_OPERATOR_OVER); +    break; +  case CD_XOR: +    cairo_set_operator (ctxcanvas->cr, CAIRO_OPERATOR_XOR); +    break; +  } + +  return write_mode; +} + +static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style) +{ +  switch (style) +  { +  case CD_SOLID: +    cairo_set_source(ctxcanvas->cr, ctxcanvas->solid); +    ctxcanvas->last_source = 0; +    break; +  /* must recriate the current pattern */ +  case CD_HATCH: +    cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); +    break; +  case CD_STIPPLE: +    cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); +    break; +  case CD_PATTERN: +    cdpattern(ctxcanvas, ctxcanvas->canvas->pattern_w, ctxcanvas->canvas->pattern_h, ctxcanvas->canvas->pattern); +    break; +  } + +  return style; +} + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ +  double dashes[10]; + +  switch (style) +  { +  case CD_CONTINUOUS : /* empty dash */ +    cairo_set_dash(ctxcanvas->cr, 0, 0, 0); +    break; +  case CD_DASHED : +    dashes[0] = 6.0;  dashes[1] = 2.0; +    cairo_set_dash(ctxcanvas->cr, dashes, 2, 0); +    break; +  case CD_DOTTED : +    dashes[0] = 2.0;  dashes[1] = 2.0; +    cairo_set_dash(ctxcanvas->cr, dashes, 2, 0); +    break; +  case CD_DASH_DOT : +    dashes[0] = 6.0;  dashes[1] = 2.0; +    dashes[2] = 2.0;  dashes[3] = 2.0; +    cairo_set_dash(ctxcanvas->cr, dashes, 4, 0); +    break; +  case CD_DASH_DOT_DOT : +    dashes[0] = 6.0;  dashes[1] = 2.0; +    dashes[2] = 2.0;  dashes[3] = 2.0; +    dashes[4] = 2.0;  dashes[5] = 2.0; +    cairo_set_dash(ctxcanvas->cr, dashes, 6, 0); +    break; +  case CD_CUSTOM : +    { +      int i; +      double* dash_style = (double*)malloc(sizeof(double)*ctxcanvas->canvas->line_dashes_count); + +      for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) +        dash_style[i] = (double)ctxcanvas->canvas->line_dashes[i]; + +      cairo_set_dash(ctxcanvas->cr, dash_style, ctxcanvas->canvas->line_dashes_count, 0); + +      free(dash_style); +    } +    break; +  } + +  return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ +  if(width == 0) +    width = 1; + +  cairo_set_line_width(ctxcanvas->cr, (double)width); + +  return width; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ +  int cd2ps_join[] = {CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_BEVEL, CAIRO_LINE_JOIN_ROUND}; + +  cairo_set_line_join(ctxcanvas->cr, cd2ps_join[join]);  + +  return join; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ +  int cd2pdf_cap[] = {CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_SQUARE, CAIRO_LINE_CAP_ROUND}; + +  cairo_set_line_cap(ctxcanvas->cr, cd2pdf_cap[cap]);  + +  return cap; +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *typeface, int style, int size) +{ +  //TODO:pango +  cairo_scaled_font_t *font; +  cairo_font_slant_t  slant  = CAIRO_FONT_SLANT_NORMAL;    /* default is */ +  cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL;   /*  CD_PLAIN  */ + +  if (cdStrEqualNoCase(typeface, "Courier") || cdStrEqualNoCase(typeface, "Monospace")) +    typeface = "Courier New"; +  else if (cdStrEqualNoCase(typeface, "Times") || cdStrEqualNoCase(typeface, "Serif")) +    typeface = "Times New Roman"; +  else if (cdStrEqualNoCase(typeface, "Helvetica") || cdStrEqualNoCase(typeface, "Sans")) +    typeface = "Arial"; + +  /* no support to underline and strikeout */ +  switch(style&3) +  { +  case CD_BOLD: +    weight = CAIRO_FONT_WEIGHT_BOLD; +    break; +  case CD_ITALIC: +    slant = CAIRO_FONT_SLANT_ITALIC; +    break; +  case CD_BOLD_ITALIC: +    weight = CAIRO_FONT_WEIGHT_BOLD; +    slant = CAIRO_FONT_SLANT_ITALIC; +    break; +  } + +  cairo_select_font_face(ctxcanvas->cr, typeface, slant, weight); +  cairo_set_font_size(ctxcanvas->cr, (double)cdGetFontSizePixels(ctxcanvas->canvas, size)); + +  font = cairo_get_scaled_font(ctxcanvas->cr); + +  if (!font) +    return 0; + +  font = cairo_scaled_font_reference(font); +  ctxcanvas->font = font; + +  return 1; +} + +static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ +  cairo_font_extents_t extents; + +  if (!ctxcanvas->font) +    return; + +  cairo_set_scaled_font(ctxcanvas->cr, ctxcanvas->font); +  cairo_font_extents(ctxcanvas->cr, &extents); + +  if (ascent)  *ascent  = (int)extents.ascent; +  if (descent) *descent = (int)extents.descent; +  if (height)  *height  = (int)extents.height; +  if (max_width) *max_width = (int)extents.max_x_advance; +} + +static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ +  if (ctxcanvas->solid) +    cairo_pattern_destroy(ctxcanvas->solid); + +  cairo_set_source_rgba(ctxcanvas->cr, cdCairoGetRed(color), +                                       cdCairoGetGreen(color), +                                       cdCairoGetBlue(color), +                                       cdCairoGetAlpha(color)); +  ctxcanvas->solid = cairo_get_source(ctxcanvas->cr); +  cairo_pattern_reference(ctxcanvas->solid); +  ctxcanvas->last_source = 0; +  return color; +} + + +/******************************************************/ + +static void cdclear(cdCtxCanvas* ctxcanvas) +{ +  cairo_save (ctxcanvas->cr); +  cairo_set_source_rgba(ctxcanvas->cr, cdCairoGetRed(ctxcanvas->canvas->background), cdCairoGetGreen(ctxcanvas->canvas->background), cdCairoGetBlue(ctxcanvas->canvas->background), cdCairoGetAlpha(ctxcanvas->canvas->background)); +  cairo_set_operator (ctxcanvas->cr, CAIRO_OPERATOR_SOURCE); +  cairo_paint (ctxcanvas->cr);  /* paints the current source everywhere within the current clip region. */ +  cairo_restore (ctxcanvas->cr); +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{  +  update_fill(ctxcanvas, 0); + +  cairo_move_to(ctxcanvas->cr, x1, y1); +  cairo_line_to(ctxcanvas->cr, x2, y2); +  cairo_stroke(ctxcanvas->cr); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ +  cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ +  update_fill(ctxcanvas, 0); + +  if (w == h) +  { +    cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*w, -a1*CD_DEG2RAD, -a2*CD_DEG2RAD); +    cairo_stroke(ctxcanvas->cr); +  } +  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_negative(ctxcanvas->cr, xc, yc, 0.5*h, -a1*CD_DEG2RAD, -a2*CD_DEG2RAD); +    cairo_stroke(ctxcanvas->cr); + +    cairo_restore(ctxcanvas->cr);  /* restore from local */ +  } +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ +  cdfarc(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ +  update_fill(ctxcanvas, 1); + +  if (w == h) +  { +    cairo_move_to(ctxcanvas->cr, xc, yc); +    cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*w, -a1*CD_DEG2RAD, -a2*CD_DEG2RAD); +    cairo_fill(ctxcanvas->cr); +  } +  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_move_to(ctxcanvas->cr, xc, yc); +    cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*h, -a1*CD_DEG2RAD, -a2*CD_DEG2RAD); + +    if (ctxcanvas->canvas->interior_style == CD_SOLID || +      ctxcanvas->canvas->interior_style == CD_PATTERN) +      cairo_fill(ctxcanvas->cr); +    else +    { +      cairo_line_to(ctxcanvas->cr, xc, yc); +      cairo_stroke(ctxcanvas->cr); +    } + +    cairo_restore(ctxcanvas->cr);  /* restore from local */ +  } +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ +  cdfsector(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ +  update_fill(ctxcanvas, 1); + +  if (w == h) +  { +    cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*w, -a1*CD_DEG2RAD, -a2*CD_DEG2RAD); +    cairo_fill_preserve(ctxcanvas->cr); +    cairo_stroke(ctxcanvas->cr); +  } +  else  /* Ellipse: change the scale to create from the circle */ +  { +    cairo_save(ctxcanvas->cr);  /* save to use the local transform */ + +    /* local transform */ +    cairo_translate(ctxcanvas->cr, xc, yc); +    cairo_scale(ctxcanvas->cr, 1.0, w/h); + +    cairo_arc_negative(ctxcanvas->cr, xc, yc, 0.5*w, -a1*CD_DEG2RAD, -a2*CD_DEG2RAD); +    cairo_fill_preserve(ctxcanvas->cr); +    cairo_stroke(ctxcanvas->cr); + +    cairo_restore(ctxcanvas->cr);  /* restore from local */ +  } +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ +  cdfchord(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ +  update_fill(ctxcanvas, 0); +  cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1); +  cairo_stroke(ctxcanvas->cr); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ +  cdfrect(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ +  update_fill(ctxcanvas, 1); +  cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1); +  cairo_fill(ctxcanvas->cr); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ +  cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len) +{ +  cairo_text_extents_t extents; +  cairo_font_extents_t font_extents; +  int dir = -1; +  double x_origin = x; +  double y_origin = y; + +  s = StrConvertToUTF8(ctxcanvas, s, len); + +  cairo_set_scaled_font(ctxcanvas->cr, ctxcanvas->font); +  cairo_font_extents(ctxcanvas->cr, &font_extents); +  cairo_text_extents(ctxcanvas->cr, s, &extents); + +  switch (ctxcanvas->canvas->text_alignment) +  { +  case CD_BASE_RIGHT: +  case CD_NORTH_EAST: +  case CD_EAST: +  case CD_SOUTH_EAST: +    x = x - (int)extents.width;  +    break; +  case CD_BASE_CENTER: +  case CD_CENTER: +  case CD_NORTH: +  case CD_SOUTH: +    x = x - (int)(extents.width/2);   +    break; +  case CD_BASE_LEFT: +  case CD_NORTH_WEST: +  case CD_WEST: +  case CD_SOUTH_WEST: +    x = x;          +    break; +  } + +  if (ctxcanvas->canvas->invert_yaxis) +    dir = 1; + +  switch (ctxcanvas->canvas->text_alignment) +  { +  case CD_BASE_LEFT: +  case CD_BASE_CENTER: +  case CD_BASE_RIGHT: +    y = y; +    break; +  case CD_SOUTH_EAST: +  case CD_SOUTH_WEST: +  case CD_SOUTH: +    y = y - dir*(int)font_extents.descent; +    break; +  case CD_NORTH_EAST: +  case CD_NORTH: +  case CD_NORTH_WEST: +    y = y + dir*(int)(extents.height - font_extents.descent); +    break; +  case CD_CENTER: +  case CD_EAST: +  case CD_WEST: +    y = y + dir*(int)(extents.height/2 - font_extents.descent); +    break; +  } + +  if (ctxcanvas->canvas->text_orientation != 0) +  { +    cairo_matrix_t matrix; +    double angle = CD_DEG2RAD * ctxcanvas->canvas->text_orientation; +    double cos_angle = cos(angle); +    double sin_angle = sin(angle); + +    cdfRotatePoint(ctxcanvas->canvas, x, y, x_origin, y_origin, &x, &y, sin_angle, cos_angle); + +    cairo_get_font_matrix(ctxcanvas->cr, &matrix); +    cairo_matrix_rotate(&matrix, -angle); +    cairo_set_font_matrix(ctxcanvas->cr, &matrix); +  } + +  update_fill(ctxcanvas, 0); + +  cairo_move_to(ctxcanvas->cr, x, y); +  cairo_show_text(ctxcanvas->cr, s); +  cairo_fill(ctxcanvas->cr); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ +  cdftext(ctxcanvas, (double)x, (double)y, s, len); +} + +static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int len, int *width, int *height) +{ +  cairo_text_extents_t extents; + +  if (!ctxcanvas->font) +    return; + +  s = StrConvertToUTF8(ctxcanvas, s, len); + +  cairo_set_scaled_font(ctxcanvas->cr, ctxcanvas->font); +  cairo_text_extents(ctxcanvas->cr, s, &extents); + +  if (width) +    *width = (int)extents.width; + +  if (height) +    *height = (int)extents.height; +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ +  int i; + +  if (mode == CD_CLIP) +    return; + +  if (mode == CD_FILL) +  { +    update_fill(ctxcanvas, 1); + +    if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) +      cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_EVEN_ODD); +    else +      cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_WINDING); +  } +  else +    update_fill(ctxcanvas, 0); + +  cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y); + +  if (mode == CD_BEZIER) +  { +    for (i=1; i<n; i+=3) +      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); +  } +  else +  { +    int hole_index = 0; + +    for (i=1; i<n; i++) +    { +      if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) +      { +        cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y); +        hole_index++; +      } +      else +        cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y); +    } +  } + +  switch (mode) +  { +  case CD_CLOSED_LINES : +    cairo_close_path(ctxcanvas->cr); +    cairo_stroke(ctxcanvas->cr); +    break; +  case CD_OPEN_LINES : +    cairo_stroke(ctxcanvas->cr); +    break; +  case CD_BEZIER : +    cairo_stroke(ctxcanvas->cr); +    break; +  case CD_FILL : +    cairo_fill(ctxcanvas->cr); +    break; +  } +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ +  int i; + +  if (mode == CD_CLIP) +    return; + +  if (mode == CD_FILL) +  { +    update_fill(ctxcanvas, 1); + +    if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) +      cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_EVEN_ODD); +    else +      cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_WINDING); +  } +  else +    update_fill(ctxcanvas, 0); + +  cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y); + +  if (mode == CD_BEZIER) +  { +    for (i=1; i<n; i+=3) +      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); +  } +  else +  { +    int hole_index = 0; + +    for (i=1; i<n; i++) +    { +      if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) +      { +        cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y); +        hole_index++; +      } +      else +        cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y); +    } +  } + +  switch (mode) +  { +  case CD_CLOSED_LINES : +    cairo_close_path(ctxcanvas->cr); +    cairo_stroke(ctxcanvas->cr); +    break; +  case CD_OPEN_LINES : +    cairo_stroke(ctxcanvas->cr); +    break; +  case CD_BEZIER : +    cairo_stroke(ctxcanvas->cr); +    break; +  case CD_FILL : +    cairo_fill(ctxcanvas->cr); +    break; +  } +} + +/******************************************************/ + +static void cdgetimagergb(cdCtxCanvas *ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ +  int col, lin, pos; +  double red, green, blue; +  cairo_pattern_t *pattern; + +  cairo_save (ctxcanvas->cr); + +  /* reset to the identity. */ +  cairo_identity_matrix(ctxcanvas->cr); + +  if (ctxcanvas->canvas->invert_yaxis==0) // if 0, invert because the transform was reset here +    y = _cdInvertYAxis(ctxcanvas->canvas, y); + +  //TODO:fix +  pattern = cairo_get_source(ctxcanvas->cr); +  if (!pattern) +    return; + +  for (lin = (y-h+1); lin < h; lin++) +  { +    for (col = x; col < w; col++) +    { +      pos = (h-lin-1) * w + col; +      cairo_pattern_get_color_stop_rgba(pattern, pos, NULL, &red, &green, &blue, NULL); +      *r = (unsigned char)(red*255.0); +      *g = (unsigned char)(green*255.0); +      *b = (unsigned char)(blue*255.0); +    } +  } + +  cairo_pattern_destroy(pattern); +  cairo_restore (ctxcanvas->cr); +} + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ +  int i, j, d, rw, rh; +  unsigned char* rgb_data; +  int stride; +  cairo_surface_t* surface, *new_surface; +  cairo_t* cr; + +  if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + +  rw = xmax-xmin+1; +  rh = ymax-ymin+1; +  y -= (h - 1);        /* Cairo image origin is at top-left */ + +  stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, rw); +  rgb_data = (unsigned char*)malloc(sizeof(unsigned char)*(stride * rh)); + +  if (!rgb_data) return; + +  surface = cairo_image_surface_create_for_data(rgb_data, CAIRO_FORMAT_RGB24, rw, rh, stride); + +  d = 0; +  for (i=ymax; i>=ymin; i--) +  { +    for (j=xmin; j<=xmax; j++) +    { +      rgb_data[d] = b[i*iw+j]; d++; +      rgb_data[d] = g[i*iw+j]; d++; +      rgb_data[d] = r[i*iw+j]; d++; +      rgb_data[d] = (unsigned char)0; d++; +    } +  } + +  /* Scaling surface to fit into the image */ +//  if (w != rw || h != rh) +  { +    new_surface = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR, w, h); +    cr = cairo_create (new_surface); + +    /* Scale *before* setting the source surface (1) */ +    cairo_scale (cr, (double)w / rw, (double)h / rh); +    cairo_set_source_surface (cr, surface, 0, 0); + +    /* To avoid getting the edge pixels blended with 0 alpha, +    * which would occur with the default EXTEND_NONE */ +    cairo_pattern_set_extend (cairo_get_source(cr), CAIRO_EXTEND_REFLECT);  + +    /* Replace the destination with the source instead of overlaying */ +    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + +    cairo_paint (cr); + +    cairo_destroy (cr); +  } + +  /* Put image rect */ +  cairo_set_source_surface(ctxcanvas->cr, new_surface, x, y); +  cairo_pattern_set_extend(cairo_get_source(ctxcanvas->cr), CAIRO_EXTEND_NONE);  +  cairo_paint(ctxcanvas->cr); + +  cairo_surface_destroy(surface); +  cairo_surface_destroy(new_surface); +  free(rgb_data); +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ +  int i, j, d, rw, rh; +  unsigned char* rgba_data; +  int stride; +  cairo_surface_t* surface, *new_surface, *new_alpha_surface; +  cairo_t* cr; + +  if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + +  rw = xmax-xmin+1; +  rh = ymax-ymin+1; +  y -= (h - 1);        /* Cairo image origin is at top-left */ + +  stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, rw); +  rgba_data = (unsigned char*)malloc(sizeof(unsigned char)*(stride * rh)); +   +  if (!rgba_data) return; + +  surface = cairo_image_surface_create_for_data(rgba_data, CAIRO_FORMAT_ARGB32, rw, rh, stride); + +  d = 0; +  for (i=ymax; i>=ymin; i--) +  { +    for (j=xmin; j<=xmax; j++) +    { +      rgba_data[d] = b[i*iw+j]; d++; +      rgba_data[d] = g[i*iw+j]; d++; +      rgba_data[d] = r[i*iw+j]; d++; +      rgba_data[d] = a[i*iw+j]; d++; +    } +  } + +  // TODO: use only one surface ????? + +  /* Scaling RGB surface to fit into the image */ +//  if (w != rw || h != rh) +  { +    new_surface = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR, w, h); +    cr = cairo_create (new_surface); + +    /* Scale *before* setting the source surface (1) */ +    cairo_scale (cr, (double)w / rw, (double)h / rh); +    cairo_set_source_surface (cr, surface, 0, 0); +    cairo_paint (cr); + +    cairo_destroy (cr); +  } + +  /* Scaling ALPHA surface to fit into the image */ +  { +    new_alpha_surface = cairo_surface_create_similar(surface, CAIRO_CONTENT_ALPHA, w, h); +    cr = cairo_create (new_alpha_surface); + +    /* Scale *before* setting the source surface (1) */ +    cairo_scale (cr, (double)w / rw, (double)h / rh); +    cairo_set_source_surface (cr, surface, 0, 0); +    cairo_paint (cr); + +    cairo_destroy (cr); +  } + +  /* Put image rect */ +  cairo_set_source_surface(ctxcanvas->cr, new_surface, x, y); +  cairo_mask_surface(ctxcanvas->cr, new_alpha_surface, x, y); +//  cairo_pattern_set_extend(cairo_get_source(ctxcanvas->cr), CAIRO_EXTEND_NONE);  +//  cairo_paint(ctxcanvas->cr); + +  cairo_surface_destroy(surface); +  cairo_surface_destroy(new_surface); +  cairo_surface_destroy(new_alpha_surface); +  free(rgba_data); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ +  int i, j, d, rw, rh; +  unsigned char* rgb_data; +  int stride; +  cairo_surface_t* surface, *new_surface; +  cairo_t* cr; + +  if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + +  rw = xmax-xmin+1; +  rh = ymax-ymin+1; +  y -= (h - 1);        /* Cairo image origin is at top-left */ + +  stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, rw); +  rgb_data = (unsigned char*)malloc(sizeof(unsigned char)*(stride * rh)); + +  if (!rgb_data) return; + +  surface = cairo_image_surface_create_for_data(rgb_data, CAIRO_FORMAT_RGB24, rw, rh, stride); + +  d = 0; +  for (i=ymax; i>=ymin; i--) +  { +    for (j=xmin; j<=xmax; j++) +    { +      long c = colors[index[i*iw+j]]; +      rgb_data[d] = cdRed(c); d++; +      rgb_data[d] = cdGreen(c); d++; +      rgb_data[d] = cdBlue(c); d++; +      rgb_data[d] = (unsigned char)0; d++; +    } +  } + +  /* Scaling surface to fit into the image */ +//  if (w != rw || h != rh) +  { +    new_surface = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR, w, h); +    cr = cairo_create (new_surface); + +    /* Scale *before* setting the source surface (1) */ +    cairo_scale (cr, (double)w / rw, (double)h / rh); +    cairo_set_source_surface (cr, surface, 0, 0); + +    /* To avoid getting the edge pixels blended with 0 alpha, +    * which would occur with the default EXTEND_NONE */ +    cairo_pattern_set_extend (cairo_get_source(cr), CAIRO_EXTEND_REFLECT);  + +    /* Replace the destination with the source instead of overlaying */ +    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + +    cairo_paint (cr); + +    cairo_destroy (cr); +  } + +  cairo_set_source_surface(ctxcanvas->cr, surface, x, y); +  cairo_pattern_set_extend(cairo_get_source(ctxcanvas->cr), CAIRO_EXTEND_NONE);  +  cairo_paint(ctxcanvas->cr); + +  cairo_surface_destroy(surface); +  cairo_surface_destroy(new_surface); +  free(rgb_data); +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ +  cairo_pattern_t* old_source = cairo_get_source(ctxcanvas->cr); +  cairo_set_source_rgba(ctxcanvas->cr, cdCairoGetRed(color), cdCairoGetGreen(color), cdCairoGetBlue(color), cdCairoGetAlpha(color)); + +  cairo_move_to(ctxcanvas->cr, (double)x, (double)y); +  cairo_arc(ctxcanvas->cr, (double)x, (double)y, 0.5, 0.0, 2 * M_PI); + +  cairo_fill(ctxcanvas->cr); +  cairo_set_source(ctxcanvas->cr, old_source); +} + +static cdCtxImage *cdcreateimage (cdCtxCanvas *ctxcanvas, int w, int h) +{ +  cdCtxImage *ctximage = (cdCtxImage *)malloc(sizeof(cdCtxImage)); +  cairo_surface_t* img_surface; + +  ctximage->w = w; +  ctximage->h = h; +  ctximage->bpp = ctxcanvas->canvas->bpp; +  ctximage->xres = ctxcanvas->canvas->xres; +  ctximage->yres = ctxcanvas->canvas->yres; +  ctximage->w_mm = ctximage->w / ctximage->xres; +  ctximage->h_mm = ctximage->h / ctximage->yres; + +  img_surface = cairo_surface_create_similar(cairo_get_target(ctxcanvas->cr), CAIRO_CONTENT_COLOR_ALPHA, w, h); +  ctximage->img = cairo_create(img_surface); + +  if (!ctximage->img) +  { +    free(ctximage); +    return (void *)0; +  } + +  cairo_rectangle(ctximage->img, 0, 0, ctximage->w, ctximage->h); +  cairo_set_source_rgba(ctximage->img, 1.0, 1.0, 1.0, 1.0); /* white opaque */ +  cairo_fill(ctximage->img); + +  cairo_surface_destroy(img_surface); + +  return (void*)ctximage; +} + +static void cdkillimage (cdCtxImage *ctximage) +{ +  cairo_destroy(ctximage->img); +  free(ctximage); +} + +static void cdgetimage (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y) +{ +  cairo_save (ctximage->img); + +  /* reset to the identity. */ +  cairo_identity_matrix(ctximage->img); + +  cairo_reset_clip(ctximage->img); + +  if (ctxcanvas->canvas->invert_yaxis==0)  /* if 0, invert because the transform was reset here */ +    y = _cdInvertYAxis(ctxcanvas->canvas, y); + +  /* y is the bottom-left of the image in CD, must be at upper-left */ +  y -= ctximage->h-1; + +  /* creates a pattern from the canvas and sets it as source in the image. */ +  cairo_set_source_surface(ctximage->img, cairo_get_target(ctxcanvas->cr), x, y); + +  cairo_pattern_set_extend (cairo_get_source(ctximage->img), CAIRO_EXTEND_NONE);  +  cairo_set_operator (ctximage->img, CAIRO_OPERATOR_SOURCE); +  cairo_paint(ctximage->img);  /* paints the current source everywhere within the current clip region. */ + +  /* must restore matrix, clipping and source */ +  cairo_restore (ctximage->img); +} + +static void cdputimagerect (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ +  cairo_save (ctxcanvas->cr); + +  /* y is the bottom-left of the image region in CD */ +  y -= (ymax-ymin+1)-1; + +  cairo_reset_clip(ctxcanvas->cr); +  cairo_rectangle(ctxcanvas->cr, x, y, xmax-xmin+1, ymax-ymin+1); +  cairo_clip(ctxcanvas->cr); + +  ymin = (ctximage->h-1) - ymax; /* ymin starts at the bottom of the image in CD, we want ymax, but oriented top-down */ + +  /* creates a pattern from the image and sets it as source in the canvas. */ +  cairo_set_source_surface(ctxcanvas->cr, cairo_get_target(ctximage->img), xmin, ymin); + +  cairo_pattern_set_extend (cairo_get_source(ctxcanvas->cr), CAIRO_EXTEND_NONE);  +  cairo_set_operator (ctxcanvas->cr, CAIRO_OPERATOR_SOURCE); +  cairo_paint(ctxcanvas->cr);  /* paints the current source everywhere within the current clip region. */ + +  /* must restore clipping and source */ +  cairo_restore (ctxcanvas->cr); +} + +static void cdscrollarea (cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ +  cairo_save (ctxcanvas->cr); + +  /* reset to identity */ +  cairo_identity_matrix(ctxcanvas->cr); + +  if (ctxcanvas->canvas->invert_yaxis==0)  /* if 0, invert because the transform was reset here */ +  { +    dy = -dy; +    ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin); +    ymax = _cdInvertYAxis(ctxcanvas->canvas, ymax); +    _cdSwapInt(ymin, ymax); +  } + +  cairo_reset_clip(ctxcanvas->cr); +  cairo_rectangle(ctxcanvas->cr, xmin+dx, ymin+dy, xmax-xmin+1, ymax-ymin+1); +  cairo_clip(ctxcanvas->cr); + +  /* creates a pattern from the canvas and sets it as source in the canvas. */ +  cairo_set_source_surface(ctxcanvas->cr, cairo_get_target(ctxcanvas->cr), xmin, ymin); + +  cairo_pattern_set_extend (cairo_get_source(ctxcanvas->cr), CAIRO_EXTEND_NONE);  +  cairo_set_operator (ctxcanvas->cr, CAIRO_OPERATOR_SOURCE); +  cairo_paint(ctxcanvas->cr);  /* paints the current source everywhere within the current clip region. */ + +  /* must restore matrix, clipping and source */ +  cairo_restore (ctxcanvas->cr); +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ +  /* reset to identity */ +  cairo_identity_matrix(ctxcanvas->cr); +  ctxcanvas->canvas->invert_yaxis = 1; + +  if (matrix) +  { +    cairo_matrix_t mtx; + +    /* configure a bottom-up coordinate system */ +    mtx.xx = 1; mtx.yx = 0; +    mtx.xy = 0; mtx.yy = -1; +    mtx.x0 = 0; mtx.y0 = (ctxcanvas->canvas->h-1); +    cairo_transform(ctxcanvas->cr, &mtx); +    ctxcanvas->canvas->invert_yaxis = 0; + +    mtx.xx = matrix[0]; mtx.yx = matrix[1]; +    mtx.xy = matrix[2]; mtx.yy = matrix[3]; +    mtx.x0 = matrix[4]; mtx.y0 = matrix[5]; +    cairo_transform(ctxcanvas->cr, &mtx); +  } +  else if (ctxcanvas->rotate_angle) +  { +    /* rotation = translate to point + rotation + translate back */ +    /* the rotation must be corrected because of the Y axis orientation */ +    cairo_translate(ctxcanvas->cr, ctxcanvas->rotate_center_x, _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); +    cairo_rotate(ctxcanvas->cr, (double)-ctxcanvas->rotate_angle * CD_DEG2RAD); +    cairo_translate(ctxcanvas->cr, -ctxcanvas->rotate_center_x, -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); +  } +} + +/******************************************************************/ + +static void set_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ +  int hatchboxsize; + +  if (data == NULL) +  { +    ctxcanvas->hatchboxsize = 8; +    return; +  } + +  sscanf(data, "%d", &hatchboxsize); +  ctxcanvas->hatchboxsize = hatchboxsize; +} + +static char* get_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas) +{ +  static char size[10]; +  sprintf(size, "%d", ctxcanvas->hatchboxsize); +  return size; +} + +static cdAttribute hatchboxsize_attrib = +{ +  "HATCHBOXSIZE", +  set_hatchboxsize_attrib, +  get_hatchboxsize_attrib +};  + +static void set_poly_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ +  int hole; + +  if (data == NULL) +  { +    ctxcanvas->holes = 0; +    return; +  } + +  sscanf(data, "%d", &hole); +  ctxcanvas->poly_holes[ctxcanvas->holes] = hole; +  ctxcanvas->holes++; +} + +static char* get_poly_attrib(cdCtxCanvas *ctxcanvas) +{ +  static char holes[10]; +  sprintf(holes, "%d", ctxcanvas->holes); +  return holes; +} + +static cdAttribute poly_attrib = +{ +  "POLYHOLE", +  set_poly_attrib, +  get_poly_attrib +};  + +static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ +  /* ignore ROTATE if transform is set,  +     because there is native support for transformations */ +  if (ctxcanvas->canvas->use_matrix) +    return; + +  if (data) +  { +    sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, +                             &ctxcanvas->rotate_center_x, +                             &ctxcanvas->rotate_center_y); +  } +  else +  { +    ctxcanvas->rotate_angle = 0; +    ctxcanvas->rotate_center_x = 0; +    ctxcanvas->rotate_center_y = 0; +  } + +  cdtransform(ctxcanvas, NULL); +} + +static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) +{ +  static char data[100]; + +  if (!ctxcanvas->rotate_angle) +    return NULL; + +  sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, +    ctxcanvas->rotate_center_x, +    ctxcanvas->rotate_center_y); + +  return data; +} + +static cdAttribute rotate_attrib = +{ +  "ROTATE", +  set_rotate_attrib, +  get_rotate_attrib +};  + +static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ +  cairo_font_options_t* options = NULL; +  cairo_scaled_font_get_font_options(ctxcanvas->font, options); + +  if (!data || data[0] == '0') +  { +    cairo_set_antialias(ctxcanvas->cr, CAIRO_ANTIALIAS_NONE); +    cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_NONE); +  } +  else +  { +    cairo_set_antialias(ctxcanvas->cr, CAIRO_ANTIALIAS_DEFAULT); +    cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_DEFAULT); +  } +   +  cairo_font_options_destroy(options); +} + +static char* get_aa_attrib(cdCtxCanvas* ctxcanvas) +{ +  if (cairo_get_antialias(ctxcanvas->cr) != CAIRO_ANTIALIAS_NONE) +    return "1"; +  else +    return "0"; +} + +static cdAttribute aa_attrib = +{ +  "ANTIALIAS", +  set_aa_attrib, +  get_aa_attrib +};  + +static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ +  if (data) +  { +    int x1, y1, x2, y2; +    double offset; +    int count = 1; + +    sscanf(data, "%d %d %d %d", &x1, &y1, &x2, &y2); + +    if (ctxcanvas->canvas->invert_yaxis) +    { +      y1 = _cdInvertYAxis(ctxcanvas->canvas, y1); +      y2 = _cdInvertYAxis(ctxcanvas->canvas, y2); +    } + +    if (ctxcanvas->pattern) +      cairo_pattern_destroy(ctxcanvas->pattern); + +    ctxcanvas->pattern = cairo_pattern_create_linear((double)x1, (double)y1, (double)x2, (double)y2); +    cairo_pattern_reference(ctxcanvas->pattern); + +    for(offset = 0.1; offset < 1.0; offset += 0.1) +    { +      if ( count % 2 ) +      { +        cairo_pattern_add_color_stop_rgb(ctxcanvas->pattern, offset, +          cdCairoGetRed(ctxcanvas->canvas->foreground), +          cdCairoGetGreen(ctxcanvas->canvas->foreground), +          cdCairoGetBlue(ctxcanvas->canvas->foreground)); +      } +      else +      { +        cairo_pattern_add_color_stop_rgb(ctxcanvas->pattern, offset, +          cdCairoGetRed(ctxcanvas->canvas->background), +          cdCairoGetGreen(ctxcanvas->canvas->background), +          cdCairoGetBlue(ctxcanvas->canvas->background)); +      } +      count++; +    } + +    cairo_pattern_set_extend(ctxcanvas->pattern, CAIRO_EXTEND_REPEAT); + +    cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern); +    ctxcanvas->last_source = 1; +  } +} + +static char* get_linegradient_attrib(cdCtxCanvas* ctxcanvas) +{ +  double x1, y1, x2, y2; + +  if (cairo_pattern_get_linear_points(ctxcanvas->pattern, &x1, &y1, &x2, &y2) == CAIRO_STATUS_SUCCESS) +  { +    static char data[100]; +    sprintf(data, "%d %d %d %d", (int)x1, (int)y1, (int)x2, (int)y2); +    return data; +  } +  else +    return NULL; +} + +static cdAttribute linegradient_attrib = +{ +  "LINEGRADIENT", +  set_linegradient_attrib, +  get_linegradient_attrib +};  + +static void set_radialgradient_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ +  if (data) +  { +    int cx1, cy1, cx2, cy2; +    float rad1, rad2; +    double offset; +    int count = 1; + +    sscanf(data, "%d %d %g %d %d %g", &cx1, &cy1, &rad1, &cx2, &cy2, &rad2); + +    if (ctxcanvas->canvas->invert_yaxis) +    { +      cy1 = _cdInvertYAxis(ctxcanvas->canvas, cy1); +      cy2 = _cdInvertYAxis(ctxcanvas->canvas, cy2); +    } + +    if (ctxcanvas->pattern) +      cairo_pattern_destroy(ctxcanvas->pattern); + +    ctxcanvas->pattern = cairo_pattern_create_radial((double)cx1, (double)cx1, (double)rad1, (double)cx2, (double)cx2, (double)rad2); +    cairo_pattern_reference(ctxcanvas->pattern); + +    for(offset = 0.1; offset < 1.0; offset += 0.1) +    { +      if ( count % 2 ) +      { +        cairo_pattern_add_color_stop_rgb(ctxcanvas->pattern, offset, +          cdCairoGetRed(ctxcanvas->canvas->foreground), +          cdCairoGetGreen(ctxcanvas->canvas->foreground), +          cdCairoGetBlue(ctxcanvas->canvas->foreground)); +      } +      else +      { +        cairo_pattern_add_color_stop_rgb(ctxcanvas->pattern, offset, +          cdCairoGetRed(ctxcanvas->canvas->background), +          cdCairoGetGreen(ctxcanvas->canvas->background), +          cdCairoGetBlue(ctxcanvas->canvas->background)); +      } +      count++; +    } + +    cairo_pattern_set_extend(ctxcanvas->pattern, CAIRO_EXTEND_REPEAT); + +    cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern); +    ctxcanvas->last_source = 1; +  } +} + +static char* get_radialgradient_attrib(cdCtxCanvas* ctxcanvas) +{ +  double cx1, cy1, rad1, cx2, cy2, rad2; + +  if (cairo_pattern_get_radial_circles(ctxcanvas->pattern, &cx1, &cy1, &rad1, &cx2, &cy2, &rad2) == CAIRO_STATUS_SUCCESS) +  { +    static char data[100]; +    sprintf(data, "%d %d %g %d %d %g", (int)cx1, (int)cy1, (float)rad1, (int)cx2, (int)cy2, (float)rad2); +    return data; +  } +  else +    return NULL; +} + +static cdAttribute radialgradient_attrib = +{ +  "RADIALGRADIENT", +  set_radialgradient_attrib, +  get_radialgradient_attrib +};  + +static char* get_version_attrib(cdCtxCanvas* ctxcanvas) +{ +  (void)ctxcanvas; +  return (char*)cairo_version_string(); +} + +static cdAttribute version_attrib = +{ +  "CAIROVERSION", +  NULL, +  get_version_attrib +}; + +static void set_interp_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ +  if (data && cdStrEqualNoCase(data, "BEST")) +    cairo_pattern_set_filter(cairo_get_source(ctxcanvas->cr), CAIRO_FILTER_BEST); +  else if (data && cdStrEqualNoCase(data, "NEAREST")) +    cairo_pattern_set_filter(cairo_get_source(ctxcanvas->cr), CAIRO_FILTER_NEAREST); +  else if (data && cdStrEqualNoCase(data, "FAST")) +    cairo_pattern_set_filter(cairo_get_source(ctxcanvas->cr), CAIRO_FILTER_FAST); +  else if (data && cdStrEqualNoCase(data, "BILINEAR")) +    cairo_pattern_set_filter(cairo_get_source(ctxcanvas->cr), CAIRO_FILTER_BILINEAR); +  else +    cairo_pattern_set_filter(cairo_get_source(ctxcanvas->cr), CAIRO_FILTER_GOOD); +} + +static char* get_interp_attrib(cdCtxCanvas* ctxcanvas) +{ +  if(cairo_pattern_get_filter(cairo_get_source(ctxcanvas->cr)) == CAIRO_FILTER_BEST) +    return "BEST"; +  else if(cairo_pattern_get_filter(cairo_get_source(ctxcanvas->cr)) == CAIRO_FILTER_NEAREST) +    return "NEAREST"; +  else if(cairo_pattern_get_filter(cairo_get_source(ctxcanvas->cr)) == CAIRO_FILTER_FAST) +    return "FAST"; +  else if(cairo_pattern_get_filter(cairo_get_source(ctxcanvas->cr)) == CAIRO_FILTER_BILINEAR) +    return "BILINEAR"; +  else +    return "GOOD"; +} + +static cdAttribute interp_attrib = +{ +  "IMGINTERP", +  set_interp_attrib, +  get_interp_attrib +}; + +static char* get_cairodc_attrib(cdCtxCanvas *ctxcanvas) +{ +  return (char*)ctxcanvas->cr; +} + +static cdAttribute cairodc_attrib = +{ +  "CAIRODC", +  NULL, +  get_cairodc_attrib +};  + + +cdCtxCanvas *cdcairoCreateCanvas(cdCanvas* canvas, cairo_t* cr) +{ +  cdCtxCanvas *ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); +  memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + +  ctxcanvas->cr = cr; +  ctxcanvas->canvas = canvas; +  ctxcanvas->last_source = -1; + +  canvas->ctxcanvas = ctxcanvas; +  canvas->invert_yaxis = 1; + +  cdRegisterAttribute(canvas, &rotate_attrib); +  cdRegisterAttribute(canvas, &version_attrib); +  cdRegisterAttribute(canvas, &poly_attrib); +  cdRegisterAttribute(canvas, &aa_attrib); +  cdRegisterAttribute(canvas, &linegradient_attrib); +  cdRegisterAttribute(canvas, &radialgradient_attrib); +  cdRegisterAttribute(canvas, &interp_attrib); +  cdRegisterAttribute(canvas, &cairodc_attrib); +  cdRegisterAttribute(canvas, &hatchboxsize_attrib); + +  cairo_save(ctxcanvas->cr); +  cairo_set_operator(ctxcanvas->cr, CAIRO_OPERATOR_OVER); + +  return ctxcanvas; +} + +void cdcairoInitTable(cdCanvas* canvas) +{ +  canvas->cxFlush = cdflush; +  canvas->cxClear = cdclear; + +  canvas->cxPixel  = cdpixel; + +  canvas->cxLine   = cdline; +  canvas->cxPoly   = cdpoly; +  canvas->cxRect   = cdrect; +  canvas->cxBox    = cdbox; +  canvas->cxArc    = cdarc; +  canvas->cxSector = cdsector; +  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->cxFText = cdftext; + +  canvas->cxClip = cdclip; +  canvas->cxClipArea = cdcliparea; +  canvas->cxLineStyle = cdlinestyle; +  canvas->cxLineWidth = cdlinewidth; +  canvas->cxLineCap = cdlinecap; +  canvas->cxLineJoin = cdlinejoin; +  canvas->cxInteriorStyle = cdinteriorstyle; +  canvas->cxHatch = cdhatch; +  canvas->cxStipple = cdstipple; +  canvas->cxPattern = cdpattern; +  canvas->cxFont = cdfont; +  canvas->cxGetFontDim = cdgetfontdim; +  canvas->cxGetTextSize = cdgettextsize; +  canvas->cxTransform = cdtransform; +  canvas->cxWriteMode = cdwritemode; +  canvas->cxForeground = cdforeground; + +  canvas->cxGetImageRGB = cdgetimagergb; +  canvas->cxScrollArea = cdscrollarea; + +  canvas->cxCreateImage = cdcreateimage; +  canvas->cxGetImage = cdgetimage; +  canvas->cxPutImageRect = cdputimagerect; +  canvas->cxKillImage = cdkillimage; + +  canvas->cxPutImageRectRGB = cdputimagerectrgb; +  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/cdcairoctx.h b/src/cairo/cdcairoctx.h new file mode 100644 index 0000000..266cfb3 --- /dev/null +++ b/src/cairo/cdcairoctx.h @@ -0,0 +1,77 @@ +/** \file + * \brief Cairo Base Driver + * + * See Copyright Notice in cd.h + */ + +#ifndef __CDCAIROCTX_H +#define __CDCAIROCTX_H + +#include <cairo.h> + +#include "cd.h" +#include "cd_private.h" + + +struct _cdCtxImage { +  unsigned int w, h; +  double w_mm, h_mm;   /* size in mm                                  */                   +  double xres, yres;   /* resolution in pixels/mm                     */      +  int bpp; +  cairo_t* img; +}; + +struct _cdCtxCanvas +{ +  cdCanvas* canvas; + +  cairo_t* cr; + +  cairo_scaled_font_t* font; + +  cairo_pattern_t *pattern, *solid; +  int last_source; + +  char* cairoLastConvertUTF8; + +  /* custom attributes */ + +  int img_format; + +  float rotate_angle; +  int rotate_center_x; +  int rotate_center_y; + +  int poly_holes[500]; +  int holes; + +  void* drawable;    /* used in NativeWindow in GDK */ + +#ifdef WIN32 +  void* hWnd;        /* used in NativeWindow in Win32 */ +  void* hDC;   +  int isOwnedDC; +#else +  void* dpy;         /* used in NativeWindow in X11 */ +  unsigned long wnd;           +#endif + +  int user_image;   /* used in ImageRGB */ +  unsigned char *rgb; + +  int eps;  /* used in PS */ + +  cdImage* image_dbuffer;       /* Used by double buffer driver */ +  cdCanvas* canvas_dbuffer; +}; + +#define cdCairoGetRed(_)   (((double)cdRed(_))/255.) +#define cdCairoGetGreen(_) (((double)cdGreen(_))/255.) +#define cdCairoGetBlue(_)  (((double)cdBlue(_))/255.) +#define cdCairoGetAlpha(_)  (((double)cdAlpha(_))/255.) + +cdCtxCanvas *cdcairoCreateCanvas(cdCanvas* canvas, cairo_t* cr); +void cdcairoInitTable(cdCanvas* canvas); +void cdcairoKillCanvas(cdCtxCanvas *ctxcanvas); + +#endif diff --git a/src/cairo/cdcairodbuf.c b/src/cairo/cdcairodbuf.c new file mode 100644 index 0000000..0e23f06 --- /dev/null +++ b/src/cairo/cdcairodbuf.c @@ -0,0 +1,170 @@ +/** \file + * \brief Cairo Double Buffer Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdcairoctx.h" +#include "cddbuf.h" +#include <stdlib.h> +#include <stdio.h> + + +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ +  cdKillImage(ctxcanvas->image_dbuffer); +  cdcairoKillCanvas(ctxcanvas); +} + +static void cddeactivate(cdCtxCanvas* ctxcanvas) +{ +  cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; +  /* this is done in the canvas_dbuffer context */ +  cdCanvasDeactivate(canvas_dbuffer); +} + +static void cdflush(cdCtxCanvas* ctxcanvas) +{ +  int old_writemode; +  cdImage* image_dbuffer = ctxcanvas->image_dbuffer; +  cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + +  /* flush the writing in the image */ +  cairo_show_page(ctxcanvas->cr); + +  /* this is done in the canvas_dbuffer context */ +  /* Flush can be affected by Origin and Clipping, but not WriteMode */ +  old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE); +  cdCanvasPutImageRect(canvas_dbuffer, image_dbuffer, 0, 0, 0, 0, 0, 0); +  cdCanvasWriteMode(canvas_dbuffer, old_writemode); +} + +static void cdcreatecanvas(cdCanvas* canvas, cdCanvas* canvas_dbuffer) +{ +  int w, h; +  cdCtxCanvas* ctxcanvas; +  cdImage* image_dbuffer; +  cdCtxImage* ctximage; + +  cdCanvasActivate(canvas_dbuffer); +  w = canvas_dbuffer->w; +  h = canvas_dbuffer->h; +  if (w==0) w=1; +  if (h==0) h=1; + +  /* this is done in the canvas_dbuffer context */ +  image_dbuffer = cdCanvasCreateImage(canvas_dbuffer, w, h); +  if (!image_dbuffer)  +    return; + +  ctximage = image_dbuffer->ctximage; + +  /* Init the driver DBuffer */ +  ctxcanvas = cdcairoCreateCanvas(canvas, ctximage->img); + +  if (!ctxcanvas) +    return; + +  ctxcanvas->image_dbuffer = image_dbuffer; +  ctxcanvas->canvas_dbuffer = canvas_dbuffer; + +  canvas->w = ctximage->w; +  canvas->h = ctximage->h; +  canvas->w_mm = ctximage->w_mm; +  canvas->h_mm = ctximage->h_mm; +  canvas->bpp = ctximage->bpp; +  canvas->xres = ctximage->xres; +  canvas->yres = ctximage->yres; +} + +static int cdactivate(cdCtxCanvas* ctxcanvas) +{ +  int w, h; +  cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + +  /* this is done in the canvas_dbuffer context */ +  /* this will update canvas size */ +  cdCanvasActivate(canvas_dbuffer); +  w = canvas_dbuffer->w; +  h = canvas_dbuffer->h; +  if (w==0) w=1; +  if (h==0) h=1; + +  /* check if the size changed */ +  if (w != ctxcanvas->image_dbuffer->w || +      h != ctxcanvas->image_dbuffer->h) +  { +    cdCanvas* canvas = ctxcanvas->canvas; +    /* save the current, if the rebuild fail */ +    cdImage* old_image_dbuffer = ctxcanvas->image_dbuffer; +    cdCtxCanvas* old_ctxcanvas = ctxcanvas; + +    /* if the image is rebuild, the canvas that uses the image must be also rebuild */ + +    /* rebuild the image and the canvas */ +    canvas->ctxcanvas = NULL; +    canvas->context->cxCreateCanvas(canvas, canvas_dbuffer); +    if (!canvas->ctxcanvas) +    { +      canvas->ctxcanvas = old_ctxcanvas; +      return CD_ERROR; +    } + +    /* remove the old image and canvas */ +    cdKillImage(old_image_dbuffer); +    cdcairoKillCanvas(old_ctxcanvas); + +    ctxcanvas = canvas->ctxcanvas; + +    /* update canvas attributes */ +    canvas->cxBackground(ctxcanvas, canvas->background); +    canvas->cxForeground(ctxcanvas, canvas->foreground); +    canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity); +    canvas->cxWriteMode(ctxcanvas, canvas->write_mode); +    canvas->cxLineStyle(ctxcanvas, canvas->line_style); +    canvas->cxLineWidth(ctxcanvas, canvas->line_width); +    canvas->cxLineCap(ctxcanvas, canvas->line_cap); +    canvas->cxLineJoin(ctxcanvas, canvas->line_join); +    canvas->cxHatch(ctxcanvas, canvas->hatch_style); +    if (canvas->stipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple); +    if (canvas->pattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern); +    canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style); +    if (canvas->native_font[0] == 0) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); +    else canvas->cxNativeFont(ctxcanvas, canvas->native_font); +/*    canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment);     */ +/*    canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation); */ +    if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax); +/*    if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax); */ +    if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n); +/*    if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n); */ +    if (canvas->clip_mode != CD_CLIPOFF) canvas->cxClip(ctxcanvas, canvas->clip_mode); +  } + +  return CD_OK; +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); + +  canvas->cxActivate = cdactivate; +  canvas->cxDeactivate = cddeactivate; +  canvas->cxFlush = cdflush; +  canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdDBufferContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS |  +                 CD_CAP_FPRIMTIVES ), +  0, +  cdcreatecanvas,   +  cdinittable, +  NULL,              +  NULL,  +}; + +cdContext* cdContextCairoDBuffer(void) +{ +  return &cdDBufferContext; +} diff --git a/src/cairo/cdcairoimg.c b/src/cairo/cdcairoimg.c new file mode 100644 index 0000000..54c2fa7 --- /dev/null +++ b/src/cairo/cdcairoimg.c @@ -0,0 +1,52 @@ +/** \file + * \brief Cairo Image Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdlib.h> + +#include "cdcairoctx.h" +#include "cdimage.h" + + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ +  cdcairoKillCanvas(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ +  cdCtxImage *ctximage = ((cdImage*)data)->ctximage; +  cdcairoCreateCanvas(canvas, (cairo_t*)ctximage->img); +  canvas->w = ctximage->w; +  canvas->h = ctximage->h; +  canvas->w_mm = ctximage->w_mm; +  canvas->h_mm = ctximage->h_mm; +  canvas->bpp = ctximage->bpp; +  canvas->xres = ctximage->xres; +  canvas->yres = ctximage->yres; +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); + +  canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdImageContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ), +  0, +  cdcreatecanvas, +  cdinittable, +  NULL, +  NULL +}; + + +cdContext* cdContextCairoImage(void) +{ +  return &cdImageContext; +} diff --git a/src/cairo/cdcairoirgb.c b/src/cairo/cdcairoirgb.c new file mode 100644 index 0000000..1bb9698 --- /dev/null +++ b/src/cairo/cdcairoirgb.c @@ -0,0 +1,159 @@ +/** \file + * \brief Cairo IMAGERGB Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "cd.h" +#include "cdcairo.h" +#include "cdcairoctx.h" + + +static char* get_stride_attrib(cdCtxCanvas* ctxcanvas) +{ +  static char data[100]; +  sprintf(data, "%d", cairo_image_surface_get_stride(cairo_get_target(ctxcanvas->cr))); +  return data; +} + +static cdAttribute stride_attrib = +{ +  "STRIDE", +  NULL, +  get_stride_attrib +};  + +static void set_write2png_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ +  if (data) +    cairo_surface_write_to_png(cairo_get_target(ctxcanvas->cr), data); +} + +static cdAttribute write2png_attrib = +{ +  "WRITE2PNG", +  set_write2png_attrib, +  NULL +};  + +static char* get_data_attrib(cdCtxCanvas* ctxcanvas) +{ +  return (char*)ctxcanvas->rgb; +} + +static cdAttribute data_attrib = +{ +  "RGBDATA", +  NULL, +  get_data_attrib +};  + +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ +  if (!ctxcanvas->user_image) +    free(ctxcanvas->rgb); + +  cdcairoKillCanvas(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ +  cdCtxCanvas* ctxcanvas; +  cairo_surface_t *surface; +  int w = 0, h = 0, use_alpha = 0; +  float res = (float)3.78; +  unsigned char *rgb = NULL; +  char* str_data = (char*)data; +  char* res_ptr = NULL; +  cairo_format_t format = CAIRO_FORMAT_RGB24; + +  /* Starting parameters */ +  if (str_data == NULL)  +    return; + +  if (strstr(str_data, "-a")) +    use_alpha = 1; + +  res_ptr = strstr(str_data, "-r"); +  if (res_ptr) +    sscanf(res_ptr+2, "%g", &res); + +  /* size and rgb */ +#ifdef SunOS_OLD +  sscanf(str_data, "%dx%d %d", &w, &h, &rgb); +#else +  sscanf(str_data, "%dx%d %p", &w, &h, &rgb); +#endif + +  if (w == 0 || h == 0) +    return; + +  canvas->w = w; +  canvas->h = h; +  canvas->yres = res; +  canvas->xres = res; +  canvas->w_mm = ((double)w) / res; +  canvas->h_mm = ((double)h) / res; +  if (use_alpha) +  { +    canvas->bpp = 32; +    format = CAIRO_FORMAT_ARGB32; +  } +  else +    canvas->bpp = 24;  /* fake value, image bpp is always 32 */ + +  if (rgb) +    surface = cairo_image_surface_create_for_data(rgb, format, w, h, w*32); +  else +  	surface = cairo_image_surface_create(format, canvas->w, canvas->h); + +  /* Starting Cairo driver */ +  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); +  cairo_surface_destroy(surface); + +  if (rgb) +  { +    ctxcanvas->user_image = 1; +    ctxcanvas->rgb = rgb; +  } +  else +  { +    ctxcanvas->user_image = 0; +    ctxcanvas->rgb = cairo_image_surface_get_data(cairo_get_target(ctxcanvas->cr)); + +    /* fill with white */ +    /* transparent, this is the normal alpha coding */ +    cairo_set_source_rgba(ctxcanvas->cr, 1.0, 1.0, 1.0, 0.0); +    cairo_rectangle(ctxcanvas->cr, 0, 0, canvas->w, canvas->h); +    cairo_fill(ctxcanvas->cr); +  } +                                       +  cdRegisterAttribute(canvas, &stride_attrib); +  cdRegisterAttribute(canvas, &write2png_attrib); +  cdRegisterAttribute(canvas, &data_attrib); +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); +  canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdCairoImageRGBContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_FPRIMTIVES), +  0, +  cdcreatecanvas,   +  cdinittable, +  NULL,                  +  NULL +}; + +cdContext* cdContextCairoImageRGB(void) +{ +  return &cdCairoImageRGBContext; +} diff --git a/src/cairo/cdcaironative_gdk.c b/src/cairo/cdcaironative_gdk.c new file mode 100644 index 0000000..98face0 --- /dev/null +++ b/src/cairo/cdcaironative_gdk.c @@ -0,0 +1,80 @@ +/** \file +* \brief Cairo Native Window Driver +* +* See Copyright Notice in cd.h +*/ + +#include <stdlib.h> +#include <stdio.h> + +#include <gdk/gdk.h> + +#include "cdcairoctx.h" +#include "cdnative.h" + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ +  cdcairoKillCanvas(ctxcanvas); +} + +int cdactivate(cdCtxCanvas *ctxcanvas) +{ +  gdk_drawable_get_size(ctxcanvas->drawable, &ctxcanvas->canvas->w, &ctxcanvas->canvas->h); + +  ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; +  ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; + +  return CD_OK; +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ +  cdCtxCanvas *ctxcanvas; +	cairo_t* cr; +  GdkScreen* screen; +  GdkDrawable* drawable = (GdkDrawable*)data; + +  cr = gdk_cairo_create(drawable); +  if (!cr)  +    return; + +  screen = gdk_drawable_get_screen(drawable); +  canvas->bpp = gdk_drawable_get_depth(drawable); +  canvas->xres = ((double)gdk_screen_get_width(screen)  / (double)gdk_screen_get_width_mm(screen)); +  canvas->yres = ((double)gdk_screen_get_height(screen) / (double)gdk_screen_get_height_mm(screen)); +  gdk_drawable_get_size(drawable, &canvas->w, &canvas->h); + +  canvas->w_mm = ((double)canvas->w) / canvas->xres; +  canvas->h_mm = ((double)canvas->h) / canvas->yres; + +  ctxcanvas = cdcairoCreateCanvas(canvas, cr); + +  ctxcanvas->drawable = drawable; +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); + +  canvas->cxKillCanvas = cdkillcanvas; +  canvas->cxActivate = cdactivate; +} + +/******************************************************/ + +static cdContext cdNativeWindowContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE | CD_CAP_FPRIMTIVES), +  1, +  cdcreatecanvas, +  cdinittable, +  NULL, +  NULL, +}; + + +cdContext* cdContextCairoNativeWindow(void) +{ +  return &cdNativeWindowContext; +} diff --git a/src/cairo/cdcaironative_win32.c b/src/cairo/cdcaironative_win32.c new file mode 100644 index 0000000..b685d12 --- /dev/null +++ b/src/cairo/cdcaironative_win32.c @@ -0,0 +1,160 @@ +/** \file +* \brief Cairo Native Window Driver +* +* See Copyright Notice in cd.h +*/ + +#include <stdlib.h> +#include <stdio.h> + +#include "cdcairoctx.h" +#include "cdnative.h" + +#include <windows.h> +#include <cairo-win32.h> + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ +  if (ctxcanvas->hDC) +    ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC); + +  cdcairoKillCanvas(ctxcanvas); +} + +int cdactivate(cdCtxCanvas *ctxcanvas) +{ +  if (ctxcanvas->hWnd) +  { +    RECT rect; +    GetClientRect(ctxcanvas->hWnd, &rect); +    ctxcanvas->canvas->w = rect.right - rect.left; +    ctxcanvas->canvas->h = rect.bottom - rect.top; +   +    ctxcanvas->canvas->bpp = cdGetScreenColorPlanes(); +  } + +  /* Se nao e' ownwer, tem que restaurar o contexto */ +  if (!ctxcanvas->isOwnedDC) +  { +    cairo_surface_t *surface; + +    if (ctxcanvas->hDC) /* deactivate not called */ +    { +      cairo_destroy(ctxcanvas->cr); +      ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC); +    } + +    ctxcanvas->hDC = GetDC(ctxcanvas->hWnd); +    surface = cairo_win32_surface_create(ctxcanvas->hDC); +    ctxcanvas->cr = cairo_create(surface); +    cairo_surface_destroy(surface); +  } + +  ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; +  ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; + +  if (ctxcanvas->canvas->use_matrix) +    ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix); + +  return CD_OK; +} + +static void cddeactivate(cdCtxCanvas *ctxcanvas) +{ +  /* If not owner, release the DC */ +  if (!ctxcanvas->isOwnedDC && ctxcanvas->hDC) +  { +    cairo_destroy(ctxcanvas->cr); +    ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC); +    ctxcanvas->cr = NULL; +    ctxcanvas->hDC = NULL; +  } +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ +  cdCtxCanvas* ctxcanvas; +  cairo_surface_t *surface; + +  HWND hWnd = (HWND)data; +  HDC ScreenDC, hDC; +  HRGN clip_hrgn; + +  ScreenDC = GetDC(NULL); +  canvas->bpp = GetDeviceCaps(ScreenDC, BITSPIXEL); +  canvas->xres = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSX)) / 25.4); +  canvas->yres = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSY)) / 25.4); +  ReleaseDC(NULL, ScreenDC); + +  if (!data) +  { +    hDC = GetDC(NULL); +    canvas->w = GetDeviceCaps(hDC, HORZRES); +    canvas->h = GetDeviceCaps(hDC, VERTRES); +  } +  else  +  { +    RECT rect; +    hWnd = (HWND)data; + +    hDC = GetDC(hWnd); +   +    GetClientRect(hWnd, &rect); +    canvas->w = rect.right - rect.left; +    canvas->h = rect.bottom - rect.top; +  } + +  /* initial clip extents controls size */ +  clip_hrgn = CreateRectRgn(0, 0, canvas->w, canvas->h); +  SelectClipRgn(hDC, clip_hrgn); +  DeleteObject(clip_hrgn); + +  surface = cairo_win32_surface_create(hDC); + +  canvas->w_mm = ((double)canvas->w) / canvas->xres; +  canvas->h_mm = ((double)canvas->h) / canvas->yres; + +  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); +  cairo_surface_destroy(surface); + +  ctxcanvas->hDC = hDC; +  ctxcanvas->hWnd = hWnd; + +  if (hWnd) +  { +    LONG style = GetClassLong(hWnd, GCL_STYLE); +    ctxcanvas->isOwnedDC = (int) ((style & CS_OWNDC) || (style & CS_CLASSDC)); +  } +  else +    ctxcanvas->isOwnedDC = 1; +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); + +  canvas->cxKillCanvas = cdkillcanvas; +  canvas->cxActivate = cdactivate; +  canvas->cxDeactivate = cddeactivate; +} + +/******************************************************/ + +static cdContext cdNativeWindowContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE | CD_CAP_FPRIMTIVES), +  1, +  cdcreatecanvas, +  cdinittable, +  NULL, +  NULL, +}; + + +cdContext* cdContextCairoNativeWindow(void) +{ +  return &cdNativeWindowContext; +} + +// cairo_win32_printing_surface_create  CD_PRINTER  diff --git a/src/cairo/cdcaironative_x11.c b/src/cairo/cdcaironative_x11.c new file mode 100644 index 0000000..027de4e --- /dev/null +++ b/src/cairo/cdcaironative_x11.c @@ -0,0 +1,98 @@ +/** \file +* \brief Cairo Native Window Driver +* +* See Copyright Notice in cd.h +*/ + +#include <stdlib.h> +#include <stdio.h> + +#include "cdcairoctx.h" +#include "cdnative.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <cairo-xlib.h> + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ +  cdcairoKillCanvas(ctxcanvas); +} + +int cdactivate(cdCtxCanvas *ctxcanvas) +{ +  Window root; +  int x, y; +  unsigned int bw, d; +  XGetGeometry(ctxcanvas->dpy, ctxcanvas->wnd, &root, &x, &y, +               (unsigned int*)&ctxcanvas->canvas->w, (unsigned int*)&ctxcanvas->canvas->h, &bw, &d); + +  ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; +  ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; + +  return CD_OK; +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ +  cdCtxCanvas* ctxcanvas; +  cairo_surface_t *surface; +  char* data_str = (char*)data; +  Window wnd, root; +  Display *dpy; +  XWindowAttributes wa; +  int x, y; +  unsigned int bw; + +#ifdef SunOS_OLD +  sscanf(data_str, "%d %lu", &dpy, &wnd);  +#else +  sscanf(data_str, "%p %lu", &dpy, &wnd);  +#endif +  if (!dpy || !wnd)  +    return; + +  XGetWindowAttributes(dpy, wnd, &wa); + +  XGetGeometry(dpy, wnd, &root, &x, &y, (unsigned int*)&canvas->w, (unsigned int*)&canvas->h, &bw, (unsigned int*)&canvas->bpp); +  canvas->xres = ((double)DisplayWidth(dpy, XScreenNumberOfScreen(wa.screen)) / (double)DisplayWidthMM(dpy, XScreenNumberOfScreen(wa.screen))); +  canvas->yres = ((double)DisplayHeight(dpy, XScreenNumberOfScreen(wa.screen)) / (double)DisplayHeightMM(dpy, XScreenNumberOfScreen(wa.screen))); + +  surface = cairo_xlib_surface_create(dpy, wnd, wa.visual, canvas->w, canvas->h); + +  canvas->w_mm = ((double)canvas->w) / canvas->xres; +  canvas->h_mm = ((double)canvas->h) / canvas->yres; + +  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); +  cairo_surface_destroy(surface); + +  ctxcanvas->dpy = dpy; +  ctxcanvas->wnd = wnd; +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); + +  canvas->cxKillCanvas = cdkillcanvas; +  canvas->cxActivate = cdactivate; +} + +/******************************************************/ + +static cdContext cdNativeWindowContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE | CD_CAP_FPRIMTIVES), +  1, +  cdcreatecanvas, +  cdinittable, +  NULL, +  NULL, +}; + + +cdContext* cdContextCairoNativeWindow(void) +{ +  return &cdNativeWindowContext; +} diff --git a/src/cairo/cdcairopdf.c b/src/cairo/cdcairopdf.c new file mode 100644 index 0000000..880a2e5 --- /dev/null +++ b/src/cairo/cdcairopdf.c @@ -0,0 +1,122 @@ +/** \file + * \brief Cairo PDF Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "cd.h" +#include "cdcairo.h" +#include "cdcairoctx.h" + +#include <cairo-pdf.h> + + +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ +  cdcairoKillCanvas(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ +  cdCtxCanvas* ctxcanvas; +  char* strdata = (char*)data; +  char filename[10240] = ""; +  cairo_surface_t *surface; +  int res = 300; +  double w_pt;         /* Largura do papel (points) */ +  double h_pt;         /* Altura do papel (points) */ +  double scale;          /* Fator de conversao de coordenadas (pixel2points) */ +  int landscape = 0;         /* page orientation */ + +  /* Starting parameters */ +  if (strdata == NULL)  +    return; + +  strdata += cdGetFileName(strdata, filename); +  if (filename[0] == 0) +    return; + +  cdSetPaperSize(CD_A4, &w_pt, &h_pt); + +  while (*strdata != '\0') +  { +    while (*strdata != '\0' && *strdata != '-')  +      strdata++; + +    if (*strdata != '\0') +    { +      float num; +      strdata++; +      switch (*strdata++) +      { +      case 'p': +        { +          int paper; +          sscanf(strdata, "%d", &paper); +          cdSetPaperSize(paper, &w_pt, &h_pt); +          break; +        } +      case 'w': +        sscanf(strdata, "%g", &num); +        w_pt = CD_MM2PT*num; +        break; +      case 'h': +        sscanf(strdata, "%g", &num); +        h_pt = CD_MM2PT*num; +        break; +      case 'o': +        landscape = 1; +        break; +      case 's': +        sscanf(strdata, "%d", &res); +        break; +      } +    } + +    while (*strdata != '\0' && *strdata != ' ')  +      strdata++; +  } + +  if (landscape) +    _cdSwapDouble(w_pt, h_pt); + +  scale = 72.0/res; + +  canvas->w = (int)(w_pt/scale + 0.5);   /* Converte p/ unidades do usuario */ +  canvas->h = (int)(h_pt/scale + 0.5); /* Converte p/ unidades do usuario */ +  canvas->w_mm = w_pt/CD_MM2PT;   /* Converte p/ milimetros */ +  canvas->h_mm = h_pt/CD_MM2PT; /* Converte p/ milimetros */ +  canvas->bpp = 24; +  canvas->xres = canvas->w / canvas->w_mm; +  canvas->yres = canvas->h / canvas->h_mm; + +	surface = cairo_pdf_surface_create(filename, w_pt, h_pt); + +  /* Starting Cairo driver */ +  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); +  cairo_surface_destroy(surface); +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); +  canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdCairoPDFContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_FPRIMTIVES), +  0, +  cdcreatecanvas,   +  cdinittable, +  NULL,                  +  NULL +}; + +cdContext* cdContextCairoPDF(void) +{ +  return &cdCairoPDFContext; +} diff --git a/src/cairo/cdcairoplus.c b/src/cairo/cdcairoplus.c new file mode 100644 index 0000000..c50f1ec --- /dev/null +++ b/src/cairo/cdcairoplus.c @@ -0,0 +1,26 @@ +/** \file + * \brief Cairo as Context Plus + * + * See Copyright Notice in cd.h + */ +  +#include "cd.h" +#include "cd_private.h" +#include "cdcairo.h" +#include <stdlib.h> +#include <memory.h> + +void cdInitContextPlus(void) +{ +  cdContext* ctx_list[NUM_CONTEXTPLUS]; +  memset(ctx_list, 0, sizeof(ctx_list)); + +  ctx_list[CD_CTX_NATIVEWINDOW] = cdContextCairoNativeWindow(); +  ctx_list[CD_CTX_IMAGE] = cdContextCairoImage(); +  ctx_list[CD_CTX_DBUFFER] = cdContextCairoDBuffer(); +#ifdef WIN32 +//  ctx_list[CD_CTX_PRINTER] = cdContextCairoPrinter(); +#endif + +  cdInitContextPlusList(ctx_list); +} diff --git a/src/cairo/cdcairops.c b/src/cairo/cdcairops.c new file mode 100644 index 0000000..ed58723 --- /dev/null +++ b/src/cairo/cdcairops.c @@ -0,0 +1,170 @@ +/** \file + * \brief Cairo PS Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "cd.h" +#include "cdps.h" +#include "cdcairo.h" +#include "cdcairoctx.h" + +#include <cairo-ps.h> + + +static void set_comment_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ +  if (data) +    cairo_ps_surface_dsc_comment(cairo_get_target(ctxcanvas->cr), data); +} + +static cdAttribute comment_attrib = +{ +  "DSCCOMMENT", +  set_comment_attrib, +  NULL +};  + +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ +  cdcairoKillCanvas(ctxcanvas); +} + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ +  if (!ctxcanvas->eps) +    cairo_show_page(ctxcanvas->cr); +} + +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ +  cdCtxCanvas *ctxcanvas; +  char* strdata = (char*)data; +  char filename[10240] = ""; +  cairo_surface_t *surface; +  int res = 300; +  double w_pt;         /* Largura do papel (points) */ +  double h_pt;         /* Altura do papel (points) */ +  double scale;          /* Fator de conversao de coordenadas (pixel2points) */ +  int eps = 0;               /* Postscrip encapsulado? */ +  int level = 0; +  int landscape = 0;         /* page orientation */ + +  /* Starting parameters */ +  if (strdata == NULL)  +    return; + +  strdata += cdGetFileName(strdata, filename); +  if (filename[0] == 0) +    return; + +  cdSetPaperSize(CD_A4, &w_pt, &h_pt); + +  while (*strdata != '\0') +  { +    while (*strdata != '\0' && *strdata != '-')  +      strdata++; + +    if (*strdata != '\0') +    { +      float num; +      strdata++; +      switch (*strdata++) +      { +      case 'p': +        { +          int paper; +          sscanf(strdata, "%d", &paper); +          cdSetPaperSize(paper, &w_pt, &h_pt); +          break; +        } +      case 'w': +        sscanf(strdata, "%g", &num); +        w_pt = CD_MM2PT*num; +        break; +      case 'h': +        sscanf(strdata, "%g", &num); +        h_pt = CD_MM2PT*num; +        break; +      case 'e': +        eps = 1; +        break; +      case 'o': +        landscape = 1; +        break; +      case '2': +        level = 2; +        break; +      case '3': +        level = 3; +        break; +      case 's': +        sscanf(strdata, "%d", &res); +        break; +      } +    } + +    while (*strdata != '\0' && *strdata != ' ')  +      strdata++; +  } + +  if (landscape) +    _cdSwapDouble(w_pt, h_pt); + +  scale = 72.0/res; + +  canvas->w = (int)(w_pt/scale + 0.5);   /* Converte p/ unidades do usuario */ +  canvas->h = (int)(h_pt/scale + 0.5); /* Converte p/ unidades do usuario */ +  canvas->w_mm = w_pt/CD_MM2PT;   /* Converte p/ milimetros */ +  canvas->h_mm = h_pt/CD_MM2PT; /* Converte p/ milimetros */ +  canvas->bpp = 24; +  canvas->xres = canvas->w / canvas->w_mm; +  canvas->yres = canvas->h / canvas->h_mm; + +  surface = cairo_ps_surface_create(filename, w_pt, h_pt); + +  if (level == 2) +    cairo_ps_surface_restrict_to_level(surface, CAIRO_PS_LEVEL_2); +  else if (level == 3) +    cairo_ps_surface_restrict_to_level(surface, CAIRO_PS_LEVEL_3); + +  if (eps) +    cairo_ps_surface_set_eps(surface, 1); + +  cairo_ps_surface_dsc_comment(surface, "%%Title: CanvasDraw"); +  cairo_ps_surface_dsc_begin_setup (surface); +  cairo_ps_surface_dsc_begin_page_setup (surface); + +  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); +  ctxcanvas->eps = eps; + +  cairo_surface_destroy(surface); + +  cdRegisterAttribute(canvas, &comment_attrib); +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); +  canvas->cxKillCanvas = cdkillcanvas; +  canvas->cxFlush = cdflush; +} + +static cdContext cdCairoPSContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_FPRIMTIVES), +  0, +  cdcreatecanvas,   +  cdinittable, +  NULL,                  +  NULL +}; + +cdContext* cdContextCairoPS(void) +{ +  return &cdCairoPSContext; +} + diff --git a/src/cairo/cdcairosvg.c b/src/cairo/cdcairosvg.c new file mode 100644 index 0000000..ce36758 --- /dev/null +++ b/src/cairo/cdcairosvg.c @@ -0,0 +1,81 @@ +/** \file + * \brief Cairo SVG Driver + * + * See Copyright Notice in cd.h + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "cd.h" +#include "cdcairo.h" +#include "cdcairoctx.h" + +#include <cairo-svg.h> + + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ +  (void)ctxcanvas;  /* Nothing to do */ +} + +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ +  cdcairoKillCanvas(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ +  cdCtxCanvas* ctxcanvas; +  char* strdata = (char*)data; +  char filename[10240] = ""; +  double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78; +  cairo_surface_t *surface; + +  /* Starting parameters */ +  if (strdata == NULL)  +    return; + +  strdata += cdGetFileName(strdata, filename); +  if (filename[0] == 0) +    return; + +  sscanf(strdata, "%lgx%lg %lg", &w_mm, &h_mm, &res); +   +  /* update canvas context */ +  canvas->w = (int)(w_mm * res); +  canvas->h = (int)(h_mm * res); +  canvas->w_mm = w_mm; +  canvas->h_mm = h_mm; +  canvas->bpp = 24; +  canvas->xres = res; +  canvas->yres = res; + +	surface = cairo_svg_surface_create(filename, CD_MM2PT*w_mm, CD_MM2PT*h_mm); + +  /* Starting Cairo driver */ +  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface)); +  cairo_surface_destroy(surface); +} + +static void cdinittable(cdCanvas* canvas) +{ +  cdcairoInitTable(canvas); +  canvas->cxKillCanvas = cdkillcanvas; +  canvas->cxFlush = cdflush; +} + +static cdContext cdCairoSVGContext = +{ +  CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_FPRIMTIVES), +  0, +  cdcreatecanvas,   +  cdinittable, +  NULL,                  +  NULL +}; + +cdContext* cdContextCairoSVG(void) +{ +  return &cdCairoSVGContext; +} @@ -20,6 +20,7 @@  /* This appears only here to avoid changing the cd.h header fo bug fixes */  #define CD_VERSION_FIX ""  #define CD_VERSION_FIX_NUMBER 0 +/* #define CD_VERSION_FIX_DATE "" */  const char cd_ident[] =    "$CD: " CD_VERSION CD_VERSION_FIX " " CD_COPYRIGHT " $\n" @@ -36,7 +37,11 @@ char* cdVersion(void)  char* cdVersionDate(void)  { +#ifdef CD_VERSION_FIX_DATE +  return CD_VERSION_FIX_DATE; +#else    return CD_VERSION_DATE; +#endif  }  int cdVersionNumber(void) @@ -716,14 +721,13 @@ static cdContext* context_plus[NUM_CONTEXTPLUS] = {NULL, NULL, NULL, NULL, NULL,  int cdUseContextPlus(int use)  { +  int old_use_context_plus = use_context_plus; +    if (use == CD_QUERY)      return use_context_plus; -  { -    int old_use_context_plus = use_context_plus; -    use_context_plus = use; -    return old_use_context_plus; -  } +  use_context_plus = use; +  return old_use_context_plus;  }  void cdInitContextPlusList(cdContext* ctx_list[]) @@ -219,6 +219,7 @@ EXPORTS    cdGetFontSizePixels    cdGetFontSizePoints    cdStrEqualNoCase +  cdSetPaperSize    wdCanvasLineWidth    wdCanvasMarkSize diff --git a/src/cd_text.c b/src/cd_text.c index 2568e25..32b0645 100644 --- a/src/cd_text.c +++ b/src/cd_text.c @@ -319,7 +319,7 @@ char* cdCanvasNativeFont(cdCanvas* canvas, const char* font)    else    {      char type_face[1024]; -    int size, style = CD_PLAIN; +    int size = 12, style = CD_PLAIN;      if (!cdParseIupWinFont(font, type_face, &style, &size))      { diff --git a/src/cd_util.c b/src/cd_util.c index 1767ac4..39d491d 100644 --- a/src/cd_util.c +++ b/src/cd_util.c @@ -263,6 +263,29 @@ void cdRotatePoint(cdCanvas* canvas, int x, int y, int cx, int cy, int *rx, int    *ry = *ry + cy;  } +void cdfRotatePoint(cdCanvas* canvas, double x, double y, double cx, double cy, double *rx, double *ry, double sin_theta, double cos_theta) +{ +  /* translate to (cx,cy) */ +  x = x - cx; +  y = y - cy; + +  /* rotate */ +  if (canvas->invert_yaxis) +  { +    *rx =  (x * cos_theta) + (y * sin_theta);  +    *ry = -(x * sin_theta) + (y * cos_theta);  +  } +  else +  { +    *rx = (x * cos_theta) - (y * sin_theta);  +    *ry = (x * sin_theta) + (y * cos_theta);  +  } + +  /* translate back */ +  *rx = *rx + cx; +  *ry = *ry + cy; +} +  void cdRotatePointY(cdCanvas* canvas, int x, int y, int cx, int cy, int *ry, double sin_theta, double cos_theta)  {    double t; @@ -349,3 +372,28 @@ char* cdStrDupN(const char *str, int len)    }    return NULL;  } + +void cdSetPaperSize(int size, double *w_pt, double *h_pt) +{ +  static struct +  { +    int w_pt; +    int h_pt; +  } paper[] = +    { +      { 2393, 3391 },   /*   A0   */ +      { 1689, 2393 },   /*   A1   */ +      { 1192, 1689 },   /*   A2   */ +      {  842, 1192 },   /*   A3   */ +      {  595,  842 },   /*   A4   */ +      {  420,  595 },   /*   A5   */ +      {  612,  792 },   /* LETTER */ +      {  612, 1008 }    /*  LEGAL */ +    }; + +  if (size<CD_A0 || size>CD_LEGAL)  +    return; + +  *w_pt = (double)paper[size].w_pt; +  *h_pt = (double)paper[size].h_pt; +} diff --git a/src/drv/cddebug.c b/src/drv/cddebug.c index 23d8446..0c5fd0d 100644 --- a/src/drv/cddebug.c +++ b/src/drv/cddebug.c @@ -68,7 +68,6 @@  struct _cdCtxCanvas   {    cdCanvas* canvas; -  char* filename;           FILE* file;    int last_line_style;    int last_fill_mode; @@ -601,7 +600,6 @@ static void cdgettextsize(cdCtxCanvas* ctxcanvas, const char *s, int len, int *w  static void cdkillcanvas(cdCtxCanvas *ctxcanvas)  {  	fprintf(ctxcanvas->file, "KillCanvas()\n"); -  free(ctxcanvas->filename);    fclose(ctxcanvas->file);    memset(ctxcanvas, 0, sizeof(cdCtxCanvas));    free(ctxcanvas); @@ -613,7 +611,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data)    char* strdata = (char*)data;    double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78;    cdCtxCanvas* ctxcanvas; -  int size;    strdata += cdGetFileName(strdata, filename);    if (filename[0] == 0) @@ -631,10 +628,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data)      return;    } -  size = strlen(filename); -  ctxcanvas->filename = malloc(size+1); -  memcpy(ctxcanvas->filename, filename, size+1); -    ctxcanvas->canvas = canvas;    /* update canvas context */ diff --git a/src/drv/cdirgb.c b/src/drv/cdirgb.c index 8baef1e..8135fa1 100644 --- a/src/drv/cdirgb.c +++ b/src/drv/cdirgb.c @@ -1781,6 +1781,7 @@ static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)  {    if (data)    { +    /* use this configuration when there is NO native tranformation support */      sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,                               &ctxcanvas->rotate_center_x,                               &ctxcanvas->rotate_center_y); diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c index a5d91d4..6a20748 100644 --- a/src/drv/cdpdf.c +++ b/src/drv/cdpdf.c @@ -56,36 +56,6 @@ struct _cdCtxCanvas  /* -%F Ajusta o tamanho do papel em points. -*/ -static void setpdfpapersize(cdCtxCanvas* ctxcanvas, int size) -{ -  static struct -  { -    int width; -    int height; -  } paper[] = -    { -      { 2393, 3391 },   /*   A0   */ -      { 1689, 2393 },   /*   A1   */ -      { 1192, 1689 },   /*   A2   */ -      {  842, 1192 },   /*   A3   */ -      {  595,  842 },   /*   A4   */ -      {  420,  595 },   /*   A5   */ -      {  612,  792 },   /* LETTER */ -      {  612, 1008 }    /*  LEGAL */ -    }; -   -  if (size<CD_A0 || size>CD_LEGAL)  -    return; - -  ctxcanvas->width_pt = paper[size].width;    -  ctxcanvas->height_pt = paper[size].height;  -  ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; -  ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT; -} - -/*  %F Registra os valores default para impressao.  */  static void setpdfdefaultvalues(cdCtxCanvas* ctxcanvas) @@ -93,7 +63,9 @@ static void setpdfdefaultvalues(cdCtxCanvas* ctxcanvas)    int i;    /* all the other values are set to 0 */ -  setpdfpapersize(ctxcanvas, CD_A4); +  cdSetPaperSize(CD_A4, &ctxcanvas->width_pt, &ctxcanvas->height_pt); +  ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; +  ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT;    ctxcanvas->res = 300;    ctxcanvas->hatchboxsize = 8;    ctxcanvas->opacity = 255; /* full opaque */ @@ -361,7 +333,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl      PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);      PDF_stroke(ctxcanvas->pdf);    } -  else /* Elipse: mudar a escala p/ criar a partir do circulo */ +  else /* Ellipse: change the scale to create from the circle */    {      PDF_save(ctxcanvas->pdf);  /* save to use the local transform */ @@ -487,8 +459,8 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i    char temp[200], options[200];    PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground),  -                                               get_green(ctxcanvas->canvas->foreground),  -                                               get_blue(ctxcanvas->canvas->foreground), 0); +                                              get_green(ctxcanvas->canvas->foreground),  +                                              get_blue(ctxcanvas->canvas->foreground), 0);    strcpy(options, ""); @@ -768,7 +740,6 @@ static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int (    PDF_suspend_page(ctxcanvas->pdf, "");    ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m,        ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1); -    PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale);    for (j=0; j<m; j++) @@ -802,21 +773,18 @@ static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *patt  static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)  { -  int ret = 1;    unsigned char* uchar_data = (unsigned char*)data;    if (uchar_data[j*n+i]) -  {      cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); -    ret = 1; -  }    else    { -    cdDecodeColor(ctxcanvas->canvas->background, r, g, b);      if (ctxcanvas->canvas->back_opacity==CD_TRANSPARENT) -        ret = -1; +      return -1; +    else +      cdDecodeColor(ctxcanvas->canvas->background, r, g, b);    } -  return ret; +  return 1;  }  static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) @@ -824,14 +792,14 @@ static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char    make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb);  } -static void make_hatch(cdCtxCanvas *ctxcanvas, int style) +static int cdhatch(cdCtxCanvas *ctxcanvas, int style)  {    unsigned char r, g, b;    int hsize = ctxcanvas->hatchboxsize - 1;    int hhalf = hsize / 2;    PDF_suspend_page(ctxcanvas->pdf, ""); -  ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, hsize + 1, hsize + 1, +  ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, hsize+1, hsize+1,        ((double)hsize)*ctxcanvas->scale, ((double)hsize)*ctxcanvas->scale, 1);    PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); @@ -883,11 +851,6 @@ static void make_hatch(cdCtxCanvas *ctxcanvas, int style)    PDF_end_pattern(ctxcanvas->pdf);    PDF_resume_page(ctxcanvas->pdf, ""); -} - -static int cdhatch(cdCtxCanvas *ctxcanvas, int style) -{ -  make_hatch(ctxcanvas, style);    return style;  } @@ -976,6 +939,7 @@ static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int  static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)  { +  /* reset to identity */    PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0);    /* default coordinate system is in points, change it to pixels. */ @@ -1202,7 +1166,8 @@ static cdAttribute hatchboxsize_attrib =  static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data)  { -  /* ignore ROTATE if transform is set */ +  /* ignore ROTATE if transform is set,  +     because there is native support for transformations */    if (ctxcanvas->canvas->use_matrix)      return; @@ -1219,15 +1184,7 @@ static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data)      ctxcanvas->rotate_center_y = 0;    } -  PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0); - -  if (ctxcanvas->rotate_angle) -  { -    /* rotation = translate to point + rotation + translate back */ -    PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); -    PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle); -    PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); -  } +  cdtransform(ctxcanvas, NULL);  }  static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) @@ -1469,7 +1426,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)          {            int paper;            sscanf(line, "%d", &paper); -          setpdfpapersize(ctxcanvas, paper); +          cdSetPaperSize(paper, &ctxcanvas->width_pt, &ctxcanvas->height_pt); +          ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; +          ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT;            break;          }        case 'w': @@ -1513,7 +1472,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; @@ -1522,6 +1483,7 @@ static void cdinittable(cdCanvas* canvas)    canvas->cxSector = cdsector;    canvas->cxChord = cdchord;    canvas->cxText = cdtext; +    canvas->cxFLine = cdfline;    canvas->cxFPoly = cdfpoly;    canvas->cxFRect = cdfrect; @@ -1530,6 +1492,7 @@ static void cdinittable(cdCanvas* canvas)    canvas->cxFSector = cdfsector;    canvas->cxFChord = cdfchord;    canvas->cxFText = cdftext; +    canvas->cxGetFontDim = cdgetfontdim;    canvas->cxGetTextSize = cdgettextsize;    canvas->cxPutImageRectRGB = cdputimagerectrgb; diff --git a/src/drv/cdps.c b/src/drv/cdps.c index ef77c4d..c54c95a 100644 --- a/src/drv/cdps.c +++ b/src/drv/cdps.c @@ -76,42 +76,13 @@ struct _cdCtxCanvas  }; - -/* -%F Ajusta o tamanho do papel em points. -*/ -static void setpspapersize(cdCtxCanvas *ctxcanvas, int size) -{ -  static struct -  { -    int width; -    int height; -  } paper[] = -    { -      { 2393, 3391 },   /*   A0   */ -      { 1689, 2393 },   /*   A1   */ -      { 1192, 1689 },   /*   A2   */ -      {  842, 1192 },   /*   A3   */ -      {  595,  842 },   /*   A4   */ -      {  420,  595 },   /*   A5   */ -      {  612,  792 },   /* LETTER */ -      {  612, 1008 }    /*  LEGAL */ -    }; - -  if (size<CD_A0 || size>CD_LEGAL)  -    return; - -  ctxcanvas->width = (double)paper[size].width; -  ctxcanvas->height = (double)paper[size].height; -} -  /*  %F Registra os valores default para impressao.  */  static void setpsdefaultvalues(cdCtxCanvas *ctxcanvas)  {    /* all the other values are set to 0 */ -  setpspapersize(ctxcanvas, CD_A4); +  cdSetPaperSize(CD_A4, &ctxcanvas->width, &ctxcanvas->height);    ctxcanvas->xmin = 25.4; /* ainda em mm, sera' convertido para points na init_ps */    ctxcanvas->xmax = 25.4;    ctxcanvas->ymin = 25.4; @@ -1379,6 +1350,7 @@ static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int  static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)  { +  /* reset to identity */    set_default_matrix(ctxcanvas);    if (matrix) @@ -1568,7 +1540,8 @@ static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color)  static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data)  { -  /* ignore ROTATE if transform is set */ +  /* ignore ROTATE if transform is set,  +     because there is native support for transformations */    if (ctxcanvas->canvas->use_matrix)      return; @@ -1585,15 +1558,7 @@ static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data)      ctxcanvas->rotate_center_y = 0;    } -  set_default_matrix(ctxcanvas); - -  if (ctxcanvas->rotate_angle) -  { -    /* rotation = translate to point + rotation + translate back */ -    fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); -    fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle); -    fprintf(ctxcanvas->file, "%d %d translate\n", -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); -  } +  cdtransform(ctxcanvas, NULL);  }  static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) @@ -1715,7 +1680,7 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)          {            int paper;            sscanf(line, "%d", &paper); -          setpspapersize(ctxcanvas, paper); +          cdSetPaperSize(paper, &ctxcanvas->width, &ctxcanvas->height);            break;          }        case 'w': diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp index 1cbed3c..aba6c1e 100644 --- a/src/gdiplus/cdwinp.cpp +++ b/src/gdiplus/cdwinp.cpp @@ -551,6 +551,7 @@ static int cdinteriorstyle(cdCtxCanvas* ctxcanvas, int style)      delete ctxcanvas->fillBrush;      ctxcanvas->fillBrush = new SolidBrush(ctxcanvas->fg);      break; +    /* the remaining styles must recreate the current brush */    case CD_HATCH:      cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);      break; @@ -1173,6 +1174,10 @@ static void sRGB2Bitmap(Bitmap& image, int width, int height, const unsigned cha    Rect rect(0,0,image.GetWidth(),image.GetHeight());    image.LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData);  +  /* ymin and xmax unused */ +  (void)ymin; +  (void)xmax; +    int line_offset;    for(int j = 0; j < rect.Height; j++)    { @@ -1206,6 +1211,10 @@ static void sRGBA2Bitmap(Bitmap& image, int width, int height, const unsigned ch    Rect rect(0,0,image.GetWidth(),image.GetHeight());    image.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);  +  /* ymin and xmax unused */ +  (void)ymin; +  (void)xmax; +    int line_offset;    for(int j = 0; j < rect.Height; j++)    { @@ -1237,6 +1246,10 @@ static void sAlpha2Bitmap(Bitmap& image, int width, int height, const unsigned c    Rect rect(0,0,image.GetWidth(),image.GetHeight());    image.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);  +  /* ymin and xmax unused */ +  (void)ymin; +  (void)xmax; +    int line_offset;    for(int j = 0; j < rect.Height; j++)    { @@ -1279,6 +1292,10 @@ static void sMap2Bitmap(Bitmap& image, int width, int height, const unsigned cha    Rect rect(0,0,image.GetWidth(),image.GetHeight());    image.LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData);  +  /* ymin and xmax unused */ +  (void)ymin; +  (void)xmax; +    int line_offset;    for(int j = 0; j < rect.Height; j++)    { @@ -1337,7 +1354,7 @@ static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned c    if (!transformMatrix.IsIdentity())      ctxcanvas->graphics->ResetTransform(); // reset to the identity. -  if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset +  if (ctxcanvas->canvas->invert_yaxis==0) // if 0, invert because the transform was reset here      y = _cdInvertYAxis(ctxcanvas->canvas, y);    int yr = y - (h - 1);  /* y starts at the bottom of the image */ @@ -1649,10 +1666,11 @@ static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int    if (!transformMatrix.IsIdentity())      ctxcanvas->graphics->ResetTransform(); // reset to the identity. -  if (ctxcanvas->canvas->invert_yaxis==0)  // if 0, then the transform was reset +  if (ctxcanvas->canvas->invert_yaxis==0)  // if 0, invert because the transform was reset here      y = _cdInvertYAxis(ctxcanvas->canvas, y); -  int yr = y - (ctximage->h - 1);  /* y0 starts at the bottom of the image */ +  /* y is the bottom-left of the image in CD, must be at upper-left */ +  y -= ctximage->h-1;    if (ctxcanvas->wtype == CDW_BMP)    { @@ -1660,7 +1678,7 @@ static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int      imggraphics.DrawImage(ctxcanvas->bitmap,                             Rect(0, 0, ctximage->w,ctximage->h),  -                          x, yr, ctximage->w, ctximage->h, UnitPixel, +                          x, y, ctximage->w, ctximage->h, UnitPixel,                            NULL, NULL, NULL);    }    else @@ -1670,7 +1688,7 @@ static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int      HDC hdc = ctxcanvas->graphics->GetHDC();      HDC img_hdc = imggraphics.GetHDC(); -    BitBlt(img_hdc,0,0,ctximage->w,ctximage->h,hdc,x,yr,SRCCOPY); +    BitBlt(img_hdc,0,0,ctximage->w,ctximage->h,hdc,x,y,SRCCOPY);      imggraphics.ReleaseHDC(img_hdc);      ctxcanvas->graphics->ReleaseHDC(hdc); @@ -1740,7 +1758,7 @@ static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, i    if (!transformMatrix.IsIdentity())      ctxcanvas->graphics->ResetTransform(); // reset to the identity. -  if (ctxcanvas->canvas->invert_yaxis==0)  // if 0, then the transform was reset +  if (ctxcanvas->canvas->invert_yaxis==0)  // if 0, invert because the transform was reset here    {      dy = -dy;      ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin); @@ -1992,7 +2010,8 @@ static cdAttribute linecap_attrib =  static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)  { -  /* ignore ROTATE if transform is set */ +  /* ignore ROTATE if transform is set,  +     because there is native support for transformations */    if (ctxcanvas->canvas->use_matrix)      return; @@ -2009,7 +2028,7 @@ static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)      ctxcanvas->rotate_center_y = 0;    } -  cdwpUpdateTransform(ctxcanvas); +  cdtransform(ctxcanvas, NULL);  }  static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) diff --git a/src/gdk/cdgdk.c b/src/gdk/cdgdk.c index b0c8ea8..1eccaa8 100644 --- a/src/gdk/cdgdk.c +++ b/src/gdk/cdgdk.c @@ -12,8 +12,6 @@  #include "cdgdk.h" -#include <gdk/gdk.h> -  #define NUM_HATCHES  6  #define HATCH_WIDTH  8  #define HATCH_HEIGHT 8 @@ -52,7 +50,7 @@ static char* gdkStrToUTF8(const char *str, const char* charset, int length)    return g_convert(str, length, "UTF-8", charset, NULL, NULL, NULL);  } -char* cdgdkStrConvertToUTF8(cdCtxCanvas *ctxcanvas, const char* str, int length)  /* From CD to GTK/GDK */ +char* cdgdkStrConvertToUTF8(cdCtxCanvas *ctxcanvas, const char* str, int length)  /* From CD to GDK */  {    const char *charset = NULL; @@ -562,28 +560,6 @@ static int cdfont(cdCtxCanvas *ctxcanvas, const char *typeface, int style, int s    return 1;  } -static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* nativefont) -{ -  int size = 12, style = CD_PLAIN; -  char typeface[1024]; - -  /* parse the old Windows format first */ -  if (!cdParseIupWinFont(nativefont, typeface, &style, &size)) -    if (!cdParseXWinFont(nativefont, typeface, &style, &size)) -      if (!cdParsePangoFont(nativefont, typeface, &style, &size)) -        return 0; - -  if (!cdfont(ctxcanvas, typeface, style, size)) -    return 0; - -  /* update cdfont parameters */ -  ctxcanvas->canvas->font_style = style; -  ctxcanvas->canvas->font_size = size; -  strcpy(ctxcanvas->canvas->font_type_face, typeface); - -  return 1; -} -  static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent)  {    PangoFontMetrics* metrics; @@ -1353,7 +1329,7 @@ static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsi    rw = xmax-xmin+1;    rh = ymax-ymin+1; -  y -= (h - 1);        /* GdkPixbuf origin is at top-left */ +  y -= (h - 1);        /* GdkPixbuf image origin is at top-left */    if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1))      return; @@ -1429,8 +1405,11 @@ static cdCtxImage *cdcreateimage (cdCtxCanvas *ctxcanvas, int w, int h)  static void cdgetimage (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y)  { +  /* y is the bottom-left of the image in CD, must be at upper-left */ +  y -= ctximage->h-1; +    gdk_draw_drawable(ctximage->img, ctxcanvas->gc, -                    ctxcanvas->wnd, x, y - ctximage->h+1, 0, 0, +                    ctxcanvas->wnd, x, y, 0, 0,                      ctximage->w, ctximage->h);  } @@ -1491,6 +1470,7 @@ static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)  {    if (data)    { +    /* use this configuration when there is NO native tranformation support */      sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,                               &ctxcanvas->rotate_center_x,                               &ctxcanvas->rotate_center_y); @@ -1687,7 +1667,6 @@ void cdgdkInitTable(cdCanvas* canvas)    canvas->cxStipple = cdstipple;    canvas->cxPattern = cdpattern;    canvas->cxFont = cdfont; -  canvas->cxNativeFont = cdnativefont;    canvas->cxGetFontDim = cdgetfontdim;    canvas->cxGetTextSize = cdgettextsize;    canvas->cxPalette = cdpalette; diff --git a/src/svg/cdsvg.c b/src/svg/cdsvg.c index 90e70d9..2441523 100644 --- a/src/svg/cdsvg.c +++ b/src/svg/cdsvg.c @@ -23,7 +23,6 @@  struct _cdCtxCanvas   {    cdCanvas* canvas; -  char* filename;           char bgColor[20];    char fgColor[20];  @@ -67,7 +66,6 @@ static void cdkillcanvas(cdCtxCanvas* ctxcanvas)    fprintf(ctxcanvas->file, "</g>\n");  /* close global container */    fprintf(ctxcanvas->file, "</svg>\n"); -  free(ctxcanvas->filename);    fclose(ctxcanvas->file);    memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); @@ -564,31 +562,31 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style)    {    case CD_HORIZONTAL:      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      0, hhalf, hsize, hhalf, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      0, hhalf, hsize, hhalf, ctxcanvas->fgColor, ctxcanvas->opacity);      break;    case CD_VERTICAL:      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      hhalf, 0, hhalf, hsize, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      hhalf, 0, hhalf, hsize, ctxcanvas->fgColor, ctxcanvas->opacity);      break;    case CD_BDIAGONAL:      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      0, hsize, hsize, 0, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      0, hsize, hsize, 0, ctxcanvas->fgColor, ctxcanvas->opacity);      break;    case CD_FDIAGONAL:      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      0, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      0, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->opacity);      break;    case CD_CROSS:      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      hsize, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      hsize, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->opacity);      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      0, hhalf, hsize, hhalf, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      0, hhalf, hsize, hhalf, ctxcanvas->fgColor, ctxcanvas->opacity);      break;    case CD_DIAGCROSS:      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      0, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      0, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->opacity);      fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", -      hsize, 0, 0, hsize, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->opacity); +      hsize, 0, 0, hsize, ctxcanvas->fgColor, ctxcanvas->opacity);      break;    } @@ -642,21 +640,18 @@ static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *patt  static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)  { -  int ret = 1;    unsigned char* uchar_data = (unsigned char*)data;    if (uchar_data[j*n+i]) -  {      cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); -    ret = 1; -  }    else    { -    cdDecodeColor(ctxcanvas->canvas->background, r, g, b);      if (ctxcanvas->canvas->back_opacity==CD_TRANSPARENT) -      ret = -1; +      return -1; +    else +      cdDecodeColor(ctxcanvas->canvas->background, r, g, b);    } -  return ret; +  return 1;  }  static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) @@ -966,7 +961,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data)    char* strdata = (char*)data;    double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78;    cdCtxCanvas* ctxcanvas; -  int size;    strdata += cdGetFileName(strdata, filename);    if (filename[0] == 0) @@ -984,10 +978,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data)      return;    } -  size = strlen(filename); -  ctxcanvas->filename = malloc(size+1); -  memcpy(ctxcanvas->filename, filename, size+1); -    /* store the base canvas */    ctxcanvas->canvas = canvas; diff --git a/src/win32/cdwdbuf.c b/src/win32/cdwdbuf.c index 85af87c..4beac10 100644 --- a/src/win32/cdwdbuf.c +++ b/src/win32/cdwdbuf.c @@ -75,6 +75,7 @@ static void cdcreatecanvas(cdCanvas* canvas, cdCanvas* canvas_dbuffer)    canvas->bpp = ctximage->bpp;    canvas->xres = ctximage->xres;    canvas->yres = ctximage->yres; +    ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = ctximage->w - 1;    ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = ctximage->h - 1;  } diff --git a/src/win32/cdwin.c b/src/win32/cdwin.c index 313e833..da9bf9d 100644 --- a/src/win32/cdwin.c +++ b/src/win32/cdwin.c @@ -626,6 +626,7 @@ static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style)      ctxcanvas->hBrush = CreateBrushIndirect(&ctxcanvas->logBrush);      ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush);      break; +    /* the remaining styles must recreate the current brush */    case CD_HATCH:      cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style);      break; @@ -963,8 +964,37 @@ static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix)    else    {      ctxcanvas->canvas->invert_yaxis = 1; -    ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); -    SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); + +    if (ctxcanvas->rotate_angle) +    { +      XFORM xForm; + +      /* the rotation  must be corrected because of the Y axis orientation */ + +      SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED); +      ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + +      xForm.eM11 = (FLOAT) cos(-CD_DEG2RAD*ctxcanvas->rotate_angle);  +      xForm.eM12 = (FLOAT) sin(-CD_DEG2RAD*ctxcanvas->rotate_angle);  +      xForm.eM21 = (FLOAT) -xForm.eM12;  +      xForm.eM22 = (FLOAT) xForm.eM11;  +      xForm.eDx  = (FLOAT) ctxcanvas->rotate_center_x;  +      xForm.eDy  = (FLOAT) _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y);  +      ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + +      xForm.eM11 = (FLOAT) 1;  +      xForm.eM12 = (FLOAT) 0;  +      xForm.eM21 = (FLOAT) 0;  +      xForm.eM22 = (FLOAT) 1;  +      xForm.eDx  = (FLOAT) -ctxcanvas->rotate_center_x;  +      xForm.eDy  = (FLOAT) -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y);  +      ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); +    } +    else +    { +      ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); +      SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); +    }    }  } @@ -1581,11 +1611,12 @@ static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned c    if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)    { +    /* reset to the identity. */      GetWorldTransform(ctxcanvas->hDC, &xForm);      ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);    } -  if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset +  if (ctxcanvas->canvas->invert_yaxis==0) /* if 0, invert because the transform was reset here */      y = _cdInvertYAxis(ctxcanvas->canvas, y);    yr = y - (h - 1);  /* y starts at the bottom of the image */ @@ -1891,20 +1922,21 @@ static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height)  static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int y)  { -  int yr;    XFORM xForm;    if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)    { +    /* reset to the identity. */      GetWorldTransform(ctxcanvas->hDC, &xForm);      ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);    } -  if (ctxcanvas->canvas->invert_yaxis==0)  // if 0, then the transform was reset +  if (ctxcanvas->canvas->invert_yaxis==0)  /* if 0, invert because the transform was reset here */      y = _cdInvertYAxis(ctxcanvas->canvas, y); -  yr = y - (ctximage->h - 1); -  BitBlt(ctximage->hDC, 0, 0, ctximage->w, ctximage->h, ctxcanvas->hDC, x, yr, SRCCOPY); +  /* y is the bottom-left of the image in CD, must be at upper-left */ +  y -= ctximage->h-1; +  BitBlt(ctximage->hDC, 0, 0, ctximage->w, ctximage->h, ctxcanvas->hDC, x, y, SRCCOPY);    if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)      ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); @@ -1971,18 +2003,15 @@ static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, i  {    XFORM xForm;    RECT rect; -  rect.left   = xmin;           -  rect.right  = xmax+1; -  rect.top    = ymin; -  rect.bottom = ymax+1;     if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED)    { +    /* reset to the identity. */      GetWorldTransform(ctxcanvas->hDC, &xForm);      ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY);    } -  if (ctxcanvas->canvas->invert_yaxis==0)  // if 0, then the transform was reset +  if (ctxcanvas->canvas->invert_yaxis==0)  /* if 0, invert because the transform was reset here */    {      dy = -dy;      ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin); @@ -1990,6 +2019,11 @@ static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, i      _cdSwapInt(ymin, ymax);    } +  rect.left   = xmin;           +  rect.right  = xmax+1; +  rect.top    = ymin; +  rect.bottom = ymax+1;  +    ScrollDC(ctxcanvas->hDC, dx, dy, &rect, NULL, NULL, NULL);    if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) @@ -2136,47 +2170,25 @@ static cdAttribute img_points_attrib =  static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)  { -  /* ignore ROTATE if transform is set */ +  /* ignore ROTATE if transform is set,  +     because there is native support for transformations */    if (ctxcanvas->canvas->use_matrix)      return;    if (data)    { -    XFORM xForm;      sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,                               &ctxcanvas->rotate_center_x,                               &ctxcanvas->rotate_center_y); - -    /* the rotation  must be corrected because of the Y axis orientation */ - -    SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED); -    ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); - -    xForm.eM11 = (FLOAT) cos(-CD_DEG2RAD*ctxcanvas->rotate_angle);  -    xForm.eM12 = (FLOAT) sin(-CD_DEG2RAD*ctxcanvas->rotate_angle);  -    xForm.eM21 = (FLOAT) -xForm.eM12;  -    xForm.eM22 = (FLOAT) xForm.eM11;  -    xForm.eDx  = (FLOAT) ctxcanvas->rotate_center_x;  -    xForm.eDy  = (FLOAT) _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y);  -    ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); - -    xForm.eM11 = (FLOAT) 1;  -    xForm.eM12 = (FLOAT) 0;  -    xForm.eM21 = (FLOAT) 0;  -    xForm.eM22 = (FLOAT) 1;  -    xForm.eDx  = (FLOAT) -ctxcanvas->rotate_center_x;  -    xForm.eDy  = (FLOAT) -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y);  -    ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY);    }    else    {      ctxcanvas->rotate_angle = 0;      ctxcanvas->rotate_center_x = 0;      ctxcanvas->rotate_center_y = 0; - -    ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); -    SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE);    } + +  cdtransform(ctxcanvas, NULL);  }  static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) diff --git a/src/win32/cdwnative.c b/src/win32/cdwnative.c index 69623e1..3534c6e 100644 --- a/src/win32/cdwnative.c +++ b/src/win32/cdwnative.c @@ -44,7 +44,6 @@ static int cdactivate(cdCtxCanvas *ctxcanvas)    if (ctxcanvas->hWnd)    {      RECT rect; -    HDC ScreenDC;      GetClientRect(ctxcanvas->hWnd, &rect);      ctxcanvas->canvas->w = rect.right - rect.left;      ctxcanvas->canvas->h = rect.bottom - rect.top; @@ -52,12 +51,7 @@ static int cdactivate(cdCtxCanvas *ctxcanvas)      ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres;      ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; -    ScreenDC = GetDC(NULL); -    ctxcanvas->canvas->bpp = GetDeviceCaps(ScreenDC, BITSPIXEL); -    ReleaseDC(NULL, ScreenDC); - -    if (ctxcanvas->canvas->use_matrix) -      ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix); +    ctxcanvas->canvas->bpp = cdGetScreenColorPlanes();    }    /* Se nao e' ownwer, tem que restaurar o contexto */ @@ -70,6 +64,9 @@ static int cdactivate(cdCtxCanvas *ctxcanvas)      cdwRestoreDC(ctxcanvas);    } +  if (ctxcanvas->canvas->use_matrix) +    ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix); +    return CD_OK;  } diff --git a/src/x11/cdx11.c b/src/x11/cdx11.c index 94aae39..35342db 100644 --- a/src/x11/cdx11.c +++ b/src/x11/cdx11.c @@ -2192,8 +2192,11 @@ static cdCtxImage *cdcreateimage (cdCtxCanvas *ctxcanvas, int w, int h)  static void cdgetimage (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y)  { +  /* y is the bottom-left of the image in CD, must be at upper-left */ +  y -= ctximage->h-1; +    XCopyArea(ctxcanvas->dpy, ctxcanvas->wnd, ctximage->img, ctxcanvas->gc, -            x, y - ctximage->h+1, ctximage->w, ctximage->h, 0, 0); +            x, y, ctximage->w, ctximage->h, 0, 0);  }  static void cdputimagerect (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax) @@ -2243,6 +2246,7 @@ static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data)  {    if (data)    { +    /* use this configuration when there is NO native tranformation support */      sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle,                               &ctxcanvas->rotate_center_x,                               &ctxcanvas->rotate_center_y);  | 
