/* -*- Mode: C; c-basic-offset: 4 -*- */ /* Dia -- a diagram creation/manipulation program * Copyright (C) 1998 Alexander Larsson * * vdx-export.c: Visio XML export filter for dia * Copyright (C) 2006-2007 Ian Redfern * based on the xfig filter code * Copyright (C) 2001 Lars Clausen * based on the dxf filter code * Copyright (C) 2000 James Henstridge, Steffen Macke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "intl.h" #include "message.h" #include "geometry.h" #include "diarenderer.h" #include "filter.h" #include "object.h" #include "properties.h" #include "dia_image.h" #include "group.h" #include "vdx.h" #include "visio-types.h" /* Following code taken from xfig-export.c */ #define VDX_TYPE_RENDERER (vdx_renderer_get_type ()) #define VDX_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VDX_TYPE_RENDERER, VDXRenderer)) #define VDX_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VDX_TYPE_RENDERER, VDXRendererClass)) #define VDX_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VDX_TYPE_RENDERER)) #define VDX_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VDX_TYPE_RENDERER, VDXRendererClass)) GType vdx_renderer_get_type (void) G_GNUC_CONST; typedef struct _VDXRenderer VDXRenderer; typedef struct _VDXRendererClass VDXRendererClass; struct _VDXRendererClass { DiaRendererClass parent_class; }; struct _VDXRenderer { DiaRenderer parent_instance; FILE *file; int depth; real linewidth; LineCaps capsmode; LineJoin joinmode; LineStyle stylemode; real dashlength; FillStyle fillmode; DiaFont *font; real fontheight; /* Additions for VDX */ gboolean first_pass; /* When we make table of colours and fonts */ GArray *Colors; /* Table of colours */ GArray *Fonts; /* Table of fonts */ unsigned int shapeid; /* Shape counter */ unsigned int version; /* Visio version */ unsigned int xml_depth; /* Pretty-printer */ }; static void begin_render(DiaRenderer *self); static void end_render(DiaRenderer *renderer); static void set_linewidth(DiaRenderer *self, real linewidth); static void set_linecaps(DiaRenderer *self, LineCaps mode); static void set_linejoin(DiaRenderer *self, LineJoin mode); static void set_linestyle(DiaRenderer *self, LineStyle mode); static void set_dashlength(DiaRenderer *self, real length); static void set_fillstyle(DiaRenderer *self, FillStyle mode); static void set_font(DiaRenderer *self, DiaFont *font, real height); static void draw_line(DiaRenderer *self, Point *start, Point *end, Color *color); static void draw_polyline(DiaRenderer *self, Point *points, int num_points, Color *color); static void draw_polygon(DiaRenderer *self, Point *points, int num_points, Color *color); static void fill_polygon(DiaRenderer *self, Point *points, int num_points, Color *color); static void draw_rect(DiaRenderer *self, Point *ul_corner, Point *lr_corner, Color *color); static void fill_rect(DiaRenderer *self, Point *ul_corner, Point *lr_corner, Color *color); static void draw_arc(DiaRenderer *self, Point *center, real width, real height, real angle1, real angle2, Color *color); static void fill_arc(DiaRenderer *self, Point *center, real width, real height, real angle1, real angle2, Color *color); static void draw_ellipse(DiaRenderer *self, Point *center, real width, real height, Color *color); static void fill_ellipse(DiaRenderer *self, Point *center, real width, real height, Color *color); static void draw_string(DiaRenderer *self, const char *text, Point *pos, Alignment alignment, Color *color); static void draw_image(DiaRenderer *self, Point *point, real width, real height, DiaImage image); static void vdx_renderer_class_init (VDXRendererClass *klass); static void export_vdx(DiagramData *data, const gchar *filename, const gchar *diafilename, void* user_data); static int vdxCheckColor(VDXRenderer *renderer, Color *color); static gpointer parent_class = NULL; /** Renderer type handler * @returns renderer type */ GType vdx_renderer_get_type (void) { static GType object_type = 0; if (!object_type) { static const GTypeInfo object_info = { sizeof (VDXRendererClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) vdx_renderer_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (VDXRenderer), 0, /* n_preallocs */ NULL /* init */ }; object_type = g_type_register_static (DIA_TYPE_RENDERER, "VDXRenderer", &object_info, 0); } return object_type; } /** Finalise a renderer * @param object a renderer */ static void vdx_renderer_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } /** Class constructor for renderer * @param klass a renderer */ static void vdx_renderer_class_init (VDXRendererClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); DiaRendererClass *renderer_class = DIA_RENDERER_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = vdx_renderer_finalize; renderer_class->begin_render = begin_render; renderer_class->end_render = end_render; renderer_class->set_linewidth = set_linewidth; renderer_class->set_linecaps = set_linecaps; renderer_class->set_linejoin = set_linejoin; renderer_class->set_linestyle = set_linestyle; renderer_class->set_dashlength = set_dashlength; renderer_class->set_fillstyle = set_fillstyle; renderer_class->set_font = set_font; renderer_class->draw_line = draw_line; renderer_class->draw_polyline = draw_polyline; renderer_class->draw_polygon = draw_polygon; renderer_class->fill_polygon = fill_polygon; renderer_class->draw_rect = draw_rect; renderer_class->fill_rect = fill_rect; renderer_class->draw_arc = draw_arc; renderer_class->fill_arc = fill_arc; renderer_class->draw_ellipse = draw_ellipse; renderer_class->fill_ellipse = fill_ellipse; /* Until we have NURBS, let Dia use lines */ /* renderer_class->draw_bezier = draw_bezier; */ /* renderer_class->fill_bezier = fill_bezier; */ /* renderer_class->draw_bezier_with_arrows = draw_bezier_with_arrows; */ renderer_class->draw_string = draw_string; renderer_class->draw_image = draw_image; /* Believe these are never used or are unnecessary */ /* renderer_class->draw_line_with_arrows = draw_line_with_arrows; */ /* renderer_class->draw_polyline_with_arrows = draw_polyline_with_arrows; */ /* renderer_class->draw_arc_with_arrows = draw_arc_with_arrows; */ /* renderer_class->draw_object = draw_object; */ } /** Initialises VDXrenderer * @param self a renderer */ static void begin_render(DiaRenderer *self) { VDXRenderer *renderer = VDX_RENDERER(self); Color c; renderer->depth = 0; renderer->linewidth = 0; renderer->capsmode = 0; renderer->joinmode = 0; renderer->stylemode = 0; renderer->dashlength = 0; renderer->fillmode = 0; renderer->font = NULL; renderer->fontheight = 1; /* Specific to VDX */ renderer->Colors = g_array_new(FALSE, TRUE, sizeof (Color)); renderer->Fonts = g_array_new(FALSE, TRUE, sizeof (char *)); renderer->shapeid = 0; /* renderer->version = 0; */ /* Black and white are 0 and 1 respectively */ c.red = 0.0; c.green = 0.0; c.blue = 0.0; vdxCheckColor(renderer, &c); c.red = 1.0; c.green = 1.0; c.blue = 1.0; vdxCheckColor(renderer, &c); } /** Destructor for renderer * @param self a renderer */ static void end_render(DiaRenderer *self) { VDXRenderer *renderer = VDX_RENDERER(self); /* Specific to VDX */ g_array_free(renderer->Colors, TRUE); g_array_free(renderer->Fonts, TRUE); } /** Convert a Dia point to a Visio one * @param p a Dia-space point * @returns a Visio-space point */ static Point visio_point(Point p) { Point q; q.x = p.x/vdx_Point_Scale; q.y = (p.y - vdx_Y_Offset)/vdx_Y_Flip/vdx_Point_Scale; return q; } /** Convert a Dia absolute length to a Visio one * @param length a length * @returns length in Visio space */ static double visio_length(double length) { return length/vdx_Point_Scale; } /** Set line width * @param self a renderer * @param linewidth new line width */ static void set_linewidth(DiaRenderer *self, real linewidth) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->linewidth = linewidth; } /** Set line caps * @param self a renderer * @param mode new line caps */ static void set_linecaps(DiaRenderer *self, LineCaps mode) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->capsmode = mode; } /** Set line join * @param self a renderer * @param mode new line join */ static void set_linejoin(DiaRenderer *self, LineJoin mode) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->joinmode = mode; } /** Set line style * @param self a renderer * @param mode new line style */ static void set_linestyle(DiaRenderer *self, LineStyle mode) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->stylemode = mode; } /** Set dash length * @param self a renderer * @param mode new dash length */ static void set_dashlength(DiaRenderer *self, real length) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->dashlength = length; } /** Set fill style * @param self a renderer * @param mode new file style */ static void set_fillstyle(DiaRenderer *self, FillStyle mode) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->fillmode = mode; } /** Set font * @param self a renderer * @param font new font * @param height new font height */ static void set_font(DiaRenderer *self, DiaFont *font, real height) { VDXRenderer *renderer = VDX_RENDERER(self); renderer->font = font; renderer->fontheight = height; } /** Get colour number from colour table * @param renderer a renderer * @param color the colour * @returns a colour index (black=0) */ static int vdxCheckColor(VDXRenderer *renderer, Color *color) { int i; Color cmp_color; for (i = 0; i < renderer->Colors->len; i++) { cmp_color = g_array_index(renderer->Colors, Color, i); if (color_equals(color, &cmp_color)) return i; } /* Grow table */ g_array_append_val(renderer->Colors, *color); return renderer->Colors->len; } /** Get font number from font table * @param renderer a renderer * @returns a font index (from 0) */ static int vdxCheckFont(VDXRenderer *renderer) { int i; const char *cmp_font; const char *font = dia_font_get_legacy_name(renderer->font); for (i = 0; i < renderer->Fonts->len; i++) { cmp_font = g_array_index(renderer->Fonts, char *, i); if (!strcmp(cmp_font, font)) return i; } /* Grow table */ g_array_append_val(renderer->Fonts, font); return renderer->Fonts->len; } /** Create a Visio line style object * @param self a VDXRenderer * @param color a colour * @param Line a Line object * @param start_arrow optional start arrow * @param end_arrow optional end arrow * @todo join, caps, dashlength */ static void create_Line(VDXRenderer *renderer, Color *color, struct vdx_Line *Line, Arrow *start_arrow, Arrow *end_arrow) { /* A Line (colour etc) */ memset(Line, 0, sizeof(*Line)); Line->type = vdx_types_Line; switch (renderer->stylemode) { case LINESTYLE_DASHED: Line->LinePattern = 2; break; case LINESTYLE_DOTTED: Line->LinePattern = 3; break; case LINESTYLE_DASH_DOT: Line->LinePattern = 4; break; case LINESTYLE_DASH_DOT_DOT: Line->LinePattern = 5; break; default: case LINESTYLE_SOLID: Line->LinePattern = 1; break; } Line->LineColor = *color; Line->LineWeight = renderer->linewidth / vdx_Line_Scale; if (start_arrow || end_arrow) { g_debug("create_Line (ARROWS)"); } } /** Create a Visio fill style object * @param self a VDXRenderer * @param color a colour * @todo fillstyle */ static void create_Fill(VDXRenderer *renderer, Color *color, struct vdx_Fill *Fill) { /* A Fill (colour etc) */ memset(Fill, 0, sizeof(*Fill)); Fill->type = vdx_types_Fill; Fill->FillForegnd = *color; Fill->FillPattern = 1; /* Solid fill */ } /** Render a Dia line * @param self a renderer * @param start start of line * @param end end of line * @param color line colour */ static void draw_line(DiaRenderer *self, Point *start, Point *end, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a, b; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_XForm1D XForm1D; struct vdx_Geom Geom; struct vdx_MoveTo MoveTo; struct vdx_LineTo LineTo; struct vdx_Line Line; char NameU[VDX_NAMEU_LEN]; /* First time through, just construct the colour table */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_line((%f,%f), (%f,%f))", start->x, start->y, end->x, end->y); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "Line.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(*start); b = visio_point(*end); XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.Width = fabs(b.x - a.x); /* Must be non-negative */ XForm.Height = fabs(b.y - a.y); /* Must be non-negative */ XForm.LocPinX = 0.0; XForm.LocPinY = 0.0; XForm.Angle = 0.0; /* Lines must have an XForm1D as well */ memset(&XForm1D, 0, sizeof(XForm1D)); XForm1D.type = vdx_types_XForm1D; XForm1D.BeginX = a.x; XForm1D.BeginY = a.y; XForm1D.EndX = b.x; XForm1D.EndY = b.y; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.NoFill = 1; Geom.type = vdx_types_Geom; /* Two children - MoveTo(start) and LineTo(end) */ memset(&MoveTo, 0, sizeof(MoveTo)); MoveTo.type = vdx_types_MoveTo; MoveTo.IX = 1; MoveTo.X = 0; MoveTo.Y = 0; memset(&LineTo, 0, sizeof(LineTo)); LineTo.type = vdx_types_LineTo; LineTo.IX = 2; LineTo.X = b.x-a.x; LineTo.Y = b.y-a.y; /* A Line (colour etc) */ create_Line(renderer, color, &Line, 0, 0); /* Setup children */ Geom.children = g_slist_append(Geom.children, &MoveTo); Geom.children = g_slist_append(Geom.children, &LineTo); Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &XForm1D); Shape.children = g_slist_append(Shape.children, &Line); Shape.children = g_slist_append(Shape.children, &Geom); /* Write out XML */ vdx_write_object(renderer->file, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(Geom.children); g_slist_free(Shape.children); } /** Render a Dia polyline * @param self a renderer * @param points the points * @param num_points how many points * @param color line colour */ static void draw_polyline(DiaRenderer *self, Point *points, int num_points, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a, b; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Geom Geom; struct vdx_MoveTo MoveTo; struct vdx_LineTo* LineTo; struct vdx_Line Line; char NameU[VDX_NAMEU_LEN]; unsigned int i; double minX, minY, maxX, maxY; /* First time through, just construct the colour table */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_polyline(%d)", num_points); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "PolyLine.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(points[0]); /* Find width and height */ minX = points[0].x; minY = points[0].y; maxX = points[0].x; maxY = points[0].y; for (i=1; i maxX) maxX = points[i].x; if (points[i].y < minY) minY = points[i].y; if (points[i].y > maxY) maxY = points[i].y; } XForm.Width = visio_length(maxX - minX); XForm.Height = visio_length(maxY - minY); XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.LocPinX = 0.0; XForm.LocPinY = 0.0; XForm.Angle = 0.0; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.NoFill = 1; Geom.type = vdx_types_Geom; /* Multiple children - MoveTo(start) and LineTo(others) */ memset(&MoveTo, 0, sizeof(MoveTo)); MoveTo.type = vdx_types_MoveTo; MoveTo.IX = 1; MoveTo.X = 0; MoveTo.Y = 0; LineTo = g_new0(struct vdx_LineTo, num_points-1); for (i=0; ifile, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(Geom.children); g_slist_free(Shape.children); g_free(LineTo); } /** Render a Dia polygon * @param self a renderer * @param points corners of polygon * @param num_points number of points * @param color line colour */ static void draw_polygon(DiaRenderer *self, Point *points, int num_points, Color *color) { Point *more_points = g_new0(Point, num_points+1); memcpy(more_points, points, num_points*sizeof(Point)); more_points[num_points] = more_points[0]; g_debug("draw_polygon -> draw_polyline"); draw_polyline(self, more_points, num_points+1, color); g_free(more_points); } /** Render a Dia filled polygon * @param self a renderer * @param points corners of polygon * @param num_points number of points * @param color line colour */ static void fill_polygon(DiaRenderer *self, Point *points, int num_points, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a, b; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Geom Geom; struct vdx_MoveTo MoveTo; struct vdx_LineTo* LineTo; struct vdx_Fill Fill; char NameU[VDX_NAMEU_LEN]; unsigned int i; double minX, minY, maxX, maxY; /* First time through, just construct the colour table */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("fill_polygon(%d)", num_points); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "FillPolygon.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(points[0]); /* Find width and height */ minX = points[0].x; minY = points[0].y; maxX = points[0].x; maxY = points[0].y; for (i=1; i maxX) maxX = points[i].x; if (points[i].y < minY) minY = points[i].y; if (points[i].y > maxY) maxY = points[i].y; } XForm.Width = visio_length(maxX - minX); XForm.Height = visio_length(maxY - minY); XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.LocPinX = 0.0; XForm.LocPinY = 0.0; XForm.Angle = 0.0; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.type = vdx_types_Geom; /* Multiple children - MoveTo(start) and LineTo(others) */ memset(&MoveTo, 0, sizeof(MoveTo)); MoveTo.type = vdx_types_MoveTo; MoveTo.IX = 1; MoveTo.X = 0; MoveTo.Y = 0; LineTo = g_new0(struct vdx_LineTo, num_points); for (i=0; ifile, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(Geom.children); g_slist_free(Shape.children); g_free(LineTo); } /** Render a Dia rectangle * @param self a renderer * @param ul_corner Upper-left corner * @param lr_corner Loower-right corner * @param color line colour */ static void draw_rect(DiaRenderer *self, Point *ul_corner, Point *lr_corner, Color *color) { Point points[5]; /* 5 so we close path */ g_debug("draw_rect((%f,%f), (%f,%f)) -> draw_polyline", ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y); points[0].x = ul_corner->x; points[0].y = lr_corner->y; points[1] = *lr_corner; points[2].x = lr_corner->x; points[2].y = ul_corner->y; points[3] = *ul_corner; points[4] = points[0]; draw_polygon(self, points, 5, color); } /** Render a Dia filled rectangle * @param self a renderer * @param ul_corner Upper-left corner * @param lr_corner Lower-right corner * @param color line colour */ static void fill_rect(DiaRenderer *self, Point *ul_corner, Point *lr_corner, Color *color) { Point points[5]; /* 5 so we close path */ g_debug("fill_rect -> fill_polygon"); points[0].x = ul_corner->x; points[0].y = lr_corner->y; points[1] = *lr_corner; points[2].x = lr_corner->x; points[2].y = ul_corner->y; points[3] = *ul_corner; points[4] = points[0]; fill_polygon(self, points, 5, color); } /** Render a Dia arc * @param self a renderer * @param center centre of arc * @param width width of ellipse * @param height height of ellipse (= width for Dia circular arcs) * @param angle1 start angle to x axis in degrees * @param angle2 end angle to x axis in degrees * @param color line colour * @todo Not done yet */ static void draw_arc(DiaRenderer *self, Point *center, real width, real height, real angle1, real angle2, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Geom Geom; struct vdx_EllipticalArcTo EllipticalArcTo; struct vdx_MoveTo MoveTo; struct vdx_Line Line; char NameU[VDX_NAMEU_LEN]; Point start, control, end; float control_angle; /* First time through, just construct the colour table */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_arc((%f,%f),%f,%f;%f,%f)", center->x, center->y, width, height, angle1, angle2); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "Arc.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; /* Find the start of the arc */ start = *center; start.x += (width/2.0)*cos(angle1*DEG_TO_RAD); start.y -= (height/2.0)*sin(angle1*DEG_TO_RAD); g_debug("start(%f,%f)", start.x, start.y); start = visio_point(start); /* Find a control point at the midpoint of the arc */ control = *center; control_angle = (angle1 + angle2)/2.0; if (angle1 > angle2) { /* Arc goes antclockwise - allow for this */ control_angle -= 180; } control.x += (width/2.0)*cos(control_angle*DEG_TO_RAD); control.y -= (height/2.0)*sin(control_angle*DEG_TO_RAD); g_debug("control(%f,%f @ %f)", control.x, control.y, control_angle); control = visio_point(control); /* And the endpoint */ end = *center; end.x += (width/2.0)*cos(angle2*DEG_TO_RAD); end.y -= (height/2.0)*sin(angle2*DEG_TO_RAD); g_debug("end(%f,%f)", end.x, end.y); end = visio_point(end); a = start; XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.Width = visio_length(width); XForm.Height = visio_length(height); XForm.LocPinX = 0; XForm.LocPinY = 0; XForm.Angle = 0.0; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.NoFill = 1; Geom.type = vdx_types_Geom; memset(&MoveTo, 0, sizeof(MoveTo)); MoveTo.type = vdx_types_MoveTo; MoveTo.IX = 1; MoveTo.X = 0; MoveTo.Y = 0; /* Second child - EllipticalArcTo */ memset(&EllipticalArcTo, 0, sizeof(EllipticalArcTo)); EllipticalArcTo.type = vdx_types_EllipticalArcTo; EllipticalArcTo.IX = 2; /* X and Y are the end point A and B are a control point on the arc C is the angle of the major axis D is the ratio of the major to minor axes */ /* Need to fix these */ EllipticalArcTo.X = end.x - a.x; EllipticalArcTo.Y = end.y - a.y; EllipticalArcTo.A = control.x - a.x; EllipticalArcTo.B = control.y - a.y; EllipticalArcTo.C = 0.0; /* Dia major axis always x axis */ if (fabs(height) > EPSILON) EllipticalArcTo.D = width/height; /* Always 1 for Dia */ else EllipticalArcTo.D = 1/EPSILON; /* A Line (colour etc) */ create_Line(renderer, color, &Line, 0, 0); /* Setup children */ Geom.children = g_slist_append(Geom.children, &MoveTo); Geom.children = g_slist_append(Geom.children, &EllipticalArcTo); Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &Line); Shape.children = g_slist_append(Shape.children, &Geom); /* Write out XML */ vdx_write_object(renderer->file, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(Geom.children); g_slist_free(Shape.children); } /** Render a Dia filled arc * @param self a renderer * @param center centre of arc * @param width width of bounding box * @param height height of bounding box * @param angle1 start angle * @param angle2 end angle * @param color line colour * @todo Not done yet - believe unused */ static void fill_arc(DiaRenderer *self, Point *center, real width, real height, real angle1, real angle2, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("fill_arc (TODO)"); } /** Render a Dia ellipse (parallel to axes) * @param self a renderer * @param center centre of ellipse * @param width width of bounding box * @param height height of bounding box * @param color line colour */ static void draw_ellipse(DiaRenderer *self, Point *center, real width, real height, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Geom Geom; struct vdx_Ellipse Ellipse; struct vdx_Line Line; char NameU[VDX_NAMEU_LEN]; /* First time through, just construct the colour table */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_ellipse"); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "Ellipse.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(*center); XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.Width = visio_length(width); XForm.Height = visio_length(height); XForm.LocPinX = XForm.Width/2.0; XForm.LocPinY = XForm.Height/2.0; XForm.Angle = 0.0; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.NoFill = 1; Geom.type = vdx_types_Geom; /* One child - Ellipse */ memset(&Ellipse, 0, sizeof(Ellipse)); Ellipse.type = vdx_types_Ellipse; Ellipse.IX = 1; Ellipse.X = XForm.Width/2.0; Ellipse.Y = XForm.Height/2.0; Ellipse.A = XForm.Width; Ellipse.B = XForm.Height/2.0; Ellipse.C = XForm.Width/2.0; Ellipse.D = XForm.Height; /* A Line (colour etc) */ create_Line(renderer, color, &Line, 0, 0); /* Setup children */ Geom.children = g_slist_append(Geom.children, &Ellipse); Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &Line); Shape.children = g_slist_append(Shape.children, &Geom); /* Write out XML */ vdx_write_object(renderer->file, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(Geom.children); g_slist_free(Shape.children); } /** Render a Dia filled ellipse (parallel to axes) * @param self a renderer * @param center centre of ellipse * @param width width of bounding box * @param height height of bounding box * @param color line colour */ static void fill_ellipse(DiaRenderer *self, Point *center, real width, real height, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Geom Geom; struct vdx_Ellipse Ellipse; struct vdx_Fill Fill; char NameU[VDX_NAMEU_LEN]; /* First time through, just construct the colour table */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("fill_ellipse"); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "FillEllipse.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(*center); XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.Width = visio_length(width); XForm.Height = visio_length(height); XForm.LocPinX = XForm.Width/2.0; XForm.LocPinY = XForm.Height/2.0; XForm.Angle = 0.0; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.type = vdx_types_Geom; /* One child - Ellipse */ memset(&Ellipse, 0, sizeof(Ellipse)); Ellipse.type = vdx_types_Ellipse; Ellipse.IX = 1; Ellipse.X = XForm.Width/2.0; Ellipse.Y = XForm.Height/2.0; Ellipse.A = XForm.Width; Ellipse.B = XForm.Height/2.0; Ellipse.C = XForm.Width/2.0; Ellipse.D = XForm.Height; /* A Fill (colour etc) */ create_Fill(renderer, color, &Fill); /* Setup children */ Geom.children = g_slist_append(Geom.children, &Ellipse); Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &Fill); Shape.children = g_slist_append(Shape.children, &Geom); /* Write out XML */ vdx_write_object(renderer->file, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(Geom.children); g_slist_free(Shape.children); } /** Render a Dia string * @param self a renderer * @param text the string * @param pos start (or centre etc.) * @param alignment alignment * @param color line colour * @todo Alignment, colour * @bug Bounding box incorrect */ static void draw_string(DiaRenderer *self, const char *text, Point *pos, Alignment alignment, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); Point a; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Char Char; struct vdx_Text Text; struct vdx_text my_text; char NameU[VDX_NAMEU_LEN]; if (renderer->first_pass) { /* Add to colour and font tables */ vdxCheckColor(renderer, color); vdxCheckFont(renderer); return; } g_debug("draw_string"); /* Standard shape */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "Text.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* XForm describes bounding box */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(*pos); XForm.PinX = a.x; XForm.PinY = a.y; XForm.Angle = 0; /* Hack to give it an approximate bounding box */ XForm.Height = renderer->fontheight/vdx_Font_Size_Conversion; XForm.Width = strlen(text)*renderer->fontheight/vdx_Font_Size_Conversion; /* Character properties */ memset(&Char, 0, sizeof(Char)); Char.type = vdx_types_Char; Char.Font = vdxCheckFont(renderer); Char.Color = *color; Char.FontScale = 1; Char.Size = renderer->fontheight/vdx_Font_Size_Conversion; /* Text object - no attributes */ memset(&Text, 0, sizeof(Text)); Text.type = vdx_types_Text; /* text object (XML pseudo-tag) - no attributes */ memset(&my_text, 0, sizeof(my_text)); my_text.type = vdx_types_text; my_text.text = (char *)text; /* Construct the children */ Text.children = g_slist_append(Text.children, &my_text); Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &Char); Shape.children = g_slist_append(Shape.children, &Text); vdx_write_object(renderer->file, renderer->xml_depth, &Shape); g_slist_free(Text.children); g_slist_free(Shape.children); } /** Reads binary file and converts to Base64 data * @param filename file to read * @returns Base64 encoded data (or NULL if problem) * @note glibc 2.12 offers g_base64_encode() */ static char * read_base64_file(const char *filename) { FILE *f; char *b64 = 0; char *s = 0; int c = 0; char map[64]; unsigned int buf_len = 0; unsigned char buf[3]; struct stat stat_buf; if (g_stat(filename, &stat_buf)) { message_error(_("Couldn't read file %s"), filename); return 0; } b64 = g_new0(char, stat_buf.st_size*4/3+5); s = b64; f = g_fopen(filename, "r+b"); if (!f) { message_error(_("Couldn't read file %s"), filename); return 0; } /* Construct Base64 mapping table */ for(c=0; c<26; c++) map[c] = 'A' + c; for(c=0; c<26; c++) map[c+26] = 'a' + c; for(c=0; c<10; c++) map[c+52] = '0' + c; map[62] = '+'; map[63] = '/'; while((c = fgetc(f)) != EOF) { buf[buf_len++] = (unsigned char)c; if (buf_len == 3) { *s++ = map[buf[0] >> 2]; *s++ = map[((buf[0] & 3) << 4) + (buf[1] >> 4)]; *s++ = map[((buf[1] & 15) << 2) + (buf[2] >> 6)]; *s++ = map[buf[2] & 63]; buf_len = 0; } } if (buf_len == 1) { *s++ = map[buf[0] >> 2]; *s++ = map[((buf[0] & 3) << 4)]; *s++ = '='; *s++ = '='; } if (buf_len == 2) { *s++ = map[buf[0] >> 2]; *s++ = map[((buf[0] & 3) << 4) + (buf[1] >> 4)]; *s++ = map[((buf[1] & 15) << 2)]; *s++ = '='; } fclose(f); *s = 0; return b64; /* Deal with any chunks left over */ if (buf_len) { fputc(buf[0] << 2 | buf[1] >> 4, f); if (buf_len > 1) { fputc(buf[1] << 4 | buf[2] >> 2, f); if (buf_len > 2) { /* This one can't happen */ fputc(buf[2] << 6 | buf[3], f); } } } fclose(f); } /** Render a Dia bitmap * @param self a renderer * @param point top left * @param width width * @param height height */ static void draw_image(DiaRenderer *self, Point *point, real width, real height, DiaImage image) { VDXRenderer *renderer = VDX_RENDERER(self); Point a, bottom_left; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_Geom Geom; struct vdx_Foreign Foreign; struct vdx_ForeignData ForeignData; struct vdx_text text; char NameU[VDX_NAMEU_LEN]; const char *filename = NULL; const char *suffix = NULL; if (renderer->first_pass) { return; } g_debug("draw_image((%f,%f), %f, %f, %s", point->x, point->y, width, height, dia_image_filename(image)); /* Setup the standard shape object */ memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Foreign"; sprintf(NameU, "Foreign.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; /* An XForm */ memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; bottom_left.x = point->x; bottom_left.y = point->y + height; a = visio_point(bottom_left); XForm.PinX = a.x; /* Start */ XForm.PinY = a.y; XForm.Width = visio_length(width); XForm.Height = visio_length(height); XForm.LocPinX = 0; XForm.LocPinY = 0; XForm.Angle = 0.0; /* Standard Geom object */ memset(&Geom, 0, sizeof(Geom)); Geom.type = vdx_types_Geom; /* We don't use it, but our decoder needs it */ /* And a Foreign */ memset(&Foreign, 0, sizeof(Foreign)); Foreign.type = vdx_types_Foreign; Foreign.ImgOffsetX = 0; Foreign.ImgOffsetY = 0; Foreign.ImgHeight = visio_length(height); Foreign.ImgWidth = visio_length(width); /* And a ForeignData */ memset(&ForeignData, 0, sizeof(ForeignData)); ForeignData.type = vdx_types_ForeignData; ForeignData.ForeignType = "Bitmap"; ForeignData.CompressionType = "JPEG"; ForeignData.CompressionLevel = 1.0; ForeignData.ObjectHeight = visio_length(height); ForeignData.ObjectWidth = visio_length(width); filename = dia_image_filename(image); if ((suffix = strrchr(filename, '.'))) { suffix++; if (!g_ascii_strncasecmp(suffix, "png", 3)) { ForeignData.CompressionType = "PNG"; } if (!g_ascii_strncasecmp(suffix, "gif", 3)) { ForeignData.CompressionType = "GIF"; } if (!g_ascii_strncasecmp(suffix, "jpg", 3) || !g_ascii_strncasecmp(suffix, "jpeg", 4)) { ForeignData.CompressionType = "JPEG"; } if (!g_ascii_strncasecmp(suffix, "tif", 3) || !g_ascii_strncasecmp(suffix, "tiff", 4)) { ForeignData.CompressionType = "TIFF"; } } /* And the data itself */ memset(&text, 0, sizeof(text)); text.type = vdx_types_text; text.text = read_base64_file(filename); if (!text.text) return; /* Problem reading file */ /* Setup children */ Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &Geom); Shape.children = g_slist_append(Shape.children, &Foreign); Shape.children = g_slist_append(Shape.children, &ForeignData); ForeignData.children = g_slist_append(ForeignData.children, &text); /* Write out XML */ vdx_write_object(renderer->file, renderer->xml_depth, &Shape); /* Free up list entries */ g_slist_free(ForeignData.children); g_slist_free(Shape.children); /* And the Base64 data */ g_free(text.text); } /** Convert Dia colour to hex string * @param c a colour * @returns string in form #000000 * @note static buffer overwritten with next call; not thread-safe */ const char * vdx_string_color(Color c) { static char buf[8]; sprintf(buf, "#%.2X%.2X%.2X", (int)(c.red*255), (int)(c.green*255), (int)(c.blue*255)); return buf; } /** Return string XML-encoded * @param s a string * @returns encoded string * @note uses static buffer so can be used as inline filter in printf */ const char * vdx_convert_xml_string(const char *s) { static char *out = 0; char *c; /* If (as almost always) no change required, return intact */ if (strcspn(s, "&<>\"'") == strlen(s)) return s; /* Ensure we have enough space, even if all the string is quotes */ out = realloc(out, 6*strlen(s)+1); c = out; while(*s) { switch(*s) { case '&': strcpy(c, "&"); c += 5; break; case '<': strcpy(c, "<"); c += 4; break; case '>': strcpy(c, ">"); c += 4; break; case '\"': case '\'': strcpy(c, """); c += 6; break; default: *c++ = *s; } s++; } *c = 0; return out; } /** Write VDX file header * @param data diagram data * @param renderer a renderer * @note Must know if 2002 or 2003 before start * @todo paper size, orientation, metadata, 2003 font attributes */ static void write_header(DiagramData *data, VDXRenderer *renderer) { FILE *file = renderer->file; Color c; const char *f; unsigned int i; struct vdx_StyleSheet StyleSheet; struct vdx_StyleProp StyleProp; struct vdx_Line Line; struct vdx_Fill Fill; struct vdx_TextBlock TextBlock; struct vdx_Char Char; struct vdx_Para Para; struct vdx_Tabs Tabs; static Color color_black = {0,0,0}; g_debug("write_header"); /* Basic XML identifying info */ fprintf(file, "\n"); fprintf(file, "\n"); if (renderer->version == 2002) { fprintf(file, "\n"); } if (renderer->version == 2003) { fprintf(file, "\n"); } /* Skipping DocumentProperties, DocumentSettings - observed unnecessary */ /* Other fields that may be useful: fprintf(file, (data->paper.is_portrait?"Portrait\n":"Landscape\n")); fprintf(file, "%s\n", data->paper.name); fprintf(file, "%f\n", data->paper.scaling*100.0); */ /* Colour table */ fprintf(file, " \n"); for (i = 0; i < renderer->Colors->len; i++) { c = g_array_index(renderer->Colors, Color, i); fprintf(file, " \n", i, vdx_string_color(c)); } fprintf(file, " \n"); /* Font table - different between the two versions (alas) */ if (renderer->version == 2002) { fprintf(file, " \n"); for (i = 0; i < renderer->Fonts->len; i++) { struct vdx_FontEntry Font; memset(&Font, 0, sizeof(Font)); Font.type = vdx_types_FontEntry; f = g_array_index(renderer->Fonts, char *, i); /* Assume want stndard fonts names converted */ if (!strcmp(f, "Helvetica")) f = "Arial"; if (!strcmp(f, "Times")) f = "Times New Roman"; Font.Name = (char *)f; /* Sensible defaults */ Font.CharSet = 0; Font.CharSet_exists = 1; Font.PitchAndFamily = 18; Font.PitchAndFamily_exists = 1; Font.Attributes = 23040; Font.Attributes_exists = 1; Font.Weight = 0; Font.Unicode = 0; /* Some observed values */ if (!strcmp(f, "Arial")) Font.PitchAndFamily = 32; if (!strcmp(f, "Wingdings") || !strcmp(f, "Monotype Sorts") || !strcmp(f, "Symbol")) Font.CharSet = 2; if (!strcmp(f, "Monotype Sorts")) Font.Attributes = 4096; if (!strcmp(f, "Wingdings") || !strcmp(f, "Monotype Sorts")) Font.PitchAndFamily = 2; vdx_write_object(renderer->file, 2, &Font); } fprintf(file, " \n"); } if (renderer->version == 2003) { fprintf(file, " \n"); for (i = 0; i < renderer->Fonts->len; i++) { f = g_array_index(renderer->Fonts, char *, i); /* Assume want stndard fonts names converted */ if (!strcmp(f, "Helvetica")) f = "Arial"; if (!strcmp(f, "Times")) f = "Times New Roman"; /* Missing attrs UnicodeRanges="31367 -2147483648 8 0" CharSets="1073742335 -65536" Panos="2 11 6 4 2 2 2 2 2 4" Flags="325" */ fprintf(file, " \n", i, f); } fprintf(file, " \n"); } /* An initial stylesheet (mandatory) */ memset(&StyleSheet, 0, sizeof(StyleSheet)); StyleSheet.type = vdx_types_StyleSheet; StyleSheet.NameU = "No Style"; /* All these values observed */ memset(&StyleProp, 0, sizeof(StyleProp)); StyleProp.type = vdx_types_StyleProp; StyleProp.EnableLineProps = 1; StyleProp.EnableFillProps = 1; StyleProp.EnableTextProps = 1; memset(&Line, 0, sizeof(Line)); Line.type = vdx_types_Line; Line.LineWeight = 0.01; Line.LinePattern = 1; memset(&Fill, 0, sizeof(Fill)); Fill.type = vdx_types_Fill; Fill.FillForegnd = color_black; Fill.FillPattern = 1; memset(&TextBlock, 0, sizeof(TextBlock)); TextBlock.type = vdx_types_TextBlock; TextBlock.VerticalAlign = 1; TextBlock.DefaultTabStop = 0.59055118110236; memset(&Char, 0, sizeof(Char)); Char.type = vdx_types_Char; Char.FontScale = 1; Char.Size = 0.16666666666667; memset(&Para, 0, sizeof(Para)); Para.type = vdx_types_Para; Para.SpLine = -1.2; Para.HorzAlign = 1; Para.BulletStr = ""; Para.BulletFontSize = "-1"; memset(&Tabs, 0, sizeof(Tabs)); Tabs.type = vdx_types_Tabs; /* Setup children */ StyleSheet.children = g_slist_append(StyleSheet.children, &StyleProp); StyleSheet.children = g_slist_append(StyleSheet.children, &Line); StyleSheet.children = g_slist_append(StyleSheet.children, &Fill); StyleSheet.children = g_slist_append(StyleSheet.children, &TextBlock); StyleSheet.children = g_slist_append(StyleSheet.children, &Char); StyleSheet.children = g_slist_append(StyleSheet.children, &Para); StyleSheet.children = g_slist_append(StyleSheet.children, &Tabs); fprintf(file, " \n"); vdx_write_object(renderer->file, 2, &StyleSheet); fprintf(file, " \n"); g_slist_free(StyleSheet.children); /* Following attributes observed */ fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); renderer->xml_depth = 4; renderer->shapeid = 1; /* Exit nested */ } /** Write VDX file trailer * @param data diagram data * @param renderer a renderer */ static void write_trailer(DiagramData *data, VDXRenderer *renderer) { FILE *file = renderer->file; g_debug("write_trailer"); /* Enter nested */ fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, "\n"); } /** Write VDX file * @param data diagram data * @param filename output file (should check suffix) * @param diafilename input filename (unused) * @param user_data user data (unused) * @note Must know if 2002 or 2003 before start */ static void export_vdx(DiagramData *data, const gchar *filename, const gchar *diafilename, void* user_data) { FILE *file; VDXRenderer *renderer; int i; Layer *layer; file = g_fopen(filename, "w"); if (file == NULL) { message_error(_("Can't open output file %s: %s\n"), dia_message_filename(filename), strerror(errno)); return; } /* Create and initialise our renderer */ renderer = g_object_new(VDX_TYPE_RENDERER, NULL); renderer->file = file; renderer->first_pass = TRUE; renderer->version = 2002; /* For now */ DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer)); /* First run through without drawing to setup tables */ for (i=0; ilayers->len; i++) { layer = (Layer *) g_ptr_array_index(data->layers, i); layer_render(layer, DIA_RENDERER(renderer), NULL, NULL, data, 0); renderer->depth++; } write_header(data, renderer); DIA_RENDERER_GET_CLASS(renderer)->end_render(DIA_RENDERER(renderer)); renderer->first_pass = FALSE; DIA_RENDERER_GET_CLASS(renderer)->begin_render(DIA_RENDERER(renderer)); /* Now render */ for (i=0; ilayers->len; i++) { layer = (Layer *) g_ptr_array_index(data->layers, i); layer_render(layer, DIA_RENDERER(renderer), NULL, NULL, data, 0); renderer->depth++; } DIA_RENDERER_GET_CLASS(renderer)->end_render(DIA_RENDERER(renderer)); /* Done */ write_trailer(data, renderer); g_object_unref(renderer); fclose(file); } /* interface from filter.h */ static const gchar *extensions[] = { "vdx", NULL }; DiaExportFilter vdx_export_filter = { N_("Visio XML format"), extensions, export_vdx }; #if 0 /* The following are not provided by vdx-export.c so we use the defaults. If they become necessary after testing, we can reinstate them */ /** Render a Dia line with arrows * @param self a renderer * @param start start of line * @param end end of line * @param line_width width of line * @param color line colour * @param start_arrow start arrow * @param end_arrow end arrow */ static void draw_line_with_arrows(DiaRenderer *self, Point *start, Point *end, real line_width, Color *color, Arrow *start_arrow, Arrow *end_arrow) { VDXRenderer *renderer = VDX_RENDERER(self); Point a, b; struct vdx_Shape Shape; struct vdx_XForm XForm; struct vdx_XForm1D XForm1D; struct vdx_Geom Geom; struct vdx_MoveTo MoveTo; struct vdx_LineTo LineTo; struct vdx_Line Line; char NameU[VDX_NAMEU_LEN]; /* Exactly as draw_line for now */ if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_line_with_arrows"); memset(&Shape, 0, sizeof(Shape)); Shape.type = vdx_types_Shape; Shape.ID = renderer->shapeid++; Shape.Type = "Shape"; sprintf(NameU, "ArrowLine.%d", Shape.ID); Shape.NameU = NameU; Shape.LineStyle_exists = 1; Shape.FillStyle_exists = 1; Shape.TextStyle_exists = 1; memset(&XForm, 0, sizeof(XForm)); XForm.type = vdx_types_XForm; a = visio_point(*start); b = visio_point(*end); XForm.PinX = a.x; XForm.PinY = a.y; XForm.Width = fabs(b.x - a.x); XForm.Height = fabs(b.y - a.y); XForm.LocPinX = 0.0; XForm.LocPinY = 0.0; XForm.Angle = 0.0; memset(&XForm1D, 0, sizeof(XForm1D)); XForm1D.type = vdx_types_XForm1D; XForm1D.BeginX = a.x; XForm1D.BeginY = a.y; XForm1D.EndX = b.x; XForm1D.EndY = b.y; memset(&Geom, 0, sizeof(Geom)); Geom.NoFill = 1; Geom.type = vdx_types_Geom; memset(&MoveTo, 0, sizeof(MoveTo)); MoveTo.type = vdx_types_MoveTo; MoveTo.IX = 1; MoveTo.X = 0; MoveTo.Y = 0; memset(&LineTo, 0, sizeof(LineTo)); LineTo.type = vdx_types_LineTo; LineTo.IX = 2; LineTo.X = b.x-a.x; LineTo.Y = b.y-a.y; create_Line(renderer, color, &Line, start_arrow, end_arrow); Geom.children = g_slist_append(Geom.children, &MoveTo); Geom.children = g_slist_append(Geom.children, &LineTo); Shape.children = g_slist_append(Shape.children, &XForm); Shape.children = g_slist_append(Shape.children, &XForm1D); Shape.children = g_slist_append(Shape.children, &Line); Shape.children = g_slist_append(Shape.children, &Geom); vdx_write_object(renderer->file, renderer->xml_depth, &Shape); g_slist_free(Geom.children); g_slist_free(Shape.children); } /** Render a Dia polyline with arrows * @param self a renderer * @param points points on line * @param num_points number of points * @param line_width width of line * @param color line colour * @param start_arrow start arrow * @param end_arrow end arrow * @todo Not done yet */ static void draw_polyline_with_arrows(DiaRenderer *self, Point *points, int num_points, real line_width, Color *color, Arrow *start_arrow, Arrow *end_arrow) { VDXRenderer *renderer = VDX_RENDERER(self); if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_polyline_with_arrows (UNUSED)"); } /** Render a Dia arc with arrows * @param self a renderer * @param startpoint start of arc * @param endpoint end of arc * @param midpoint middle of arc * @param line_width line width * @param color line colour * @param start_arrow start arrow * @param end_arrow end arrow * @todo Not done yet - believe unused */ static void draw_arc_with_arrows(DiaRenderer *self, Point *startpoint, Point *endpoint, Point *midpoint, real line_width, Color *color, Arrow *start_arrow, Arrow *end_arrow) { VDXRenderer *renderer = VDX_RENDERER(self); if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_arc_with_arrows (TODO)"); } /** Render a Dia Bezier * @param self a renderer * @param points list of Bezier points * @param numpoints number of points * @param color line colour * @todo Not done yet - either convert to arcs or NURBS (Visio 2003) */ static void draw_bezier(DiaRenderer *self, BezPoint *points, int numpoints, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_bezier (TODO)"); } /** Render a Dia Bezier with arrows * @param self a renderer * @param points list of Bezier points * @param numpoints number of points * @param line_width line width * @param color line colour * @param start_arrow start arrow * @param end_arrow end arrow * @todo Not done yet - either convert to arcs or NURBS (Visio 2003) */ static void draw_bezier_with_arrows(DiaRenderer *self, BezPoint *points, int numpoints, real line_width, Color *color, Arrow *start_arrow, Arrow *end_arrow) { VDXRenderer *renderer = VDX_RENDERER(self); if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("draw_bezier_with_arrows (TODO)"); } /** Render a Dia filled Bezier * @param self a renderer * @param points list of Bezier points (last = first) * @param numpoints number of points * @param color line colour * @todo Not done yet - either convert to arcs or NURBS (Visio 2003) */ static void fill_bezier(DiaRenderer *self, BezPoint *points, int numpoints, Color *color) { VDXRenderer *renderer = VDX_RENDERER(self); if (renderer->first_pass) { vdxCheckColor(renderer, color); return; } g_debug("fill_bezier (TODO)"); } /** Render a Dia object * @param self a renderer * @param object an object * @note No work done here - perhaps should push/pop renderer state */ static void draw_object(DiaRenderer *self, DiaObject *object) { VDXRenderer *renderer = VDX_RENDERER(self); g_debug("draw_object -> renderer"); /* Get the object to draw itself */ object->ops->draw(object, DIA_RENDERER(renderer)); } #endif