1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * render_svg.c - an SVG renderer for dia, based on render_eps.c
5 * Copyright (C) 1999, 2000 James Henstridge
7 * diasvgrenderer.c - refactoring of the above to serve as the
8 * base class for plug-ins/svg/render_svg.c and
9 * plug-ins/shape/shape-export.c
10 * Copyright (C) 2002, Hans Breuer
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #include <libxml/entities.h>
39 #include <libxml/tree.h>
40 #include <libxml/xmlmemory.h>
45 #include "dia_xml_libxml.h"
46 #include "dia_image.h"
48 #include "diasvgrenderer.h"
51 #define DTOSTR_BUF_SIZE G_ASCII_DTOSTR_BUF_SIZE
52 #define dia_svg_dtostr(buf,d) \
53 g_ascii_formatd(buf,sizeof(buf),"%g",d)
55 /* DiaSvgRenderer methods */
57 begin_render(DiaRenderer
*self
)
59 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
61 renderer
->linewidth
= 0;
62 renderer
->linecap
= "butt";
63 renderer
->linejoin
= "miter";
64 renderer
->linestyle
= NULL
;
68 end_render(DiaRenderer
*self
)
70 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
71 g_free(renderer
->linestyle
);
73 xmlSetDocCompressMode(renderer
->doc
, 0);
74 xmlDiaSaveFile(renderer
->filename
, renderer
->doc
);
75 g_free(renderer
->filename
);
76 xmlFreeDoc(renderer
->doc
);
80 set_linewidth(DiaRenderer
*self
, real linewidth
)
81 { /* 0 == hairline **/
82 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
85 renderer
->linewidth
= 0.001;
87 renderer
->linewidth
= linewidth
;
91 set_linecaps(DiaRenderer
*self
, LineCaps mode
)
93 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
97 renderer
->linecap
= "butt";
100 renderer
->linecap
= "round";
102 case LINECAPS_PROJECTING
:
103 renderer
->linecap
= "square";
106 renderer
->linecap
= "butt";
111 set_linejoin(DiaRenderer
*self
, LineJoin mode
)
113 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
117 renderer
->linejoin
= "miter";
120 renderer
->linejoin
= "round";
123 renderer
->linejoin
= "bevel";
126 renderer
->linejoin
= "miter";
131 set_linestyle(DiaRenderer
*self
, LineStyle mode
)
133 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
135 gchar dash_length_buf
[DTOSTR_BUF_SIZE
];
136 gchar dot_length_buf
[DTOSTR_BUF_SIZE
];
137 gchar hole_width_buf
[DTOSTR_BUF_SIZE
];
139 renderer
->saved_line_style
= mode
;
141 g_free(renderer
->linestyle
);
143 case LINESTYLE_SOLID
:
144 renderer
->linestyle
= NULL
;
146 case LINESTYLE_DASHED
:
147 dia_svg_dtostr(dash_length_buf
, renderer
->dash_length
);
148 renderer
->linestyle
= g_strdup_printf("%s", dash_length_buf
);
150 case LINESTYLE_DASH_DOT
:
151 hole_width
= (renderer
->dash_length
- renderer
->dot_length
) / 2.0;
153 dia_svg_dtostr(dash_length_buf
, renderer
->dash_length
);
154 dia_svg_dtostr(dot_length_buf
, renderer
->dot_length
);
155 dia_svg_dtostr(hole_width_buf
, hole_width
);
157 renderer
->linestyle
= g_strdup_printf("%s %s %s %s",
163 case LINESTYLE_DASH_DOT_DOT
:
164 hole_width
= (renderer
->dash_length
- 2.0*renderer
->dot_length
) / 3.0;
166 dia_svg_dtostr(dash_length_buf
, renderer
->dash_length
);
167 dia_svg_dtostr(dot_length_buf
, renderer
->dot_length
);
168 dia_svg_dtostr(hole_width_buf
, hole_width
);
170 renderer
->linestyle
= g_strdup_printf("%s %s %s %s %s %s",
178 case LINESTYLE_DOTTED
:
180 dia_svg_dtostr(dot_length_buf
, renderer
->dot_length
);
182 renderer
->linestyle
= g_strdup_printf("%s", dot_length_buf
);
185 renderer
->linestyle
= NULL
;
190 set_dashlength(DiaRenderer
*self
, real length
)
191 { /* dot = 20% of len */
192 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
197 renderer
->dash_length
= length
;
198 renderer
->dot_length
= length
*0.2;
200 set_linestyle(self
, renderer
->saved_line_style
);
204 set_fillstyle(DiaRenderer
*self
, FillStyle mode
)
207 case FILLSTYLE_SOLID
:
210 message_error("svg_renderer: Unsupported fill mode specified!\n");
214 /* the return value of this function should not be saved anywhere */
216 get_draw_style(DiaSvgRenderer
*renderer
,
219 static GString
*str
= NULL
;
220 gchar linewidth_buf
[DTOSTR_BUF_SIZE
];
222 if (!str
) str
= g_string_new(NULL
);
223 g_string_truncate(str
, 0);
225 /* TODO(CHECK): the shape-export didn't have 'fill: none' here */
226 g_string_sprintf(str
, "fill: none; fill-opacity:0; stroke-width: %s", dia_svg_dtostr(linewidth_buf
, renderer
->linewidth
) );
227 if (strcmp(renderer
->linecap
, "butt"))
228 g_string_sprintfa(str
, "; stroke-linecap: %s", renderer
->linecap
);
229 if (strcmp(renderer
->linejoin
, "miter"))
230 g_string_sprintfa(str
, "; stroke-linejoin: %s", renderer
->linejoin
);
231 if (renderer
->linestyle
)
232 g_string_sprintfa(str
, "; stroke-dasharray: %s", renderer
->linestyle
);
235 g_string_sprintfa(str
, "; stroke: #%02x%02x%02x",
236 (int)ceil(255*colour
->red
), (int)ceil(255*colour
->green
),
237 (int)ceil(255*colour
->blue
));
242 /* the return value of this function should not be saved anywhere */
244 get_fill_style(DiaSvgRenderer
*renderer
,
247 static GString
*str
= NULL
;
249 if (!str
) str
= g_string_new(NULL
);
251 g_string_sprintf(str
, "fill: #%02x%02x%02x",
252 (int)ceil(255*colour
->red
), (int)ceil(255*colour
->green
),
253 (int)ceil(255*colour
->blue
));
259 draw_line(DiaRenderer
*self
,
260 Point
*start
, Point
*end
,
263 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
265 gchar d_buf
[DTOSTR_BUF_SIZE
];
267 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "line", NULL
);
269 xmlSetProp(node
, "style", get_draw_style(renderer
, line_colour
));
271 dia_svg_dtostr(d_buf
, start
->x
);
272 xmlSetProp(node
, "x1", d_buf
);
273 dia_svg_dtostr(d_buf
, start
->y
);
274 xmlSetProp(node
, "y1", d_buf
);
275 dia_svg_dtostr(d_buf
, end
->x
);
276 xmlSetProp(node
, "x2", d_buf
);
277 dia_svg_dtostr(d_buf
, end
->y
);
278 xmlSetProp(node
, "y2", d_buf
);
282 draw_polyline(DiaRenderer
*self
,
283 Point
*points
, int num_points
,
286 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
290 gchar px_buf
[DTOSTR_BUF_SIZE
];
291 gchar py_buf
[DTOSTR_BUF_SIZE
];
293 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "polyline", NULL
);
295 xmlSetProp(node
, "style", get_draw_style(renderer
, line_colour
));
297 str
= g_string_new(NULL
);
298 for (i
= 0; i
< num_points
; i
++)
299 g_string_sprintfa(str
, "%s,%s ",
300 dia_svg_dtostr(px_buf
, points
[i
].x
),
301 dia_svg_dtostr(py_buf
, points
[i
].y
) );
302 xmlSetProp(node
, "points", str
->str
);
303 g_string_free(str
, TRUE
);
307 draw_polygon(DiaRenderer
*self
,
308 Point
*points
, int num_points
,
311 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
315 gchar px_buf
[DTOSTR_BUF_SIZE
];
316 gchar py_buf
[DTOSTR_BUF_SIZE
];
318 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "polygon", NULL
);
320 xmlSetProp(node
, "style", get_draw_style(renderer
, line_colour
));
322 str
= g_string_new(NULL
);
323 for (i
= 0; i
< num_points
; i
++)
324 g_string_sprintfa(str
, "%s,%s ",
325 dia_svg_dtostr(px_buf
, points
[i
].x
),
326 dia_svg_dtostr(py_buf
, points
[i
].y
) );
327 xmlSetProp(node
, "points", str
->str
);
328 g_string_free(str
, TRUE
);
332 fill_polygon(DiaRenderer
*self
,
333 Point
*points
, int num_points
,
336 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
340 gchar px_buf
[DTOSTR_BUF_SIZE
];
341 gchar py_buf
[DTOSTR_BUF_SIZE
];
343 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "polygon", NULL
);
345 xmlSetProp(node
, "style", get_fill_style(renderer
, colour
));
347 str
= g_string_new(NULL
);
348 for (i
= 0; i
< num_points
; i
++)
349 g_string_sprintfa(str
, "%s,%s ",
350 dia_svg_dtostr(px_buf
, points
[i
].x
),
351 dia_svg_dtostr(py_buf
, points
[i
].y
) );
352 xmlSetProp(node
, "points", str
->str
);
353 g_string_free(str
, TRUE
);
357 draw_rect(DiaRenderer
*self
,
358 Point
*ul_corner
, Point
*lr_corner
,
361 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
363 gchar d_buf
[DTOSTR_BUF_SIZE
];
365 node
= xmlNewChild(renderer
->root
, NULL
, "rect", NULL
);
367 xmlSetProp(node
, "style", get_draw_style(renderer
, colour
));
369 dia_svg_dtostr(d_buf
, ul_corner
->x
);
370 xmlSetProp(node
, "x", d_buf
);
371 dia_svg_dtostr(d_buf
, ul_corner
->y
);
372 xmlSetProp(node
, "y", d_buf
);
373 dia_svg_dtostr(d_buf
, lr_corner
->x
- ul_corner
->x
);
374 xmlSetProp(node
, "width", d_buf
);
375 dia_svg_dtostr(d_buf
, lr_corner
->y
- ul_corner
->y
);
376 xmlSetProp(node
, "height", d_buf
);
380 fill_rect(DiaRenderer
*self
,
381 Point
*ul_corner
, Point
*lr_corner
,
384 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
386 gchar d_buf
[DTOSTR_BUF_SIZE
];
388 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "rect", NULL
);
390 xmlSetProp(node
, "style", get_fill_style(renderer
, colour
));
392 dia_svg_dtostr(d_buf
, ul_corner
->x
);
393 xmlSetProp(node
, "x", d_buf
);
394 dia_svg_dtostr(d_buf
, ul_corner
->y
);
395 xmlSetProp(node
, "y", d_buf
);
396 dia_svg_dtostr(d_buf
, lr_corner
->x
- ul_corner
->x
);
397 xmlSetProp(node
, "width", d_buf
);
398 dia_svg_dtostr(d_buf
, lr_corner
->y
- ul_corner
->y
);
399 xmlSetProp(node
, "height", d_buf
);
403 draw_arc(DiaRenderer
*self
,
405 real width
, real height
,
406 real angle1
, real angle2
,
409 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
412 real rx
= width
/ 2, ry
= height
/ 2;
413 real sx
=center
->x
+ rx
*cos(angle1
*G_PI
/180);
414 real sy
=center
->y
- ry
*sin(angle1
*G_PI
/180);
415 real ex
=center
->x
+ rx
*cos(angle2
*G_PI
/180);
416 real ey
=center
->y
- ry
*sin(angle2
*G_PI
/180);
417 int swp
= 0; /* always drawin negative direction */
418 int large_arc
= (angle2
- angle1
>= 180);
419 gchar sx_buf
[DTOSTR_BUF_SIZE
];
420 gchar sy_buf
[DTOSTR_BUF_SIZE
];
421 gchar rx_buf
[DTOSTR_BUF_SIZE
];
422 gchar ry_buf
[DTOSTR_BUF_SIZE
];
423 gchar ex_buf
[DTOSTR_BUF_SIZE
];
424 gchar ey_buf
[DTOSTR_BUF_SIZE
];
426 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "path", NULL
);
428 xmlSetProp(node
, "style", get_draw_style(renderer
, colour
));
430 g_snprintf(buf
, sizeof(buf
), "M %s,%s A %s,%s 0 %d %d %s,%s",
431 dia_svg_dtostr(sx_buf
, sx
), dia_svg_dtostr(sy_buf
, sy
),
432 dia_svg_dtostr(rx_buf
, rx
), dia_svg_dtostr(ry_buf
, ry
),
434 dia_svg_dtostr(ex_buf
, ex
), dia_svg_dtostr(ey_buf
, ey
) );
436 xmlSetProp(node
, "d", buf
);
440 fill_arc(DiaRenderer
*self
,
442 real width
, real height
,
443 real angle1
, real angle2
,
446 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
449 real rx
= width
/ 2, ry
= height
/ 2;
450 real sx
=center
->x
+ rx
*cos(angle1
*G_PI
/180);
451 real sy
=center
->y
- ry
*sin(angle1
*G_PI
/180);
452 real ex
=center
->x
+ rx
*cos(angle2
*G_PI
/180);
453 real ey
=center
->y
- ry
*sin(angle2
*G_PI
/180);
454 int swp
= 0; /* always drawin negative direction */
455 int large_arc
= (angle2
- angle1
>= 180);
456 gchar sx_buf
[DTOSTR_BUF_SIZE
];
457 gchar sy_buf
[DTOSTR_BUF_SIZE
];
458 gchar rx_buf
[DTOSTR_BUF_SIZE
];
459 gchar ry_buf
[DTOSTR_BUF_SIZE
];
460 gchar ex_buf
[DTOSTR_BUF_SIZE
];
461 gchar ey_buf
[DTOSTR_BUF_SIZE
];
462 gchar cx_buf
[DTOSTR_BUF_SIZE
];
463 gchar cy_buf
[DTOSTR_BUF_SIZE
];
465 node
= xmlNewChild(renderer
->root
, NULL
, "path", NULL
);
467 xmlSetProp(node
, "style", get_fill_style(renderer
, colour
));
469 g_snprintf(buf
, sizeof(buf
), "M %s,%s A %s,%s 0 %d %d %s,%s L %s,%s z",
470 dia_svg_dtostr(sx_buf
, sx
), dia_svg_dtostr(sy_buf
, sy
),
471 dia_svg_dtostr(rx_buf
, rx
), dia_svg_dtostr(ry_buf
, ry
),
473 dia_svg_dtostr(ex_buf
, ex
), dia_svg_dtostr(ey_buf
, ey
),
474 dia_svg_dtostr(cx_buf
, center
->x
),
475 dia_svg_dtostr(cy_buf
, center
->y
) );
477 xmlSetProp(node
, "d", buf
);
481 draw_ellipse(DiaRenderer
*self
,
483 real width
, real height
,
486 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
488 gchar d_buf
[DTOSTR_BUF_SIZE
];
490 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "ellipse", NULL
);
492 xmlSetProp(node
, "style", get_draw_style(renderer
, colour
));
494 dia_svg_dtostr(d_buf
, center
->x
);
495 xmlSetProp(node
, "cx", d_buf
);
496 dia_svg_dtostr(d_buf
, center
->y
);
497 xmlSetProp(node
, "cy", d_buf
);
498 dia_svg_dtostr(d_buf
, width
/ 2);
499 xmlSetProp(node
, "rx", d_buf
);
500 dia_svg_dtostr(d_buf
, height
/ 2);
501 xmlSetProp(node
, "ry", d_buf
);
505 fill_ellipse(DiaRenderer
*self
,
507 real width
, real height
,
510 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
512 gchar d_buf
[DTOSTR_BUF_SIZE
];
514 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "ellipse", NULL
);
516 xmlSetProp(node
, "style", get_fill_style(renderer
, colour
));
518 dia_svg_dtostr(d_buf
, center
->x
);
519 xmlSetProp(node
, "cx", d_buf
);
520 dia_svg_dtostr(d_buf
, center
->y
);
521 xmlSetProp(node
, "cy", d_buf
);
522 dia_svg_dtostr(d_buf
, width
/ 2);
523 xmlSetProp(node
, "rx", d_buf
);
524 dia_svg_dtostr(d_buf
, height
/ 2);
525 xmlSetProp(node
, "ry", d_buf
);
529 draw_bezier(DiaRenderer
*self
,
534 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
538 gchar p1x_buf
[DTOSTR_BUF_SIZE
];
539 gchar p1y_buf
[DTOSTR_BUF_SIZE
];
540 gchar p2x_buf
[DTOSTR_BUF_SIZE
];
541 gchar p2y_buf
[DTOSTR_BUF_SIZE
];
542 gchar p3x_buf
[DTOSTR_BUF_SIZE
];
543 gchar p3y_buf
[DTOSTR_BUF_SIZE
];
545 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "path", NULL
);
547 xmlSetProp(node
, "style", get_draw_style(renderer
, colour
));
549 str
= g_string_new(NULL
);
551 if (points
[0].type
!= BEZ_MOVE_TO
)
552 g_warning("first BezPoint must be a BEZ_MOVE_TO");
554 g_string_sprintf(str
, "M %s %s",
555 dia_svg_dtostr(p1x_buf
, (gdouble
) points
[0].p1
.x
),
556 dia_svg_dtostr(p1y_buf
, (gdouble
) points
[0].p1
.y
) );
558 for (i
= 1; i
< numpoints
; i
++)
559 switch (points
[i
].type
) {
561 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
564 g_string_sprintfa(str
, " L %s,%s",
565 dia_svg_dtostr(p1x_buf
, (gdouble
) points
[i
].p1
.x
),
566 dia_svg_dtostr(p1y_buf
, (gdouble
) points
[i
].p1
.y
) );
569 g_string_sprintfa(str
, " C %s,%s %s,%s %s,%s",
570 dia_svg_dtostr(p1x_buf
, (gdouble
) points
[i
].p1
.x
),
571 dia_svg_dtostr(p1y_buf
, (gdouble
) points
[i
].p1
.y
),
572 dia_svg_dtostr(p2x_buf
, (gdouble
) points
[i
].p2
.x
),
573 dia_svg_dtostr(p2y_buf
, (gdouble
) points
[i
].p2
.y
),
574 dia_svg_dtostr(p3x_buf
, (gdouble
) points
[i
].p3
.x
),
575 dia_svg_dtostr(p3y_buf
, (gdouble
) points
[i
].p3
.y
) );
578 xmlSetProp(node
, "d", str
->str
);
579 g_string_free(str
, TRUE
);
583 fill_bezier(DiaRenderer
*self
,
584 BezPoint
*points
, /* Last point must be same as first point */
588 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
592 gchar p1x_buf
[DTOSTR_BUF_SIZE
];
593 gchar p1y_buf
[DTOSTR_BUF_SIZE
];
594 gchar p2x_buf
[DTOSTR_BUF_SIZE
];
595 gchar p2y_buf
[DTOSTR_BUF_SIZE
];
596 gchar p3x_buf
[DTOSTR_BUF_SIZE
];
597 gchar p3y_buf
[DTOSTR_BUF_SIZE
];
599 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "path", NULL
);
601 xmlSetProp(node
, "style", get_fill_style(renderer
, colour
));
603 str
= g_string_new(NULL
);
605 if (points
[0].type
!= BEZ_MOVE_TO
)
606 g_warning("first BezPoint must be a BEZ_MOVE_TO");
608 g_string_sprintf(str
, "M %s %s",
609 dia_svg_dtostr(p1x_buf
, (gdouble
) points
[0].p1
.x
),
610 dia_svg_dtostr(p1y_buf
, (gdouble
) points
[0].p1
.y
) );
612 for (i
= 1; i
< numpoints
; i
++)
613 switch (points
[i
].type
) {
615 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
618 g_string_sprintfa(str
, " L %s,%s",
619 dia_svg_dtostr(p1x_buf
, (gdouble
) points
[i
].p1
.x
),
620 dia_svg_dtostr(p1y_buf
, (gdouble
) points
[i
].p1
.y
) );
623 g_string_sprintfa(str
, " C %s,%s %s,%s %s,%s",
624 dia_svg_dtostr(p1x_buf
, (gdouble
) points
[i
].p1
.x
),
625 dia_svg_dtostr(p1y_buf
, (gdouble
) points
[i
].p1
.y
),
626 dia_svg_dtostr(p2x_buf
, (gdouble
) points
[i
].p2
.x
),
627 dia_svg_dtostr(p2y_buf
, (gdouble
) points
[i
].p2
.y
),
628 dia_svg_dtostr(p3x_buf
, (gdouble
) points
[i
].p3
.x
),
629 dia_svg_dtostr(p3y_buf
, (gdouble
) points
[i
].p3
.y
) );
632 g_string_append(str
, "z");
633 xmlSetProp(node
, "d", str
->str
);
634 g_string_free(str
, TRUE
);
638 draw_string(DiaRenderer
*self
,
640 Point
*pos
, Alignment alignment
,
643 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
647 gchar d_buf
[DTOSTR_BUF_SIZE
];
649 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "text", text
);
651 saved_width
= renderer
->linewidth
;
652 renderer
->linewidth
= 0.001;
653 style
= (char*)get_fill_style(renderer
, colour
);
654 /* return value must not be freed */
655 renderer
->linewidth
= saved_width
;
656 /* This is going to break for non-LTR texts, as SVG thinks 'start' is
661 style
= g_strconcat(style
, "; text-anchor:start", NULL
);
664 style
= g_strconcat(style
, "; text-anchor:middle", NULL
);
667 style
= g_strconcat(style
, "; text-anchor:end", NULL
);
670 tmp
= g_strdup_printf("%s; font-size: %s", style
,
671 dia_svg_dtostr(d_buf
, self
->font_height
) );
676 tmp
= g_strdup_printf("%s; font-family: %s; font-style: %s; "
677 "font-weight: %s",style
,
678 dia_font_get_family(self
->font
),
679 dia_font_get_slant_string(self
->font
),
680 dia_font_get_weight_string(self
->font
));
685 /* have to do something about fonts here ... */
687 xmlSetProp(node
, "style", style
);
690 dia_svg_dtostr(d_buf
, pos
->x
);
691 xmlSetProp(node
, "x", d_buf
);
692 dia_svg_dtostr(d_buf
, pos
->y
);
693 xmlSetProp(node
, "y", d_buf
);
698 draw_text_line(DiaRenderer
*self
, TextLine
*text_line
,
699 Point
*pos
, Color
*colour
)
701 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
705 gchar d_buf
[DTOSTR_BUF_SIZE
];
708 node
= xmlNewChild(renderer
->root
, renderer
->svg_name_space
, "text",
709 text_line_get_string(text_line
));
711 saved_width
= renderer
->linewidth
;
712 renderer
->linewidth
= 0.001;
713 style
= (char*)get_fill_style(renderer
, colour
);
714 /* return value must not be freed */
715 renderer
->linewidth
= saved_width
;
716 tmp
= g_strdup_printf("%s; font-size: %s", style
,
717 dia_svg_dtostr(d_buf
, text_line_get_height(text_line
)));
721 tmp
= g_strdup_printf("%s; length: %s", style
,
722 dia_svg_dtostr(d_buf
, text_line_get_width(text_line
)));
726 font
= text_line_get_font(text_line
);
727 tmp
= g_strdup_printf("%s; font-family: %s; font-style: %s; "
728 "font-weight: %s",style
,
729 dia_font_get_family(font
),
730 dia_font_get_slant_string(font
),
731 dia_font_get_weight_string(font
));
735 /* have to do something about fonts here ... */
737 xmlSetProp(node
, "style", style
);
740 dia_svg_dtostr(d_buf
, pos
->x
);
741 xmlSetProp(node
, "x", d_buf
);
742 dia_svg_dtostr(d_buf
, pos
->y
);
743 xmlSetProp(node
, "y", d_buf
);
747 draw_image(DiaRenderer
*self
,
749 real width
, real height
,
752 DiaSvgRenderer
*renderer
= DIA_SVG_RENDERER (self
);
754 gchar d_buf
[DTOSTR_BUF_SIZE
];
756 node
= xmlNewChild(renderer
->root
, NULL
, "image", NULL
);
758 dia_svg_dtostr(d_buf
, point
->x
);
759 xmlSetProp(node
, "x", d_buf
);
760 dia_svg_dtostr(d_buf
, point
->y
);
761 xmlSetProp(node
, "y", d_buf
);
762 dia_svg_dtostr(d_buf
, width
);
763 xmlSetProp(node
, "width", d_buf
);
764 dia_svg_dtostr(d_buf
, height
);
765 xmlSetProp(node
, "height", d_buf
);
766 xmlSetProp(node
, "xlink:href", dia_image_filename(image
));
771 dia_svg_renderer_init (GTypeInstance
*instance
, gpointer g_class
)
775 static gpointer parent_class
= NULL
;
779 dia_svg_renderer_finalize (GObject
*object
)
781 G_OBJECT_CLASS (parent_class
)->finalize (object
);
784 /* gobject boiler plate, vtable initialization */
785 static void dia_svg_renderer_class_init (DiaSvgRendererClass
*klass
);
788 dia_svg_renderer_get_type (void)
790 static GType object_type
= 0;
794 static const GTypeInfo object_info
=
796 sizeof (DiaSvgRendererClass
),
797 (GBaseInitFunc
) NULL
,
798 (GBaseFinalizeFunc
) NULL
,
799 (GClassInitFunc
) dia_svg_renderer_class_init
,
800 NULL
, /* class_finalize */
801 NULL
, /* class_data */
802 sizeof (DiaSvgRenderer
),
804 dia_svg_renderer_init
/* init */
807 object_type
= g_type_register_static (DIA_TYPE_RENDERER
,
816 dia_svg_renderer_class_init (DiaSvgRendererClass
*klass
)
818 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
819 DiaRendererClass
*renderer_class
= DIA_RENDERER_CLASS (klass
);
820 DiaSvgRendererClass
*svg_renderer_class
= DIA_SVG_RENDERER_CLASS (klass
);
822 parent_class
= g_type_class_peek_parent (klass
);
824 object_class
->finalize
= dia_svg_renderer_finalize
;
826 /* renderer members */
827 renderer_class
->begin_render
= begin_render
;
828 renderer_class
->end_render
= end_render
;
830 renderer_class
->set_linewidth
= set_linewidth
;
831 renderer_class
->set_linecaps
= set_linecaps
;
832 renderer_class
->set_linejoin
= set_linejoin
;
833 renderer_class
->set_linestyle
= set_linestyle
;
834 renderer_class
->set_dashlength
= set_dashlength
;
835 renderer_class
->set_fillstyle
= set_fillstyle
;
837 renderer_class
->draw_line
= draw_line
;
838 renderer_class
->fill_polygon
= fill_polygon
;
839 renderer_class
->draw_rect
= draw_rect
;
840 renderer_class
->fill_rect
= fill_rect
;
841 renderer_class
->draw_arc
= draw_arc
;
842 renderer_class
->fill_arc
= fill_arc
;
843 renderer_class
->draw_ellipse
= draw_ellipse
;
844 renderer_class
->fill_ellipse
= fill_ellipse
;
846 renderer_class
->draw_string
= draw_string
;
847 renderer_class
->draw_image
= draw_image
;
849 /* medium level functions */
850 renderer_class
->draw_rect
= draw_rect
;
851 renderer_class
->draw_polyline
= draw_polyline
;
852 renderer_class
->draw_polygon
= draw_polygon
;
854 renderer_class
->draw_bezier
= draw_bezier
;
855 renderer_class
->fill_bezier
= fill_bezier
;
856 /* renderer_class->draw_text_line = draw_text_line;*/
859 svg_renderer_class
->get_draw_style
= get_draw_style
;
860 svg_renderer_class
->get_fill_style
= get_fill_style
;