diff options
Diffstat (limited to 'cd/src/svg')
-rw-r--r-- | cd/src/svg/cdsvg.c | 920 |
1 files changed, 623 insertions, 297 deletions
diff --git a/cd/src/svg/cdsvg.c b/cd/src/svg/cdsvg.c index 184031c..0510919 100644 --- a/cd/src/svg/cdsvg.c +++ b/cd/src/svg/cdsvg.c @@ -19,37 +19,33 @@ #include "lodepng.h" #include "base64.h" + struct _cdCtxCanvas { cdCanvas* canvas; - char* filename; char bgColor[20]; char fgColor[20]; - char linecap[10]; - char linejoin[10]; - char linestyle[20]; - char poly[256]; - char pattern[30]; - - char font_weight[15]; - char font_style[15]; - char font_decoration[15]; + char* linecap; + char* linejoin; + char linestyle[50]; + char pattern[50]; + + char* font_weight; + char* font_style; + char* font_decoration; char font_family[256]; char font_size[10]; - int backopacity; - int writemode; - int linewidth; + double opacity; int hatchboxsize; - double xmatrix[6]; /* Transformation matrix that includes axis inversion */ - /* private */ int last_fill_mode; - int last_clip_path; - int clip_off_control; + int last_clip_poly; + int last_clip_rect; + int clip_control; int clip_polygon; int transform_control; @@ -57,100 +53,85 @@ struct _cdCtxCanvas FILE* file; }; +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix); + static void cdkillcanvas(cdCtxCanvas* ctxcanvas) { - while(ctxcanvas->clip_off_control > 0) - { - fprintf(ctxcanvas->file, "</g>\n"); - --ctxcanvas->clip_off_control; - } + if (ctxcanvas->clip_control) + fprintf(ctxcanvas->file, "</g>\n"); /* close clipping container */ - if(ctxcanvas->transform_control) - fprintf(ctxcanvas->file, "</g>\n"); + if (ctxcanvas->transform_control) + fprintf(ctxcanvas->file, "</g>\n"); /* close transform container */ - fprintf(ctxcanvas->file, "</g>\n"); + fprintf(ctxcanvas->file, "</g>\n"); /* close global container */ fprintf(ctxcanvas->file, "</svg>\n"); - free(ctxcanvas->filename); fclose(ctxcanvas->file); memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); free(ctxcanvas); } -static void setclip_area(cdCtxCanvas *ctxcanvas) +static int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode) { - cdRect* clip_rect = &ctxcanvas->canvas->clip_rect; - - fprintf(ctxcanvas->file, "<clipPath id=\"clippath%d\">\n", ++ctxcanvas->last_clip_path); - - if (ctxcanvas->canvas->use_matrix) - { - cdPoint poly[4]; - poly[0].x = clip_rect->xmin; poly[0].y = clip_rect->ymin; - poly[1].x = clip_rect->xmin; poly[1].y = clip_rect->ymax; - poly[2].x = clip_rect->xmax; poly[2].y = clip_rect->ymax; - poly[3].x = clip_rect->xmax; poly[3].y = clip_rect->ymin; - - sprintf(ctxcanvas->poly, "%g,%g", (double)poly[0].x, (double)poly[0].y); - sprintf(ctxcanvas->poly, "%s %g,%g", ctxcanvas->poly, (double)poly[1].x, (double)poly[1].y); - sprintf(ctxcanvas->poly, "%s %g,%g", ctxcanvas->poly, (double)poly[2].x, (double)poly[2].y); - sprintf(ctxcanvas->poly, "%s %g,%g", ctxcanvas->poly, (double)poly[3].x, (double)poly[3].y); - - fprintf(ctxcanvas->file, "<polygon points=\"%s\" />\n", ctxcanvas->poly); - } - else + if (ctxcanvas->clip_control) { - double x, y, w, h; - x = (double)clip_rect->xmin; - y = (double)clip_rect->ymin; - w = (double)(clip_rect->xmax - clip_rect->xmin + 1); - h = (double)(clip_rect->ymax - clip_rect->ymin + 1); - - fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" />\n", x, y, w, h); - } + int old_transform_control = ctxcanvas->transform_control; + if (ctxcanvas->transform_control) + { + fprintf(ctxcanvas->file, "</g>\n"); /* close transform container */ + ctxcanvas->transform_control = 0; + } - fprintf(ctxcanvas->file, "</clipPath>\n"); + fprintf(ctxcanvas->file, "</g>\n"); /* close clipping container */ + ctxcanvas->clip_control = 0; - fprintf(ctxcanvas->file, "<g clip-path=\"url(#clippath%d)\">\n", ctxcanvas->last_clip_path); - ++ctxcanvas->clip_off_control; -} + if (old_transform_control) + cdtransform(ctxcanvas, ctxcanvas->canvas->matrix); /* reopen transform container */ + } -int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode) -{ switch (clip_mode) { - case CD_CLIPOFF: - if(ctxcanvas->clip_off_control > 0) - { - fprintf(ctxcanvas->file, "</g>\n"); - --ctxcanvas->clip_off_control; - } - break; case CD_CLIPAREA: - setclip_area(ctxcanvas); + /* open clipping container */ + fprintf(ctxcanvas->file, "<g clip-path=\"url(#cliprect%d)\">\n", ctxcanvas->last_clip_rect); + ctxcanvas->clip_control = 1; break; case CD_CLIPPOLYGON: if (ctxcanvas->clip_polygon) { - fprintf(ctxcanvas->file, "<g clip-path=\"url(#clippath%d)\">\n", ctxcanvas->last_clip_path); - ++ctxcanvas->clip_off_control; + /* open clipping container */ + 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; } static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) { + double x, y, w, h; + + ctxcanvas->canvas->clip_rect.xmin = (int)xmin; + ctxcanvas->canvas->clip_rect.ymin = (int)ymin; + ctxcanvas->canvas->clip_rect.xmax = (int)xmax; + ctxcanvas->canvas->clip_rect.ymax = (int)ymax; + + x = xmin; + y = ymin; + w = xmax - xmin + 1; + h = ymax - ymin + 1; + + fprintf(ctxcanvas->file, "<clipPath id=\"cliprect%d\">\n", ++ctxcanvas->last_clip_rect); + + fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" />\n", x, y, w, h); + + fprintf(ctxcanvas->file, "</clipPath>\n"); + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) - { - ctxcanvas->canvas->clip_rect.xmin = (int)xmin; - ctxcanvas->canvas->clip_rect.ymin = (int)ymin; - ctxcanvas->canvas->clip_rect.xmax = (int)xmax; - ctxcanvas->canvas->clip_rect.ymax = (int)ymax; cdclip(ctxcanvas, CD_CLIPAREA); - } } static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) @@ -160,39 +141,51 @@ static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) { - if (matrix) + if (ctxcanvas->transform_control) { - /* Matrix identity */ - ctxcanvas->xmatrix[0] = 1; - ctxcanvas->xmatrix[1] = 0; - ctxcanvas->xmatrix[2] = 0; - ctxcanvas->xmatrix[3] = -1; - ctxcanvas->xmatrix[4] = 0; - ctxcanvas->xmatrix[5] = (ctxcanvas->canvas->h-1); - - if(ctxcanvas->transform_control) + int old_clip_control = ctxcanvas->clip_control; + if (ctxcanvas->clip_control) { - fprintf(ctxcanvas->file, "</g>\n"); - --ctxcanvas->transform_control; + fprintf(ctxcanvas->file, "</g>\n"); /* close clipping container */ + ctxcanvas->clip_control = 0; } - cdMatrixMultiply(matrix, ctxcanvas->xmatrix); + fprintf(ctxcanvas->file, "</g>\n"); /* close transform container */ + ctxcanvas->transform_control = 0; + + if (old_clip_control) + cdclip(ctxcanvas, ctxcanvas->canvas->clip_mode); /* reopen clipping container */ + } - ++ctxcanvas->transform_control; - fprintf(ctxcanvas->file, "<g transform=\"matrix(%g %g %g %g %g %g)\">\n", ctxcanvas->xmatrix[0], ctxcanvas->xmatrix[1], ctxcanvas->xmatrix[2], ctxcanvas->xmatrix[3], ctxcanvas->xmatrix[4], ctxcanvas->xmatrix[5]); + if (matrix) + { + double xmatrix[6]; + + /* Matrix identity + invert axis */ + xmatrix[0] = 1; + xmatrix[1] = 0; + xmatrix[2] = 0; + xmatrix[3] = -1; + xmatrix[4] = 0; + xmatrix[5] = (ctxcanvas->canvas->h-1); + + /* compose transform */ + cdMatrixMultiply(matrix, xmatrix); + + /* open transform container */ + fprintf(ctxcanvas->file, "<g transform=\"matrix(%g %g %g %g %g %g)\">\n", xmatrix[0], xmatrix[1], xmatrix[2], xmatrix[3], xmatrix[4], xmatrix[5]); + ctxcanvas->transform_control = 1; ctxcanvas->canvas->invert_yaxis = 0; } else - { ctxcanvas->canvas->invert_yaxis = 1; - } } static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) { - fprintf(ctxcanvas->file, "<line x1=\"%g\" y1=\"%g\" x2=\"%g\" y2=\"%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - x1, y1, x2, y2, ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%g\" y1=\"%g\" x2=\"%g\" y2=\"%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n", + x1, y1, x2, y2, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity); } static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) @@ -202,8 +195,8 @@ 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) { - fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - xmin, ymin, xmax-xmin, ymax-ymin, ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n", + xmin, ymin, xmax-xmin, ymax-ymin, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity); } static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) @@ -213,9 +206,8 @@ 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) { - fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - xmin, ymin, xmax-xmin, ymax-ymin, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : ctxcanvas->pattern, - (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : "none", ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", + xmin, ymin, xmax-xmin, ymax-ymin, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, ctxcanvas->opacity); } static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) @@ -223,36 +215,51 @@ static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); } +static void sCalcArc(cdCanvas* canvas, double xc, double yc, double w, double h, double a1, double a2, double *arcStartX, double *arcStartY, double *arcEndX, double *arcEndY, int *largeArc, int swap) +{ + /* computation is done as if the angles are counterclockwise, + and yaxis is NOT inverted. */ + + cdfCanvasGetArcStartEnd(xc, yc, w, h, a1, a2, arcStartX, arcStartY, arcEndX, arcEndY); + + if (canvas->invert_yaxis) + { + /* fix axis orientation */ + *arcStartY = 2*yc - *arcStartY; + *arcEndY = 2*yc - *arcEndY; + } + else + { + /* it is clock-wise when axis NOT inverted */ + if (swap) + { + _cdSwapDouble(*arcStartX, *arcEndX); + _cdSwapDouble(*arcStartY, *arcEndY); + } + } + + if (fabs(a2-a1) > 180.0) + *largeArc = 1; + else + *largeArc = 0; +} + static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) { double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; + int largeArc; if((a1 == 0.0) && (a2 == 360.0)) /* an ellipse/circle */ { - fprintf(ctxcanvas->file, "<ellipse cx=\"%g\" cy=\"%g\" rx=\"%g\" ry=\"%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - xc, yc, w/2, h/2, ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); - + fprintf(ctxcanvas->file, "<ellipse cx=\"%g\" cy=\"%g\" rx=\"%g\" ry=\"%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n", + xc, yc, w/2, h/2, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity); return; } - 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; + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc, 1); - fprintf(ctxcanvas->file, "<path d=\"M%g,%g A%g,%g 0 %d,0 %g,%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<path d=\"M%g,%g A%g,%g 0 %d,0 %g,%g\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%g\" />\n", + arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, ctxcanvas->fgColor, ctxcanvas->canvas->line_width, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->opacity); } static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) @@ -263,35 +270,19 @@ 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) { double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; + int largeArc; if((a1 == 0.0) && (a2 == 360.0)) /* an ellipse/circle */ { - fprintf(ctxcanvas->file, "<ellipse cx=\"%g\" cy=\"%g\" rx=\"%g\" ry=\"%g\" style=\"fill:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - xc, yc, w/2, h/2, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : ctxcanvas->pattern, - (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : "none", ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); - + fprintf(ctxcanvas->file, "<ellipse cx=\"%g\" cy=\"%g\" rx=\"%g\" ry=\"%g\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", + xc, yc, w/2, h/2, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, ctxcanvas->opacity); return; } - 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; + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc, 1); - fprintf(ctxcanvas->file, "<path d=\"M%g,%g L%g,%g A%g,%g 0 %d,0 %g,%g Z\" style=\"fill:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - xc, yc, arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : ctxcanvas->pattern, - (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : "none", ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<path d=\"M%g,%g L%g,%g A%g,%g 0 %d,0 %g,%g Z\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", + xc, yc, arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, ctxcanvas->opacity); } static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) @@ -302,26 +293,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) { double arcStartX, arcStartY, arcEndX, arcEndY; - int largeArc = 0; - - if (ctxcanvas->canvas->use_matrix) /* Transformation active */ - { - double temp = 360 - a1; - a1 = 360 - a2; - a2 = temp; - } + int largeArc; - 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)); + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc, 1); - if((a2-a1) > 180.0) - largeArc = 1; - - fprintf(ctxcanvas->file, "<path d=\"M%g,%g A%g,%g 0 %d,0 %g,%g Z\" style=\"fill:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : ctxcanvas->pattern, - (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : "none", ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<path d=\"M%g,%g A%g,%g 0 %d,0 %g,%g Z\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", + arcStartX, arcStartY, w/2, h/2, largeArc, arcEndX, arcEndY, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor: ctxcanvas->pattern, ctxcanvas->opacity); } static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) @@ -331,8 +308,8 @@ static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text, int len) { - char anchor[10]; - char alignment[20]; + char* anchor; + char* alignment; int i; switch (ctxcanvas->canvas->text_alignment) @@ -340,22 +317,23 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text case CD_NORTH: case CD_NORTH_EAST: case CD_NORTH_WEST: - sprintf(alignment, "%s", "text-before-edge"); + alignment = "text-before-edge"; break; case CD_SOUTH: case CD_SOUTH_EAST: case CD_SOUTH_WEST: - sprintf(alignment, "%s", "text-after-edge"); + alignment = "text-after-edge"; break; case CD_CENTER: case CD_EAST: case CD_WEST: - sprintf(alignment, "%s", "middle"); + alignment = "middle"; break; case CD_BASE_CENTER: case CD_BASE_LEFT: case CD_BASE_RIGHT: - sprintf(alignment, "%s", "baseline"); + default: + alignment = "baseline"; break; } @@ -365,19 +343,20 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text case CD_NORTH_WEST: case CD_SOUTH_WEST: case CD_BASE_LEFT: - sprintf(anchor, "%s", "start"); + anchor = "start"; break; case CD_CENTER: case CD_NORTH: case CD_SOUTH: case CD_BASE_CENTER: - sprintf(anchor, "%s", "middle"); + anchor = "middle"; break; case CD_EAST: case CD_NORTH_EAST: case CD_SOUTH_EAST: case CD_BASE_RIGHT: - sprintf(anchor, "%s", "end"); + default: + anchor = "end"; break; } @@ -392,10 +371,10 @@ static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text if (ctxcanvas->canvas->use_matrix) /* Transformation active */ fprintf(ctxcanvas->file, "<text transform=\"matrix(%g %g %g %g %g %g)\" font-family=\"%s\" font-size=\"%s\" font-style=\"%s\" font-weight=\"%s\" text-decoration=\"%s\" text-anchor=\"%s\" dominant-baseline=\"%s\" fill=\"%s\">\n", - text_cos, text_sin, text_sin, -text_cos, x, y, ctxcanvas->font_family, ctxcanvas->font_size, ctxcanvas->font_style, ctxcanvas->font_weight, ctxcanvas->font_decoration, anchor, alignment, ctxcanvas->fgColor); + text_cos, text_sin, text_sin, -text_cos, x, y, ctxcanvas->font_family, ctxcanvas->font_size, ctxcanvas->font_style, ctxcanvas->font_weight, ctxcanvas->font_decoration, anchor, alignment, ctxcanvas->fgColor); else fprintf(ctxcanvas->file, "<text transform=\"matrix(%g %g %g %g %g %g)\" font-family=\"%s\" font-size=\"%s\" font-style=\"%s\" font-weight=\"%s\" text-decoration=\"%s\" text-anchor=\"%s\" dominant-baseline=\"%s\" fill=\"%s\">\n", - text_cos, -text_sin, text_sin, text_cos, x, y, ctxcanvas->font_family, ctxcanvas->font_size, ctxcanvas->font_style, ctxcanvas->font_weight, ctxcanvas->font_decoration, anchor, alignment, ctxcanvas->fgColor); + text_cos, -text_sin, text_sin, text_cos, x, y, ctxcanvas->font_family, ctxcanvas->font_size, ctxcanvas->font_style, ctxcanvas->font_weight, ctxcanvas->font_decoration, anchor, alignment, ctxcanvas->fgColor); for(i = 0; i < len; i++) fprintf(ctxcanvas->file, "&#x%02X;", (unsigned char)text[i]); @@ -419,46 +398,178 @@ static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int l cdftext(ctxcanvas, (double)x, (double)y, text, len); } +static void sWritePointsF(cdCtxCanvas *ctxcanvas, cdfPoint* poly, int n, int close) +{ + int i; + for(i = 0; i<n; i++) + fprintf(ctxcanvas->file, "%g,%g ", poly[i].x, poly[i].y); + if (close) + 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) { - int i, m = 0; - char rule[8]; + char* rule; - if(mode == CD_BEZIER) - m = 1; + if (mode == CD_PATH) + { + int i, p, clip_path = 0, end_path, current_set; - sprintf(ctxcanvas->poly, "%g,%g", poly[m].x, poly[m].y); - for(i = m+1; i<n; i++) - sprintf(ctxcanvas->poly, "%s %g,%g", ctxcanvas->poly, poly[i].x, poly[i].y); + 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; + current_set = 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; + current_set = 0; + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "M %g %g ", poly[i].x, poly[i].y); + current_set = 1; + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "L %g %g ", poly[i].x, poly[i].y); + current_set = 1; + i++; + break; + case CD_PATH_ARC: + { + double xc, yc, w, h, a1, a2; + double arcStartX, arcStartY, arcEndX, arcEndY; + int largeArc, sweep = 0; + + if (i+3 > n) return; + + if (!cdfCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc, 0); + + if (ctxcanvas->canvas->invert_yaxis && (a2-a1)<0) /* can be clockwise */ + sweep = 1; + + if (current_set) + fprintf(ctxcanvas->file, "L %g %g A %g %g 0 %d %d %g %g ", + arcStartX, arcStartY, w/2, h/2, largeArc, sweep, arcEndX, arcEndY); + else + fprintf(ctxcanvas->file, "M %g %g A %g %g 0 %d %d %g %g ", + arcStartX, arcStartY, w/2, h/2, largeArc, sweep, arcEndX, arcEndY); + + current_set = 1; + 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); + current_set = 1; + 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:%d\" points=\"%s\" />\n", - ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity, ctxcanvas->poly); + 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); + 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:%d\" points=\"%s\" />\n", - ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity, ctxcanvas->poly); + 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); + sWritePointsF(ctxcanvas, poly, n, 0); + fprintf(ctxcanvas->file, "\" />\n"); break; - case CD_BEZIER : - fprintf(ctxcanvas->file, "<path d=\"M%g,%g C%s\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - poly[0].x, poly[0].y, ctxcanvas->poly, ctxcanvas->fgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + case CD_BEZIER: + fprintf(ctxcanvas->file, "<path d=\"M%g,%g C", poly[0].x, poly[0].y); + 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; - case CD_FILL : + case CD_FILL: if(ctxcanvas->canvas->fill_mode==CD_EVENODD) - sprintf(rule, "%s", "evenodd"); + rule = "evenodd"; else - sprintf(rule, "%s", "nonzero"); + rule = "nonzero"; - fprintf(ctxcanvas->file, "<polygon style=\"fill:%s; fill-rule:%s; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" points=\"%s\" />\n", - (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : ctxcanvas->pattern, rule, (ctxcanvas->canvas->interior_style == CD_SOLID) ? ctxcanvas->fgColor : "none", - ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity, ctxcanvas->poly); + 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); + sWritePointsF(ctxcanvas, poly, n, 0); + fprintf(ctxcanvas->file, "\" />\n"); break; case CD_CLIP: - fprintf(ctxcanvas->file, "<clipPath id=\"clippath%d\">\n", ++ctxcanvas->last_clip_path); + fprintf(ctxcanvas->file, "<clipPath id=\"clippoly%d\">\n", ++ctxcanvas->last_clip_poly); - fprintf(ctxcanvas->file, "<polygon points=\"%s\" />\n", ctxcanvas->poly); + fprintf(ctxcanvas->file, "<polygon points=\""); + sWritePointsF(ctxcanvas, poly, n, 0); + fprintf(ctxcanvas->file, "\" />\n"); fprintf(ctxcanvas->file, "</clipPath>\n"); @@ -474,48 +585,193 @@ 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, current_set; + + 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; + current_set = 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; + current_set = 0; + break; + case CD_PATH_MOVETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "M %d %d ", poly[i].x, poly[i].y); + current_set = 1; + i++; + break; + case CD_PATH_LINETO: + if (i+1 > n) return; + fprintf(ctxcanvas->file, "L %d %d ", poly[i].x, poly[i].y); + current_set = 1; + i++; + break; + case CD_PATH_ARC: + { + int xc, yc, w, h; + double a1, a2; + double arcStartX, arcStartY, arcEndX, arcEndY; + int largeArc, sweep = 0; + + if (i+3 > n) return; + + if (!cdCanvasGetArcPath(ctxcanvas->canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2)) + return; + + sCalcArc(ctxcanvas->canvas, xc, yc, w, h, a1, a2, &arcStartX, &arcStartY, &arcEndX, &arcEndY, &largeArc, 0); + + if (ctxcanvas->canvas->invert_yaxis && (a2-a1)<0) /* can be clockwise */ + sweep = 1; + + if (current_set) + fprintf(ctxcanvas->file, "L %g %g A %d %d 0 %d %d %g %g ", + arcStartX, arcStartY, w/2, h/2, largeArc, sweep, arcEndX, arcEndY); + else + fprintf(ctxcanvas->file, "M %g %g A %d %d 0 %d %d %g %g ", + arcStartX, arcStartY, w/2, h/2, largeArc, sweep, arcEndX, arcEndY); + + current_set = 1; + 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); + current_set = 1; + 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%d,%d 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); -static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opacity) -{ - ctxcanvas->backopacity = opacity; - return opacity; + 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) { switch (style) { - case CD_CONTINUOUS : /* empty dash */ + case CD_CONTINUOUS: /* empty dash */ + default: sprintf(ctxcanvas->linestyle, "%s", "0"); break; - case CD_DASHED : + case CD_DASHED: sprintf(ctxcanvas->linestyle, "%s", "6,2"); break; - case CD_DOTTED : + case CD_DOTTED: sprintf(ctxcanvas->linestyle, "%s", "2,2"); break; - case CD_DASH_DOT : + case CD_DASH_DOT: sprintf(ctxcanvas->linestyle, "%s", "6,2,2,2"); break; - case CD_DASH_DOT_DOT : + case CD_DASH_DOT_DOT: sprintf(ctxcanvas->linestyle, "%s", "6,2,2,2,2,2"); break; - case CD_CUSTOM : + case CD_CUSTOM: { int i; sprintf(ctxcanvas->linestyle, "%d", ctxcanvas->canvas->line_dashes[0]); @@ -529,34 +785,25 @@ static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) return style; } -static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) -{ - ctxcanvas->linewidth = width; - - return width; -} - static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) { if(cap == CD_CAPROUND) - sprintf(ctxcanvas->linecap, "%s", "round"); + ctxcanvas->linecap = "round"; else if(cap == CD_CAPSQUARE) - sprintf(ctxcanvas->linecap, "%s", "square"); + ctxcanvas->linecap = "square"; else /* CD_CAPFLAT */ - sprintf(ctxcanvas->linecap, "%s", "butt"); - + ctxcanvas->linecap = "butt"; return cap; } static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) { if(join == CD_ROUND) - sprintf(ctxcanvas->linejoin, "%s", "round"); + ctxcanvas->linejoin = "round"; else if(join == CD_BEVEL) - sprintf(ctxcanvas->linejoin, "%s", "bevel"); + ctxcanvas->linejoin = "bevel"; else /* CD_MITER */ - sprintf(ctxcanvas->linejoin, "%s", "miter"); - + ctxcanvas->linejoin = "miter"; return join; } @@ -565,39 +812,44 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style) int hsize = ctxcanvas->hatchboxsize - 1; int hhalf = hsize / 2; - ctxcanvas->canvas->interior_style = CD_HATCH; sprintf(ctxcanvas->pattern, "url(#pattern%d)", ++ctxcanvas->last_fill_mode); fprintf(ctxcanvas->file, "<pattern id=\"pattern%d\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"%d\" height=\"%d\">\n", ctxcanvas->last_fill_mode, hsize, hsize); + if (ctxcanvas->canvas->back_opacity==CD_OPAQUE) + { + fprintf(ctxcanvas->file, "<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" style=\"fill:%s; stroke:none; opacity:%g\" />\n", + hsize, hsize, ctxcanvas->bgColor, ctxcanvas->opacity); + } + switch(style) { case CD_HORIZONTAL: - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - 0, hhalf, hsize, hhalf, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + 0, hhalf, hsize, hhalf, ctxcanvas->fgColor, ctxcanvas->opacity); break; case CD_VERTICAL: - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - hhalf, 0, hhalf, hsize, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + hhalf, 0, hhalf, hsize, ctxcanvas->fgColor, ctxcanvas->opacity); break; case CD_BDIAGONAL: - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - 0, hsize, hsize, 0, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + 0, hsize, hsize, 0, ctxcanvas->fgColor, ctxcanvas->opacity); break; case CD_FDIAGONAL: - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - 0, 0, hsize, hsize, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + 0, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->opacity); break; case CD_CROSS: - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - hsize, 0, hsize, hsize, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - 0, hhalf, hsize, hhalf, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + hsize, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->opacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + 0, hhalf, hsize, hhalf, ctxcanvas->fgColor, ctxcanvas->opacity); break; case CD_DIAGCROSS: - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - 0, 0, hsize, hsize, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); - fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; opacity:%d\" />\n", - hsize, 0, 0, hsize, (ctxcanvas->canvas->back_opacity != CD_OPAQUE) ? ctxcanvas->fgColor : ctxcanvas->bgColor, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + 0, 0, hsize, hsize, ctxcanvas->fgColor, ctxcanvas->opacity); + fprintf(ctxcanvas->file, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"fill:none; stroke:%s; opacity:%g\" />\n", + hsize, 0, 0, hsize, ctxcanvas->fgColor, ctxcanvas->opacity); break; } @@ -608,7 +860,7 @@ static int cdhatch(cdCtxCanvas *ctxcanvas, int style) static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)) { - int i, j; + int i, j, ret; unsigned char r, g, b; char color[20]; @@ -619,13 +871,18 @@ static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int ( { for (i = 0; i < n; i++) { - int ret = data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b); + /* internal transform, affects also pattern orientation */ + if (ctxcanvas->canvas->invert_yaxis) + ret = data2rgb(ctxcanvas, n, i, m-1 - j, data, &r, &g, &b); + else + ret = data2rgb(ctxcanvas, n, i, j, data, &r, &g, &b); + if (ret == -1) continue; sprintf(color, "rgb(%d,%d,%d)", (int)r, (int)g, (int)b); - fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:%s; opacity:%d\" />\n", - (double)i, (double)j, 1.0, 1.0, color, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:%s; opacity:%g\" />\n", + (double)i, (double)j, 1.0, 1.0, color, ctxcanvas->opacity); } } @@ -642,65 +899,69 @@ static int long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, uns static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) { - ctxcanvas->canvas->interior_style = CD_PATTERN; make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb); } static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) { - int ret = 1; unsigned char* uchar_data = (unsigned char*)data; if (uchar_data[j*n+i]) - { cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); - ret = 1; - } else { - cdDecodeColor(ctxcanvas->canvas->background, r, g, b); if (ctxcanvas->canvas->back_opacity==CD_TRANSPARENT) - ret = -1; + return -1; + else + cdDecodeColor(ctxcanvas->canvas->background, r, g, b); } - return ret; + return 1; } static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) { - ctxcanvas->canvas->interior_style = CD_STIPPLE; make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb); } static int cdfont(cdCtxCanvas *ctxcanvas, const char* type_face, int style, int size) { /* Define type_face and size */ - if(type_face != NULL) + if (type_face != NULL) sprintf(ctxcanvas->font_family, "%s", type_face); - if(size > 0) + if (size > 0) sprintf(ctxcanvas->font_size, "%dpt", size); else sprintf(ctxcanvas->font_size, "%dpx", (-1)*size); - if(style != -1) + if (style != -1) { - /* Default: CD_PLAIN */ - sprintf(ctxcanvas->font_weight, "%s", "normal"); - sprintf(ctxcanvas->font_style, "%s", "normal"); - sprintf(ctxcanvas->font_decoration, "%s", "none"); - /* Define styles and decorations */ if (style & CD_BOLD) - sprintf(ctxcanvas->font_weight, "%s", "bold"); + ctxcanvas->font_weight = "bold"; + else + ctxcanvas->font_weight = "normal"; if (style & CD_ITALIC) - sprintf(ctxcanvas->font_style, "%s", "italic"); + ctxcanvas->font_style = "italic"; + else + ctxcanvas->font_style = "normal"; - if (style & CD_STRIKEOUT) - sprintf(ctxcanvas->font_decoration, "%s", "line-through"); + if (style & CD_STRIKEOUT || style & CD_UNDERLINE) + { + if (style & CD_STRIKEOUT && style & CD_UNDERLINE) + ctxcanvas->font_decoration = "line-through underline"; + else + { + if (style & CD_STRIKEOUT) + ctxcanvas->font_decoration = "line-through"; - if (style & CD_UNDERLINE) - sprintf(ctxcanvas->font_decoration, "%s", "underline"); + if (style & CD_UNDERLINE) + ctxcanvas->font_decoration = "underline"; + } + } + else + ctxcanvas->font_decoration = "none"; } return 1; @@ -711,7 +972,6 @@ static long cdbackground(cdCtxCanvas *ctxcanvas, long int color) unsigned char r, g, b; cdDecodeColor(color, &r, &g, &b); sprintf(ctxcanvas->bgColor, "rgb(%d,%d,%d)", (int)r, (int)g, (int)b); - return color; } @@ -720,7 +980,6 @@ static long cdforeground(cdCtxCanvas *ctxcanvas, long int color) unsigned char r, g, b; cdDecodeColor(color, &r, &g, &b); sprintf(ctxcanvas->fgColor, "rgb(%d,%d,%d)", (int)r, (int)g, (int)b); - return color; } @@ -762,10 +1021,10 @@ static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsi if (ctxcanvas->canvas->use_matrix) /* Transformation active */ fprintf(ctxcanvas->file, "<image transform=\"matrix(%d %d %d %d %d %d)\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,%s\"/>\n", - 1, 0, 0, -1, x, y+h, w, h, rgb_target); + 1, 0, 0, -1, x, y+h, w, h, rgb_target); else fprintf(ctxcanvas->file, "<image transform=\"matrix(%d %d %d %d %d %d)\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,%s\"/>\n", - 1, 0, 0, 1, x, y-h, w, h, rgb_target); + 1, 0, 0, 1, x, y-h, w, h, rgb_target); free(rgb_data); free(rgb_buffer); @@ -811,10 +1070,10 @@ static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const uns if (ctxcanvas->canvas->use_matrix) /* Transformation active */ fprintf(ctxcanvas->file, "<image transform=\"matrix(%d %d %d %d %d %d)\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,%s\"/>\n", - 1, 0, 0, -1, x, y+h, w, h, rgb_target); + 1, 0, 0, -1, x, y+h, w, h, rgb_target); else fprintf(ctxcanvas->file, "<image transform=\"matrix(%d %d %d %d %d %d)\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,%s\"/>\n", - 1, 0, 0, 1, x, y-h, w, h, rgb_target); + 1, 0, 0, 1, x, y-h, w, h, rgb_target); free(rgb_data); free(rgb_buffer); @@ -862,10 +1121,10 @@ static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsi if (ctxcanvas->canvas->use_matrix) /* Transformation active */ fprintf(ctxcanvas->file, "<image transform=\"matrix(%d %d %d %d %d %d)\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,%s\"/>\n", - 1, 0, 0, -1, x, y+h, w, h, rgb_target); + 1, 0, 0, -1, x, y+h, w, h, rgb_target); else fprintf(ctxcanvas->file, "<image transform=\"matrix(%d %d %d %d %d %d)\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,%s\"/>\n", - 1, 0, 0, 1, x, y-h, w, h, rgb_target); + 1, 0, 0, 1, x, y-h, w, h, rgb_target); free(rgb_data); free(rgb_buffer); @@ -878,8 +1137,8 @@ static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) unsigned char r, g, b; cdDecodeColor(color, &r, &g, &b); - fprintf(ctxcanvas->file, "<circle cx=\"%d\" cy=\"%d\" r=\"0.1\" style=\"fill:rgb(%d,%d,%d); stroke:rgb(%d,%d,%d); stroke-width:%d; stroke-linecap:%s; stroke-linejoin:%s; stroke-dasharray:%s; opacity:%d\" />\n", - x, y, r, g, b, r, g, b, ctxcanvas->linewidth, ctxcanvas->linecap, ctxcanvas->linejoin, ctxcanvas->linestyle, ctxcanvas->backopacity); + fprintf(ctxcanvas->file, "<circle cx=\"%d\" cy=\"%d\" r=\"0.5\" style=\"fill:rgb(%d,%d,%d); stroke:none; opacity:%g\" />\n", + x, y, r, g, b, ctxcanvas->opacity); } static void cddeactivate (cdCtxCanvas* ctxcanvas) @@ -892,13 +1151,80 @@ static void cdflush (cdCtxCanvas* ctxcanvas) fflush(ctxcanvas->file); } +static void set_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int hatchboxsize; + + if (data == NULL) + { + ctxcanvas->hatchboxsize = 8; + return; + } + + sscanf(data, "%d", &hatchboxsize); + ctxcanvas->hatchboxsize = hatchboxsize; +} + +static char* get_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas) +{ + static char size[10]; + sprintf(size, "%d", ctxcanvas->hatchboxsize); + return size; +} + +static cdAttribute hatchboxsize_attrib = +{ + "HATCHBOXSIZE", + set_hatchboxsize_attrib, + get_hatchboxsize_attrib +}; + +static void set_opacity_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + if (data) + { + int opacity = 255; + sscanf(data, "%d", &opacity); + if (opacity < 0) ctxcanvas->opacity = 0.0; + else if (opacity > 255) ctxcanvas->opacity = 1.0; + else ctxcanvas->opacity = (double)opacity/255.0; + } + else + ctxcanvas->opacity = 1.0; +} + +static char* get_opacity_attrib(cdCtxCanvas *ctxcanvas) +{ + static char data[50]; + sprintf(data, "%d", cdRound(ctxcanvas->opacity*255.0)); + return data; +} + +static cdAttribute opacity_attrib = +{ + "OPACITY", + set_opacity_attrib, + get_opacity_attrib +}; + +static void set_cmd_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + fprintf(ctxcanvas->file, "%s", data); +} + +static cdAttribute cmd_attrib = +{ + "CMD", + set_cmd_attrib, + NULL +}; + static void cdcreatecanvas(cdCanvas *canvas, void *data) { char filename[10240] = ""; char* strdata = (char*)data; double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78; cdCtxCanvas* ctxcanvas; - int size; strdata += cdGetFileName(strdata, filename); if (filename[0] == 0) @@ -916,10 +1242,6 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data) return; } - size = strlen(filename); - ctxcanvas->filename = malloc(size+1); - memcpy(ctxcanvas->filename, filename, size+1); - /* store the base canvas */ ctxcanvas->canvas = canvas; @@ -937,17 +1259,23 @@ static void cdcreatecanvas(cdCanvas *canvas, void *data) canvas->ctxcanvas = ctxcanvas; ctxcanvas->last_fill_mode = -1; - ctxcanvas->last_clip_path = -1; + ctxcanvas->last_clip_poly = -1; + ctxcanvas->last_clip_rect = -1; - ctxcanvas->clip_off_control = 0; + ctxcanvas->clip_control = 0; ctxcanvas->transform_control = 0; ctxcanvas->clip_polygon = 0; ctxcanvas->hatchboxsize = 8; + ctxcanvas->opacity = 1.0; + + cdRegisterAttribute(canvas, &cmd_attrib); + cdRegisterAttribute(canvas, &hatchboxsize_attrib); + cdRegisterAttribute(canvas, &opacity_attrib); fprintf(ctxcanvas->file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); - fprintf(ctxcanvas->file, "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"%dpt\" height=\"%dpt\" viewBox=\"0 0 %d %d\" version=\"1.1\">\n", canvas->w, canvas->h, canvas->w, canvas->h); - fprintf(ctxcanvas->file, "<g>\n"); + fprintf(ctxcanvas->file, "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"%gpt\" height=\"%gpt\" viewBox=\"0 0 %d %d\" version=\"1.1\">\n", CD_MM2PT*canvas->w_mm, CD_MM2PT*canvas->h_mm, canvas->w, canvas->h); + fprintf(ctxcanvas->file, "<g>\n"); /* open global container */ } static void cdinittable(cdCanvas* canvas) @@ -979,9 +1307,7 @@ static void cdinittable(cdCanvas* canvas) canvas->cxFText = cdftext; canvas->cxFClipArea = cdfcliparea; - canvas->cxBackOpacity = cdbackopacity; canvas->cxLineStyle = cdlinestyle; - canvas->cxLineWidth = cdlinewidth; canvas->cxLineCap = cdlinecap; canvas->cxLineJoin = cdlinejoin; @@ -996,7 +1322,7 @@ static void cdinittable(cdCanvas* canvas) canvas->cxFlush = cdflush; canvas->cxDeactivate = cddeactivate; - canvas->cxKillCanvas = (void (*)(cdCtxCanvas*))cdkillcanvas; + canvas->cxKillCanvas = cdkillcanvas; } static cdContext cdSVGContext = |