[dia] Bug 735430 - vdx: Box rounding support for export and import



commit 11c3108a01a05ea1e3e249bc7be794b42ca7cdaf
Author: Hans Breuer <hans breuer org>
Date:   Sat Sep 6 14:37:08 2014 +0200

    Bug 735430 - vdx: Box rounding support for export and import
    
    VDX 'Rounding' is basically the same as Dia corner_radius, so
    draw_rounded_rect() was really easy to implement. While at it
    remove all superfluous prototypes instead of adding a new one.
    
    The import has to be a little more elaborated, because corner_radius
    can only be handled with "Standard - Box", but VDX has no rectangle.
    So we check the polygon for being rectangular and if so apply the
    rounding.
    
    Checked with ellipse.dia round-trip as well as with Visio Viewer 2010.
    
    Also included some minor line style/caps tweaking.

 plug-ins/vdx/vdx-export.c |  183 +++++++++++++++++++++------------------------
 plug-ins/vdx/vdx-import.c |   73 ++++++++++++++++--
 samples/ellipse.dia       |  Bin 0 -> 2565 bytes
 3 files changed, 150 insertions(+), 106 deletions(-)
---
diff --git a/plug-ins/vdx/vdx-export.c b/plug-ins/vdx/vdx-export.c
index dc59b75..97b64c5 100644
--- a/plug-ins/vdx/vdx-export.c
+++ b/plug-ins/vdx/vdx-export.c
@@ -97,46 +97,6 @@ struct _VDXRenderer
 };
 
 
-static void begin_render(DiaRenderer *self, const Rectangle *update);
-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, real dash_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 *fill, Color *stroke);
-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 *fill, Color *stroke);
-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 gboolean export_vdx(DiagramData *data, DiaContext *ctx,
@@ -191,52 +151,6 @@ 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_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->draw_arc = draw_arc;
-  renderer_class->fill_arc = fill_arc;
-
-  renderer_class->draw_ellipse = draw_ellipse;
-
-  /* Until we have NURBS, let Dia use lines */
-  /* renderer_class->draw_bezier = draw_bezier; */
-  /* renderer_class->draw_beziergon = draw_beziergon; */
-  /* renderer_class->draw_bezier_with_arrows = draw_bezier_with_arrows; */
-
-  renderer_class->draw_string = draw_string;
-
-  renderer_class->draw_image = draw_image;
-
-  /* Further high level methods not required (or desired) */
-}
-
 /** Initialises VDXrenderer
  * @param self a renderer
  */
@@ -446,7 +360,6 @@ vdxCheckFont(VDXRenderer *renderer)
  * @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) 
