static void draw_polygon (DiaRenderer *self, Point *points, int num_points, Color *fill, Color *stroke) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); int i; xmlNodePtr node; GString *str; gchar px_buf[DTOSTR_BUF_SIZE]; gchar py_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"polygon", NULL); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) get_draw_style (renderer, fill, stroke)); if (fill) xmlSetProp(node, (const xmlChar *)"fill-rule", (const xmlChar *) "evenodd"); str = g_string_new(NULL); for (i = 0; i < num_points; i++) g_string_append_printf(str, "%s,%s ", dia_svg_dtostr(px_buf, points[i].x), dia_svg_dtostr(py_buf, points[i].y) ); xmlSetProp(node, (const xmlChar *)"points", (xmlChar *) str->str); g_string_free(str, TRUE); }
static void draw_text (DiaRenderer *self, Text *text) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); Point pos = text->position; int i; xmlNodePtr node_text, node_tspan; gchar d_buf[G_ASCII_DTOSTR_BUF_SIZE]; node_text = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"text", NULL); /* text 'global' properties */ node_set_text_style(node_text, renderer, text->font, text->height, text->alignment, &text->color); dia_svg_dtostr(d_buf, pos.x); xmlSetProp(node_text, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos.y); xmlSetProp(node_text, (const xmlChar *)"y", (xmlChar *) d_buf); pos = text->position; for (i=0;i<text->numlines;i++) { TextLine *text_line = text->lines[i]; node_tspan = xmlNewTextChild(node_text, renderer->svg_name_space, (const xmlChar *)"tspan", (const xmlChar *)text_line_get_string(text_line)); dia_svg_dtostr(d_buf, pos.x); xmlSetProp(node_tspan, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos.y); xmlSetProp(node_tspan, (const xmlChar *)"y", (xmlChar *) d_buf); pos.y += text->height; } }
static void draw_image(DiaRenderer *self, Point *point, real width, real height, DiaImage *image) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; gchar d_buf[DTOSTR_BUF_SIZE]; gchar *uri; node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"image", NULL); dia_svg_dtostr(d_buf, point->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, point->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, width); xmlSetProp(node, (const xmlChar *)"width", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, height); xmlSetProp(node, (const xmlChar *)"height", (xmlChar *) d_buf); uri = g_filename_to_uri(dia_image_filename(image), NULL, NULL); if (uri) xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) uri); else /* not sure if this fallbach is better than nothing */ xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) dia_image_filename(image)); g_free (uri); }
static void draw_text_line(DiaRenderer *self, TextLine *text_line, Point *pos, Alignment alignment, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; char *style, *tmp; real saved_width; gchar d_buf[DTOSTR_BUF_SIZE]; DiaFont *font; node = xmlNewTextChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"text", (xmlChar *) text_line_get_string(text_line)); saved_width = renderer->linewidth; renderer->linewidth = 0.001; style = (char*)get_fill_style(renderer, colour); /* return value must not be freed */ renderer->linewidth = saved_width; tmp = g_strdup_printf("%s; font-size: %s", style, dia_svg_dtostr(d_buf, text_line_get_height(text_line))); style = tmp; /* This is going to break for non-LTR texts, as SVG thinks 'start' is * 'right' for those. */ switch (alignment) { case ALIGN_LEFT: tmp = g_strconcat(style, "; text-anchor:start", NULL); break; case ALIGN_CENTER: tmp = g_strconcat(style, "; text-anchor:middle", NULL); break; case ALIGN_RIGHT: tmp = g_strconcat(style, "; text-anchor:end", NULL); break; } g_free (style); style = tmp; font = text_line_get_font(text_line); tmp = g_strdup_printf("%s; font-family: %s; font-style: %s; " "font-weight: %s",style, dia_font_get_family(font), dia_font_get_slant_string(font), dia_font_get_weight_string(font)); g_free(style); style = tmp; /* have to do something about fonts here ... */ xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) style); g_free(style); dia_svg_dtostr(d_buf, pos->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, text_line_get_width(text_line)); xmlSetProp(node, (const xmlChar*)"textLength", (xmlChar *) d_buf); }
static void set_linestyle(DiaRenderer *self, LineStyle mode) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); real hole_width; gchar dash_length_buf[DTOSTR_BUF_SIZE]; gchar dot_length_buf[DTOSTR_BUF_SIZE]; gchar hole_width_buf[DTOSTR_BUF_SIZE]; renderer->saved_line_style = mode; g_free(renderer->linestyle); switch(mode) { case LINESTYLE_SOLID: renderer->linestyle = NULL; break; case LINESTYLE_DASHED: dia_svg_dtostr(dash_length_buf, renderer->dash_length); renderer->linestyle = g_strdup_printf("%s", dash_length_buf); break; case LINESTYLE_DASH_DOT: hole_width = (renderer->dash_length - renderer->dot_length) / 2.0; dia_svg_dtostr(dash_length_buf, renderer->dash_length); dia_svg_dtostr(dot_length_buf, renderer->dot_length); dia_svg_dtostr(hole_width_buf, hole_width); renderer->linestyle = g_strdup_printf("%s %s %s %s", dash_length_buf, hole_width_buf, dot_length_buf, hole_width_buf ); break; case LINESTYLE_DASH_DOT_DOT: hole_width = (renderer->dash_length - 2.0*renderer->dot_length) / 3.0; dia_svg_dtostr(dash_length_buf, renderer->dash_length); dia_svg_dtostr(dot_length_buf, renderer->dot_length); dia_svg_dtostr(hole_width_buf, hole_width); renderer->linestyle = g_strdup_printf("%s %s %s %s %s %s", dash_length_buf, hole_width_buf, dot_length_buf, hole_width_buf, dot_length_buf, hole_width_buf ); break; case LINESTYLE_DOTTED: dia_svg_dtostr(dot_length_buf, renderer->dot_length); renderer->linestyle = g_strdup_printf("%s", dot_length_buf); break; default: renderer->linestyle = NULL; } }
/* the return value of this function should not be saved anywhere */ static const gchar * get_draw_style(DiaSvgRenderer *renderer, Color *colour) { static GString *str = NULL; gchar linewidth_buf[DTOSTR_BUF_SIZE]; if (!str) str = g_string_new(NULL); g_string_truncate(str, 0); /* TODO(CHECK): the shape-export didn't have 'fill: none' here */ g_string_printf(str, "fill: none; fill-opacity:0; stroke-width: %s", dia_svg_dtostr(linewidth_buf, renderer->linewidth) ); if (strcmp(renderer->linecap, "butt")) g_string_append_printf(str, "; stroke-linecap: %s", renderer->linecap); if (strcmp(renderer->linejoin, "miter")) g_string_append_printf(str, "; stroke-linejoin: %s", renderer->linejoin); if (renderer->linestyle) g_string_append_printf(str, "; stroke-dasharray: %s", renderer->linestyle); if (colour) g_string_append_printf(str, "; stroke: #%02x%02x%02x", (int)(255*colour->red), (int)(255*colour->green), (int)(255*colour->blue)); return str->str; }
static void draw_string(DiaRenderer *self, const char *text, Point *pos, Alignment alignment, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; gchar d_buf[G_ASCII_DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (xmlChar *)"text", (xmlChar *)text); node_set_text_style(node, renderer, self->font, self->font_height, alignment, colour); dia_svg_dtostr(d_buf, pos->x); xmlSetProp(node, (xmlChar *)"x", (xmlChar *)d_buf); dia_svg_dtostr(d_buf, pos->y); xmlSetProp(node, (xmlChar *)"y", (xmlChar *)d_buf); }
static void draw_image(DiaRenderer *self, Point *point, real width, real height, DiaImage *image) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; gchar d_buf[DTOSTR_BUF_SIZE]; gchar *uri = NULL; node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"image", NULL); dia_svg_dtostr(d_buf, point->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, point->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, width); xmlSetProp(node, (const xmlChar *)"width", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, height); xmlSetProp(node, (const xmlChar *)"height", (xmlChar *) d_buf); /* if the image file location is relative to the SVG file's store * a relative path - if it does not have a path: inline it */ if (strcmp (dia_image_filename(image), "(null)") == 0) { gchar *b64 = pixbuf_encode_base64 (dia_image_pixbuf (image)); gchar *uri; if (b64) uri = g_strdup_printf ("data:image/png;base64,%s", b64); else uri = g_strdup ("(null)"); xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) uri); g_free (b64); } else if ((uri = dia_relativize_filename (renderer->filename, dia_image_filename(image))) != NULL) xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) uri); else if ((uri = g_filename_to_uri(dia_image_filename(image), NULL, NULL)) != NULL) xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) uri); else /* not sure if this fallback is better than nothing */ xmlSetProp(node, (const xmlChar *)"xlink:href", (xmlChar *) dia_image_filename(image)); g_free (uri); }
static void draw_line(DiaRenderer *self, Point *start, Point *end, Color *line_colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; gchar d_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"line", NULL); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) get_draw_style(renderer, NULL, line_colour)); dia_svg_dtostr(d_buf, start->x); xmlSetProp(node, (const xmlChar *)"x1", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, start->y); xmlSetProp(node, (const xmlChar *)"y1", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, end->x); xmlSetProp(node, (const xmlChar *)"x2", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, end->y); xmlSetProp(node, (const xmlChar *)"y2", (xmlChar *) d_buf); }
static void draw_rect(DiaRenderer *self, Point *ul_corner, Point *lr_corner, Color *fill, Color *stroke) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; gchar d_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"rect", NULL); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) get_draw_style (renderer, fill, stroke)); dia_svg_dtostr(d_buf, ul_corner->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, ul_corner->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, lr_corner->x - ul_corner->x); xmlSetProp(node, (const xmlChar *)"width", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, lr_corner->y - ul_corner->y); xmlSetProp(node, (const xmlChar *)"height", (xmlChar *) d_buf); }
static void draw_ellipse(DiaRenderer *self, Point *center, real width, real height, Color *fill, Color *stroke) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; gchar d_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"ellipse", NULL); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) get_draw_style (renderer, fill, stroke)); dia_svg_dtostr(d_buf, center->x); xmlSetProp(node, (const xmlChar *)"cx", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, center->y); xmlSetProp(node, (const xmlChar *)"cy", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, width / 2); xmlSetProp(node, (const xmlChar *)"rx", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, height / 2); xmlSetProp(node, (const xmlChar *)"ry", (xmlChar *) d_buf); }
static void draw_text_line(DiaRenderer *self, TextLine *text_line, Point *pos, Alignment alignment, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; DiaFont *font = text_line_get_font(text_line); /* no reference? */ real font_height = text_line_get_height(text_line); gchar d_buf[G_ASCII_DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"text", (xmlChar *) text_line_get_string(text_line)); /* not using the renderers font but the textlines */ node_set_text_style(node, renderer, font, font_height, alignment, colour); dia_svg_dtostr(d_buf, pos->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, text_line_get_width(text_line)); xmlSetProp(node, (const xmlChar*)"textLength", (xmlChar *) d_buf); }
/* the return value of this function should not be saved anywhere */ static const gchar * get_draw_style(DiaSvgRenderer *renderer, Color *fill, Color *stroke) { static GString *str = NULL; gchar linewidth_buf[DTOSTR_BUF_SIZE]; gchar alpha_buf[DTOSTR_BUF_SIZE]; if (!str) str = g_string_new(NULL); g_string_truncate(str, 0); /* we only append a semicolon with the second attribute */ if (fill) { if (renderer->active_pattern) { gchar *key = _make_pattern_key (renderer->active_pattern); g_string_printf(str, "fill:url(#%s)", key); g_free (key); } else { g_string_printf(str, "fill: #%02x%02x%02x; fill-opacity: %s", (int)(255*fill->red), (int)(255*fill->green), (int)(255*fill->blue), g_ascii_formatd(alpha_buf, sizeof(alpha_buf), "%g", fill->alpha)); } } else { g_string_printf(str, "fill: none"); } if (stroke) { g_string_append_printf(str, "; stroke-opacity: %s; stroke-width: %s", g_ascii_formatd (alpha_buf, sizeof(alpha_buf), "%g", stroke->alpha), dia_svg_dtostr(linewidth_buf, renderer->linewidth) ); if (strcmp(renderer->linecap, "butt")) g_string_append_printf(str, "; stroke-linecap: %s", renderer->linecap); if (strcmp(renderer->linejoin, "miter")) g_string_append_printf(str, "; stroke-linejoin: %s", renderer->linejoin); if (renderer->linestyle) g_string_append_printf(str, "; stroke-dasharray: %s", renderer->linestyle); g_string_append_printf(str, "; stroke: #%02x%02x%02x", (int)(255*stroke->red), (int)(255*stroke->green), (int)(255*stroke->blue)); } else { g_string_append_printf(str, "; stroke: none"); } return str->str; }
static void fill_arc(DiaRenderer *self, Point *center, real width, real height, real angle1, real angle2, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; char buf[512]; real rx = width / 2, ry = height / 2; real sx=center->x + rx*cos(angle1*G_PI/180); real sy=center->y - ry*sin(angle1*G_PI/180); real ex=center->x + rx*cos(angle2*G_PI/180); real ey=center->y - ry*sin(angle2*G_PI/180); int swp = (angle2 > angle1) ? 0 : 1; /* preserve direction */ int large_arc = (fabs(angle2 - angle1) >= 180); gchar sx_buf[DTOSTR_BUF_SIZE]; gchar sy_buf[DTOSTR_BUF_SIZE]; gchar rx_buf[DTOSTR_BUF_SIZE]; gchar ry_buf[DTOSTR_BUF_SIZE]; gchar ex_buf[DTOSTR_BUF_SIZE]; gchar ey_buf[DTOSTR_BUF_SIZE]; gchar cx_buf[DTOSTR_BUF_SIZE]; gchar cy_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"path", NULL); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *)get_draw_style(renderer, colour, NULL)); g_snprintf(buf, sizeof(buf), "M %s,%s A %s,%s 0 %d %d %s,%s L %s,%s z", dia_svg_dtostr(sx_buf, sx), dia_svg_dtostr(sy_buf, sy), dia_svg_dtostr(rx_buf, rx), dia_svg_dtostr(ry_buf, ry), large_arc, swp, dia_svg_dtostr(ex_buf, ex), dia_svg_dtostr(ey_buf, ey), dia_svg_dtostr(cx_buf, center->x), dia_svg_dtostr(cy_buf, center->y) ); xmlSetProp(node, (const xmlChar *)"d", (xmlChar *) buf); }
static void node_set_text_style (xmlNodePtr node, DiaSvgRenderer *renderer, const DiaFont *font, real font_height, Alignment alignment, Color *colour) { char *style, *tmp; real saved_width; gchar d_buf[G_ASCII_DTOSTR_BUF_SIZE]; DiaSvgRendererClass *svg_renderer_class = DIA_SVG_RENDERER_GET_CLASS (renderer); /* SVG font-size is the (line-) height, from SVG Spec: * ... property refers to the size of the font from baseline to baseline when multiple lines of text are set ... so we should be able to use font_height directly instead of: */ real font_size = dia_font_get_size (font) * (font_height / dia_font_get_height (font)); /* ... but at least Inkscape and Firefox would produce the wrong font-size */ const gchar *family = dia_font_get_family(font); saved_width = renderer->linewidth; renderer->linewidth = 0.001; style = (char*)svg_renderer_class->get_fill_style(renderer, colour); /* return value must not be freed */ renderer->linewidth = saved_width; /* This is going to break for non-LTR texts, as SVG thinks 'start' is * 'right' for those. */ switch (alignment) { case ALIGN_LEFT: style = g_strconcat(style, ";text-anchor:start", NULL); break; case ALIGN_CENTER: style = g_strconcat(style, ";text-anchor:middle", NULL); break; case ALIGN_RIGHT: style = g_strconcat(style, ";text-anchor:end", NULL); break; } #if 0 /* would need a unit according to https://bugzilla.mozilla.org/show_bug.cgi?id=707071#c4 */ tmp = g_strdup_printf("%s;font-size:%s", style, dia_svg_dtostr(d_buf, font_size) ); g_free (style); style = tmp; #else /* font-size as attribute can work like the other length w/o unit */ dia_svg_dtostr(d_buf, font_size); xmlSetProp(node, (const xmlChar *)"font-size", (xmlChar *) d_buf); #endif if (font) { tmp = g_strdup_printf("%s;font-family:%s;font-style:%s;" "font-weight:%s",style, strcmp(family, "sans") == 0 ? "sans-serif" : family, dia_font_get_slant_string(font), dia_font_get_weight_string(font)); g_free(style); style = tmp; } /* have to do something about fonts here ... */ xmlSetProp(node, (xmlChar *)"style", (xmlChar *)style); g_free(style); }
static void draw_text_line(DiaRenderer *self, TextLine *text_line, Point *pos, Alignment alignment, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; real saved_width; gchar d_buf[DTOSTR_BUF_SIZE]; DiaFont *font; GString *style; node = xmlNewTextChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"text", (xmlChar *) text_line_get_string(text_line)); saved_width = renderer->linewidth; renderer->linewidth = 0.001; /* return value must not be freed */ renderer->linewidth = saved_width; #if 0 /* would need a unit: https://bugzilla.mozilla.org/show_bug.cgi?id=707071#c4 */ style = g_strdup_printf("%s; font-size: %s", get_draw_style(renderer, colour, NULL), dia_svg_dtostr(d_buf, text_line_get_height(text_line))); #else /* get_draw_style: the return value of this function must not be saved * anywhere. And of course it must not be free'd */ style = g_string_new (get_draw_style(renderer, colour, NULL)); #endif /* This is going to break for non-LTR texts, as SVG thinks 'start' is * 'right' for those. */ switch (alignment) { case ALIGN_LEFT: g_string_append (style, "; text-anchor:start"); break; case ALIGN_CENTER: g_string_append (style, "; text-anchor:middle"); break; case ALIGN_RIGHT: g_string_append (style, "; text-anchor:end"); break; default: break; } font = text_line_get_font(text_line); g_string_append_printf (style, "font-family: %s; font-style: %s; font-weight: %s", dia_font_get_family(font), dia_font_get_slant_string(font), dia_font_get_weight_string(font)); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) style->str); g_string_free (style, TRUE); dia_svg_dtostr(d_buf, pos->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); /* font-size as single attribute can work like the other length w/o unit */ dia_svg_dtostr(d_buf, text_line_get_height(text_line)); xmlSetProp(node, (const xmlChar *)"font-size", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, text_line_get_width(text_line)); xmlSetProp(node, (const xmlChar*)"textLength", (xmlChar *) d_buf); }
static void _bezier(DiaRenderer *self, BezPoint *points, int numpoints, Color *fill, Color *stroke, gboolean closed) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); int i; xmlNodePtr node; GString *str; gchar p1x_buf[DTOSTR_BUF_SIZE]; gchar p1y_buf[DTOSTR_BUF_SIZE]; gchar p2x_buf[DTOSTR_BUF_SIZE]; gchar p2y_buf[DTOSTR_BUF_SIZE]; gchar p3x_buf[DTOSTR_BUF_SIZE]; gchar p3y_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"path", NULL); if (fill || stroke) xmlSetProp(node, (const xmlChar *)"style", (xmlChar *)get_draw_style(renderer, fill, stroke)); str = g_string_new(NULL); if (points[0].type != BEZ_MOVE_TO) g_warning("first BezPoint must be a BEZ_MOVE_TO"); g_string_printf(str, "M %s %s", dia_svg_dtostr(p1x_buf, (gdouble) points[0].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[0].p1.y) ); for (i = 1; i < numpoints; i++) switch (points[i].type) { case BEZ_MOVE_TO: if (!DIA_RENDERER_GET_CLASS (self)->is_capable_to(self, RENDER_HOLES)) { g_warning("only first BezPoint should be a BEZ_MOVE_TO"); g_string_printf(str, "M %s %s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y) ); } else { g_string_append_printf(str, "M %s %s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y) ); } break; case BEZ_LINE_TO: g_string_append_printf(str, " L %s,%s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y) ); break; case BEZ_CURVE_TO: g_string_append_printf(str, " C %s,%s %s,%s %s,%s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y), dia_svg_dtostr(p2x_buf, (gdouble) points[i].p2.x), dia_svg_dtostr(p2y_buf, (gdouble) points[i].p2.y), dia_svg_dtostr(p3x_buf, (gdouble) points[i].p3.x), dia_svg_dtostr(p3y_buf, (gdouble) points[i].p3.y) ); break; } if (fill) { xmlSetProp(node, (const xmlChar *)"fill-rule", (const xmlChar *) "evenodd"); g_string_append(str, "z"); } xmlSetProp(node, (const xmlChar *)"d", (xmlChar *) str->str); g_string_free(str, TRUE); }
static void fill_bezier(DiaRenderer *self, BezPoint *points, /* Last point must be same as first point */ int numpoints, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); int i; xmlNodePtr node; GString *str; gchar p1x_buf[DTOSTR_BUF_SIZE]; gchar p1y_buf[DTOSTR_BUF_SIZE]; gchar p2x_buf[DTOSTR_BUF_SIZE]; gchar p2y_buf[DTOSTR_BUF_SIZE]; gchar p3x_buf[DTOSTR_BUF_SIZE]; gchar p3y_buf[DTOSTR_BUF_SIZE]; node = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"path", NULL); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) get_fill_style(renderer, colour)); str = g_string_new(NULL); if (points[0].type != BEZ_MOVE_TO) g_warning("first BezPoint must be a BEZ_MOVE_TO"); g_string_printf(str, "M %s %s", dia_svg_dtostr(p1x_buf, (gdouble) points[0].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[0].p1.y) ); for (i = 1; i < numpoints; i++) switch (points[i].type) { case BEZ_MOVE_TO: g_warning("only first BezPoint should be a BEZ_MOVE_TO"); g_string_printf(str, "M %s %s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y) ); break; case BEZ_LINE_TO: g_string_append_printf(str, " L %s,%s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y) ); break; case BEZ_CURVE_TO: g_string_append_printf(str, " C %s,%s %s,%s %s,%s", dia_svg_dtostr(p1x_buf, (gdouble) points[i].p1.x), dia_svg_dtostr(p1y_buf, (gdouble) points[i].p1.y), dia_svg_dtostr(p2x_buf, (gdouble) points[i].p2.x), dia_svg_dtostr(p2y_buf, (gdouble) points[i].p2.y), dia_svg_dtostr(p3x_buf, (gdouble) points[i].p3.x), dia_svg_dtostr(p3y_buf, (gdouble) points[i].p3.y) ); break; } g_string_append(str, "z"); xmlSetProp(node, (const xmlChar *)"d", (xmlChar *) str->str); g_string_free(str, TRUE); }