summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cairo/cdcairo.c249
-rw-r--r--src/cairo/cdcaironative_win32.c2
-rw-r--r--src/cd.def1
-rw-r--r--src/cd_primitives.c39
-rw-r--r--src/drv/cdpdf.c194
-rw-r--r--src/drv/cdps.c368
-rw-r--r--src/gdiplus/cdwdbufp.cpp2
-rw-r--r--src/gdiplus/cdwinp.cpp445
-rw-r--r--src/gdiplus/cdwinp.h5
-rw-r--r--src/svg/cdsvg.c313
-rw-r--r--src/win32/cdwin.c87
11 files changed, 1609 insertions, 96 deletions
diff --git a/src/cairo/cdcairo.c b/src/cairo/cdcairo.c
index 6b536a4..286d5ad 100644
--- a/src/cairo/cdcairo.c
+++ b/src/cairo/cdcairo.c
@@ -79,7 +79,7 @@ char* StrConvertToUTF8(cdCtxCanvas *ctxcanvas, const char* str, int length)
return (char*)str;
}
-static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill)
{
if (fill == 0 || ctxcanvas->canvas->interior_style == CD_SOLID)
{
@@ -320,7 +320,6 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style)
cairo_t* cr;
hatch_surface = cairo_surface_create_similar(cairo_get_target(ctxcanvas->cr), CAIRO_CONTENT_COLOR_ALPHA, hsize, hsize);
-
cr = cairo_create(hatch_surface);
if (ctxcanvas->canvas->back_opacity == CD_OPAQUE)
@@ -576,7 +575,7 @@ static void cdclear(cdCtxCanvas* ctxcanvas)
static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, x1, y1);
cairo_line_to(ctxcanvas->cr, x2, y2);
@@ -608,7 +607,7 @@ static void sFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
sFixAngles(ctxcanvas, &a1, &a2);
@@ -639,7 +638,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
sFixAngles(ctxcanvas, &a1, &a2);
@@ -673,15 +672,14 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
sFixAngles(ctxcanvas, &a1, &a2);
if (w == h)
{
cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
- cairo_fill_preserve(ctxcanvas->cr);
- cairo_stroke(ctxcanvas->cr);
+ cairo_fill(ctxcanvas->cr);
}
else /* Ellipse: change the scale to create from the circle */
{
@@ -693,8 +691,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
cairo_translate(ctxcanvas->cr, -xc, -yc);
cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
- cairo_fill_preserve(ctxcanvas->cr);
- cairo_stroke(ctxcanvas->cr);
+ cairo_fill(ctxcanvas->cr);
cairo_restore(ctxcanvas->cr); /* restore from local */
}
@@ -707,7 +704,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double
static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
cairo_stroke(ctxcanvas->cr);
}
@@ -719,7 +716,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma
static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
cairo_rectangle(ctxcanvas->cr, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
cairo_fill(ctxcanvas->cr);
}
@@ -806,7 +803,7 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, i
cairo_set_font_matrix(ctxcanvas->cr, &matrix);
}
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, x, y);
cairo_show_text(ctxcanvas->cr, s);
@@ -844,9 +841,102 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ cairo_new_path(ctxcanvas->cr);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ cairo_new_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ sFixAngles(ctxcanvas, &a1, &a2);
+
+ if (w == h)
+ {
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Ellipse: change the scale to create from the circle */
+ {
+ cairo_save(ctxcanvas->cr); /* save to use the local transform */
+
+ cairo_translate(ctxcanvas->cr, xc, yc);
+ cairo_scale(ctxcanvas->cr, w/h, 1.0);
+ cairo_translate(ctxcanvas->cr, -xc, -yc);
+
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
+
+ cairo_restore(ctxcanvas->cr); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ cairo_curve_to(ctxcanvas->cr, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ cairo_close_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill(ctxcanvas->cr);
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill_preserve(ctxcanvas->cr);
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_CLIP:
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_clip(ctxcanvas->cr);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_EVEN_ODD);
@@ -854,7 +944,7 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_WINDING);
}
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y);
@@ -904,9 +994,102 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ cairo_new_path(ctxcanvas->cr);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ cairo_new_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ cairo_move_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ cairo_line_to(ctxcanvas->cr, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ sFixAngles(ctxcanvas, &a1, &a2);
+
+ if (w == h)
+ {
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Ellipse: change the scale to create from the circle */
+ {
+ cairo_save(ctxcanvas->cr); /* save to use the local transform */
+
+ cairo_translate(ctxcanvas->cr, xc, yc);
+ cairo_scale(ctxcanvas->cr, w/h, 1.0);
+ cairo_translate(ctxcanvas->cr, -xc, -yc);
+
+ cairo_arc(ctxcanvas->cr, xc, yc, 0.5*h, a1, a2);
+
+ cairo_restore(ctxcanvas->cr); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ cairo_curve_to(ctxcanvas->cr, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ cairo_close_path(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill(ctxcanvas->cr);
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_fill_preserve(ctxcanvas->cr);
+ sUpdateFill(ctxcanvas, 0);
+ cairo_stroke(ctxcanvas->cr);
+ break;
+ case CD_PATH_CLIP:
+ cairo_set_fill_rule(ctxcanvas->cr, ctxcanvas->canvas->fill_mode==CD_EVENODD? CAIRO_FILL_RULE_EVEN_ODD: CAIRO_FILL_RULE_WINDING);
+ cairo_clip(ctxcanvas->cr);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_EVEN_ODD);
@@ -914,7 +1097,7 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
cairo_set_fill_rule(ctxcanvas->cr, CAIRO_FILL_RULE_WINDING);
}
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cairo_move_to(ctxcanvas->cr, poly[0].x, poly[0].y);
@@ -1476,6 +1659,31 @@ static cdAttribute aa_attrib =
get_aa_attrib
};
+static void set_pattern_image_attrib(cdCtxCanvas *ctxcanvas, char* data)
+{
+ if (data)
+ {
+ cdCtxImage *ctximage = (cdCtxImage *)data;
+
+ if (ctxcanvas->pattern)
+ cairo_pattern_destroy(ctxcanvas->pattern);
+
+ ctxcanvas->pattern = cairo_pattern_create_for_surface(cairo_get_target(ctximage->cr));
+ cairo_pattern_reference(ctxcanvas->pattern);
+ cairo_pattern_set_extend(ctxcanvas->pattern, CAIRO_EXTEND_REPEAT);
+
+ cairo_set_source(ctxcanvas->cr, ctxcanvas->pattern);
+ ctxcanvas->last_source = 1;
+ }
+}
+
+static cdAttribute pattern_image_attrib =
+{
+ "PATTERNIMAGE",
+ set_pattern_image_attrib,
+ NULL
+};
+
static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data)
{
if (data)
@@ -1698,6 +1906,7 @@ cdCtxCanvas *cdcairoCreateCanvas(cdCanvas* canvas, cairo_t* cr)
cdRegisterAttribute(canvas, &interp_attrib);
cdRegisterAttribute(canvas, &cairodc_attrib);
cdRegisterAttribute(canvas, &hatchboxsize_attrib);
+ cdRegisterAttribute(canvas, &pattern_image_attrib);
cairo_save(ctxcanvas->cr);
cairo_set_operator(ctxcanvas->cr, CAIRO_OPERATOR_OVER);
@@ -1759,9 +1968,3 @@ void cdcairoInitTable(cdCanvas* canvas)
canvas->cxPutImageRectMap = cdputimagerectmap;
canvas->cxPutImageRectRGBA = cdputimagerectrgba;
}
-
-/*
-cairo_arc (cr, 128.0, 128.0, 76.8, 0, 2*M_PI);
-cairo_clip (cr);
-cairo_new_path (cr); // path not consumed by clip()
-*/
diff --git a/src/cairo/cdcaironative_win32.c b/src/cairo/cdcaironative_win32.c
index b685d12..e0b860e 100644
--- a/src/cairo/cdcaironative_win32.c
+++ b/src/cairo/cdcaironative_win32.c
@@ -143,7 +143,7 @@ static void cdinittable(cdCanvas* canvas)
static cdContext cdNativeWindowContext =
{
- CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE | CD_CAP_FPRIMTIVES),
+ CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_REGION | CD_CAP_WRITEMODE | CD_CAP_PALETTE),
1,
cdcreatecanvas,
cdinittable,
diff --git a/src/cd.def b/src/cd.def
index f5ae417..eda5beb 100644
--- a/src/cd.def
+++ b/src/cd.def
@@ -361,6 +361,7 @@ EXPORTS
cdCanvasVectorTextDirection
cdCanvasVectorTextSize
cdCanvasVertex
+ cdCanvasPathSet
cdfCanvasGetClipArea
cdfCanvasArc
diff --git a/src/cd_primitives.c b/src/cd_primitives.c
index b1a19ba..71e0fcd 100644
--- a/src/cd_primitives.c
+++ b/src/cd_primitives.c
@@ -123,12 +123,15 @@ void cdCanvasBegin(cdCanvas* canvas, int mode)
assert(mode>=CD_FILL);
if (!_cdCheckCanvas(canvas)) return;
+ canvas->use_fpoly = -1;
+ canvas->poly_n = 0;
+ canvas->path_n = 0;
+
if (mode == CD_REGION)
{
if (!canvas->cxNewRegion) return;
canvas->new_region = 1;
- canvas->poly_n = 0;
canvas->cxNewRegion(canvas->ctxcanvas);
return;
}
@@ -147,8 +150,6 @@ void cdCanvasBegin(cdCanvas* canvas, int mode)
if (mode == CD_FILL && canvas->sim_mode & CD_SIM_POLYGON)
canvas->sim_poly = 1;
- canvas->use_fpoly = -1;
- canvas->poly_n = 0;
canvas->poly_mode = mode;
}
@@ -233,6 +234,30 @@ void cdfCanvasVertex(cdCanvas* canvas, double x, double y)
canvas->poly_n++;
}
+void cdCanvasPathSet(cdCanvas* canvas, int action)
+{
+ assert(canvas);
+ if (!_cdCheckCanvas(canvas)) return;
+
+ if (canvas->poly_mode!=CD_PATH)
+ return;
+
+ if (!canvas->path)
+ {
+ canvas->path = (int*)malloc(sizeof(int)*(_CD_POLY_BLOCK+1));
+ canvas->path_size = _CD_POLY_BLOCK;
+ }
+
+ if (canvas->path_n == canvas->path_size)
+ {
+ canvas->path_size += _CD_POLY_BLOCK;
+ canvas->path = (int*)realloc(canvas->path, sizeof(int) * (canvas->path_size+1));
+ }
+
+ canvas->path[canvas->path_n] = action;
+ canvas->path_n++;
+}
+
void cdCanvasEnd(cdCanvas* canvas)
{
assert(canvas);
@@ -245,6 +270,13 @@ void cdCanvasEnd(cdCanvas* canvas)
return;
}
+ if (canvas->poly_mode==CD_PATH && canvas->poly_n < 2)
+ {
+ canvas->poly_n = 0;
+ canvas->path_n = 0;
+ return;
+ }
+
if (canvas->poly_mode==CD_OPEN_LINES && canvas->poly_n < 2)
{
canvas->poly_n = 0;
@@ -303,6 +335,7 @@ void cdCanvasEnd(cdCanvas* canvas)
}
}
+ canvas->path_n = 0;
canvas->poly_n = 0;
canvas->use_fpoly = -1;
}
diff --git a/src/drv/cdpdf.c b/src/drv/cdpdf.c
index e6f3f73..eb9371f 100644
--- a/src/drv/cdpdf.c
+++ b/src/drv/cdpdf.c
@@ -138,7 +138,7 @@ static void cdkillcanvas(cdCtxCanvas *ctxcanvas)
free(ctxcanvas);
}
-static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill)
{
if (fill == 0)
{
@@ -283,7 +283,7 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
PDF_moveto(ctxcanvas->pdf, x1, y1);
PDF_lineto(ctxcanvas->pdf, x2, y2);
@@ -297,7 +297,7 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
PDF_rect(ctxcanvas->pdf, xmin, ymin, xmax-xmin, ymax-ymin);
PDF_stroke(ctxcanvas->pdf);
@@ -310,7 +310,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma
static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
PDF_moveto(ctxcanvas->pdf, xmin, ymin);
PDF_lineto(ctxcanvas->pdf, xmax, ymin);
@@ -326,7 +326,7 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax
static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (w==h)
{
@@ -355,7 +355,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h)
{
@@ -386,12 +386,12 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h)
{
PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
- PDF_fill_stroke(ctxcanvas->pdf);
+ PDF_fill(ctxcanvas->pdf);
}
else /* Elipse: mudar a escala p/ criar a partir do circulo */
{
@@ -403,7 +403,7 @@ static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, dou
PDF_translate(ctxcanvas->pdf, -xc, -yc);
PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
- PDF_fill_stroke(ctxcanvas->pdf);
+ PDF_fill(ctxcanvas->pdf);
PDF_restore(ctxcanvas->pdf); /* restore from local */
}
@@ -537,10 +537,94 @@ static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ PDF_endpath(ctxcanvas->pdf);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ PDF_endpath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ if (w==h)
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ else /* Ellipse: change the scale to create from the circle */
+ {
+ PDF_save(ctxcanvas->pdf); /* save to use the local transform */
+
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, w/h, 1);
+ PDF_translate(ctxcanvas->pdf, -xc, -yc);
+
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ PDF_closepath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILL:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill(ctxcanvas->pdf);
+ break;
+ case CD_PATH_STROKE:
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILLSTROKE:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_CLIP:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_clip(ctxcanvas->pdf);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (mode==CD_FILL)
{
@@ -599,10 +683,94 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
if (mode == CD_CLIP)
return;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ PDF_endpath(ctxcanvas->pdf);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ PDF_endpath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ if (w==h)
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2);
+ else /* Ellipse: change the scale to create from the circle */
+ {
+ PDF_save(ctxcanvas->pdf); /* save to use the local transform */
+
+ PDF_translate(ctxcanvas->pdf, xc, yc);
+ PDF_scale(ctxcanvas->pdf, w/h, 1);
+ PDF_translate(ctxcanvas->pdf, -xc, -yc);
+
+ PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2);
+
+ PDF_restore(ctxcanvas->pdf); /* restore from local */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ PDF_curveto(ctxcanvas->pdf, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ PDF_closepath(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILL:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill(ctxcanvas->pdf);
+ break;
+ case CD_PATH_STROKE:
+ PDF_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_FILLSTROKE:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_fill_stroke(ctxcanvas->pdf);
+ break;
+ case CD_PATH_CLIP:
+ PDF_set_parameter(ctxcanvas->pdf, "fillrule", ctxcanvas->canvas->fill_mode==CD_EVENODD? "evenodd": "winding");
+ PDF_clip(ctxcanvas->pdf);
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (mode==CD_FILL)
{
diff --git a/src/drv/cdps.c b/src/drv/cdps.c
index c54c95a..ce45397 100644
--- a/src/drv/cdps.c
+++ b/src/drv/cdps.c
@@ -64,6 +64,7 @@ struct _cdCtxCanvas
int level1; /* if true generates level 1 only function calls */
int landscape; /* page orientation */
int debug; /* print debug strings in the file */
+
float rotate_angle;
int rotate_center_x,
rotate_center_y;
@@ -73,7 +74,6 @@ struct _cdCtxCanvas
int poly_holes[500];
int holes;
-
};
/*
@@ -396,7 +396,7 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style);
static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple);
static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern);
-static void update_fill(cdCtxCanvas *ctxcanvas, int fill)
+static void sUpdateFill(cdCtxCanvas *ctxcanvas, int fill)
{
if (fill == 0)
{
@@ -504,7 +504,7 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int mode)
static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
fprintf(ctxcanvas->file, "N %d %d %d %d LL\n", x1, y1, x2, y2);
@@ -517,7 +517,7 @@ static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2)
static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
fprintf(ctxcanvas->file, "N %g %g %g %g LL\n", x1, y1, x2, y2);
@@ -530,7 +530,7 @@ static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, dou
static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (ctxcanvas->level1)
{
@@ -553,7 +553,7 @@ static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int yma
static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (ctxcanvas->level1)
{
@@ -576,7 +576,7 @@ static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymi
static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->level1)
{
@@ -599,7 +599,7 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax
static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (ctxcanvas->level1)
{
@@ -622,7 +622,7 @@ static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin
static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -654,7 +654,7 @@ static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a
static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -686,7 +686,7 @@ static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, doubl
static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -727,7 +727,7 @@ static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -768,7 +768,7 @@ static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, do
static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -806,7 +806,7 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double
static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
{
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
if (w==h) /* Circulo: PS implementa direto */
{
@@ -849,7 +849,7 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len)
int i;
int ascent, height, baseline;
- update_fill(ctxcanvas, 0);
+ sUpdateFill(ctxcanvas, 0);
cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL);
baseline = height - ascent;
@@ -960,30 +960,242 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len)
if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n");
}
+static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len)
+{
+ int i;
+ int ascent, height, baseline;
+
+ sUpdateFill(ctxcanvas, 0);
+
+ cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL);
+ baseline = height - ascent;
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdText Begin\n");
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ set_default_matrix(ctxcanvas);
+
+ fprintf(ctxcanvas->file, "N 0 0 M\n");
+ putc('(', ctxcanvas->file);
+
+ for (i=0; i<len; i++)
+ {
+ if (s[i]=='(' || s[i]==')')
+ putc('\\', ctxcanvas->file);
+ putc(s[i], ctxcanvas->file);
+ }
+
+ fprintf(ctxcanvas->file, ")\n");
+ fprintf(ctxcanvas->file, "dup true charpath\n");
+ fprintf(ctxcanvas->file, "flattenpath\n");
+ fprintf(ctxcanvas->file, "pathbbox\n"); /* bbox na pilha: llx lly urx ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: llx lly ury urx */
+ fprintf(ctxcanvas->file, "4 1 roll\n"); /* roda: urx llx lly ury */
+ fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: urx llx ury lly */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: urx llx h */
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: h urx llx */
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: h w */
+ fprintf(ctxcanvas->file, "0 0\n"); /* empilha: h w 0 0 */
+ fprintf(ctxcanvas->file, "4 -1 roll\n"); /* roda: w 0 0 h */
+
+ if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle)
+ cdtransform(ctxcanvas, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL);
+
+ fprintf(ctxcanvas->file, "gsave\n"); /* save to use local transform */
+ fprintf(ctxcanvas->file, "%g %g translate\n", x, y);
+
+ if (ctxcanvas->canvas->text_orientation != 0)
+ fprintf(ctxcanvas->file, "%g rotate\n", ctxcanvas->canvas->text_orientation);
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em Y. topo da pilha: w x y h */
+ {
+ case CD_NORTH:
+ case CD_NORTH_EAST:
+ case CD_NORTH_WEST:
+ fprintf(ctxcanvas->file, "%d sub sub\n", baseline); /* empilha, subtrai, subtrai: w x y-(h-baseline) */
+ break;
+ case CD_EAST:
+ case CD_WEST:
+ case CD_CENTER:
+ fprintf(ctxcanvas->file, "2 div %d sub sub\n", baseline); /* empilha, divide, empilha, subtrai, subtrai: w x y-(h/2-baseline) */
+ break;
+ case CD_SOUTH_EAST:
+ case CD_SOUTH:
+ case CD_SOUTH_WEST:
+ fprintf(ctxcanvas->file, "pop %d add\n", baseline); /* desempilha, empilha, adiciona: w x y+baseline */
+ break;
+ case CD_BASE_RIGHT:
+ case CD_BASE_CENTER:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha h: w x y */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: y' w x */
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: y' x w */
+
+ switch (ctxcanvas->canvas->text_alignment) /* Operacao em X, topo da pilha: x w */
+ {
+ case CD_NORTH:
+ case CD_SOUTH:
+ case CD_CENTER:
+ case CD_BASE_CENTER:
+ fprintf(ctxcanvas->file, "2 div sub\n"); /* empilha, divide, subtrai: y' x-w/2 */
+ break;
+ case CD_NORTH_EAST:
+ case CD_EAST:
+ case CD_SOUTH_EAST:
+ case CD_BASE_RIGHT:
+ fprintf(ctxcanvas->file, "sub\n"); /* subtrai: y' x-w */
+ break;
+ case CD_SOUTH_WEST:
+ case CD_WEST:
+ case CD_NORTH_WEST:
+ case CD_BASE_LEFT:
+ fprintf(ctxcanvas->file, "pop\n"); /* desempilha: y' x */
+ break;
+ }
+
+ fprintf(ctxcanvas->file, "exch\n"); /* inverte: x' y' */
+ fprintf(ctxcanvas->file, "M\n"); /* moveto */
+
+ fprintf(ctxcanvas->file, "show\n");
+
+ if (ctxcanvas->eps)
+ {
+ int xmin, xmax, ymin, ymax;
+ s = cdStrDupN(s, len);
+ cdCanvasGetTextBox(ctxcanvas->canvas, (int)x, (int)y, s, &xmin, &xmax, &ymin, &ymax);
+ free((char*)s);
+ fbbox(ctxcanvas, (double)xmin, (double)ymin);
+ fbbox(ctxcanvas, (double)xmax, (double)ymax);
+ }
+
+ fprintf(ctxcanvas->file, "grestore\n");
+
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n");
+}
+
static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
{
int i;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ fprintf(ctxcanvas->file, "newpath\n");
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ fprintf(ctxcanvas->file, "newpath\n");
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%d %d M\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%d %d L\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */
+ fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "%d %d %d %d %d %d B\n", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "closepath\n");
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ fprintf(ctxcanvas->file, "gsave\n");
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ fprintf(ctxcanvas->file, "grestore\n");
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_CLIP:
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_CLIP)
{
if (ctxcanvas->eps) /* initclip not allowed in EPS */
return;
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
-
fprintf(ctxcanvas->file, "/clip_polygon {\n");
fprintf(ctxcanvas->file, "initclip\n");
}
else
{
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
-
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+ sUpdateFill(ctxcanvas, 0);
}
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode);
+
fprintf(ctxcanvas->file, "N\n");
fprintf(ctxcanvas->file, "%d %d M\n", poly[0].x, poly[0].y);
@@ -1061,26 +1273,122 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
{
int i, hole_index = 0;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ fprintf(ctxcanvas->file, "newpath\n");
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ fprintf(ctxcanvas->file, "newpath\n");
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%g %g M\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "%g %g L\n", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ if (w==h) /* Circulo: PS implementa direto */
+ {
+ fprintf(ctxcanvas->file, "N %g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2);
+ }
+ else /* Elipse: mudar a escala p/ criar a partir do circulo */
+ {
+ fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */
+ fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc);
+ fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w);
+ fprintf(ctxcanvas->file, "N\n");
+ fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2);
+ fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */
+ }
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "%g %g %g %g %g %g B\n", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "closepath\n");
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ fprintf(ctxcanvas->file, "gsave\n");
+ if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "eofill\n");
+ else
+ fprintf(ctxcanvas->file, "fill\n");
+ fprintf(ctxcanvas->file, "grestore\n");
+ sUpdateFill(ctxcanvas, 0);
+ fprintf(ctxcanvas->file, "stroke\n");
+ break;
+ case CD_PATH_CLIP:
+ if (ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ fprintf(ctxcanvas->file, "C eoclip\n");
+ else
+ fprintf(ctxcanvas->file, "C clip\n");
+ break;
+ }
+ }
+ return;
+ }
+
if (mode == CD_CLIP)
{
if (ctxcanvas->eps) /* initclip not allowed in EPS */
return;
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
-
fprintf(ctxcanvas->file, "/clip_polygon {\n");
fprintf(ctxcanvas->file, "initclip\n");
}
else
{
if (mode == CD_FILL)
- update_fill(ctxcanvas, 1);
+ sUpdateFill(ctxcanvas, 1);
else
- update_fill(ctxcanvas, 0);
-
- if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+ sUpdateFill(ctxcanvas, 0);
}
+ if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode);
+
fprintf(ctxcanvas->file, "N\n");
fprintf(ctxcanvas->file, "%g %g M\n", poly[0].x, poly[0].y);
@@ -1752,7 +2060,9 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)
static void cdinittable(cdCanvas* canvas)
{
canvas->cxFlush = cdflush;
+
canvas->cxPixel = cdpixel;
+
canvas->cxLine = cdline;
canvas->cxPoly = cdpoly;
canvas->cxRect = cdrect;
@@ -1761,8 +2071,10 @@ static void cdinittable(cdCanvas* canvas)
canvas->cxSector = cdsector;
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+
canvas->cxPutImageRectRGB = cdputimagerectrgb;
canvas->cxPutImageRectMap = cdputimagerectmap;
+
canvas->cxFLine = cdfline;
canvas->cxFPoly = cdfpoly;
canvas->cxFRect = cdfrect;
@@ -1770,6 +2082,8 @@ static void cdinittable(cdCanvas* canvas)
canvas->cxFArc = cdfarc;
canvas->cxFSector = cdfsector;
canvas->cxFChord = cdfchord;
+ canvas->cxFText = cdftext;
+
canvas->cxClip = cdclip;
canvas->cxFClipArea = cdfcliparea;
canvas->cxLineStyle = cdlinestyle;
diff --git a/src/gdiplus/cdwdbufp.cpp b/src/gdiplus/cdwdbufp.cpp
index 95cfe2e..87957fb 100644
--- a/src/gdiplus/cdwdbufp.cpp
+++ b/src/gdiplus/cdwdbufp.cpp
@@ -120,7 +120,7 @@ static void cdcreatecanvas(cdCanvas* canvas, void *data)
bitmap->SetResolution((REAL)(canvas_dbuffer->xres*25.4), (REAL)(canvas_dbuffer->yres*25.4));
Graphics imggraphics(bitmap);
- imggraphics.Clear(Color::White);
+ imggraphics.Clear(Color((ARGB)Color::White));
Graphics* graphics = new Graphics(bitmap);
diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp
index ea14628..a8d3f9c 100644
--- a/src/gdiplus/cdwinp.cpp
+++ b/src/gdiplus/cdwinp.cpp
@@ -51,10 +51,10 @@ void cdwpShowStatus(const char* title, Status status)
void cdwpKillCanvas(cdCtxCanvas* ctxcanvas)
{
if (ctxcanvas->clip_poly) delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_fpoly) delete[] ctxcanvas->clip_fpoly;
if (ctxcanvas->clip_region) delete ctxcanvas->clip_region;
if (ctxcanvas->new_region) delete ctxcanvas->new_region;
if (ctxcanvas->font) delete ctxcanvas->font;
- if (ctxcanvas->wdpoly) delete ctxcanvas->wdpoly;
delete ctxcanvas->fillBrush;
delete ctxcanvas->lineBrush;
@@ -245,7 +245,10 @@ static void sClipPoly(cdCtxCanvas* ctxcanvas)
GraphicsPath path;
path.SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
- path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
+ if (ctxcanvas->clip_fpoly)
+ path.AddPolygon(ctxcanvas->clip_fpoly, ctxcanvas->clip_poly_n);
+ else
+ path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
ctxcanvas->clip_region = new Region(&path);
ctxcanvas->graphics->SetClip(ctxcanvas->clip_region);
@@ -572,6 +575,12 @@ static void cdline(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
ctxcanvas->dirty = 1;
}
+static void cdfline(cdCtxCanvas* ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ ctxcanvas->graphics->DrawLine(ctxcanvas->linePen, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
+ ctxcanvas->dirty = 1;
+}
+
static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
Rect rect(xmin, ymin, xmax-xmin, ymax-ymin); // in this case Size = Max - Min
@@ -579,6 +588,13 @@ static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int yma
ctxcanvas->dirty = 1;
}
+static void cdfrect(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ RectF rect((REAL)xmin, (REAL)ymin, (REAL)(xmax-xmin), (REAL)(ymax-ymin)); // in this case Size = Max - Min
+ ctxcanvas->graphics->DrawRectangle(ctxcanvas->linePen, rect);
+ ctxcanvas->dirty = 1;
+}
+
static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1);
@@ -594,6 +610,21 @@ static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax
}
}
+static void cdfbox(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ RectF rect((REAL)xmin, (REAL)ymin, (REAL)(xmax-xmin+1), (REAL)(ymax-ymin+1));
+ if (ctxcanvas->canvas->new_region)
+ {
+ Region region(rect);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ ctxcanvas->graphics->FillRectangle(ctxcanvas->fillBrush, rect);
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
{
if (ctxcanvas->canvas->invert_yaxis)
@@ -617,6 +648,19 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a
ctxcanvas->dirty = 1;
}
+static void cdfarc(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (angle1 == 0 && angle2 == 360)
+ ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+}
+
static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
Rect rect(xc - w/2, yc - h/2, w, h);
@@ -653,6 +697,42 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
}
}
+static void cdfsector(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ // complete the remaining pixels using an Arc
+ Pen pen(ctxcanvas->fillBrush);
+
+ if (angle1==0 && angle2==360)
+ {
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ ctxcanvas->graphics->DrawEllipse(&pen, rect);
+ }
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
Rect rect(xc - w/2, yc - h/2, w, h);
@@ -687,10 +767,135 @@ static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
}
}
+static void cdfchord(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ path.CloseFigure();
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ if (angle1==0 && angle2==360)
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ else
+ {
+ GraphicsPath path;
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path);
+ }
+ Pen pen(ctxcanvas->fillBrush); // complete the remaining pixels using an Arc
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
{
- switch( mode )
+ switch (mode)
{
+ case CD_PATH:
+ {
+ int p, i, current_x = 0, current_y = 0;
+ GraphicsPath* graphics_path;
+ PointF lastPoint;
+
+ /* starts a new path */
+ graphics_path = new GraphicsPath(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ graphics_path->Reset();
+ graphics_path->SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ graphics_path->AddLine(current_x, current_y, poly[i].x, poly[i].y);
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ Rect rect(xc - w/2, yc - h/2, w, h);
+ if (a1 == 0 && a2 == 360)
+ graphics_path->AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &a1, &a2);
+ graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
+ }
+
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = (int)lastPoint.X;
+ current_y = (int)lastPoint.Y;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ graphics_path->AddBezier(current_x, current_y, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = (int)lastPoint.X;
+ current_y = (int)lastPoint.Y;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ graphics_path->CloseFigure();
+ break;
+ case CD_PATH_FILL:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ break;
+ case CD_PATH_STROKE:
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_FILLSTROKE:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_CLIP:
+ ctxcanvas->graphics->SetClip(graphics_path, CombineModeIntersect);
+ break;
+ }
+ }
+
+ delete graphics_path;
+ break;
+ }
case CD_BEZIER:
if (n < 4) return;
ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (Point*)poly, n);
@@ -749,6 +954,11 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
if (ctxcanvas->clip_poly)
delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_fpoly)
+ {
+ delete[] ctxcanvas->clip_fpoly;
+ ctxcanvas->clip_fpoly = NULL;
+ }
ctxcanvas->clip_poly = new Point [n];
@@ -780,6 +990,223 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
ctxcanvas->dirty = 1;
}
+static PointF* sPolyToFloat(cdfPoint* poly, int n)
+{
+ PointF* fpoly = new PointF[n+1];
+
+ for (int i = 0; i < n; i++)
+ {
+ fpoly[i].X = (REAL)poly[i].x;
+ fpoly[i].Y = (REAL)poly[i].y;
+ }
+
+ return fpoly;
+}
+
+static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ PointF* fpoly = NULL;
+
+ switch (mode)
+ {
+ case CD_PATH:
+ {
+ int p, i;
+ double current_x = 0, current_y = 0;
+ GraphicsPath* graphics_path;
+ PointF lastPoint;
+
+ /* starts a new path */
+ graphics_path = new GraphicsPath(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ graphics_path->Reset();
+ graphics_path->SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ graphics_path->AddLine((REAL)current_x, (REAL)current_y, (REAL)poly[i].x, (REAL)poly[i].y);
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (a1 == 0 && a2 == 360)
+ graphics_path->AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &a1, &a2);
+ graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
+ }
+
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = lastPoint.X;
+ current_y = lastPoint.Y;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ graphics_path->AddBezier((REAL)current_x, (REAL)current_y, (REAL)poly[i].x, (REAL)poly[i].y, (REAL)poly[i+1].x, (REAL)poly[i+1].y, (REAL)poly[i+2].x, (REAL)poly[i+2].y);
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = lastPoint.X;
+ current_y = lastPoint.Y;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ graphics_path->CloseFigure();
+ break;
+ case CD_PATH_FILL:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ break;
+ case CD_PATH_STROKE:
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_FILLSTROKE:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_CLIP:
+ ctxcanvas->graphics->SetClip(graphics_path, CombineModeIntersect);
+ break;
+ }
+ }
+
+ delete graphics_path;
+ break;
+ }
+ case CD_BEZIER:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_FILLSPLINE:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddClosedCurve((PointF*)fpoly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillClosedCurve(ctxcanvas->fillBrush, (PointF*)fpoly, n);
+ break;
+ case CD_SPLINE:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawClosedCurve(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_CLOSED_LINES:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawLines(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_FILLGRADIENT:
+ {
+ int count = n;
+ PathGradientBrush* brush = new PathGradientBrush((PointF*)fpoly, n);
+ fpoly = sPolyToFloat(poly, n);
+ brush->SetSurroundColors(ctxcanvas->pathGradient, &count);
+ brush->SetCenterColor(ctxcanvas->pathGradient[n]);
+ ctxcanvas->graphics->FillPolygon(brush, (PointF*)fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ delete brush;
+ }
+ break;
+ case CD_FILL:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ fpoly = sPolyToFloat(poly, n);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddPolygon((PointF*)fpoly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillPolygon(ctxcanvas->fillBrush, (PointF*)fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_CLIP:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+
+ if (ctxcanvas->clip_fpoly)
+ delete[] ctxcanvas->clip_fpoly;
+ if (ctxcanvas->clip_poly)
+ {
+ delete[] ctxcanvas->clip_poly;
+ ctxcanvas->clip_poly = NULL;
+ }
+
+ ctxcanvas->clip_fpoly = new PointF [n];
+
+ cdfPoint* pnt = poly;
+ int t = n;
+ int nc = 1;
+
+ ctxcanvas->clip_fpoly[0].X = (REAL)pnt->x;
+ ctxcanvas->clip_fpoly[0].Y = (REAL)pnt->y;
+ pnt++;
+
+ for (int i = 1; i < t-1; i++, pnt++)
+ {
+ if (!(((REAL)pnt->x == ctxcanvas->clip_fpoly[nc-1].X && pnt->x == (pnt + 1)->x) ||
+ ((REAL)pnt->y == ctxcanvas->clip_fpoly[nc-1].Y && pnt->y == (pnt + 1)->y)))
+ {
+ ctxcanvas->clip_fpoly[nc].X = (REAL)pnt->x;
+ ctxcanvas->clip_fpoly[nc].Y = (REAL)pnt->y;
+ nc++;
+ }
+ }
+
+ ctxcanvas->clip_poly_n = nc;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ sClipPoly(ctxcanvas);
+
+ break;
+ }
+
+ if (fpoly)
+ delete[] fpoly;
+
+ ctxcanvas->dirty = 1;
+}
+
WCHAR* cdwpString2Unicode(const char* s, int len)
{
static WCHAR wstr[10240] = L"";
@@ -1654,7 +2081,7 @@ static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height)
ctximage->h_mm = ctximage->h / ctximage->yres;
Graphics imggraphics(ctximage->bitmap);
- imggraphics.Clear(Color::White);
+ imggraphics.Clear(Color((ARGB)Color::White));
return ctximage;
}
@@ -2248,6 +2675,7 @@ cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype)
canvas->invert_yaxis = 1;
ctxcanvas->clip_poly = NULL;
+ ctxcanvas->clip_fpoly = NULL;
ctxcanvas->clip_poly_n = 0;
ctxcanvas->clip_region = NULL;
ctxcanvas->new_region = NULL;
@@ -2303,6 +2731,7 @@ void cdwpInitTable(cdCanvas* canvas)
canvas->cxFlush = cdflush;
canvas->cxPixel = cdpixel;
+
canvas->cxLine = cdline;
canvas->cxPoly = cdpoly;
canvas->cxRect = cdrect;
@@ -2312,6 +2741,14 @@ void cdwpInitTable(cdCanvas* canvas)
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+
canvas->cxNewRegion = cdnewregion;
canvas->cxIsPointInRegion = cdispointinregion;
canvas->cxOffsetRegion = cdoffsetregion;
diff --git a/src/gdiplus/cdwinp.h b/src/gdiplus/cdwinp.h
index 0c4ae55..b42dc9a 100644
--- a/src/gdiplus/cdwinp.h
+++ b/src/gdiplus/cdwinp.h
@@ -48,15 +48,12 @@ struct _cdCtxCanvas
} fontinfo;
Point *clip_poly; /* coordenadas do pixel no X,Y */
+ PointF *clip_fpoly; /* coordenadas do pixel no X,Y */
int clip_poly_n; /* numero de pontos correntes */
Region *clip_region;
Region *new_region;
- int max_points;
- PointF *wdpoly; // cache buffer for wdpoly
- Point *cdpoly; // alias to cache buffer (float=int)
-
int antialias;
Point gradient[2];
diff --git a/src/svg/cdsvg.c b/src/svg/cdsvg.c
index 2441523..fd48559 100644
--- a/src/svg/cdsvg.c
+++ b/src/svg/cdsvg.c
@@ -101,11 +101,12 @@ static int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode)
if (ctxcanvas->clip_polygon)
{
/* open clipping container */
- fprintf(ctxcanvas->file, "<g clip-path=\"url(#clippoly%d)\">\n", ctxcanvas->last_clip_poly);
+ fprintf(ctxcanvas->file, "<g clip-path=\"url(#clippoly%d)\" clip-rule:%s >\n", ctxcanvas->last_clip_poly, (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero");
ctxcanvas->clip_control = 1;
}
break;
}
+
return clip_mode;
}
@@ -407,7 +408,7 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int l
cdftext(ctxcanvas, (double)x, (double)y, text, len);
}
-static void write_points(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int close)
+static void sWritePointsF(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int close)
{
int i;
for(i = 0; i<n; i++)
@@ -416,27 +417,153 @@ static void write_points(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int clos
fprintf(ctxcanvas->file, "%g,%g ", poly[0].x, poly[0].y);
}
+static void sWritePoints(cdCtxCanvas *ctxcanvas, cdPoint* poly, int n, int close)
+{
+ int i;
+ for(i = 0; i<n; i++)
+ fprintf(ctxcanvas->file, "%d,%d ", poly[i].x, poly[i].y);
+ if (close)
+ fprintf(ctxcanvas->file, "%d,%d ", poly[0].x, poly[0].y);
+}
+
static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
{
char* rule;
+ if (mode == CD_PATH)
+ {
+ int i, p, clip_path = 0, end_path;
+
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP)
+ {
+ clip_path = 1;
+ break;
+ }
+ }
+
+ if (clip_path)
+ fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
+
+ /* starts a new path */
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ if (!end_path)
+ fprintf(ctxcanvas->file, "\" />\n");
+
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "M %g %g ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "L %g %g ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h, a1, a2;
+ double arcStartX, arcStartY, arcEndX, arcEndY;
+ int largeArc = 0;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ if (ctxcanvas->canvas->use_matrix) /* Transformation active */
+ {
+ double temp = 360 - a1;
+ a1 = 360 - a2;
+ a2 = temp;
+ }
+
+ arcStartX = (xc+(w/2)*cos(a1*CD_DEG2RAD));
+ arcStartY = (yc-(h/2)*sin(a1*CD_DEG2RAD));
+ arcEndX = (xc+(w/2)*cos(a2*CD_DEG2RAD));
+ arcEndY = (yc-(h/2)*sin(a2*CD_DEG2RAD));
+
+ if ((a2-a1) > 180.0)
+ largeArc = 1;
+
+ fprintf(ctxcanvas->file, "M %g %g A %g %g 0 %d 0 %g %g ",
+ arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY);
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "C %g %g %g %g %g %g ", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "Z ");
+ break;
+ case CD_PATH_FILL:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_STROKE:
+ fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_FILLSTROKE:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_CLIP:
+ fprintf(ctxcanvas->file, "\" />\n");
+ fprintf(ctxcanvas->file, "</clipPath>\n");
+ ctxcanvas->clip_polygon = 1;
+ cdclip(ctxcanvas, CD_CLIPPOLYGON);
+ end_path = 1;
+ break;
+ }
+ }
+ return;
+ }
+
switch (mode)
{
case CD_CLOSED_LINES:
fprintf(ctxcanvas->file, "<polygon style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
- write_points(ctxcanvas, poly, n, 1);
+ sWritePointsF(ctxcanvas, poly, n, 1);
fprintf(ctxcanvas->file, "\" />\n");
break;
case CD_OPEN_LINES:
fprintf(ctxcanvas->file, "<polyline style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
- write_points(ctxcanvas, poly, n, 0);
+ sWritePointsF(ctxcanvas, poly, n, 0);
fprintf(ctxcanvas->file, "\" />\n");
break;
case CD_BEZIER:
fprintf(ctxcanvas->file, "<path d=\"M%g,%g C", poly[0].x, poly[0].y);
- write_points(ctxcanvas, poly+1, n-1, 0);
+ sWritePointsF(ctxcanvas, poly+1, n-1, 0);
fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
break;
@@ -448,14 +575,14 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
fprintf(ctxcanvas->file, "<polygon style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" points=\"",
(ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
- write_points(ctxcanvas, poly, n, 0);
+ sWritePointsF(ctxcanvas, poly, n, 0);
fprintf(ctxcanvas->file, "\" />\n");
break;
case CD_CLIP:
fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
fprintf(ctxcanvas->file, "<polygon points=\"");
- write_points(ctxcanvas, poly, n, 0);
+ sWritePointsF(ctxcanvas, poly, n, 0);
fprintf(ctxcanvas->file, "\" />\n");
fprintf(ctxcanvas->file, "</clipPath>\n");
@@ -472,20 +599,174 @@ static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n)
static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n)
{
- int i;
- cdfPoint* newPoly = NULL;
-
- newPoly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+1));
+ char* rule;
- for(i = 0; i < n; i++)
+ if (mode == CD_PATH)
{
- newPoly[i].x = (double)poly[i].x;
- newPoly[i].y = (double)poly[i].y;
+ int i, p, clip_path = 0, end_path;
+
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP)
+ {
+ clip_path = 1;
+ break;
+ }
+ }
+
+ if (clip_path)
+ fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
+
+ /* starts a new path */
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ if (!end_path)
+ fprintf(ctxcanvas->file, "\" />\n");
+
+ fprintf(ctxcanvas->file, "<path d=\"");
+ end_path = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "M %d %d ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ fprintf(ctxcanvas->file, "L %d %d ", poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+ int arcStartX, arcStartY, arcEndX, arcEndY;
+ int largeArc = 0;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ if (ctxcanvas->canvas->use_matrix) /* Transformation active */
+ {
+ double temp = 360 - a1;
+ a1 = 360 - a2;
+ a2 = temp;
+ }
+
+ arcStartX = (int)(xc+(w/2)*cos(a1*CD_DEG2RAD));
+ arcStartY = (int)(yc-(h/2)*sin(a1*CD_DEG2RAD));
+ arcEndX = (int)(xc+(w/2)*cos(a2*CD_DEG2RAD));
+ arcEndY = (int)(yc-(h/2)*sin(a2*CD_DEG2RAD));
+
+ if ((a2-a1) > 180.0)
+ largeArc = 1;
+
+ fprintf(ctxcanvas->file, "M %d %d A %d %d 0 %d 0 %d %d ",
+ arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY);
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ fprintf(ctxcanvas->file, "C %d %d %d %d %d %d ", poly[i].x, poly[i].y,
+ poly[i+1].x, poly[i+1].y,
+ poly[i+2].x, poly[i+2].y);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ fprintf(ctxcanvas->file, "Z ");
+ break;
+ case CD_PATH_FILL:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_STROKE:
+ fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_FILLSTROKE:
+ rule = (ctxcanvas->canvas->fill_mode==CD_EVENODD)? "evenodd": "nonzero";
+ fprintf(ctxcanvas->file, "\" style=\"fill:%s; fill-rule:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ end_path = 1;
+ break;
+ case CD_PATH_CLIP:
+ fprintf(ctxcanvas->file, "\" />\n");
+ fprintf(ctxcanvas->file, "</clipPath>\n");
+ ctxcanvas->clip_polygon = 1;
+ cdclip(ctxcanvas, CD_CLIPPOLYGON);
+ end_path = 1;
+ break;
+ }
+ }
+ return;
}
- cdfpoly(ctxcanvas, mode, (cdfPoint*)newPoly, n);
+ switch (mode)
+ {
+ case CD_CLOSED_LINES:
+ fprintf(ctxcanvas->file, "<polygon style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ sWritePoints(ctxcanvas, poly, n, 1);
+ fprintf(ctxcanvas->file, "\" />\n");
+ break;
+ case CD_OPEN_LINES:
+ fprintf(ctxcanvas->file, "<polyline style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" points=\"",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ sWritePoints(ctxcanvas, poly, n, 0);
+ fprintf(ctxcanvas->file, "\" />\n");
+ break;
+ case CD_BEZIER:
+ fprintf(ctxcanvas->file, "<path d=\"M%g,%g C", poly[0].x, poly[0].y);
+ sWritePoints(ctxcanvas, poly+1, n-1, 0);
+ fprintf(ctxcanvas->file, "\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n",
+ ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity);
+ break;
+ case CD_FILL:
+ if(ctxcanvas->canvas->fill_mode==CD_EVENODD)
+ rule = "evenodd";
+ else
+ rule = "nonzero";
- free(newPoly);
+ fprintf(ctxcanvas->file, "<polygon style=\"fill:%s; fill-rule:%s; stroke:none; opacity:%g\" points=\"",
+ (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, rule, ctxcanvas->opacity);
+ sWritePoints(ctxcanvas, poly, n, 0);
+ fprintf(ctxcanvas->file, "\" />\n");
+ break;
+ case CD_CLIP:
+ fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly);
+
+ fprintf(ctxcanvas->file, "<polygon points=\"");
+ sWritePoints(ctxcanvas, poly, n, 0);
+ fprintf(ctxcanvas->file, "\" />\n");
+
+ fprintf(ctxcanvas->file, "</clipPath>\n");
+
+ ctxcanvas->clip_polygon = 1;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ cdclip(ctxcanvas, CD_CLIPPOLYGON);
+
+ break;
+
+ }
}
static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style)
diff --git a/src/win32/cdwin.c b/src/win32/cdwin.c
index da9bf9d..baaff13 100644
--- a/src/win32/cdwin.c
+++ b/src/win32/cdwin.c
@@ -697,7 +697,7 @@ typedef struct _winArcParam
YEndArc; /* second radial ending point */
} winArcParam;
-static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc)
+static void sCalcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc)
{
arc->LeftRect = xc - w/2;
arc->RightRect = xc + w/2 + 1;
@@ -727,7 +727,7 @@ static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
if (ctxcanvas->rebuild_pen)
sCreatePen(ctxcanvas);
@@ -738,7 +738,7 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a
static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
(ctxcanvas->canvas->interior_style != CD_PATTERN) )
@@ -782,7 +782,7 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
winArcParam arc;
- calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
+ sCalcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc);
if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) &&
(ctxcanvas->canvas->interior_style != CD_PATTERN) )
@@ -829,6 +829,84 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
POINT* pnt;
HPEN oldPen = NULL, Pen = NULL;
+ if (mode == CD_PATH)
+ {
+ int p;
+
+ /* if there is any current path, remove it */
+ BeginPath(ctxcanvas->hDC);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ BeginPath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) return;
+ MoveToEx(ctxcanvas->hDC, poly[i].x, poly[i].y, NULL);
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) return;
+ LineTo(ctxcanvas->hDC, poly[i].x, poly[i].y);
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+ winArcParam arc;
+
+ if (i+3 > n) return;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ sCalcArc(ctxcanvas, xc, yc, w, h, a1, a2, &arc);
+
+ Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc);
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) return;
+ PolyBezierTo(ctxcanvas->hDC, (POINT*)(poly + i), 3);
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ CloseFigure(ctxcanvas->hDC);
+ break;
+ case CD_PATH_FILL:
+ sUpdateFill(ctxcanvas, 1);
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ FillPath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_STROKE:
+ sUpdateFill(ctxcanvas, 0);
+ StrokePath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_FILLSTROKE:
+ sUpdateFill(ctxcanvas, 1);
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ StrokeAndFillPath(ctxcanvas->hDC);
+ break;
+ case CD_PATH_CLIP:
+ SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING);
+ SelectClipPath(ctxcanvas->hDC, RGN_AND);
+ break;
+ }
+ }
+ return;
+ }
+
switch( mode )
{
case CD_CLOSED_LINES:
@@ -2337,6 +2415,7 @@ void cdwInitTable(cdCanvas* canvas)
canvas->cxSector = cdsector;
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+
canvas->cxGetFontDim = cdgetfontdim;
canvas->cxGetTextSize = cdgettextsize;
canvas->cxPutImageRectRGB = cdputimagerectrgb;