[dia] svg: improve transform support for <use/>
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] svg: improve transform support for <use/>
- Date: Sat, 20 Jul 2013 22:26:14 +0000 (UTC)
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]