From cc487d4de29a48d8e20a9a8492957a5950d5c181 Mon Sep 17 00:00:00 2001 From: scuri Date: Fri, 21 May 2010 04:51:07 +0000 Subject: *** empty log message *** --- src/cairo/cdcairo.c | 249 +++++++++++++++++++--- src/cairo/cdcaironative_win32.c | 2 +- src/cd.def | 1 + src/cd_primitives.c | 39 +++- src/drv/cdpdf.c | 194 ++++++++++++++++-- src/drv/cdps.c | 368 ++++++++++++++++++++++++++++++--- src/gdiplus/cdwdbufp.cpp | 2 +- src/gdiplus/cdwinp.cpp | 445 +++++++++++++++++++++++++++++++++++++++- src/gdiplus/cdwinp.h | 5 +- src/svg/cdsvg.c | 313 ++++++++++++++++++++++++++-- src/win32/cdwin.c | 87 +++++++- 11 files changed, 1609 insertions(+), 96 deletions(-) (limited to 'src') 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; pcanvas->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; pcanvas->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; pcanvas->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; pcanvas->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; ifile); + 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; pcanvas->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; pcanvas->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; pcanvas->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; pcanvas->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, "\n", ctxcanvas->last_clip_poly); + fprintf(ctxcanvas->file, "\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; ifile, "%g,%g ", poly[0].x, poly[0].y); } +static void sWritePoints(cdCtxCanvas *ctxcanvas, cdPoint* poly, int n, int close) +{ + int i; + for(i = 0; ifile, "%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; pcanvas->path_n; p++) + { + if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP) + { + clip_path = 1; + break; + } + } + + if (clip_path) + fprintf(ctxcanvas->file, "\n", ++ctxcanvas->last_clip_poly); + + /* starts a new path */ + fprintf(ctxcanvas->file, "canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + if (!end_path) + fprintf(ctxcanvas->file, "\" />\n"); + + fprintf(ctxcanvas->file, " 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, "\n"); + ctxcanvas->clip_polygon = 1; + cdclip(ctxcanvas, CD_CLIPPOLYGON); + end_path = 1; + break; + } + } + return; + } + switch (mode) { case CD_CLOSED_LINES: fprintf(ctxcanvas->file, "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, "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, "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, "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, "\n", ++ctxcanvas->last_clip_poly); fprintf(ctxcanvas->file, "file, "\" />\n"); fprintf(ctxcanvas->file, "\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; pcanvas->path_n; p++) + { + if (ctxcanvas->canvas->path[p] == CD_PATH_CLIP) + { + clip_path = 1; + break; + } + } + + if (clip_path) + fprintf(ctxcanvas->file, "\n", ++ctxcanvas->last_clip_poly); + + /* starts a new path */ + fprintf(ctxcanvas->file, "canvas->path_n; p++) + { + switch(ctxcanvas->canvas->path[p]) + { + case CD_PATH_NEW: + if (!end_path) + fprintf(ctxcanvas->file, "\" />\n"); + + fprintf(ctxcanvas->file, " 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, "\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, "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, "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, "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, "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, "\n", ++ctxcanvas->last_clip_poly); + + fprintf(ctxcanvas->file, "file, "\" />\n"); + + fprintf(ctxcanvas->file, "\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; pcanvas->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; -- cgit v1.2.3