@@ -476,6 +389,9 @@ create_Line(VDXRenderer *renderer, Color *color, struct vdx_Line *Line,
     Line->LineColor = *color;
     Line->LineColorTrans = 1.0 - color->alpha;
     Line->LineWeight = renderer->linewidth / vdx_Line_Scale;
+    /* VDX only has Rounded (0) or Square (1) ends */
+    if (renderer->capsmode != LINECAPS_ROUND)
+       Line->LineCap = 1; /* Square */
     if (start_arrow || end_arrow) 
     {
         g_debug("create_Line (ARROWS)");
@@ -713,16 +629,11 @@ static void draw_polyline(DiaRenderer *self, Point *points, int num_points,
     g_free(LineTo);
 }
 
-/** 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
-draw_polygon (DiaRenderer *self, 
-             Point *points, int num_points, 
-             Color *fill, Color *stroke)
+_polygon (DiaRenderer *self,
+         Point *points, int num_points,
+         Color *fill, Color *stroke,
+         real radius)
 {
     VDXRenderer *renderer = VDX_RENDERER(self);
     Point a, b;
@@ -812,6 +723,7 @@ draw_polygon (DiaRenderer *self,
        create_Fill(renderer, fill, &Fill);
     if (stroke)
        create_Line(renderer, stroke, &Line, NULL, NULL);
+    Line.Rounding = visio_length (radius);
 
     Geom.NoFill = fill ? 0 : 1;
     Geom.NoLine = stroke ? 0 : 1;
@@ -825,7 +737,7 @@ draw_polygon (DiaRenderer *self,
     Shape.any.children = g_slist_append(Shape.any.children, &XForm);
     if (fill)
        Shape.any.children = g_slist_append(Shape.any.children, &Fill);
-    if (stroke)
+    if (stroke || radius > 0.0)
        Shape.any.children = g_slist_append(Shape.any.children, &Line);
     Shape.any.children = g_slist_append(Shape.any.children, &Geom);
 
@@ -838,6 +750,37 @@ draw_polygon (DiaRenderer *self,
     g_free(LineTo);
 }
 
+/** 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
+draw_polygon (DiaRenderer *self,
+             Point *points, int num_points,
+             Color *fill, Color *stroke)
+{
+  _polygon (self, points, num_points, fill, stroke, 0.0);
+}
+
+static void
+draw_rounded_rect (DiaRenderer *self,
+                  Point *ul_corner, Point *lr_corner,
+                  Color *fill, Color *stroke,
+                  real radius)
+{
+    Point points[4];            /* close path done by _polygon() */
+
+    g_debug("draw_rounded_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;
+
+    _polygon (self, points, 4, fill, stroke, radius);
+}
 /** Render a Dia arc
  * @param self a renderer
  * @param center centre of arc
@@ -2094,3 +2037,49 @@ draw_object (DiaRenderer *self,
 
 
 #endif
+
+/** 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_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->draw_arc = draw_arc;
+  renderer_class->fill_arc = fill_arc;
+
+  renderer_class->draw_ellipse = draw_ellipse;
+
+  /* Until we have NURBS, let Dia use lines */
+  /* renderer_class->draw_bezier = draw_bezier; */
+  /* renderer_class->draw_beziergon = draw_beziergon; */
+  /* renderer_class->draw_bezier_with_arrows = draw_bezier_with_arrows; */
+
+  renderer_class->draw_string = draw_string;
+
+  renderer_class->draw_image = draw_image;
+
+  renderer_class->draw_rounded_rect = draw_rounded_rect;
+  /* Further high level methods not required (or desired?) */
+}
diff --git a/plug-ins/vdx/vdx-import.c b/plug-ins/vdx/vdx-import.c
index 73c5578..c4e5a75 100644
--- a/plug-ins/vdx/vdx-import.c
+++ b/plug-ins/vdx/vdx-import.c
@@ -631,19 +631,25 @@ vdx_simple_properties(DiaObject *obj,
                 (LinestyleProperty *)make_new_prop("line_style",
                                                    PROP_TYPE_LINESTYLE,
                                                    PROP_FLAG_DONT_SAVE);
-            lsprop->style = LINESTYLE_SOLID;
-
-            if (Line->LinePattern > 1)
-                lsprop->style = LINESTYLE_DASHED;
-            if (Line->LinePattern == 4)
-                lsprop->style = LINESTYLE_DASH_DOT;
-            if (Line->LinePattern == 3)
-                lsprop->style = LINESTYLE_DOTTED;
+           if (Line->LinePattern == 2)
+               lsprop->style = LINESTYLE_DASHED;
+           else if (Line->LinePattern == 4)
+               lsprop->style = LINESTYLE_DASH_DOT;
+           else if (Line->LinePattern == 3)
+               lsprop->style = LINESTYLE_DOTTED;
+           else if (Line->LinePattern == 5)
+               lsprop->style = LINESTYLE_DASH_DOT_DOT;
+           else
+               lsprop->style = LINESTYLE_SOLID;
 
             lsprop->dash = vdx_Dash_Length;
 
             g_ptr_array_add(props,lsprop);
         }
+       if (Line->Rounding > 0.0)
+       {
+           prop_list_add_real(props, "corner_radius", Line->Rounding * vdx_Line_Scale);
+       }
     }
 
     if (Fill && Fill->FillPattern)
@@ -809,6 +815,46 @@ make_arrow(const struct vdx_Line *Line, char start_end,
     return a;
 }
 
+/*!
+ * \brief Translate points to rectangle representation if possible
+ */
+static gboolean
+_is_rect (int count, Point *points, real *x, real *y, real *w, real *h)
+{
+    int i;
+    real minx, miny, maxdx = 0.0, maxdy = 0.0, sumdx = 0.0, sumdy = 0.0;
+
+    if (count != 5)
+       return FALSE;
+    minx = points[0].x;
+    miny = points[0].y;
+    for (i = 1; i< 5; ++i)
+    {
+       real dx = points[i-1].x - points[i].x;
+       real dy = points[i-1].y - points[i].y;
+
+       /* must be both 0 for a real rectangle */
+       sumdx += dx;
+       sumdy += dy;
+
+       dx = fabs (dx);
+       dy = fabs (dy);
+
+       if (dx > EPSILON && dy > EPSILON)
+           return FALSE;
+       minx = MIN(minx, points[i].x);
+       miny = MIN(miny, points[i].y);
+       maxdx = MAX(maxdx, dx);
+       maxdy = MAX(maxdy, dy);
+    }
+    if (fabs(sumdx) > EPSILON || fabs(sumdy) > EPSILON)
+       return FALSE;
+    *x = minx;
+    *y = miny;
+    *w = maxdx;
+    *h = maxdy;
+    return TRUE;
+}
 
 /* The following functions create the Dia standard objects */
 
@@ -942,7 +988,16 @@ plot_polyline(const struct vdx_Geom *Geom, const struct vdx_XForm *XForm,
         }
         else
         {
-            newobj = create_standard_polygon(count, points);
+           real x, y, w, h;
+
+           if (_is_rect (count, points, &x, &y, &w, &h))
+           {
+               newobj = create_standard_box(x, y, w, h);
+           }
+           else
+           {
+               newobj = create_standard_polygon(count, points);
+           }
         }
     }
     else
diff --git a/samples/ellipse.dia b/samples/ellipse.dia
new file mode 100644
index 0000000..79fccbc
Binary files /dev/null and b/samples/ellipse.dia differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]