summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorscuri <scuri>2010-05-12 20:38:46 +0000
committerscuri <scuri>2010-05-12 20:38:46 +0000
commitb7d97c7ed82f0d0472cf0c2ae5d61e99a73b33a8 (patch)
tree0da03500210df1ac835203e2bb83748564e67423 /src
parentafaff9e085b51c822f0ce31ac91cc8196bfa5113 (diff)
New Cairo driver
Diffstat (limited to 'src')
-rw-r--r--src/cairo/cdcairo.c1758
-rw-r--r--src/cairo/cdcairoctx.h77
-rw-r--r--src/cairo/cdcairodbuf.c170
-rw-r--r--src/cairo/cdcairoimg.c52
-rw-r--r--src/cairo/cdcairoirgb.c159
-rw-r--r--src/cairo/cdcaironative_gdk.c80
-rw-r--r--src/cairo/cdcaironative_win32.c160
-rw-r--r--src/cairo/cdcaironative_x11.c98
-rw-r--r--src/cairo/cdcairopdf.c122
-rw-r--r--src/cairo/cdcairoplus.c26
-rw-r--r--src/cairo/cdcairops.c170
-rw-r--r--src/cairo/cdcairosvg.c81
-rw-r--r--src/cd.c14
-rw-r--r--src/cd.def1
-rw-r--r--src/cd_text.c2
-rw-r--r--src/cd_util.c48
-rw-r--r--src/drv/cddebug.c7
-rw-r--r--src/drv/cdirgb.c1
-rw-r--r--src/drv/cdpdf.c83
-rw-r--r--src/drv/cdps.c47
-rw-r--r--src/gdiplus/cdwinp.cpp35
-rw-r--r--src/gdk/cdgdk.c35
-rw-r--r--src/svg/cdsvg.c34
-rw-r--r--src/win32/cdwdbuf.c1
-rw-r--r--src/win32/cdwin.c88
-rw-r--r--src/win32/cdwnative.c11
-rw-r--r--src/x11/cdx11.c6
27 files changed, 3148 insertions, 218 deletions
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;
+}
diff --git a/src/cd.c b/src/cd.c
index 6435d0a..1843a27 100644
--- a/src/cd.c
+++ b/src/cd.c
@@ -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[])
diff --git a/src/cd.def b/src/cd.def
index c087d9d..f5ae417 100644
--- a/src/cd.def
+++ b/src/cd.def
@@ -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);