[dia] svg-import: some more transform support
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] svg-import: some more transform support
- Date: Sat, 30 Jul 2011 12:16:57 +0000 (UTC)
commit 65e96f6958c765bbfbe612d1d777a4f4ad45aeaa
Author: Hans Breuer <hans breuer org>
Date: Tue Jul 26 22:15:52 2011 +0200
svg-import: some more transform support
- move old matrix functions to it's only user (wanlink.c)
- implement some of them taking a DiaMatrix*
- svg-import.c : direct apply of (some) transformation to
the corresponding object
lib/geometry.c | 126 ++++-----------------------------------
lib/geometry.h | 13 +----
lib/libdia.def | 3 +-
objects/network/wanlink.c | 72 +++++++++++++++++++++-
plug-ins/svg/svg-import.c | 147 ++++++++++++++++++++++++++++++++++++--------
5 files changed, 202 insertions(+), 159 deletions(-)
---
diff --git a/lib/geometry.c b/lib/geometry.c
index 5e5660f..9fe1d52 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -412,132 +412,28 @@ distance_ellipse_point(const Point *centre, real width, real height,
return dist - rad;
}
-
void
-transform_point (Matrix m, Point *src, Point *dest)
+transform_point (Point *pt, const DiaMatrix *m)
{
- real xx, yy, ww;
+ real x, y;
- xx = m[0][0] * src->x + m[0][1] * src->y + m[0][2];
- yy = m[1][0] * src->x + m[1][1] * src->y + m[1][2];
- ww = m[2][0] * src->x + m[2][1] * src->y + m[2][2];
+ g_return_if_fail (pt != NULL && m != NULL);
- if (!ww)
- ww = 1.0;
+ x = pt->x;
+ y = pt->y;
- dest->x = xx / ww;
- dest->y = yy / ww;
+ pt->x = x * m->xx + y * m->xy + m->x0;
+ pt->y = x * m->yx + y * m->yy + m->y0;
}
-
void
-mult_matrix (Matrix m1, Matrix m2)
+transform_bezpoint (BezPoint *bpt, const DiaMatrix *m)
{
- Matrix result;
- int i, j, k;
-
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- {
- result [i][j] = 0.0;
- for (k = 0; k < 3; k++)
- result [i][j] += m1 [i][k] * m2[k][j];
- }
-
- /* copy the result into matrix 2 */
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- m2 [i][j] = result [i][j];
+ transform_point (&bpt->p1, m);
+ transform_point (&bpt->p2, m);
+ transform_point (&bpt->p3, m);
}
void
-identity_matrix (Matrix m)
-{
- int i, j;
-
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- m[i][j] = (i == j) ? 1 : 0;
-
-}
-
-void
-translate_matrix (Matrix m, real x, real y)
-{
- Matrix trans;
-
- identity_matrix (trans);
- trans[0][2] = x;
- trans[1][2] = y;
- mult_matrix (trans, m);
-}
-
-void
-scale_matrix (Matrix m, real x, real y)
-{
- Matrix scale;
-
- identity_matrix (scale);
- scale[0][0] = x;
- scale[1][1] = y;
- mult_matrix (scale, m);
-}
-
-void
-rotate_matrix (Matrix m, real theta)
-{
- Matrix rotate;
- real cos_theta, sin_theta;
-
- cos_theta = cos (theta);
- sin_theta = sin (theta);
-
- identity_matrix (rotate);
- rotate[0][0] = cos_theta;
- rotate[0][1] = -sin_theta;
- rotate[1][0] = sin_theta;
- rotate[1][1] = cos_theta;
- mult_matrix (rotate, m);
-}
-
-void
-xshear_matrix (Matrix m, real shear)
-{
- Matrix shear_m;
-
- identity_matrix (shear_m);
- shear_m[0][1] = shear;
- mult_matrix (shear_m, m);
-}
-
-void
-yshear_matrix (Matrix m, real shear)
-{
- Matrix shear_m;
-
- identity_matrix (shear_m);
- shear_m[1][0] = shear;
- mult_matrix (shear_m, m);
-}
-
-/* find the determinate for a 3x3 matrix */
-G_GNUC_UNUSED static real
-determinate (Matrix m)
-{
- int i;
- double det = 0;
-
- for (i = 0; i < 3; i ++)
- {
- det += m[0][i] * m[1][(i+1)%3] * m[2][(i+2)%3];
- det -= m[2][i] * m[1][(i+1)%3] * m[0][(i+2)%3];
- }
-
- return det;
-}
-
-
-
-void
point_convex(Point *dst, const Point *src1, const Point *src2, real alpha)
{
/* Make convex combination of src1 and src2:
diff --git a/lib/geometry.h b/lib/geometry.h
index 19905b0..889e1af 100644
--- a/lib/geometry.h
+++ b/lib/geometry.h
@@ -363,17 +363,8 @@ real distance_bez_shape_point(const BezPoint *b, guint npoints,
real distance_ellipse_point(const Point *centre, real width, real height,
real line_width, const Point *point);
-typedef real Vector[3];
-typedef Vector Matrix[3];
-
-void transform_point (Matrix, Point *, Point *);
-void mult_matrix (Matrix, Matrix);
-void identity_matrix (Matrix);
-void translate_matrix (Matrix, real, real);
-void scale_matrix (Matrix, real, real);
-void rotate_matrix (Matrix, real);
-void xshear_matrix (Matrix, real);
-void yshear_matrix (Matrix, real);
+void transform_point (Point *pt, const DiaMatrix *m);
+void transform_bezpoint (BezPoint *bpt, const DiaMatrix *m);
real dot2(Point *p1, Point *p2);
void line_coef(real *a, real *b, real *c, Point *p1, Point *p2);
diff --git a/lib/libdia.def b/lib/libdia.def
index 7b5c200..fa55e43 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -457,7 +457,6 @@ EXPORTS
give_focus
; give_focus_to_object
- identity_matrix
int_rectangle_union
intl_score_locale
@@ -616,6 +615,7 @@ EXPORTS
point_scale
point_sub
transform_point
+ transform_bezpoint
point_get_perp
three_point_circle
@@ -691,7 +691,6 @@ EXPORTS
reset_foci_on_diagram
- rotate_matrix
nearest_pow
new_text
diff --git a/objects/network/wanlink.c b/objects/network/wanlink.c
index 3b4acf9..e968b3b 100644
--- a/objects/network/wanlink.c
+++ b/objects/network/wanlink.c
@@ -362,6 +362,70 @@ wanlink_load(ObjectNode obj_node, int version, const char *filename)
return obj;
}
+typedef real Vector[3];
+typedef Vector Matrix[3];
+
+static void
+_transform_point (Matrix m, Point *src, Point *dest)
+{
+ real xx, yy, ww;
+
+ xx = m[0][0] * src->x + m[0][1] * src->y + m[0][2];
+ yy = m[1][0] * src->x + m[1][1] * src->y + m[1][2];
+ ww = m[2][0] * src->x + m[2][1] * src->y + m[2][2];
+
+ if (!ww)
+ ww = 1.0;
+
+ dest->x = xx / ww;
+ dest->y = yy / ww;
+}
+static void
+_identity_matrix (Matrix m)
+{
+ int i, j;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ m[i][j] = (i == j) ? 1 : 0;
+
+}
+static void
+_mult_matrix (Matrix m1, Matrix m2)
+{
+ Matrix result;
+ int i, j, k;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ {
+ result [i][j] = 0.0;
+ for (k = 0; k < 3; k++)
+ result [i][j] += m1 [i][k] * m2[k][j];
+ }
+
+ /* copy the result into matrix 2 */
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ m2 [i][j] = result [i][j];
+}
+static void
+_rotate_matrix (Matrix m, real theta)
+{
+ Matrix rotate;
+ real cos_theta, sin_theta;
+
+ cos_theta = cos (theta);
+ sin_theta = sin (theta);
+
+ _identity_matrix (rotate);
+ rotate[0][0] = cos_theta;
+ rotate[0][1] = -sin_theta;
+ rotate[1][0] = sin_theta;
+ rotate[1][1] = cos_theta;
+ _mult_matrix (rotate, m);
+}
+
static void
wanlink_update_data(WanLink *wanlink)
{
@@ -417,8 +481,8 @@ wanlink_update_data(WanLink *wanlink)
wanlink->poly[5].y = (len * 0.55);
/* rotate */
- identity_matrix (m);
- rotate_matrix (m, angle);
+ _identity_matrix (m);
+ _rotate_matrix (m, angle);
obj->bounding_box.top = origin.y;
obj->bounding_box.left = origin.x;
@@ -428,8 +492,8 @@ wanlink_update_data(WanLink *wanlink)
{
Point new_pt;
- transform_point (m, &wanlink->poly[i],
- &new_pt);
+ _transform_point (m, &wanlink->poly[i],
+ &new_pt);
point_add (&new_pt, &origin);
wanlink->poly[i] = new_pt;
if (wanlink->poly [i].y < obj->bounding_box.top)
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index a95caf0..90a58f5 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -289,6 +289,9 @@ apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style)
g_free(gs);
}
+/* all the basic SVG elements allow their own transformation which
+ * is not directly supported by Dia and also not especially useful
+ */
/* read a path */
static GList *
read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
@@ -301,7 +304,14 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
GArray *bezpoints = NULL;
gboolean closed = FALSE;
gint i;
-
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
+
pathdata = str = (char *) xmlGetProp(node, (const xmlChar *)"d");
do {
bezpoints = dia_svg_parse_path (pathdata, &unparsed, &closed);
@@ -331,6 +341,8 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
bcd->points[i].p2.y /= user_scale;
bcd->points[i].p3.x /= user_scale;
bcd->points[i].p3.y /= user_scale;
+ if (matrix)
+ transform_bezpoint (&bcd->points[i], matrix);
}
new_obj = otype->ops->create(NULL, bcd, &h1, &h2);
if (!closed)
@@ -347,6 +359,8 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
if (bezpoints)
g_array_free (bezpoints, TRUE);
+ if (matrix)
+ g_free (matrix);
xmlFree (str);
@@ -367,6 +381,13 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
gchar *multiline = NULL;
DiaSvgStyle *gs;
gboolean any_tspan = FALSE;
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
gs = g_new(DiaSvgStyle, 1);
dia_svg_style_init (gs, parent_style);
@@ -419,6 +440,11 @@ read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
str = xmlNodeGetContent(node);
}
if(str || multiline) {
+ if (matrix) {
+ /* TODO: transform the text, too - when it is supported */
+ transform_point (&point, matrix);
+ g_free (matrix);
+ }
new_obj = otype->ops->create(&point, otype->default_user_data,
&h1, &h2);
list = g_list_append (list, new_obj);
@@ -481,6 +507,13 @@ read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, char *obj
xmlChar *str;
char *tmp;
int i;
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
str = xmlGetProp(node, (const xmlChar *)"points");
tmp = (char *) str;
@@ -504,8 +537,12 @@ read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, char *obj
for (i = 0; i < pcd->num_points; i++) {
points[i].x = rarr[2*i];
points[i].y = rarr[2*i+1];
+ if (matrix)
+ transform_point (&points[i], matrix);
}
g_array_free(arr, TRUE);
+ if (matrix)
+ g_free (matrix);
pcd->points = points;
new_obj = otype->ops->create(NULL, pcd,
@@ -530,19 +567,24 @@ read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
Handle *h1, *h2;
GPtrArray *props;
Point start = {0, 0};
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
str = xmlGetProp(node, (const xmlChar *)"cx");
if (str) {
start.x = get_value_as_cm((char *) str, NULL);
xmlFree(str);
}
- else return list;
str = xmlGetProp(node, (const xmlChar *)"cy");
if (str) {
start.y = get_value_as_cm((char *) str, NULL);
xmlFree(str);
}
- else return list;
str = xmlGetProp(node, (const xmlChar *)"rx");
if (str) {
width = get_value_as_cm((char *) str, NULL)*2;
@@ -553,20 +595,24 @@ read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
height = get_value_as_cm((char *) str, NULL)*2;
xmlFree(str);
}
- str = xmlGetProp(node, (const xmlChar *)"ry");
- if (str) {
- height = get_value_as_cm((char *) str, NULL)*2;
- xmlFree(str);
- }
+ /* not part of ellipse attributes, just here for circle */
str = xmlGetProp(node, (const xmlChar *)"r");
if (str) {
width = height = get_value_as_cm((char *) str, NULL)*2;
xmlFree(str);
}
- if (width <= 0.0 || height <= 0.0) {
- g_debug ("Ellipse too small %gx%g", width, height);
- return list;
+ if (matrix) {
+ /* TODO: transform angle - when it is supported */
+ Point wh = {width, height};
+ transform_point (&wh, matrix);
+ width = wh.x;
+ height = wh.y;
+ transform_point (&start, matrix);
+ g_free (matrix);
}
+ /* A negative value is an error [...]. A value of zero disables rendering of the element. */
+ if (width <= 0.0 || height <= 0.0)
+ return list;
new_obj = otype->ops->create(&start, otype->default_user_data,
&h1, &h2);
apply_style(new_obj, node, parent_style);
@@ -589,31 +635,44 @@ read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
PointProperty *ptprop;
GPtrArray *props;
Point start, end;
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
str = xmlGetProp(node, (const xmlChar *)"x1");
if (str) {
start.x = get_value_as_cm((char *) str, NULL);
xmlFree(str);
- }
- else return list;
+ } else
+ start.x = 0.0;
str = xmlGetProp(node, (const xmlChar *)"y1");
if (str) {
start.y = get_value_as_cm((char *) str, NULL);
xmlFree(str);
- }
- else return list;
+ } else
+ start.y;
str = xmlGetProp(node, (const xmlChar *)"x2");
if (str) {
end.x = get_value_as_cm((char *) str, NULL);
xmlFree(str);
- }
- else return list;
+ } else
+ end.x = start.x;
str = xmlGetProp(node, (const xmlChar *)"y2");
if (str) {
end.y = get_value_as_cm((char *) str, NULL);
xmlFree(str);
+ } else
+ end.y = start.y;
+
+ if (matrix) {
+ transform_point (&start, matrix);
+ transform_point (&end, matrix);
+ g_free (matrix);
}
- else return list;
new_obj = otype->ops->create(&start, otype->default_user_data,
&h1, &h2);
@@ -642,7 +701,7 @@ static GList *
read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
{
xmlChar *str;
- real width, height;
+ real width = 0.0, height = 0.0;
DiaObjectType *otype = object_get_type("Standard - Box");
DiaObject *new_obj;
Handle *h1, *h2;
@@ -651,33 +710,36 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
GPtrArray *props;
Point start,end;
real corner_radius = 0.0;
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
str = xmlGetProp(node, (const xmlChar *)"x");
if (str) {
start.x = get_value_as_cm((char *) str, NULL);
xmlFree(str);
- }
- else
+ } else
start.x = 0.0;
str = xmlGetProp(node, (const xmlChar *)"y");
if (str) {
start.y = get_value_as_cm((char *) str, NULL);
xmlFree(str);
- }
- else
+ } else
start.y = 0.0;
str = xmlGetProp(node, (const xmlChar *)"width");
if (str) {
width = get_value_as_cm((char *) str, NULL);
xmlFree(str);
}
- else return list;
str = xmlGetProp(node, (const xmlChar *)"height");
if (str) {
height = get_value_as_cm((char *) str, NULL);
xmlFree(str);
}
- else return list;
str = xmlGetProp(node, (const xmlChar *)"rx");
if (str) {
corner_radius = get_value_as_cm((char *) str, NULL);
@@ -693,7 +755,16 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list)
}
xmlFree(str);
}
-
+
+ if (matrix) {
+ /* TODO: for rotated rects we would need to create a polygon */
+ transform_point (&start, matrix);
+ transform_point (&end, matrix);
+ g_free (matrix);
+ }
+ /* A negative value is an error [...]. A value of zero disables rendering of the element. */
+ if (width <= 0.0 || height <= 0.0)
+ return list; /* just ignore it w/o much complaints */
new_obj = otype->ops->create(&start, otype->default_user_data,
&h1, &h2);
list = g_list_append (list, new_obj);
@@ -728,6 +799,13 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, const gc
xmlChar *str;
real x = 0, y = 0, width = 0, height = 0;
DiaObject *new_obj;
+ DiaMatrix *matrix = NULL;
+
+ str = (char *) xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = dia_svg_parse_transform (str, user_scale);
+ xmlFree (str);
+ }
str = xmlGetProp(node, (const xmlChar *)"x");
if (str) {
@@ -750,7 +828,22 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GList *list, const gc
xmlFree(str);
}
/* TODO: aspect ratio? */
-
+
+ if (matrix) {
+ /* TODO: transform angle - when it is supported */
+ Point xy = {x, y};
+ Point wh = {width, height};
+
+ transform_point (&xy, matrix);
+ transform_point (&wh, matrix);
+ width = wh.x;
+ height = wh.y;
+ x = xy.x;
+ y = xy.y;
+
+ g_free (matrix);
+ }
+
str = xmlGetProp(node, (const xmlChar *)"xlink:href");
if (!str) /* this doesn't look right but it appears to work w/o namespace --hb */
str = xmlGetProp(node, (const xmlChar *)"href");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]