1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2 /* Dia -- a diagram creation/manipulation program
3 * Copyright (C) 1998 Alexander Larsson
5 * vdx-export.c: Visio XML export filter for dia
6 * Copyright (C) 2006 Ian Redfern
7 * based on the xfig filter code
8 * Copyright (C) 2001 Lars Clausen
9 * based on the dxf filter code
10 * Copyright (C) 2000 James Henstridge, Steffen Macke
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.
39 #include <glib/gstdio.h>
44 #include "diarenderer.h"
47 #include "properties.h"
48 #include "dia_image.h"
52 #include "visio-types.h"
54 /* Following code taken from xfig-export.c */
56 #define VDX_TYPE_RENDERER (vdx_renderer_get_type ())
57 #define VDX_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VDX_TYPE_RENDERER, VDXRenderer))
58 #define VDX_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VDX_TYPE_RENDERER, VDXRendererClass))
59 #define VDX_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VDX_TYPE_RENDERER))
60 #define VDX_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VDX_TYPE_RENDERER, VDXRendererClass))
62 GType
vdx_renderer_get_type (void) G_GNUC_CONST
;
64 typedef struct _VDXRenderer VDXRenderer
;
65 typedef struct _VDXRendererClass VDXRendererClass
;
67 struct _VDXRendererClass
69 DiaRendererClass parent_class
;
74 DiaRenderer parent_instance
;
89 /* Additions for VDX */
91 gboolean first_pass
; /* When we make table of colours and fonts */
92 GArray
*Colors
; /* Table of colours */
93 GArray
*Fonts
; /* Table of fonts */
94 unsigned int shapeid
; /* Shape counter */
95 unsigned int version
; /* Visio version */
96 unsigned int xml_depth
; /* Pretty-printer */
100 static void begin_render(DiaRenderer
*self
);
101 static void end_render(DiaRenderer
*renderer
);
102 static void set_linewidth(DiaRenderer
*self
, real linewidth
);
103 static void set_linecaps(DiaRenderer
*self
, LineCaps mode
);
104 static void set_linejoin(DiaRenderer
*self
, LineJoin mode
);
105 static void set_linestyle(DiaRenderer
*self
, LineStyle mode
);
106 static void set_dashlength(DiaRenderer
*self
, real length
);
107 static void set_fillstyle(DiaRenderer
*self
, FillStyle mode
);
108 static void set_font(DiaRenderer
*self
, DiaFont
*font
, real height
);
109 static void draw_line(DiaRenderer
*self
,
110 Point
*start
, Point
*end
,
112 static void draw_polyline(DiaRenderer
*self
,
113 Point
*points
, int num_points
,
115 static void draw_polygon(DiaRenderer
*self
,
116 Point
*points
, int num_points
,
118 static void fill_polygon(DiaRenderer
*self
,
119 Point
*points
, int num_points
,
121 static void draw_rect(DiaRenderer
*self
,
122 Point
*ul_corner
, Point
*lr_corner
,
124 static void fill_rect(DiaRenderer
*self
,
125 Point
*ul_corner
, Point
*lr_corner
,
127 static void draw_arc(DiaRenderer
*self
,
129 real width
, real height
,
130 real angle1
, real angle2
,
132 static void fill_arc(DiaRenderer
*self
,
134 real width
, real height
,
135 real angle1
, real angle2
,
137 static void draw_ellipse(DiaRenderer
*self
,
139 real width
, real height
,
141 static void fill_ellipse(DiaRenderer
*self
,
143 real width
, real height
,
145 static void draw_string(DiaRenderer
*self
,
147 Point
*pos
, Alignment alignment
,
149 static void draw_image(DiaRenderer
*self
,
151 real width
, real height
,
154 static void vdx_renderer_class_init (VDXRendererClass
*klass
);
157 export_vdx(DiagramData
*data
, const gchar
*filename
,
158 const gchar
*diafilename
, void* user_data
);
161 vdxCheckColor(VDXRenderer
*renderer
, Color
*color
);
163 static gpointer parent_class
= NULL
;
166 /** Renderer type handler
167 * @returns renderer type
171 vdx_renderer_get_type (void)
173 static GType object_type
= 0;
177 static const GTypeInfo object_info
=
179 sizeof (VDXRendererClass
),
180 (GBaseInitFunc
) NULL
,
181 (GBaseFinalizeFunc
) NULL
,
182 (GClassInitFunc
) vdx_renderer_class_init
,
183 NULL
, /* class_finalize */
184 NULL
, /* class_data */
185 sizeof (VDXRenderer
),
190 object_type
= g_type_register_static (DIA_TYPE_RENDERER
,
198 /** Finalise a renderer
199 * @param object a renderer
203 vdx_renderer_finalize (GObject
*object
)
205 G_OBJECT_CLASS (parent_class
)->finalize (object
);
208 /** Class constructor for renderer
209 * @param klass a renderer
213 vdx_renderer_class_init (VDXRendererClass
*klass
)
215 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
216 DiaRendererClass
*renderer_class
= DIA_RENDERER_CLASS (klass
);
218 parent_class
= g_type_class_peek_parent (klass
);
220 object_class
->finalize
= vdx_renderer_finalize
;
222 renderer_class
->begin_render
= begin_render
;
223 renderer_class
->end_render
= end_render
;
225 renderer_class
->set_linewidth
= set_linewidth
;
226 renderer_class
->set_linecaps
= set_linecaps
;
227 renderer_class
->set_linejoin
= set_linejoin
;
228 renderer_class
->set_linestyle
= set_linestyle
;
229 renderer_class
->set_dashlength
= set_dashlength
;
230 renderer_class
->set_fillstyle
= set_fillstyle
;
231 renderer_class
->set_font
= set_font
;
233 renderer_class
->draw_line
= draw_line
;
234 renderer_class
->draw_polyline
= draw_polyline
;
236 renderer_class
->draw_polygon
= draw_polygon
;
237 renderer_class
->fill_polygon
= fill_polygon
;
239 renderer_class
->draw_rect
= draw_rect
;
240 renderer_class
->fill_rect
= fill_rect
;
242 renderer_class
->draw_arc
= draw_arc
;
243 renderer_class
->fill_arc
= fill_arc
;
245 renderer_class
->draw_ellipse
= draw_ellipse
;
246 renderer_class
->fill_ellipse
= fill_ellipse
;
248 /* Until we have NURBS, let Dia use lines */
249 /* renderer_class->draw_bezier = draw_bezier; */
250 /* renderer_class->fill_bezier = fill_bezier; */
251 /* renderer_class->draw_bezier_with_arrows = draw_bezier_with_arrows; */
253 renderer_class
->draw_string
= draw_string
;
255 renderer_class
->draw_image
= draw_image
;
257 /* Believe these are never used or are unnecessary */
258 /* renderer_class->draw_line_with_arrows = draw_line_with_arrows; */
259 /* renderer_class->draw_polyline_with_arrows = draw_polyline_with_arrows; */
260 /* renderer_class->draw_arc_with_arrows = draw_arc_with_arrows; */
261 /* renderer_class->draw_object = draw_object; */
265 /** Initialises VDXrenderer
266 * @param self a renderer
270 begin_render(DiaRenderer
*self
)
272 VDXRenderer
*renderer
= VDX_RENDERER(self
);
277 renderer
->linewidth
= 0;
278 renderer
->capsmode
= 0;
279 renderer
->joinmode
= 0;
280 renderer
->stylemode
= 0;
281 renderer
->dashlength
= 0;
282 renderer
->fillmode
= 0;
283 renderer
->font
= NULL
;
284 renderer
->fontheight
= 1;
286 /* Specific to VDX */
288 renderer
->Colors
= g_array_new(FALSE
, TRUE
, sizeof (Color
));
289 renderer
->Fonts
= g_array_new(FALSE
, TRUE
, sizeof (char *));
290 renderer
->shapeid
= 0;
291 /* renderer->version = 0; */
293 /* Black and white are 0 and 1 respectively */
294 c
.red
= 0.0; c
.green
= 0.0; c
.blue
= 0.0;
295 vdxCheckColor(renderer
, &c
);
296 c
.red
= 1.0; c
.green
= 1.0; c
.blue
= 1.0;
297 vdxCheckColor(renderer
, &c
);
300 /** Destructor for renderer
301 * @param self a renderer
305 end_render(DiaRenderer
*self
)
307 VDXRenderer
*renderer
= VDX_RENDERER(self
);
309 /* Specific to VDX */
310 g_array_free(renderer
->Colors
, TRUE
);
311 g_array_free(renderer
->Fonts
, TRUE
);
314 /** Convert a Dia point to a Visio one
315 * @param p a Dia-space point
316 * @returns a Visio-space point
323 q
.x
= p
.x
/vdx_Point_Scale
;
324 q
.y
= (p
.y
- vdx_Y_Offset
)/vdx_Y_Flip
/vdx_Point_Scale
;
328 /** Convert a Dia absolute length to a Visio one
329 * @param length a length
330 * @returns length in Visio space
334 visio_length(double length
)
336 return length
/vdx_Point_Scale
;
340 * @param self a renderer
341 * @param linewidth new line width
345 set_linewidth(DiaRenderer
*self
, real linewidth
)
347 VDXRenderer
*renderer
= VDX_RENDERER(self
);
349 renderer
->linewidth
= linewidth
;
353 * @param self a renderer
354 * @param mode new line caps
358 set_linecaps(DiaRenderer
*self
, LineCaps mode
)
360 VDXRenderer
*renderer
= VDX_RENDERER(self
);
362 renderer
->capsmode
= mode
;
366 * @param self a renderer
367 * @param mode new line join
371 set_linejoin(DiaRenderer
*self
, LineJoin mode
)
373 VDXRenderer
*renderer
= VDX_RENDERER(self
);
375 renderer
->joinmode
= mode
;
379 * @param self a renderer
380 * @param mode new line style
384 set_linestyle(DiaRenderer
*self
, LineStyle mode
)
386 VDXRenderer
*renderer
= VDX_RENDERER(self
);
388 renderer
->stylemode
= mode
;
392 * @param self a renderer
393 * @param mode new dash length
397 set_dashlength(DiaRenderer
*self
, real length
)
399 VDXRenderer
*renderer
= VDX_RENDERER(self
);
401 renderer
->dashlength
= length
;
405 * @param self a renderer
406 * @param mode new file style
410 set_fillstyle(DiaRenderer
*self
, FillStyle mode
)
412 VDXRenderer
*renderer
= VDX_RENDERER(self
);
414 renderer
->fillmode
= mode
;
418 * @param self a renderer
419 * @param font new font
420 * @param height new font height
424 set_font(DiaRenderer
*self
, DiaFont
*font
, real height
)
426 VDXRenderer
*renderer
= VDX_RENDERER(self
);
428 renderer
->font
= font
;
429 renderer
->fontheight
= height
;
432 /** Get colour number from colour table
433 * @param renderer a renderer
434 * @param color the colour
435 * @returns a colour index (black=0)
439 vdxCheckColor(VDXRenderer
*renderer
, Color
*color
)
444 for (i
= 0; i
< renderer
->Colors
->len
; i
++)
446 cmp_color
= g_array_index(renderer
->Colors
, Color
, i
);
447 if (color_equals(color
, &cmp_color
)) return i
;
450 g_array_append_val(renderer
->Colors
, *color
);
451 return renderer
->Colors
->len
;
454 /** Get font number from font table
455 * @param renderer a renderer
456 * @returns a font index (from 0)
460 vdxCheckFont(VDXRenderer
*renderer
)
464 const char *cmp_font
;
465 const char *font
= dia_font_get_legacy_name(renderer
->font
);
466 for (i
= 0; i
< renderer
->Fonts
->len
; i
++)
468 cmp_font
= g_array_index(renderer
->Fonts
, char *, i
);
469 if (!strcmp(cmp_font
, font
)) return i
;
472 g_array_append_val(renderer
->Fonts
, font
);
473 return renderer
->Fonts
->len
;
476 /** Create a Visio line style object
477 * @param self a VDXRenderer
478 * @param color a colour
479 * @param Line a Line object
480 * @param start_arrow optional start arrow
481 * @param end_arrow optional end arrow
482 * @todo join, caps, dashlength
486 create_Line(VDXRenderer
*renderer
, Color
*color
, struct vdx_Line
*Line
,
487 Arrow
*start_arrow
, Arrow
*end_arrow
)
489 /* A Line (colour etc) */
490 memset(Line
, 0, sizeof(*Line
));
491 Line
->type
= vdx_types_Line
;
492 switch (renderer
->stylemode
)
494 case LINESTYLE_DASHED
:
495 Line
->LinePattern
= 2;
497 case LINESTYLE_DOTTED
:
498 Line
->LinePattern
= 3;
500 case LINESTYLE_DASH_DOT
:
501 Line
->LinePattern
= 4;
503 case LINESTYLE_DASH_DOT_DOT
:
504 Line
->LinePattern
= 5;
507 case LINESTYLE_SOLID
:
508 Line
->LinePattern
= 1;
511 Line
->LineColor
= *color
;
512 Line
->LineWeight
= renderer
->linewidth
/ vdx_Line_Scale
;
513 if (start_arrow
|| end_arrow
)
515 g_debug("create_Line (ARROWS)");
520 /** Create a Visio fill style object
521 * @param self a VDXRenderer
522 * @param color a colour
527 create_Fill(VDXRenderer
*renderer
, Color
*color
, struct vdx_Fill
*Fill
)
529 /* A Fill (colour etc) */
530 memset(Fill
, 0, sizeof(*Fill
));
531 Fill
->type
= vdx_types_Fill
;
532 Fill
->FillForegnd
= *color
;
533 Fill
->FillPattern
= 1; /* Solid fill */
537 /** Render a Dia line
538 * @param self a renderer
539 * @param start start of line
540 * @param end end of line
541 * @param color line colour
545 draw_line(DiaRenderer
*self
, Point
*start
, Point
*end
, Color
*color
)
547 VDXRenderer
*renderer
= VDX_RENDERER(self
);
549 struct vdx_Shape Shape
;
550 struct vdx_XForm XForm
;
551 struct vdx_XForm1D XForm1D
;
552 struct vdx_Geom Geom
;
553 struct vdx_MoveTo MoveTo
;
554 struct vdx_LineTo LineTo
;
555 struct vdx_Line Line
;
556 char NameU
[VDX_NAMEU_LEN
];
558 /* First time through, just construct the colour table */
559 if (renderer
->first_pass
)
561 vdxCheckColor(renderer
, color
);
565 g_debug("draw_line((%f,%f), (%f,%f))", start
->x
, start
->y
, end
->x
, end
->y
);
567 /* Setup the standard shape object */
568 memset(&Shape
, 0, sizeof(Shape
));
569 Shape
.type
= vdx_types_Shape
;
570 Shape
.ID
= renderer
->shapeid
++;
571 Shape
.Type
= "Shape";
572 sprintf(NameU
, "Line.%d", Shape
.ID
);
574 Shape
.LineStyle_exists
= 1;
575 Shape
.FillStyle_exists
= 1;
576 Shape
.TextStyle_exists
= 1;
579 memset(&XForm
, 0, sizeof(XForm
));
580 XForm
.type
= vdx_types_XForm
;
581 a
= visio_point(*start
);
582 b
= visio_point(*end
);
583 XForm
.PinX
= a
.x
; /* Start */
585 XForm
.Width
= fabs(b
.x
- a
.x
); /* Must be non-negative */
586 XForm
.Height
= fabs(b
.y
- a
.y
); /* Must be non-negative */
591 /* Lines must have an XForm1D as well */
592 memset(&XForm1D
, 0, sizeof(XForm1D
));
593 XForm1D
.type
= vdx_types_XForm1D
;
594 XForm1D
.BeginX
= a
.x
;
595 XForm1D
.BeginY
= a
.y
;
599 /* Standard Geom object */
600 memset(&Geom
, 0, sizeof(Geom
));
602 Geom
.type
= vdx_types_Geom
;
604 /* Two children - MoveTo(start) and LineTo(end) */
605 memset(&MoveTo
, 0, sizeof(MoveTo
));
606 MoveTo
.type
= vdx_types_MoveTo
;
611 memset(&LineTo
, 0, sizeof(LineTo
));
612 LineTo
.type
= vdx_types_LineTo
;
617 /* A Line (colour etc) */
618 create_Line(renderer
, color
, &Line
, 0, 0);
621 Geom
.children
= g_slist_append(Geom
.children
, &MoveTo
);
622 Geom
.children
= g_slist_append(Geom
.children
, &LineTo
);
624 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
625 Shape
.children
= g_slist_append(Shape
.children
, &XForm1D
);
626 Shape
.children
= g_slist_append(Shape
.children
, &Line
);
627 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
630 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
632 /* Free up list entries */
633 g_slist_free(Geom
.children
);
634 g_slist_free(Shape
.children
);
638 /** Render a Dia polyline
639 * @param self a renderer
640 * @param points the points
641 * @param num_points how many points
642 * @param color line colour
645 static void draw_polyline(DiaRenderer
*self
, Point
*points
, int num_points
,
648 VDXRenderer
*renderer
= VDX_RENDERER(self
);
650 struct vdx_Shape Shape
;
651 struct vdx_XForm XForm
;
652 struct vdx_Geom Geom
;
653 struct vdx_MoveTo MoveTo
;
654 struct vdx_LineTo
* LineTo
;
655 struct vdx_Line Line
;
656 char NameU
[VDX_NAMEU_LEN
];
658 double minX
, minY
, maxX
, maxY
;
660 /* First time through, just construct the colour table */
661 if (renderer
->first_pass
)
663 vdxCheckColor(renderer
, color
);
667 g_debug("draw_polyline(%d)", num_points
);
669 /* Setup the standard shape object */
670 memset(&Shape
, 0, sizeof(Shape
));
671 Shape
.type
= vdx_types_Shape
;
672 Shape
.ID
= renderer
->shapeid
++;
673 Shape
.Type
= "Shape";
674 sprintf(NameU
, "PolyLine.%d", Shape
.ID
);
676 Shape
.LineStyle_exists
= 1;
677 Shape
.FillStyle_exists
= 1;
678 Shape
.TextStyle_exists
= 1;
681 memset(&XForm
, 0, sizeof(XForm
));
682 XForm
.type
= vdx_types_XForm
;
683 a
= visio_point(points
[0]);
685 /* Find width and height */
686 minX
= points
[0].x
; minY
= points
[0].y
;
687 maxX
= points
[0].x
; maxY
= points
[0].y
;
688 for (i
=1; i
<num_points
; i
++)
690 if (points
[i
].x
< minX
) minX
= points
[i
].x
;
691 if (points
[i
].x
> maxX
) maxX
= points
[i
].x
;
692 if (points
[i
].y
< minY
) minY
= points
[i
].y
;
693 if (points
[i
].y
> maxY
) maxY
= points
[i
].y
;
695 XForm
.Width
= visio_length(maxX
- minX
);
696 XForm
.Height
= visio_length(maxY
- minY
);
698 XForm
.PinX
= a
.x
; /* Start */
704 /* Standard Geom object */
705 memset(&Geom
, 0, sizeof(Geom
));
707 Geom
.type
= vdx_types_Geom
;
709 /* Multiple children - MoveTo(start) and LineTo(others) */
710 memset(&MoveTo
, 0, sizeof(MoveTo
));
711 MoveTo
.type
= vdx_types_MoveTo
;
716 LineTo
= g_new0(struct vdx_LineTo
, num_points
-1);
717 for (i
=0; i
<num_points
-1; i
++)
719 LineTo
[i
].type
= vdx_types_LineTo
;
721 b
= visio_point(points
[i
+1]);
722 LineTo
[i
].X
= b
.x
-a
.x
;
723 LineTo
[i
].Y
= b
.y
-a
.y
;
726 /* A Line (colour etc) */
727 create_Line(renderer
, color
, &Line
, 0, 0);
730 Geom
.children
= g_slist_append(Geom
.children
, &MoveTo
);
731 for (i
=0; i
<num_points
-1; i
++)
733 Geom
.children
= g_slist_append(Geom
.children
, &LineTo
[i
]);
736 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
737 Shape
.children
= g_slist_append(Shape
.children
, &Line
);
738 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
741 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
743 /* Free up list entries */
744 g_slist_free(Geom
.children
);
745 g_slist_free(Shape
.children
);
749 /** Render a Dia polygon
750 * @param self a renderer
751 * @param points corners of polygon
752 * @param num_points number of points
753 * @param color line colour
756 static void draw_polygon(DiaRenderer
*self
,
757 Point
*points
, int num_points
,
760 Point
*more_points
= g_new0(Point
, num_points
+1);
761 memcpy(more_points
, points
, num_points
*sizeof(Point
));
762 more_points
[num_points
] = more_points
[0];
763 g_debug("draw_polygon -> draw_polyline");
764 draw_polyline(self
, more_points
, num_points
+1, color
);
768 /** Render a Dia filled polygon
769 * @param self a renderer
770 * @param points corners of polygon
771 * @param num_points number of points
772 * @param color line colour
775 static void fill_polygon(DiaRenderer
*self
,
776 Point
*points
, int num_points
,
779 VDXRenderer
*renderer
= VDX_RENDERER(self
);
781 struct vdx_Shape Shape
;
782 struct vdx_XForm XForm
;
783 struct vdx_Geom Geom
;
784 struct vdx_MoveTo MoveTo
;
785 struct vdx_LineTo
* LineTo
;
786 struct vdx_Fill Fill
;
787 char NameU
[VDX_NAMEU_LEN
];
789 double minX
, minY
, maxX
, maxY
;
791 /* First time through, just construct the colour table */
792 if (renderer
->first_pass
)
794 vdxCheckColor(renderer
, color
);
798 g_debug("fill_polygon(%d)", num_points
);
800 /* Setup the standard shape object */
801 memset(&Shape
, 0, sizeof(Shape
));
802 Shape
.type
= vdx_types_Shape
;
803 Shape
.ID
= renderer
->shapeid
++;
804 Shape
.Type
= "Shape";
805 sprintf(NameU
, "FillPolygon.%d", Shape
.ID
);
807 Shape
.LineStyle_exists
= 1;
808 Shape
.FillStyle_exists
= 1;
809 Shape
.TextStyle_exists
= 1;
812 memset(&XForm
, 0, sizeof(XForm
));
813 XForm
.type
= vdx_types_XForm
;
814 a
= visio_point(points
[0]);
816 /* Find width and height */
817 minX
= points
[0].x
; minY
= points
[0].y
;
818 maxX
= points
[0].x
; maxY
= points
[0].y
;
819 for (i
=1; i
<num_points
; i
++)
821 if (points
[i
].x
< minX
) minX
= points
[i
].x
;
822 if (points
[i
].x
> maxX
) maxX
= points
[i
].x
;
823 if (points
[i
].y
< minY
) minY
= points
[i
].y
;
824 if (points
[i
].y
> maxY
) maxY
= points
[i
].y
;
826 XForm
.Width
= visio_length(maxX
- minX
);
827 XForm
.Height
= visio_length(maxY
- minY
);
829 XForm
.PinX
= a
.x
; /* Start */
835 /* Standard Geom object */
836 memset(&Geom
, 0, sizeof(Geom
));
837 Geom
.type
= vdx_types_Geom
;
839 /* Multiple children - MoveTo(start) and LineTo(others) */
840 memset(&MoveTo
, 0, sizeof(MoveTo
));
841 MoveTo
.type
= vdx_types_MoveTo
;
846 LineTo
= g_new0(struct vdx_LineTo
, num_points
);
847 for (i
=0; i
<num_points
; i
++)
849 LineTo
[i
].type
= vdx_types_LineTo
;
851 /* Last point = first */
852 if (i
== num_points
-1) b
= a
;
853 else b
= visio_point(points
[i
+1]);
854 LineTo
[i
].X
= b
.x
-a
.x
;
855 LineTo
[i
].Y
= b
.y
-a
.y
;
858 /* A Line (colour etc) */
859 create_Fill(renderer
, color
, &Fill
);
862 Geom
.children
= g_slist_append(Geom
.children
, &MoveTo
);
863 for (i
=0; i
<num_points
; i
++)
865 Geom
.children
= g_slist_append(Geom
.children
, &LineTo
[i
]);
868 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
869 Shape
.children
= g_slist_append(Shape
.children
, &Fill
);
870 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
873 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
875 /* Free up list entries */
876 g_slist_free(Geom
.children
);
877 g_slist_free(Shape
.children
);
881 /** Render a Dia rectangle
882 * @param self a renderer
883 * @param ul_corner Upper-left corner
884 * @param lr_corner Loower-right corner
885 * @param color line colour
888 static void draw_rect(DiaRenderer
*self
,
889 Point
*ul_corner
, Point
*lr_corner
,
892 Point points
[5]; /* 5 so we close path */
894 g_debug("draw_rect((%f,%f), (%f,%f)) -> draw_polyline",
895 ul_corner
->x
, ul_corner
->y
, lr_corner
->x
, lr_corner
->y
);
896 points
[0].x
= ul_corner
->x
; points
[0].y
= lr_corner
->y
;
897 points
[1] = *lr_corner
;
898 points
[2].x
= lr_corner
->x
; points
[2].y
= ul_corner
->y
;
899 points
[3] = *ul_corner
;
900 points
[4] = points
[0];
902 draw_polygon(self
, points
, 5, color
);
905 /** Render a Dia filled rectangle
906 * @param self a renderer
907 * @param ul_corner Upper-left corner
908 * @param lr_corner Lower-right corner
909 * @param color line colour
912 static void fill_rect(DiaRenderer
*self
,
913 Point
*ul_corner
, Point
*lr_corner
,
916 Point points
[5]; /* 5 so we close path */
918 g_debug("fill_rect -> fill_polygon");
919 points
[0].x
= ul_corner
->x
; points
[0].y
= lr_corner
->y
;
920 points
[1] = *lr_corner
;
921 points
[2].x
= lr_corner
->x
; points
[2].y
= ul_corner
->y
;
922 points
[3] = *ul_corner
;
923 points
[4] = points
[0];
925 fill_polygon(self
, points
, 5, color
);
929 * @param self a renderer
930 * @param center centre of arc
931 * @param width width of ellipse
932 * @param height height of ellipse (= width for Dia circular arcs)
933 * @param angle1 start angle to x axis in degrees
934 * @param angle2 end angle to x axis in degrees
935 * @param color line colour
939 static void draw_arc(DiaRenderer
*self
,
941 real width
, real height
,
942 real angle1
, real angle2
,
945 VDXRenderer
*renderer
= VDX_RENDERER(self
);
947 struct vdx_Shape Shape
;
948 struct vdx_XForm XForm
;
949 struct vdx_Geom Geom
;
950 struct vdx_EllipticalArcTo EllipticalArcTo
;
951 struct vdx_MoveTo MoveTo
;
952 struct vdx_Line Line
;
953 char NameU
[VDX_NAMEU_LEN
];
954 Point start
, control
, end
;
957 /* First time through, just construct the colour table */
958 if (renderer
->first_pass
)
960 vdxCheckColor(renderer
, color
);
964 g_debug("draw_arc((%f,%f),%f,%f;%f,%f)", center
->x
, center
->y
,
965 width
, height
, angle1
, angle2
);
967 /* Setup the standard shape object */
968 memset(&Shape
, 0, sizeof(Shape
));
969 Shape
.type
= vdx_types_Shape
;
970 Shape
.ID
= renderer
->shapeid
++;
971 Shape
.Type
= "Shape";
972 sprintf(NameU
, "Arc.%d", Shape
.ID
);
974 Shape
.LineStyle_exists
= 1;
975 Shape
.FillStyle_exists
= 1;
976 Shape
.TextStyle_exists
= 1;
979 memset(&XForm
, 0, sizeof(XForm
));
980 XForm
.type
= vdx_types_XForm
;
982 /* Find the start of the arc */
984 start
.x
+= (width
/2.0)*cos(angle1
*DEG_TO_RAD
);
985 start
.y
-= (height
/2.0)*sin(angle1
*DEG_TO_RAD
);
986 g_debug("start(%f,%f)", start
.x
, start
.y
);
987 start
= visio_point(start
);
989 /* Find a control point at the midpoint of the arc */
991 control_angle
= (angle1
+ angle2
)/2.0;
994 /* Arc goes antclockwise - allow for this */
995 control_angle
-= 180;
997 control
.x
+= (width
/2.0)*cos(control_angle
*DEG_TO_RAD
);
998 control
.y
-= (height
/2.0)*sin(control_angle
*DEG_TO_RAD
);
999 g_debug("control(%f,%f @ %f)", control
.x
, control
.y
, control_angle
);
1000 control
= visio_point(control
);
1002 /* And the endpoint */
1004 end
.x
+= (width
/2.0)*cos(angle2
*DEG_TO_RAD
);
1005 end
.y
-= (height
/2.0)*sin(angle2
*DEG_TO_RAD
);
1006 g_debug("end(%f,%f)", end
.x
, end
.y
);
1007 end
= visio_point(end
);
1010 XForm
.PinX
= a
.x
; /* Start */
1012 XForm
.Width
= visio_length(width
);
1013 XForm
.Height
= visio_length(height
);
1018 /* Standard Geom object */
1019 memset(&Geom
, 0, sizeof(Geom
));
1021 Geom
.type
= vdx_types_Geom
;
1023 memset(&MoveTo
, 0, sizeof(MoveTo
));
1024 MoveTo
.type
= vdx_types_MoveTo
;
1029 /* Second child - EllipticalArcTo */
1030 memset(&EllipticalArcTo
, 0, sizeof(EllipticalArcTo
));
1031 EllipticalArcTo
.type
= vdx_types_EllipticalArcTo
;
1032 EllipticalArcTo
.IX
= 2;
1034 /* X and Y are the end point
1035 A and B are a control point on the arc
1036 C is the angle of the major axis
1037 D is the ratio of the major to minor axes */
1039 /* Need to fix these */
1040 EllipticalArcTo
.X
= end
.x
- a
.x
;
1041 EllipticalArcTo
.Y
= end
.y
- a
.y
;
1042 EllipticalArcTo
.A
= control
.x
- a
.x
;
1043 EllipticalArcTo
.B
= control
.y
- a
.y
;
1044 EllipticalArcTo
.C
= 0.0; /* Dia major axis always x axis */
1045 if (fabs(height
) > EPSILON
)
1046 EllipticalArcTo
.D
= width
/height
; /* Always 1 for Dia */
1048 EllipticalArcTo
.D
= 1/EPSILON
;
1050 /* A Line (colour etc) */
1051 create_Line(renderer
, color
, &Line
, 0, 0);
1053 /* Setup children */
1054 Geom
.children
= g_slist_append(Geom
.children
, &MoveTo
);
1055 Geom
.children
= g_slist_append(Geom
.children
, &EllipticalArcTo
);
1057 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
1058 Shape
.children
= g_slist_append(Shape
.children
, &Line
);
1059 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
1062 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
1064 /* Free up list entries */
1065 g_slist_free(Geom
.children
);
1066 g_slist_free(Shape
.children
);
1069 /** Render a Dia filled arc
1070 * @param self a renderer
1071 * @param center centre of arc
1072 * @param width width of bounding box
1073 * @param height height of bounding box
1074 * @param angle1 start angle
1075 * @param angle2 end angle
1076 * @param color line colour
1077 * @todo Not done yet - believe unused
1080 static void fill_arc(DiaRenderer
*self
,
1082 real width
, real height
,
1083 real angle1
, real angle2
,
1086 VDXRenderer
*renderer
= VDX_RENDERER(self
);
1088 if (renderer
->first_pass
)
1090 vdxCheckColor(renderer
, color
);
1093 g_debug("fill_arc (TODO)");
1096 /** Render a Dia ellipse (parallel to axes)
1097 * @param self a renderer
1098 * @param center centre of ellipse
1099 * @param width width of bounding box
1100 * @param height height of bounding box
1101 * @param color line colour
1104 static void draw_ellipse(DiaRenderer
*self
,
1106 real width
, real height
,
1109 VDXRenderer
*renderer
= VDX_RENDERER(self
);
1111 struct vdx_Shape Shape
;
1112 struct vdx_XForm XForm
;
1113 struct vdx_Geom Geom
;
1114 struct vdx_Ellipse Ellipse
;
1115 struct vdx_Line Line
;
1116 char NameU
[VDX_NAMEU_LEN
];
1118 /* First time through, just construct the colour table */
1119 if (renderer
->first_pass
)
1121 vdxCheckColor(renderer
, color
);
1125 g_debug("draw_ellipse");
1127 /* Setup the standard shape object */
1128 memset(&Shape
, 0, sizeof(Shape
));
1129 Shape
.type
= vdx_types_Shape
;
1130 Shape
.ID
= renderer
->shapeid
++;
1131 Shape
.Type
= "Shape";
1132 sprintf(NameU
, "Ellipse.%d", Shape
.ID
);
1133 Shape
.NameU
= NameU
;
1134 Shape
.LineStyle_exists
= 1;
1135 Shape
.FillStyle_exists
= 1;
1136 Shape
.TextStyle_exists
= 1;
1139 memset(&XForm
, 0, sizeof(XForm
));
1140 XForm
.type
= vdx_types_XForm
;
1141 a
= visio_point(*center
);
1142 XForm
.PinX
= a
.x
; /* Start */
1144 XForm
.Width
= visio_length(width
);
1145 XForm
.Height
= visio_length(height
);
1146 XForm
.LocPinX
= XForm
.Width
/2.0;
1147 XForm
.LocPinY
= XForm
.Height
/2.0;
1150 /* Standard Geom object */
1151 memset(&Geom
, 0, sizeof(Geom
));
1153 Geom
.type
= vdx_types_Geom
;
1155 /* One child - Ellipse */
1156 memset(&Ellipse
, 0, sizeof(Ellipse
));
1157 Ellipse
.type
= vdx_types_Ellipse
;
1159 Ellipse
.X
= XForm
.Width
/2.0;
1160 Ellipse
.Y
= XForm
.Height
/2.0;
1161 Ellipse
.A
= XForm
.Width
;
1162 Ellipse
.B
= XForm
.Height
/2.0;
1163 Ellipse
.C
= XForm
.Width
/2.0;
1164 Ellipse
.D
= XForm
.Height
;
1166 /* A Line (colour etc) */
1167 create_Line(renderer
, color
, &Line
, 0, 0);
1169 /* Setup children */
1170 Geom
.children
= g_slist_append(Geom
.children
, &Ellipse
);
1172 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
1173 Shape
.children
= g_slist_append(Shape
.children
, &Line
);
1174 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
1177 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
1179 /* Free up list entries */
1180 g_slist_free(Geom
.children
);
1181 g_slist_free(Shape
.children
);
1184 /** Render a Dia filled ellipse (parallel to axes)
1185 * @param self a renderer
1186 * @param center centre of ellipse
1187 * @param width width of bounding box
1188 * @param height height of bounding box
1189 * @param color line colour
1192 static void fill_ellipse(DiaRenderer
*self
,
1194 real width
, real height
,
1197 VDXRenderer
*renderer
= VDX_RENDERER(self
);
1199 struct vdx_Shape Shape
;
1200 struct vdx_XForm XForm
;
1201 struct vdx_Geom Geom
;
1202 struct vdx_Ellipse Ellipse
;
1203 struct vdx_Fill Fill
;
1204 char NameU
[VDX_NAMEU_LEN
];
1206 /* First time through, just construct the colour table */
1207 if (renderer
->first_pass
)
1209 vdxCheckColor(renderer
, color
);
1213 g_debug("fill_ellipse");
1215 /* Setup the standard shape object */
1216 memset(&Shape
, 0, sizeof(Shape
));
1217 Shape
.type
= vdx_types_Shape
;
1218 Shape
.ID
= renderer
->shapeid
++;
1219 Shape
.Type
= "Shape";
1220 sprintf(NameU
, "FillEllipse.%d", Shape
.ID
);
1221 Shape
.NameU
= NameU
;
1222 Shape
.LineStyle_exists
= 1;
1223 Shape
.FillStyle_exists
= 1;
1224 Shape
.TextStyle_exists
= 1;
1227 memset(&XForm
, 0, sizeof(XForm
));
1228 XForm
.type
= vdx_types_XForm
;
1229 a
= visio_point(*center
);
1230 XForm
.PinX
= a
.x
; /* Start */
1232 XForm
.Width
= visio_length(width
);
1233 XForm
.Height
= visio_length(height
);
1234 XForm
.LocPinX
= XForm
.Width
/2.0;
1235 XForm
.LocPinY
= XForm
.Height
/2.0;
1238 /* Standard Geom object */
1239 memset(&Geom
, 0, sizeof(Geom
));
1240 Geom
.type
= vdx_types_Geom
;
1242 /* One child - Ellipse */
1243 memset(&Ellipse
, 0, sizeof(Ellipse
));
1244 Ellipse
.type
= vdx_types_Ellipse
;
1246 Ellipse
.X
= XForm
.Width
/2.0;
1247 Ellipse
.Y
= XForm
.Height
/2.0;
1248 Ellipse
.A
= XForm
.Width
;
1249 Ellipse
.B
= XForm
.Height
/2.0;
1250 Ellipse
.C
= XForm
.Width
/2.0;
1251 Ellipse
.D
= XForm
.Height
;
1253 /* A Fill (colour etc) */
1254 create_Fill(renderer
, color
, &Fill
);
1256 /* Setup children */
1257 Geom
.children
= g_slist_append(Geom
.children
, &Ellipse
);
1259 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
1260 Shape
.children
= g_slist_append(Shape
.children
, &Fill
);
1261 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
1264 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
1266 /* Free up list entries */
1267 g_slist_free(Geom
.children
);
1268 g_slist_free(Shape
.children
);
1271 /** Render a Dia string
1272 * @param self a renderer
1273 * @param text the string
1274 * @param pos start (or centre etc.)
1275 * @param alignment alignment
1276 * @param color line colour
1277 * @todo Alignment, colour
1278 * @bug Bounding box incorrect
1281 static void draw_string(DiaRenderer
*self
,
1283 Point
*pos
, Alignment alignment
,
1286 VDXRenderer
*renderer
= VDX_RENDERER(self
);
1288 struct vdx_Shape Shape
;
1289 struct vdx_XForm XForm
;
1290 struct vdx_Char Char
;
1291 struct vdx_Text Text
;
1292 struct vdx_text my_text
;
1293 char NameU
[VDX_NAMEU_LEN
];
1295 if (renderer
->first_pass
)
1297 /* Add to colour and font tables */
1298 vdxCheckColor(renderer
, color
);
1299 vdxCheckFont(renderer
);
1303 g_debug("draw_string");
1304 /* Standard shape */
1305 memset(&Shape
, 0, sizeof(Shape
));
1306 Shape
.type
= vdx_types_Shape
;
1307 Shape
.ID
= renderer
->shapeid
++;
1308 Shape
.Type
= "Shape";
1309 sprintf(NameU
, "Text.%d", Shape
.ID
);
1310 Shape
.NameU
= NameU
;
1311 Shape
.LineStyle_exists
= 1;
1312 Shape
.FillStyle_exists
= 1;
1313 Shape
.TextStyle_exists
= 1;
1315 /* XForm describes bounding box */
1316 memset(&XForm
, 0, sizeof(XForm
));
1317 XForm
.type
= vdx_types_XForm
;
1318 a
= visio_point(*pos
);
1322 /* Hack to give it an approximate bounding box */
1323 XForm
.Height
= renderer
->fontheight
/vdx_Font_Size_Conversion
;
1324 XForm
.Width
= strlen(text
)*renderer
->fontheight
/vdx_Font_Size_Conversion
;
1326 /* Character properties */
1327 memset(&Char
, 0, sizeof(Char
));
1328 Char
.type
= vdx_types_Char
;
1329 Char
.Font
= vdxCheckFont(renderer
);
1330 Char
.Color
= *color
;
1332 Char
.Size
= renderer
->fontheight
/vdx_Font_Size_Conversion
;
1334 /* Text object - no attributes */
1335 memset(&Text
, 0, sizeof(Text
));
1336 Text
.type
= vdx_types_Text
;
1338 /* text object (XML pseudo-tag) - no attributes */
1339 memset(&my_text
, 0, sizeof(my_text
));
1340 my_text
.type
= vdx_types_text
;
1341 my_text
.text
= (char *)text
;
1343 /* Construct the children */
1344 Text
.children
= g_slist_append(Text
.children
, &my_text
);
1346 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
1347 Shape
.children
= g_slist_append(Shape
.children
, &Char
);
1348 Shape
.children
= g_slist_append(Shape
.children
, &Text
);
1350 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
1352 g_slist_free(Text
.children
);
1353 g_slist_free(Shape
.children
);
1356 /** Reads binary file and converts to Base64 data
1357 * @param filename file to read
1358 * @returns Base64 encoded data (or NULL if problem)
1359 * @note glibc 2.12 offers g_base64_encode()
1363 read_base64_file(const char *filename
)
1370 unsigned int buf_len
= 0;
1371 unsigned char buf
[3];
1372 struct stat stat_buf
;
1374 if (g_stat(filename
, &stat_buf
))
1376 message_error(_("Couldn't read file %s"), filename
);
1379 b64
= g_new0(char, stat_buf
.st_size
*4/3+5);
1382 f
= g_fopen(filename
, "r+b");
1385 message_error(_("Couldn't read file %s"), filename
);
1389 /* Construct Base64 mapping table */
1390 for(c
=0; c
<26; c
++) map
[c
] = 'A' + c
;
1391 for(c
=0; c
<26; c
++) map
[c
+26] = 'a' + c
;
1392 for(c
=0; c
<10; c
++) map
[c
+52] = '0' + c
;
1396 while((c
= fgetc(f
)) != EOF
)
1398 buf
[buf_len
++] = (unsigned char)c
;
1401 *s
++ = map
[buf
[0] >> 2];
1402 *s
++ = map
[((buf
[0] & 3) << 4) + (buf
[1] >> 4)];
1403 *s
++ = map
[((buf
[1] & 15) << 2) + (buf
[2] >> 6)];
1404 *s
++ = map
[buf
[2] & 63];
1411 *s
++ = map
[buf
[0] >> 2];
1412 *s
++ = map
[((buf
[0] & 3) << 4)];
1418 *s
++ = map
[buf
[0] >> 2];
1419 *s
++ = map
[((buf
[0] & 3) << 4) + (buf
[1] >> 4)];
1420 *s
++ = map
[((buf
[1] & 15) << 2)];
1428 /* Deal with any chunks left over */
1431 fputc(buf
[0] << 2 | buf
[1] >> 4, f
);
1434 fputc(buf
[1] << 4 | buf
[2] >> 2, f
);
1437 /* This one can't happen */
1438 fputc(buf
[2] << 6 | buf
[3], f
);
1446 /** Render a Dia bitmap
1447 * @param self a renderer
1448 * @param point top left
1449 * @param width width
1450 * @param height height
1453 static void draw_image(DiaRenderer
*self
,
1455 real width
, real height
,
1458 VDXRenderer
*renderer
= VDX_RENDERER(self
);
1459 Point a
, bottom_left
;
1460 struct vdx_Shape Shape
;
1461 struct vdx_XForm XForm
;
1462 struct vdx_Geom Geom
;
1463 struct vdx_Foreign Foreign
;
1464 struct vdx_ForeignData ForeignData
;
1465 struct vdx_text text
;
1466 char NameU
[VDX_NAMEU_LEN
];
1467 const char *filename
= NULL
;
1468 const char *suffix
= NULL
;
1470 if (renderer
->first_pass
)
1475 g_debug("draw_image((%f,%f), %f, %f, %s", point
->x
, point
->y
,
1476 width
, height
, dia_image_filename(image
));
1477 /* Setup the standard shape object */
1478 memset(&Shape
, 0, sizeof(Shape
));
1479 Shape
.type
= vdx_types_Shape
;
1480 Shape
.ID
= renderer
->shapeid
++;
1481 Shape
.Type
= "Foreign";
1482 sprintf(NameU
, "Foreign.%d", Shape
.ID
);
1483 Shape
.NameU
= NameU
;
1484 Shape
.LineStyle_exists
= 1;
1485 Shape
.FillStyle_exists
= 1;
1486 Shape
.TextStyle_exists
= 1;
1489 memset(&XForm
, 0, sizeof(XForm
));
1490 XForm
.type
= vdx_types_XForm
;
1491 bottom_left
.x
= point
->x
;
1492 bottom_left
.y
= point
->y
+ height
;
1493 a
= visio_point(bottom_left
);
1494 XForm
.PinX
= a
.x
; /* Start */
1496 XForm
.Width
= visio_length(width
);
1497 XForm
.Height
= visio_length(height
);
1502 /* Standard Geom object */
1503 memset(&Geom
, 0, sizeof(Geom
));
1504 Geom
.type
= vdx_types_Geom
;
1505 /* We don't use it, but our decoder needs it */
1508 memset(&Foreign
, 0, sizeof(Foreign
));
1509 Foreign
.type
= vdx_types_Foreign
;
1510 Foreign
.ImgOffsetX
= 0;
1511 Foreign
.ImgOffsetY
= 0;
1512 Foreign
.ImgHeight
= visio_length(height
);
1513 Foreign
.ImgWidth
= visio_length(width
);
1515 /* And a ForeignData */
1516 memset(&ForeignData
, 0, sizeof(ForeignData
));
1517 ForeignData
.type
= vdx_types_ForeignData
;
1518 ForeignData
.ForeignType
= "Bitmap";
1519 ForeignData
.CompressionType
= "JPEG";
1520 ForeignData
.CompressionLevel
= 1.0;
1521 ForeignData
.ObjectHeight
= visio_length(height
);
1522 ForeignData
.ObjectWidth
= visio_length(width
);
1524 filename
= dia_image_filename(image
);
1525 if ((suffix
= strrchr(filename
, '.')))
1528 if (!g_ascii_strncasecmp(suffix
, "png", 3)) { ForeignData
.CompressionType
= "PNG"; }
1529 if (!g_ascii_strncasecmp(suffix
, "gif", 3)) { ForeignData
.CompressionType
= "GIF"; }
1530 if (!g_ascii_strncasecmp(suffix
, "jpg", 3) || !g_ascii_strncasecmp(suffix
, "jpeg", 4))
1531 { ForeignData
.CompressionType
= "JPEG"; }
1532 if (!g_ascii_strncasecmp(suffix
, "tif", 3) || !g_ascii_strncasecmp(suffix
, "tiff", 4))
1533 { ForeignData
.CompressionType
= "TIFF"; }
1536 /* And the data itself */
1537 memset(&text
, 0, sizeof(text
));
1538 text
.type
= vdx_types_text
;
1539 text
.text
= read_base64_file(filename
);
1540 if (!text
.text
) return; /* Problem reading file */
1542 /* Setup children */
1543 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
1544 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
1545 Shape
.children
= g_slist_append(Shape
.children
, &Foreign
);
1546 Shape
.children
= g_slist_append(Shape
.children
, &ForeignData
);
1547 ForeignData
.children
= g_slist_append(ForeignData
.children
, &text
);
1550 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
1552 /* Free up list entries */
1553 g_slist_free(ForeignData
.children
);
1554 g_slist_free(Shape
.children
);
1556 /* And the Base64 data */
1560 /** Convert Dia colour to hex string
1562 * @returns string in form #000000
1563 * @note static buffer overwritten with next call; not thread-safe
1567 vdx_string_color(Color c
)
1570 sprintf(buf
, "#%.2X%.2X%.2X",
1571 (int)(c
.red
*255), (int)(c
.green
*255), (int)(c
.blue
*255));
1575 /** Return string XML-encoded
1577 * @returns encoded string
1578 * @note uses static buffer so can be used as inline filter in printf
1582 vdx_convert_xml_string(const char *s
)
1584 static char *out
= 0;
1587 /* If (as almost always) no change required, return intact */
1588 if (strcspn(s
, "&<>\"'") == strlen(s
)) return s
;
1590 /* Ensure we have enough space, even if all the string is quotes */
1591 out
= realloc(out
, 6*strlen(s
)+1);
1599 strcpy(c
, "&"); c
+= 5;
1602 strcpy(c
, "<"); c
+= 4;
1605 strcpy(c
, ">"); c
+= 4;
1609 strcpy(c
, """); c
+= 6;
1620 /** Write VDX file header
1621 * @param data diagram data
1622 * @param renderer a renderer
1623 * @note Must know if 2002 or 2003 before start
1624 * @todo paper size, orientation, metadata, 2003 font attributes
1628 write_header(DiagramData
*data
, VDXRenderer
*renderer
)
1630 FILE *file
= renderer
->file
;
1634 struct vdx_StyleSheet StyleSheet
;
1635 struct vdx_StyleProp StyleProp
;
1636 struct vdx_Line Line
;
1637 struct vdx_Fill Fill
;
1638 struct vdx_TextBlock TextBlock
;
1639 struct vdx_Char Char
;
1640 struct vdx_Para Para
;
1641 struct vdx_Tabs Tabs
;
1642 static Color color_black
= {0,0,0};
1644 g_debug("write_header");
1646 /* Basic XML identifying info */
1648 fprintf(file
, "<?xml version='1.0' encoding='utf-8'?>\n");
1649 fprintf(file
, "<!-- Created by Dia -->\n");
1650 if (renderer
->version
== 2002)
1654 "xmlns='urn:schemas-microsoft-com:office:visio'>\n");
1656 if (renderer
->version
== 2003)
1658 fprintf(file
, "<VisioDocument "
1659 "xmlns='http://schemas.microsoft.com/visio/2003/core' "
1660 "start='190' metric='0' "
1661 "DocLangID='1033' version='11.0' xml:space='preserve'>\n");
1664 /* Skipping DocumentProperties, DocumentSettings - observed unnecessary */
1666 /* Other fields that may be useful:
1667 fprintf(file, (data->paper.is_portrait?"Portrait\n":"Landscape\n"));
1668 fprintf(file, "%s\n", data->paper.name);
1669 fprintf(file, "%f\n", data->paper.scaling*100.0);
1674 fprintf(file
, " <Colors>\n");
1675 for (i
= 0; i
< renderer
->Colors
->len
; i
++)
1677 c
= g_array_index(renderer
->Colors
, Color
, i
);
1678 fprintf(file
, " <ColorEntry IX='%d' RGB='%s'/>\n",
1679 i
, vdx_string_color(c
));
1681 fprintf(file
, " </Colors>\n");
1683 /* Font table - different between the two versions (alas) */
1685 if (renderer
->version
== 2002)
1687 fprintf(file
, " <Fonts>\n");
1688 for (i
= 0; i
< renderer
->Fonts
->len
; i
++)
1690 struct vdx_FontEntry Font
;
1691 memset(&Font
, 0, sizeof(Font
));
1692 Font
.type
= vdx_types_FontEntry
;
1693 f
= g_array_index(renderer
->Fonts
, char *, i
);
1695 /* Assume want stndard fonts names converted */
1696 if (!strcmp(f
, "Helvetica")) f
= "Arial";
1697 if (!strcmp(f
, "Times")) f
= "Times New Roman";
1699 Font
.Name
= (char *)f
;
1700 /* Sensible defaults */
1702 Font
.CharSet_exists
= 1;
1703 Font
.PitchAndFamily
= 18;
1704 Font
.PitchAndFamily_exists
= 1;
1705 Font
.Attributes
= 23040;
1706 Font
.Attributes_exists
= 1;
1710 /* Some observed values */
1711 if (!strcmp(f
, "Arial")) Font
.PitchAndFamily
= 32;
1712 if (!strcmp(f
, "Wingdings") || !strcmp(f
, "Monotype Sorts") ||
1713 !strcmp(f
, "Symbol")) Font
.CharSet
= 2;
1714 if (!strcmp(f
, "Monotype Sorts")) Font
.Attributes
= 4096;
1715 if (!strcmp(f
, "Wingdings") || !strcmp(f
, "Monotype Sorts"))
1716 Font
.PitchAndFamily
= 2;
1717 vdx_write_object(renderer
->file
, 2, &Font
);
1719 fprintf(file
, " </Fonts>\n");
1721 if (renderer
->version
== 2003)
1723 fprintf(file
, " <FaceNames>\n");
1724 for (i
= 0; i
< renderer
->Fonts
->len
; i
++)
1726 f
= g_array_index(renderer
->Fonts
, char *, i
);
1728 /* Assume want stndard fonts names converted */
1729 if (!strcmp(f
, "Helvetica")) f
= "Arial";
1730 if (!strcmp(f
, "Times")) f
= "Times New Roman";
1732 /* Missing attrs UnicodeRanges="31367 -2147483648 8 0"
1733 CharSets="1073742335 -65536"
1734 Panos="2 11 6 4 2 2 2 2 2 4" Flags="325" */
1735 fprintf(file
, " <FaceName ID='%d' Name='%s'/>\n",
1738 fprintf(file
, " </FaceNames>\n");
1741 /* An initial stylesheet (mandatory) */
1742 memset(&StyleSheet
, 0, sizeof(StyleSheet
));
1743 StyleSheet
.type
= vdx_types_StyleSheet
;
1744 StyleSheet
.NameU
= "No Style";
1746 /* All these values observed */
1747 memset(&StyleProp
, 0, sizeof(StyleProp
));
1748 StyleProp
.type
= vdx_types_StyleProp
;
1749 StyleProp
.EnableLineProps
= 1;
1750 StyleProp
.EnableFillProps
= 1;
1751 StyleProp
.EnableTextProps
= 1;
1753 memset(&Line
, 0, sizeof(Line
));
1754 Line
.type
= vdx_types_Line
;
1755 Line
.LineWeight
= 0.01;
1756 Line
.LinePattern
= 1;
1758 memset(&Fill
, 0, sizeof(Fill
));
1759 Fill
.type
= vdx_types_Fill
;
1760 Fill
.FillForegnd
= color_black
;
1761 Fill
.FillPattern
= 1;
1763 memset(&TextBlock
, 0, sizeof(TextBlock
));
1764 TextBlock
.type
= vdx_types_TextBlock
;
1765 TextBlock
.VerticalAlign
= 1;
1766 TextBlock
.DefaultTabStop
= 0.59055118110236;
1768 memset(&Char
, 0, sizeof(Char
));
1769 Char
.type
= vdx_types_Char
;
1771 Char
.Size
= 0.16666666666667;
1773 memset(&Para
, 0, sizeof(Para
));
1774 Para
.type
= vdx_types_Para
;
1777 Para
.BulletStr
= "";
1779 memset(&Tabs
, 0, sizeof(Tabs
));
1780 Tabs
.type
= vdx_types_Tabs
;
1782 /* Setup children */
1783 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &StyleProp
);
1784 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &Line
);
1785 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &Fill
);
1786 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &TextBlock
);
1787 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &Char
);
1788 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &Para
);
1789 StyleSheet
.children
= g_slist_append(StyleSheet
.children
, &Tabs
);
1791 fprintf(file
, " <StyleSheets>\n");
1792 vdx_write_object(renderer
->file
, 2, &StyleSheet
);
1793 fprintf(file
, " </StyleSheets>\n");
1795 g_slist_free(StyleSheet
.children
);
1797 /* Following attributes observed */
1798 fprintf(file
, " <Pages>\n");
1799 fprintf(file
, " <Page ID='0' NameU='Page-1' ViewScale='-1' "
1800 "ViewCenterX='5.8425196850394' ViewCenterY='3.7244094488189'>\n");
1801 fprintf(file
, " <Shapes>\n");
1802 renderer
->xml_depth
= 4;
1803 renderer
->shapeid
= 1;
1805 /* Exit nested <VisioDocument><Pages><Page><Shapes> */
1808 /** Write VDX file trailer
1809 * @param data diagram data
1810 * @param renderer a renderer
1814 write_trailer(DiagramData
*data
, VDXRenderer
*renderer
)
1816 FILE *file
= renderer
->file
;
1818 g_debug("write_trailer");
1820 /* Enter nested <VisioDocument><Pages><Page><Shapes> */
1822 fprintf(file
, " </Shapes>\n");
1823 fprintf(file
, " </Page>\n");
1824 fprintf(file
, " </Pages>\n");
1825 fprintf(file
, "</VisioDocument>\n");
1829 * @param data diagram data
1830 * @param filename output file (should check suffix)
1831 * @param diafilename input filename (unused)
1832 * @param user_data user data (unused)
1833 * @note Must know if 2002 or 2003 before start
1837 export_vdx(DiagramData
*data
, const gchar
*filename
,
1838 const gchar
*diafilename
, void* user_data
)
1841 VDXRenderer
*renderer
;
1845 file
= fopen(filename
, "w");
1848 message_error(_("Can't open output file %s: %s\n"),
1849 dia_message_filename(filename
), strerror(errno
));
1853 /* Create and initialise our renderer */
1854 renderer
= g_object_new(VDX_TYPE_RENDERER
, NULL
);
1856 renderer
->file
= file
;
1858 renderer
->first_pass
= TRUE
;
1860 renderer
->version
= 2002; /* For now */
1862 DIA_RENDERER_GET_CLASS(renderer
)->begin_render(DIA_RENDERER(renderer
));
1864 /* First run through without drawing to setup tables */
1865 for (i
=0; i
<data
->layers
->len
; i
++)
1867 layer
= (Layer
*) g_ptr_array_index(data
->layers
, i
);
1868 layer_render(layer
, DIA_RENDERER(renderer
), NULL
, NULL
, data
, 0);
1872 write_header(data
, renderer
);
1874 DIA_RENDERER_GET_CLASS(renderer
)->end_render(DIA_RENDERER(renderer
));
1876 renderer
->first_pass
= FALSE
;
1878 DIA_RENDERER_GET_CLASS(renderer
)->begin_render(DIA_RENDERER(renderer
));
1882 for (i
=0; i
<data
->layers
->len
; i
++)
1884 layer
= (Layer
*) g_ptr_array_index(data
->layers
, i
);
1885 layer_render(layer
, DIA_RENDERER(renderer
), NULL
, NULL
, data
, 0);
1889 DIA_RENDERER_GET_CLASS(renderer
)->end_render(DIA_RENDERER(renderer
));
1893 write_trailer(data
, renderer
);
1895 g_object_unref(renderer
);
1900 /* interface from filter.h */
1902 static const gchar
*extensions
[] = { "vdx", NULL
};
1903 DiaExportFilter vdx_export_filter
= {
1904 N_("Visio XML format"),
1911 /* The following are not provided by vdx-export.c so we use the defaults.
1912 If they become necessary after testing, we can reinstate them */
1914 /** Render a Dia line with arrows
1915 * @param self a renderer
1916 * @param start start of line
1917 * @param end end of line
1918 * @param line_width width of line
1919 * @param color line colour
1920 * @param start_arrow start arrow
1921 * @param end_arrow end arrow
1924 static void draw_line_with_arrows(DiaRenderer
*self
,
1925 Point
*start
, Point
*end
,
1931 VDXRenderer
*renderer
= VDX_RENDERER(self
);
1933 struct vdx_Shape Shape
;
1934 struct vdx_XForm XForm
;
1935 struct vdx_XForm1D XForm1D
;
1936 struct vdx_Geom Geom
;
1937 struct vdx_MoveTo MoveTo
;
1938 struct vdx_LineTo LineTo
;
1939 struct vdx_Line Line
;
1940 char NameU
[VDX_NAMEU_LEN
];
1942 /* Exactly as draw_line for now */
1944 if (renderer
->first_pass
)
1946 vdxCheckColor(renderer
, color
);
1950 g_debug("draw_line_with_arrows");
1951 memset(&Shape
, 0, sizeof(Shape
));
1952 Shape
.type
= vdx_types_Shape
;
1953 Shape
.ID
= renderer
->shapeid
++;
1954 Shape
.Type
= "Shape";
1955 sprintf(NameU
, "ArrowLine.%d", Shape
.ID
);
1956 Shape
.NameU
= NameU
;
1957 Shape
.LineStyle_exists
= 1;
1958 Shape
.FillStyle_exists
= 1;
1959 Shape
.TextStyle_exists
= 1;
1961 memset(&XForm
, 0, sizeof(XForm
));
1962 XForm
.type
= vdx_types_XForm
;
1963 a
= visio_point(*start
);
1964 b
= visio_point(*end
);
1967 XForm
.Width
= fabs(b
.x
- a
.x
);
1968 XForm
.Height
= fabs(b
.y
- a
.y
);
1969 XForm
.LocPinX
= 0.0;
1970 XForm
.LocPinY
= 0.0;
1973 memset(&XForm1D
, 0, sizeof(XForm1D
));
1974 XForm1D
.type
= vdx_types_XForm1D
;
1975 XForm1D
.BeginX
= a
.x
;
1976 XForm1D
.BeginY
= a
.y
;
1980 memset(&Geom
, 0, sizeof(Geom
));
1982 Geom
.type
= vdx_types_Geom
;
1984 memset(&MoveTo
, 0, sizeof(MoveTo
));
1985 MoveTo
.type
= vdx_types_MoveTo
;
1990 memset(&LineTo
, 0, sizeof(LineTo
));
1991 LineTo
.type
= vdx_types_LineTo
;
1996 create_Line(renderer
, color
, &Line
, start_arrow
, end_arrow
);
1998 Geom
.children
= g_slist_append(Geom
.children
, &MoveTo
);
1999 Geom
.children
= g_slist_append(Geom
.children
, &LineTo
);
2001 Shape
.children
= g_slist_append(Shape
.children
, &XForm
);
2002 Shape
.children
= g_slist_append(Shape
.children
, &XForm1D
);
2003 Shape
.children
= g_slist_append(Shape
.children
, &Line
);
2004 Shape
.children
= g_slist_append(Shape
.children
, &Geom
);
2006 vdx_write_object(renderer
->file
, renderer
->xml_depth
, &Shape
);
2008 g_slist_free(Geom
.children
);
2009 g_slist_free(Shape
.children
);
2012 /** Render a Dia polyline with arrows
2013 * @param self a renderer
2014 * @param points points on line
2015 * @param num_points number of points
2016 * @param line_width width of line
2017 * @param color line colour
2018 * @param start_arrow start arrow
2019 * @param end_arrow end arrow
2020 * @todo Not done yet
2023 static void draw_polyline_with_arrows(DiaRenderer
*self
,
2024 Point
*points
, int num_points
,
2030 VDXRenderer
*renderer
= VDX_RENDERER(self
);
2032 if (renderer
->first_pass
)
2034 vdxCheckColor(renderer
, color
);
2037 g_debug("draw_polyline_with_arrows (UNUSED)");
2040 /** Render a Dia arc with arrows
2041 * @param self a renderer
2042 * @param startpoint start of arc
2043 * @param endpoint end of arc
2044 * @param midpoint middle of arc
2045 * @param line_width line width
2046 * @param color line colour
2047 * @param start_arrow start arrow
2048 * @param end_arrow end arrow
2049 * @todo Not done yet - believe unused
2052 static void draw_arc_with_arrows(DiaRenderer
*self
,
2061 VDXRenderer
*renderer
= VDX_RENDERER(self
);
2063 if (renderer
->first_pass
)
2065 vdxCheckColor(renderer
, color
);
2068 g_debug("draw_arc_with_arrows (TODO)");
2071 /** Render a Dia Bezier
2072 * @param self a renderer
2073 * @param points list of Bezier points
2074 * @param numpoints number of points
2075 * @param color line colour
2076 * @todo Not done yet - either convert to arcs or NURBS (Visio 2003)
2079 static void draw_bezier(DiaRenderer
*self
,
2084 VDXRenderer
*renderer
= VDX_RENDERER(self
);
2086 if (renderer
->first_pass
)
2088 vdxCheckColor(renderer
, color
);
2091 g_debug("draw_bezier (TODO)");
2094 /** Render a Dia Bezier with arrows
2095 * @param self a renderer
2096 * @param points list of Bezier points
2097 * @param numpoints number of points
2098 * @param line_width line width
2099 * @param color line colour
2100 * @param start_arrow start arrow
2101 * @param end_arrow end arrow
2102 * @todo Not done yet - either convert to arcs or NURBS (Visio 2003)
2105 static void draw_bezier_with_arrows(DiaRenderer
*self
,
2113 VDXRenderer
*renderer
= VDX_RENDERER(self
);
2115 if (renderer
->first_pass
)
2117 vdxCheckColor(renderer
, color
);
2120 g_debug("draw_bezier_with_arrows (TODO)");
2123 /** Render a Dia filled Bezier
2124 * @param self a renderer
2125 * @param points list of Bezier points (last = first)
2126 * @param numpoints number of points
2127 * @param color line colour
2128 * @todo Not done yet - either convert to arcs or NURBS (Visio 2003)
2131 static void fill_bezier(DiaRenderer
*self
,
2136 VDXRenderer
*renderer
= VDX_RENDERER(self
);
2138 if (renderer
->first_pass
)
2140 vdxCheckColor(renderer
, color
);
2144 g_debug("fill_bezier (TODO)");
2147 /** Render a Dia object
2148 * @param self a renderer
2149 * @param object an object
2150 * @note No work done here - perhaps should push/pop renderer state
2153 static void draw_object(DiaRenderer
*self
,
2156 VDXRenderer
*renderer
= VDX_RENDERER(self
);
2158 g_debug("draw_object -> renderer");
2159 /* Get the object to draw itself */
2160 object
->ops
->draw(object
, DIA_RENDERER(renderer
));