[dia] svg: improve transform support for <use/>



commit 526c8b7562ecd182e48080a2bdc9548a66743e52
Author: Hans Breuer <hans breuer org>
Date:   Sat Jul 20 18:31:51 2013 +0200

    svg: improve transform support for <use/>
    
     - with <use/> transform also (bez)points
     - implement and use group_transform()

 lib/geometry.c            |   17 ++++++++
 lib/geometry.h            |    2 +
 lib/group.h               |    2 +-
 lib/libdia.def            |    3 +
 lib/properties.h          |    3 +-
 lib/proplist.c            |   16 +++++++
 plug-ins/svg/svg-import.c |   98 +++++++++++++++++++++++++++++++--------------
 7 files changed, 109 insertions(+), 32 deletions(-)
---
diff --git a/lib/geometry.c b/lib/geometry.c
index 7cf4916..662d562 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -701,6 +701,23 @@ dia_matrix_is_identity (const DiaMatrix *matrix)
   return FALSE;
 }
 
+void
+dia_matrix_multiply (DiaMatrix *result, const DiaMatrix *a, const DiaMatrix *b)
+{
+    DiaMatrix r;
+
+    r.xx = a->xx * b->xx + a->yx * b->xy;
+    r.yx = a->xx * b->yx + a->yx * b->yy;
+
+    r.xy = a->xy * b->xx + a->yy * b->xy;
+    r.yy = a->xy * b->yx + a->yy * b->yy;
+
+    r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
+    r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
+
+    *result = r;
+}
+
 /*!
  * \brief Splitting the given matrix into angle and scales
  * @param m matrix
diff --git a/lib/geometry.h b/lib/geometry.h
index 0335565..494b671 100644
--- a/lib/geometry.h
+++ b/lib/geometry.h
@@ -135,6 +135,8 @@ void dia_matrix_set_angle_and_scales (DiaMatrix *m,
                                       real       a,
                                      real       sx,
                                      real       sy);
+void dia_matrix_multiply (DiaMatrix *result, const DiaMatrix *a, const DiaMatrix *b);
+
 #define ROUND(x) ((int) floor((x)+0.5))
 
 /* inline these functions if the platform supports it */
diff --git a/lib/group.h b/lib/group.h
index 24b863b..101f187 100644
--- a/lib/group.h
+++ b/lib/group.h
@@ -31,7 +31,7 @@ DiaObject *group_create_with_matrix(GList *objects, DiaMatrix *matrix);
 GList *group_objects(DiaObject *group);
 
 void group_destroy_shallow(DiaObject *group);
-
+void group_transform (Group *group, const DiaMatrix *mat);
 #define IS_GROUP(obj) ((obj)->type == &group_type)
 
 #endif /* GROUP_H */
diff --git a/lib/libdia.def b/lib/libdia.def
index a903c10..e5e862d 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -470,6 +470,7 @@ EXPORTS
  group_destroy_shallow
  group_objects
  group_type
+ group_transform
 
  get_active_focus
  give_focus
@@ -678,6 +679,7 @@ EXPORTS
  prop_list_add_line_colour
  prop_list_add_line_style
  prop_list_add_line_width
+ prop_list_add_matrix
  prop_list_add_point
  prop_list_add_real
  prop_list_add_string
@@ -777,6 +779,7 @@ EXPORTS
  dia_matrix_is_identity
  dia_matrix_get_angle_and_scales
  dia_matrix_set_angle_and_scales
+ dia_matrix_multiply
 
  dia_option_menu_add_item
  dia_option_menu_get_active
diff --git a/lib/properties.h b/lib/properties.h
index ce0d93f..fc4a10d 100644
--- a/lib/properties.h
+++ b/lib/properties.h
@@ -416,7 +416,6 @@ const PropertyOps *prop_type_get_ops(PropertyType type);
 
 void       prop_list_free(GPtrArray *plist);
 
-
 /*! copies the whole property structure, including the data. */
 GPtrArray *prop_list_copy(GPtrArray *plist);
 /*! copies the whole property structure, excluding the data. */
@@ -458,6 +457,8 @@ void prop_list_add_filename (GPtrArray *plist, const char *name, const char *val
 void prop_list_add_enum (GPtrArray *plist, const char *name, int val);
 /* adding a font */
 void prop_list_add_font (GPtrArray *plist, const char *name, const DiaFont *font);
+/* add transformation matrix */
+void prop_list_add_matrix (GPtrArray *plist, const DiaMatrix *m);
 
 /* Some predicates: */
 gboolean pdtpp_true(const PropDescription *pdesc); /* always true */
diff --git a/lib/proplist.c b/lib/proplist.c
index 8e7f28a..e9b54cb 100644
--- a/lib/proplist.c
+++ b/lib/proplist.c
@@ -180,6 +180,13 @@ prop_list_save(GPtrArray *props, DataNode data)
   }
 }
 
+/*!
+ * \brief Search a property list for a named property
+ *
+ * Check if a given property is included in the list
+ * With a better naming convention this function would be
+ * called prop_list_find_prop_by_name()
+ */
 Property *
 find_prop_by_name(const GPtrArray *props, const gchar *name) 
 {
@@ -344,3 +351,12 @@ prop_list_add_text_colour (GPtrArray *plist, const Color *color)
 {
   _prop_list_add_colour (plist, "text_colour", color);
 }
+void
+prop_list_add_matrix (GPtrArray *plist, const DiaMatrix *m)
+{
+  Property *prop = make_new_prop ("matrix", PROP_TYPE_MATRIX, 0);
+
+  g_free (((MatrixProperty *)prop)->matrix);
+  (( MatrixProperty *)prop)->matrix = g_memdup (m, sizeof(DiaMatrix));
+  g_ptr_array_add (plist, prop);
+}
\ No newline at end of file
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 78dd5dc..274905a 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -213,34 +213,69 @@ use_position (DiaObject *obj, xmlNodePtr node)
         DiaMatrix *m = dia_svg_parse_transform ((char *)str, user_scale);
 
        if (m) {
-           GPtrArray *props = g_ptr_array_new ();
-           PointProperty *pp;
-           RealProperty  *pr;
-
-           prop_list_add_point (props, "obj_pos", &pos); 
-           prop_list_add_point (props, "elem_corner", &pos); 
-           prop_list_add_real (props, "elem_width", 1.0);
-           prop_list_add_real (props, "elem_height", 1.0);
-           prop_list_add_real (props, PROP_STDNAME_LINE_WIDTH, 0.1);
-           obj->ops->get_props (obj, props);
-           /* try to transform the object without the full matrix  */
-           pp = g_ptr_array_index (props, 0);
-           pp->point_data.x +=  m->x0;
-           pp->point_data.y +=  m->y0;
-           /* set position a second time, now for non-elements */
-           pp = g_ptr_array_index (props, 1);
-           pp->point_data.x +=  m->x0;
-           pp->point_data.y +=  m->y0;
-
-           pr = g_ptr_array_index (props, 2);
-           pr->real_data *= m->xx;
-           pr = g_ptr_array_index (props, 3);
-           pr->real_data *= m->yy;
-           pr = g_ptr_array_index (props, 4);
-           pr->real_data *= m->yy;
-           obj->ops->set_props (obj, props);
-
-           prop_list_free (props);
+           if (IS_GROUP (obj)) {
+             /* it is the only one transformation aware yet */
+             Group *grp = (Group *)obj;
+
+             group_transform (grp, m);
+           } else {
+             GPtrArray *props = g_ptr_array_new ();
+
+             PointProperty *pp;
+             RealProperty  *pr;
+             PointarrayProperty *pap = NULL;
+             BezPointarrayProperty *bpap = NULL;
+             Property *prop = NULL;
+
+             /* setting obj_pos is pointless, it is read-only in all objects */
+             prop_list_add_point (props, "obj_pos", &pos); 
+             prop_list_add_point (props, "elem_corner", &pos); 
+             prop_list_add_real (props, "elem_width", 1.0);
+             prop_list_add_real (props, "elem_height", 1.0);
+             prop_list_add_real (props, PROP_STDNAME_LINE_WIDTH, 0.1);
+
+             if ((prop = object_prop_by_name_type (obj, "bez_points", PROP_TYPE_BEZPOINTARRAY)) != NULL) {
+               prop_list_add_list (props, prop_list_from_single (prop));
+               bpap = g_ptr_array_index (props, 5);
+             } else if ((prop = object_prop_by_name_type (obj, "poly_points", PROP_TYPE_POINTARRAY)) != 
NULL) {
+               prop_list_add_list (props, prop_list_from_single (prop));
+               pap = g_ptr_array_index (props, 5);
+             }
+
+             obj->ops->get_props (obj, props);
+             /* try to transform the object without the full matrix  */
+             pp = g_ptr_array_index (props, 0);
+             pp->point_data.x +=  m->x0;
+             pp->point_data.y +=  m->y0;
+             /* set position a second time, now for non-elements */
+             pp = g_ptr_array_index (props, 1);
+             pp->point_data.x +=  m->x0;
+             pp->point_data.y +=  m->y0;
+
+             pr = g_ptr_array_index (props, 2);
+             pr->real_data *= m->xx;
+             pr = g_ptr_array_index (props, 3);
+             pr->real_data *= m->yy;
+             pr = g_ptr_array_index (props, 4);
+             pr->real_data *= m->yy;
+
+             if (bpap) {
+               GArray *data = bpap->bezpointarray_data;
+               int i;
+               for (i = 0; i < data->len; ++i)
+                 transform_bezpoint (&g_array_index(data, BezPoint, i), m);
+             } else if (pap) {
+               GArray *data = pap->pointarray_data;
+               int i;
+               for (i = 0; i < data->len; ++i)
+                 transform_point (&g_array_index(data, Point, i), m);
+             }
+
+             obj->ops->set_props (obj, props);
+             if (prop)
+               prop->ops->free (prop);
+             prop_list_free (props);
+           }
            g_free (m);
        }
         xmlFree(str);
@@ -843,11 +878,16 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
     xmlFree(str);
   }
 
+  end.x = start.x + width;
+  end.y = start.y + height;
+
   if (matrix) {
     /* TODO: for rotated rects we would need to create a polygon */
     transform_point (&start, matrix);
     transform_point (&end, matrix);
     g_free (matrix);
+    width = end.x - start.x;
+    height = end.y - start.y;
   }
   /* A negative value is an error [...]. A value of zero disables rendering of the element. */
   if (width <= 0.0 || height <= 0.0)
@@ -861,8 +901,6 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
   ptprop = g_ptr_array_index(props,0);
   ptprop->point_data = start;
 
-  end.x = start.x + width;
-  end.y = start.y + height;
   ptprop = g_ptr_array_index(props,1);
   ptprop->point_data = end;
 


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