[dia] introduce graphene
- From: Zander <zbrown src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] introduce graphene
- Date: Sun, 3 May 2020 11:36:54 +0000 (UTC)
commit 2bbd4fe78a20dab56295abe65cbdfab63b688e97
Author: Zander Brown <zbrown gnome org>
Date: Sun May 3 12:36:34 2020 +0100
introduce graphene
Add a dependency on graphene, eventually this will replace our geometry functions
Replace usage of DiaMatrix in DiaSvg with graphene_matrix_t
lib/dia-graphene.h | 52 +++
lib/dia_svg.c | 399 ++++++++++-------
lib/dia_svg.h | 53 ++-
lib/geometry.h | 3 +
lib/meson.build | 2 +
meson.build | 1 +
plug-ins/svg/render_svg.c | 23 +-
plug-ins/svg/svg-import.c | 1092 +++++++++++++++++++++++++--------------------
8 files changed, 958 insertions(+), 667 deletions(-)
---
diff --git a/lib/dia-graphene.h b/lib/dia-graphene.h
new file mode 100644
index 00000000..af2fd0a9
--- /dev/null
+++ b/lib/dia-graphene.h
@@ -0,0 +1,52 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * 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.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright © 2020 Zander Brown <zbrown gnome org>
+ */
+
+#pragma once
+
+#include <graphene.h>
+
+#include "geometry.h"
+
+static inline void
+dia_matrix_from_graphene (DiaMatrix *matrix,
+ graphene_matrix_t *graphene)
+{
+ matrix->xx = graphene_matrix_get_value (graphene, 0, 0);
+ matrix->yx = graphene_matrix_get_value (graphene, 0, 1);
+ matrix->xy = graphene_matrix_get_value (graphene, 1, 0);
+ matrix->yy = graphene_matrix_get_value (graphene, 1, 1);
+ matrix->x0 = graphene_matrix_get_x_translation (graphene);
+ matrix->y0 = graphene_matrix_get_y_translation (graphene);
+}
+
+static inline void
+dia_graphene_from_matrix (graphene_matrix_t *graphene,
+ const DiaMatrix *matrix)
+{
+ graphene_matrix_init_from_2d (graphene,
+ matrix->xx,
+ matrix->yx,
+ matrix->xy,
+ matrix->yy,
+ matrix->x0,
+ matrix->y0);
+}
diff --git a/lib/dia_svg.c b/lib/dia_svg.c
index 28fcb5a0..36e10f5a 100644
--- a/lib/dia_svg.c
+++ b/lib/dia_svg.c
@@ -30,10 +30,10 @@
#include "dia_svg.h"
-/*!
- * \defgroup DiaSvg Services for SVG
- * \ingroup Plugins
- * \brief A set of function helping to read and write SVG with Dia
+/**
+ * SECTION:dia_svg
+ * @title: Dia SVG
+ * @short_description: A set of function helping to read and write SVG with Dia
*
* The Dia application supports various variants of SVG. There are
* at least two importers of SVG dialects, namely \ref Shapes and
@@ -347,7 +347,7 @@ _parse_color(gint32 *color, const char *str)
*color = ((0xFF<<24) & 0xFF000000) | ((r<<16) & 0xFF0000) | ((g<<8) & 0xFF00) | (b & 0xFF);
} else if (strchr (str+4, '%')) {
/* e.g. cairo uses percent values */
- gchar **vals = g_strsplit (str+4, "%,", -1);
+ char **vals = g_strsplit (str+4, "%,", -1);
int i;
*color = 0xFF000000;
@@ -392,7 +392,7 @@ _parse_color(gint32 *color, const char *str)
* \ingroup DiaSvg
*/
gboolean
-dia_svg_parse_color (const gchar *str, Color *color)
+dia_svg_parse_color (const char *str, Color *color)
{
gint32 c;
gboolean ret = _parse_color (&c, str);
@@ -412,13 +412,13 @@ enum
};
static void
-_parse_dasharray (DiaSvgStyle *s, real user_scale, gchar *str, gchar **end)
+_parse_dasharray (DiaSvgStyle *s, double user_scale, char *str, char **end)
{
- gchar *ptr;
+ char *ptr;
/* by also splitting on ';' we can also parse the continued style string */
- gchar **dashes = g_regex_split_simple ("[\\s,;]+", (gchar *)str, 0, 0);
+ char **dashes = g_regex_split_simple ("[\\s,;]+", (char *)str, 0, 0);
int n = 0;
- real dl;
+ double dl;
s->dashlength = g_ascii_strtod(str, &ptr);
if (s->dashlength <= 0.0) /* e.g. "none" */
@@ -515,7 +515,7 @@ _style_adjust_font (DiaSvgStyle *s, const char *family, const char *style, const
* seen, like 'Arial'. If the given family name can not be resolved by
* Pango it complaints loudly with g_warning().
*/
- gchar **families = g_strsplit (family, ",", -1);
+ char **families = g_strsplit (family, ",", -1);
int i = 0;
gboolean found = FALSE;
while (!found && families[i]) {
@@ -550,7 +550,7 @@ _style_adjust_font (DiaSvgStyle *s, const char *family, const char *style, const
static void
-_parse_text_align(DiaSvgStyle *s, const gchar *ptr)
+_parse_text_align (DiaSvgStyle *s, const char *ptr)
{
if (!strncmp(ptr, "start", 5))
s->alignment = ALIGN_LEFT;
@@ -572,10 +572,10 @@ _parse_text_align(DiaSvgStyle *s, const gchar *ptr)
* \ingroup DiaSvg
*/
void
-dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str)
+dia_svg_parse_style_string (DiaSvgStyle *s, double user_scale, const char *str)
{
int i = 0;
- gchar *ptr = (gchar *)str;
+ char *ptr = (char *) str;
char *family = NULL, *style = NULL, *weight = NULL;
while (ptr[0] != '\0') {
@@ -658,7 +658,7 @@ dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str)
ptr += 13;
s->stop_opacity = g_ascii_strtod(ptr, &ptr);
} else if (!strncmp("opacity", ptr, 7)) {
- real opacity;
+ double opacity;
ptr += 7;
opacity = g_ascii_strtod(ptr, &ptr);
/* multiplicative effect of opacity */
@@ -751,14 +751,14 @@ dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str)
* \ingroup DiaSvg
*/
void
-dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
+dia_svg_parse_style (xmlNodePtr node, DiaSvgStyle *s, double user_scale)
{
xmlChar *str;
str = xmlGetProp(node, (const xmlChar *)"style");
if (str) {
- dia_svg_parse_style_string (s, user_scale, (gchar *)str);
+ dia_svg_parse_style_string (s, user_scale, (char *)str);
xmlFree(str);
}
@@ -774,7 +774,7 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
}
str = xmlGetProp(node, (const xmlChar *)"opacity");
if (str) {
- real opacity = g_ascii_strtod((char *) str, NULL);
+ double opacity = g_ascii_strtod ((char *) str, NULL);
/* multiplicative effect of opacity */
s->stroke_opacity *= opacity;
s->fill_opacity *= opacity;
@@ -823,19 +823,19 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
str = xmlGetProp(node, (const xmlChar *)"stroke-dasharray");
if (str) {
if (strcmp ((const char *)str, "inherit") != 0)
- _parse_dasharray (s, user_scale, (gchar *)str, NULL);
+ _parse_dasharray (s, user_scale, (char *)str, NULL);
xmlFree(str);
}
str = xmlGetProp(node, (const xmlChar *)"stroke-linejoin");
if (str) {
if (strcmp ((const char *)str, "inherit") != 0)
- _parse_linejoin (s, (gchar *)str);
+ _parse_linejoin (s, (char *)str);
xmlFree(str);
}
str = xmlGetProp(node, (const xmlChar *)"stroke-linecap");
if (str) {
if (strcmp ((const char *)str, "inherit") != 0)
- _parse_linecap (s, (gchar *)str);
+ _parse_linecap (s, (char *)str);
xmlFree(str);
}
@@ -846,7 +846,7 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
* should be initialized by parent style already
*/
if (strcmp ((const char *)str, "inherit") != 0) {
- s->font_height = g_ascii_strtod((gchar *)str, NULL);
+ s->font_height = g_ascii_strtod ((char *)str, NULL);
if (user_scale > 0)
s->font_height /= user_scale;
}
@@ -854,7 +854,7 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
}
str = xmlGetProp(node, (const xmlChar *)"text-anchor");
if (str) {
- _parse_text_align (s, (const gchar*)str);
+ _parse_text_align (s, (const char*) str);
xmlFree(str);
}
{
@@ -862,7 +862,7 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
xmlChar *slant = xmlGetProp(node, (const xmlChar *)"font-style");
xmlChar *weight = xmlGetProp(node, (const xmlChar *)"font-weight");
if (family || slant || weight) {
- _style_adjust_font (s, (gchar *)family, (gchar *)slant, (gchar *)weight);
+ _style_adjust_font (s, (char *)family, (char *)slant, (char *)weight);
if (family)
xmlFree(family);
@@ -874,37 +874,45 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
}
}
-/*!
- * \brief Parse a SVG description of an arc segment.
+
+/**
+ * _path_arc_segment:
+ * @points: destination array of #BezPoint
+ * @xc: center x
+ * @yc: center y
+ * @th0: first angle
+ * @th1: second angle
+ * @rx: radius x
+ * @ry: radius y
+ * @x_axis_rotation: rotation of the axis
+ * @last_p2: the resulting current point
+ *
+ * Parse a SVG description of an arc segment.
+ *
* Code stolen from (and adapted)
* http://www.inkscape.org/doc/doxygen/html/svg-path_8cpp.php#a7
* which may have got it from rsvg, hope it is correct ;)
- * @param points destination array of _BezPoint
- * @param xc center x
- * @param yc center y
- * @param th0 first angle
- * @param th1 second angle
- * @param rx radius x
- * @param ry radius y
- * @param x_axis_rotation rotation of the axis
- * @param last_p2 the resulting current point
+ *
* If you want the description of the algorithm read the SVG specs:
* http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
*/
static void
-_path_arc_segment(GArray* points,
- real xc, real yc,
- real th0, real th1,
- real rx, real ry,
- real x_axis_rotation,
- Point *last_p2)
+_path_arc_segment (GArray *points,
+ double xc,
+ double yc,
+ double th0,
+ double th1,
+ double rx,
+ double ry,
+ double x_axis_rotation,
+ Point *last_p2)
{
BezPoint bez;
- real sin_th, cos_th;
- real a00, a01, a10, a11;
- real x1, y1, x2, y2, x3, y3;
- real t;
- real th_half;
+ double sin_th, cos_th;
+ double a00, a01, a10, a11;
+ double x1, y1, x2, y2, x3, y3;
+ double t;
+ double th_half;
sin_th = sin (x_axis_rotation * (M_PI / 180.0));
cos_th = cos (x_axis_rotation * (M_PI / 180.0));
@@ -1032,20 +1040,21 @@ _path_arc (GArray *points,
/* routine to chomp off the start of the string */
#define path_chomp(path) while (path[0]!='\0'&&strchr(" \t\n\r,", path[0])) path++
-/*!
- * \brief Takes SVG path content and converts it in an array of BezPoint.
+/**
+ * dia_svg_parse_path:
+ * @path_str: A string describing an SVG path.
+ * @unparsed: The position in @path_str where parsing ended, or %NULL if
+ * the string was completely parsed. This should be used for
+ * calling the function until it is fully parsed.
+ * @closed: Whether the path was closed.
+ * @current_point: to retain it over splitting
+ *
+ * Takes SVG path content and converts it in an array of BezPoint.
*
* SVG pathes can contain multiple MOVE_TO commands while Dia's bezier
* object can only contain one so you may need to call this function
* multiple times.
*
- * @param path_str A string describing an SVG path.
- * @param unparsed The position in `path_str' where parsing ended, or NULL if
- * the string was completely parsed. This should be used for
- * calling the function until it is fully parsed.
- * @param closed Whether the path was closed.
- * @param current_point to retain it over splitting
- * @return TRUE if there is any useful data in parsed to points
* @bug This function is way too long (324 lines). So dont touch it. please!
* Shouldn't we try to turn straight lines, simple arc, polylines and
* zigzaglines into their appropriate objects? Could either be done by
@@ -1053,10 +1062,15 @@ _path_arc (GArray *points,
* specific simple paths.
* NOPE: Dia is capable to handle beziers and the file has given us some so
* WHY should be break it in to pieces ???
+ *
+ * Returns: %TRUE if there is any useful data in parsed to points
*/
gboolean
-dia_svg_parse_path(GArray *points, const gchar *path_str, gchar **unparsed,
- gboolean *closed, Point *current_point)
+dia_svg_parse_path (GArray *points,
+ const char *path_str,
+ char **unparsed,
+ gboolean *closed,
+ Point *current_point)
{
enum {
PATH_MOVE, PATH_LINE, PATH_HLINE, PATH_VLINE, PATH_CURVE,
@@ -1067,7 +1081,7 @@ dia_svg_parse_path(GArray *points, const gchar *path_str, gchar **unparsed,
Point last_control = {0.0, 0.0};
gboolean last_relative = FALSE;
BezPoint bez = { 0, };
- gchar *path = (gchar *)path_str;
+ char *path = (char *)path_str;
gboolean need_next_element = FALSE;
/* we can grow the same array in multiple steps */
gsize points_at_start = points->len;
@@ -1378,7 +1392,7 @@ dia_svg_parse_path(GArray *points, const gchar *path_str, gchar **unparsed,
break;
case PATH_QUBICCURVE: {
/* raise quadratic bezier to cubic (copied from librsvg) */
- real x1, y1;
+ double x1, y1;
x1 = g_ascii_strtod (path, &path);
path_chomp (path);
y1 = g_ascii_strtod (path, &path);
@@ -1435,10 +1449,10 @@ dia_svg_parse_path(GArray *points, const gchar *path_str, gchar **unparsed,
break;
case PATH_ARC:
{
- real rx, ry;
- real xrot;
- int largearc, sweep;
- Point dest, dest_c;
+ double rx, ry;
+ double xrot;
+ int largearc, sweep;
+ Point dest, dest_c;
dest_c.x=0;
dest_c.y=0;
@@ -1549,143 +1563,226 @@ MORETOPARSE:
static gboolean
-_parse_transform (const gchar *trans, DiaMatrix *m, real scale)
+_parse_transform (const char *trans, graphene_matrix_t *m, double scale)
{
- gchar **list;
- gchar *p = strchr (trans, '(');
+ char **list;
+ char *p = strchr (trans, '(');
int i = 0;
while ( (*trans != '\0')
- && (*trans == ' ' || *trans == ',' || *trans == '\t' || *trans == '\n' || *trans == '\r'))
+ && (*trans == ' ' || *trans == ',' || *trans == '\t' ||
+ *trans == '\n' || *trans == '\r')) {
++trans; /* skip whitespace */
+ }
- if (!p || !*trans)
+ if (!p || !*trans) {
return FALSE; /* silently fail */
+ }
- list = g_regex_split_simple ("[\\s,]+", p+1, 0, 0);
+ list = g_regex_split_simple ("[\\s,]+", p + 1, 0, 0);
if (strncmp (trans, "matrix", 6) == 0) {
- if (list[i])
- m->xx = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->yx = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->xy = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->yy = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->x0 = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->y0 = g_ascii_strtod (list[i], NULL), ++i;
+ float xx = 0, yx = 0, xy = 0, yy = 0, x0 = 0, y0 = 0;
+
+ if (list[i]) {
+ xx = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ yx = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ xy = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ yy = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ x0 = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ y0 = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ graphene_matrix_init_from_2d (m, xx, yx, xy, yy, x0 / scale, y0 / scale);
} else if (strncmp (trans, "translate", 9) == 0) {
- m->xx = m->yy = 1.0;
- if (list[i])
- m->x0 = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->y0 = g_ascii_strtod (list[i], NULL), ++i;
+ double x0 = 0, y0 = 0;
+
+ if (list[i]) {
+ x0 = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ y0 = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ graphene_matrix_init_translate (m, &GRAPHENE_POINT3D_INIT (x0 / scale, y0 / scale, 0));
} else if (strncmp (trans, "scale", 5) == 0) {
- if (list[i])
- m->xx = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- m->yy = g_ascii_strtod (list[i], NULL), ++i;
- else
- m->yy = m->xx;
+ double xx = 0, yy = 0;
+
+ if (list[i]) {
+ xx = g_ascii_strtod (list[i], NULL);
+ ++i;
+ }
+
+ if (list[i]) {
+ yy = g_ascii_strtod (list[i], NULL);
+ ++i;
+ } else {
+ yy = xx;
+ }
+
+ graphene_matrix_init_scale (m, xx, yy, 1.0);
} else if (strncmp (trans, "rotate", 6) == 0) {
- DiaMatrix translate = {1, 0, 0, 1, 0, 0 };
- real angle;
+ double angle = 0;
+ double cx = 0, cy = 0;
- if (list[i])
- angle = g_ascii_strtod (list[i], NULL), ++i;
- else {
- angle = 0;
+ if (list[i]) {
+ angle = g_ascii_strtod (list[i], NULL);
+ ++i;
+ } else {
g_warning ("transform=rotate no angle?");
}
- m->xx = cos(G_PI*angle/180);
- m->yx = sin(G_PI*angle/180);
- m->xy = -sin(G_PI*angle/180);
- m->yy = cos(G_PI*angle/180);
+
/* FIXME: check with real world data, I'm uncertain */
+ /* rotate around the given offset */
if (list[i]) {
- real cx, cy;
- cx = g_ascii_strtod (list[i], NULL), ++i;
- if (list[i])
- cy = g_ascii_strtod (list[i], NULL), ++i;
- else
+ graphene_point3d_t point;
+
+ cx = g_ascii_strtod (list[i], NULL);
+ ++i;
+
+ if (list[i]) {
+ cy = g_ascii_strtod (list[i], NULL);
+ ++i;
+ } else {
cy = 0.0; /* if offsets don't come in pairs */
- /* rotate around the given offset */
- translate.x0 = cx;
- translate.y0 = cy;
- dia_matrix_multiply (m, m, &translate);
- translate.x0 = -cx;
- translate.y0 = -cy;
- dia_matrix_multiply (m, &translate, m);
+ }
+
+ /* translate by -cx,-cy */
+ graphene_point3d_init (&point, -(cx / scale), -(cy / scale), 0);
+ graphene_matrix_init_translate (m, &point);
+
+ /* rotate by angle */
+ graphene_matrix_rotate_z (m, angle);
+
+ /* translate by cx,cy */
+ graphene_point3d_init (&point, cx / scale, cy / scale, 0);
+ graphene_matrix_translate (m, &point);
+ } else {
+ graphene_matrix_init_rotate (m, angle, graphene_vec3_z_axis ());
}
} else if (strncmp (trans, "skewX", 5) == 0) {
- m->xx = m->yy = 1.0;
- if (list[i])
- m->xy = tan (G_PI*g_ascii_strtod (list[i], NULL)/180);
+ float skew = 0;
+
+ if (list[i]) {
+ skew = g_ascii_strtod (list[i], NULL);
+ }
+
+ graphene_matrix_init_skew (m, DIA_RADIANS (skew), 0);
} else if (strncmp (trans, "skewY", 5) == 0) {
- m->xx = m->yy = 1.0;
- if (list[i])
- m->yx = tan (G_PI*g_ascii_strtod (list[i], NULL)/180);
+ float skew = 0;
+
+ if (list[i]) {
+ skew = g_ascii_strtod (list[i], NULL);
+ }
+
+ graphene_matrix_init_skew (m, 0, DIA_RADIANS (skew));
} else {
g_warning ("SVG: %s?", trans);
+
return FALSE;
}
- g_strfreev(list);
- if (scale > 0 && m) {
- m->x0 /= scale;
- m->y0 /= scale;
- }
+ g_clear_pointer (&list, g_strfreev);
+
return TRUE;
}
-DiaMatrix *
-dia_svg_parse_transform(const gchar *trans, real scale)
+
+graphene_matrix_t *
+dia_svg_parse_transform (const char *trans, double scale)
{
- DiaMatrix *m = NULL;
- gchar **transforms = g_regex_split_simple ("\\)", trans, 0, 0);
+ graphene_matrix_t *m = NULL;
+ char **transforms = g_regex_split_simple ("\\)", trans, 0, 0);
int i = 0;
/* go through the list of transformations - not that one would be enough ;) */
while (transforms[i]) {
- DiaMatrix mat = { 0, };
+ graphene_matrix_t mat;
if (_parse_transform (transforms[i], &mat, scale)) {
if (!m) {
- m = g_new0 (DiaMatrix, 1);
- *m = mat;
+ m = graphene_matrix_alloc ();
+ graphene_matrix_init_from_matrix (m, &mat);
} else {
- dia_matrix_multiply (m, &mat, m);
+ graphene_matrix_multiply (m, &mat, m);
}
}
++i;
}
- g_strfreev(transforms);
+
+ g_clear_pointer (&transforms, g_strfreev);
return m;
}
-gchar *
-dia_svg_from_matrix(const DiaMatrix *matrix, real scale)
+
+char *
+dia_svg_from_matrix (const graphene_matrix_t *matrix, double scale)
{
/* transform="matrix(1,0,0,1,0,0)" */
- gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
GString *sm = g_string_new ("matrix(");
- gchar *s;
-
- g_ascii_formatd (buf, sizeof(buf), "%g", matrix->xx);
- g_string_append (sm, buf); g_string_append (sm, ",");
- g_ascii_formatd (buf, sizeof(buf), "%g", matrix->yx);
- g_string_append (sm, buf); g_string_append (sm, ",");
- g_ascii_formatd (buf, sizeof(buf), "%g", matrix->xy);
- g_string_append (sm, buf); g_string_append (sm, ",");
- g_ascii_formatd (buf, sizeof(buf), "%g", matrix->yy);
- g_string_append (sm, buf); g_string_append (sm, ",");
- g_ascii_formatd (buf, sizeof(buf), "%g", matrix->x0 * scale);
- g_string_append (sm, buf); g_string_append (sm, ",");
- g_ascii_formatd (buf, sizeof(buf), "%g", matrix->y0 * scale);
- g_string_append (sm, buf); g_string_append (sm, ")");
+ char *s;
+
+ g_ascii_formatd (buf,
+ sizeof (buf),
+ "%g",
+ graphene_matrix_get_value (matrix, 0, 0));
+ g_string_append (sm, buf);
+ g_string_append (sm, ",");
+ g_ascii_formatd (buf,
+ sizeof (buf),
+ "%g",
+ graphene_matrix_get_value (matrix, 0, 1));
+ g_string_append (sm, buf);
+ g_string_append (sm, ",");
+ g_ascii_formatd (buf,
+ sizeof (buf),
+ "%g",
+ graphene_matrix_get_value (matrix, 1, 0));
+ g_string_append (sm, buf);
+ g_string_append (sm, ",");
+ g_ascii_formatd (buf,
+ sizeof (buf),
+ "%g",
+ graphene_matrix_get_value (matrix, 1, 1));
+ g_string_append (sm, buf);
+ g_string_append (sm, ",");
+ g_ascii_formatd (buf,
+ sizeof (buf),
+ "%g",
+ graphene_matrix_get_x_translation (matrix) * scale);
+ g_string_append (sm, buf);
+ g_string_append (sm, ",");
+ g_ascii_formatd (buf,
+ sizeof (buf),
+ "%g",
+ graphene_matrix_get_y_translation (matrix) * scale);
+ g_string_append (sm, buf);
+ g_string_append (sm, ")");
s = sm->str;
g_string_free (sm, FALSE);
diff --git a/lib/dia_svg.h b/lib/dia_svg.h
index 08beca3e..cdb7155e 100644
--- a/lib/dia_svg.h
+++ b/lib/dia_svg.h
@@ -16,15 +16,15 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef DIA_SVG_H
-#define DIA_SVG_H
+#pragma once
+
+#include <graphene.h>
#include "dia_xml.h"
#include "font.h"
/* special colours */
-enum DiaSvgColours
-{
+enum DiaSvgColours {
DIA_SVG_COLOUR_NONE = -1,
DIA_SVG_COLOUR_FOREGROUND = -2,
DIA_SVG_COLOUR_BACKGROUND = -3,
@@ -35,34 +35,45 @@ enum DiaSvgColours
typedef struct _DiaSvgStyle DiaSvgStyle;
struct _DiaSvgStyle {
- real line_width;
+ double line_width;
gint32 stroke;
- real stroke_opacity;
+ double stroke_opacity;
gint32 fill;
- real fill_opacity;
+ double fill_opacity;
LineCaps linecap;
LineJoin linejoin;
LineStyle linestyle;
- real dashlength;
+ double dashlength;
DiaFont *font;
- real font_height;
+ double font_height;
Alignment alignment;
gint32 stop_color;
- real stop_opacity;
+ double stop_opacity;
};
-void dia_svg_style_init (DiaSvgStyle *gs, DiaSvgStyle *parent_style);
-void dia_svg_style_copy (DiaSvgStyle *dest, DiaSvgStyle *src);
-gboolean dia_svg_parse_color(const gchar *str, Color *color);
-void dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale);
-void dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str);
-/* parse the svg sub format for pathes int an array of BezPoint */
-gboolean dia_svg_parse_path(GArray *points, const gchar *path_str, gchar **unparsed,
- gboolean *closed, Point *current_point);
-DiaMatrix *dia_svg_parse_transform(const gchar *trans, real scale);
-gchar *dia_svg_from_matrix(const DiaMatrix *matrix, real scale);
-#endif /* DIA_SVG_H */
+void dia_svg_style_init (DiaSvgStyle *gs,
+ DiaSvgStyle *parent_style);
+void dia_svg_style_copy (DiaSvgStyle *dest,
+ DiaSvgStyle *src);
+gboolean dia_svg_parse_color (const char *str,
+ Color *color);
+void dia_svg_parse_style (xmlNodePtr node,
+ DiaSvgStyle *s,
+ double user_scale);
+void dia_svg_parse_style_string (DiaSvgStyle *s,
+ double user_scale,
+ const char *str);
+/* parse the svg sub format for pathes int an array of BezPoint */
+gboolean dia_svg_parse_path (GArray *points,
+ const char *path_str,
+ char **unparsed,
+ gboolean *closed,
+ Point *current_point);
+graphene_matrix_t *dia_svg_parse_transform (const char *trans,
+ double scale);
+char *dia_svg_from_matrix (const graphene_matrix_t *matrix,
+ double scale);
diff --git a/lib/geometry.h b/lib/geometry.h
index ef0ce36c..05e964c4 100644
--- a/lib/geometry.h
+++ b/lib/geometry.h
@@ -68,6 +68,9 @@
G_BEGIN_DECLS
+#define DIA_RADIANS(degrees) ((degrees) * G_PI / 180.0)
+#define DIA_DEGREES(radians) ((radians) * 180.0 / G_PI)
+
/*
Coordinate system used:
diff --git a/lib/meson.build b/lib/meson.build
index 634981e4..a9c40d36 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -160,6 +160,7 @@ libdia_sources = stdprop_sources + [
'dia-simple-list.c',
'dia-simple-list.h',
'dia-autoptr.h',
+ 'dia-graphene.h',
]
gnome = import('gnome')
@@ -187,6 +188,7 @@ libdia_deps = [
libm_dep,
libzlib_dep,
gmodule_dep,
+ graphene_dep,
]
libdia_inc = include_directories('.')
diff --git a/meson.build b/meson.build
index ea54a764..9dd51821 100644
--- a/meson.build
+++ b/meson.build
@@ -15,6 +15,7 @@ libxml_dep = dependency('libxml-2.0', version: '>= 2.9.4')
gmodule_dep = dependency('gmodule-2.0')
libzlib_dep = dependency('zlib')
libcairo_dep = dependency('cairo')
+graphene_dep = dependency('graphene-1.0')
# Not required since not all platforms ship a separate libm.
libm_dep = cc.find_library('m', required: false)
diff --git a/plug-ins/svg/render_svg.c b/plug-ins/svg/render_svg.c
index 2a3dccca..fe084553 100644
--- a/plug-ins/svg/render_svg.c
+++ b/plug-ins/svg/render_svg.c
@@ -47,6 +47,7 @@
#include "textline.h"
#include "dia_svg.h"
#include "dia-layer.h"
+#include "dia-graphene.h"
G_BEGIN_DECLS
@@ -352,23 +353,37 @@ draw_object(DiaRenderer *self,
GList *objs = group_objects (object);
if (gm) {
- char *s = dia_svg_from_matrix (gm, renderer->scale);
- xmlSetProp(renderer->root, (const xmlChar *)"transform", (xmlChar *) s);
+ char *s;
+ graphene_matrix_t graphene_matrix;
+
+ dia_graphene_from_matrix (&graphene_matrix, gm);
+
+ s = dia_svg_from_matrix (&graphene_matrix, renderer->scale);
+
+ xmlSetProp (renderer->root, (const xmlChar *) "transform", (xmlChar *) s);
+
g_clear_pointer (&s, g_free);
}
while (objs) {
DiaObject *obj = (DiaObject *)objs->data;
- obj->ops->draw(obj, DIA_RENDERER (renderer));
+ dia_object_draw (obj, DIA_RENDERER (renderer));
objs = objs->next;
}
renderer->root = g_queue_pop_tail (svg_renderer->parents);
xmlAddChild (renderer->root, group);
} else {
if (matrix) {
- char *s = dia_svg_from_matrix (matrix, renderer->scale);
+ char *s;
+ graphene_matrix_t graphene_matrix;
+
+ dia_graphene_from_matrix (&graphene_matrix, matrix);
+
+ s = dia_svg_from_matrix (&graphene_matrix, renderer->scale);
+
xmlSetProp(renderer->root, (const xmlChar *)"transform", (xmlChar *) s);
+
g_clear_pointer (&s, g_free);
}
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 93b700d7..11fd7a4b 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -50,11 +50,14 @@
#include "attributes.h"
#include "pattern.h"
#include "dia-layer.h"
+#include "dia-graphene.h"
-/*!
- * \defgroup SvgImport Import SVG
- * \ingroup SvgPlugin
- * \brief Based on \ref DiaSvg this plug-in translates SVG to Dia \ref StandardObjects.
+/**
+ * SECTION:svg-import
+ *
+ * Import SVG
+ *
+ * Based on \ref DiaSvg this plug-in translates SVG to Dia \ref StandardObjects.
*
* Sometimes SVG import is the only way to create complex objects ...
*/
@@ -156,20 +159,23 @@ static PropDescription _arrow_prop_descs[] = {
PROP_DESC_END
};
+
static void
reset_arrows (DiaObject *obj)
{
- GPtrArray *props;
- int i;
-
- props = prop_list_from_descs(_arrow_prop_descs,pdtpp_true);
- g_assert(props->len == 2);
- for (i = 0; i < 2; ++i)
- ((ArrowProperty *)g_ptr_array_index(props, 0))->arrow_data.type = ARROW_NONE;
- obj->ops->set_props(obj, props);
- prop_list_free(props);
+ GPtrArray *props;
+ int i;
+
+ props = prop_list_from_descs (_arrow_prop_descs, pdtpp_true);
+ g_return_if_fail (props->len == 2);
+ for (i = 0; i < 2; ++i) {
+ ((ArrowProperty *) g_ptr_array_index (props, 0))->arrow_data.type = ARROW_NONE;
+ }
+ dia_object_set_properties (obj, props);
+ prop_list_free (props);
}
+
static GPtrArray *
make_element_props(real xpos, real ypos,
real width, real height)
@@ -211,15 +217,15 @@ _node_get_real (xmlNodePtr node, const char *name, real defval)
return val;
}
+
static void
_transform_object (DiaObject *obj, DiaMatrix *m, DiaContext *ctx)
{
- g_return_if_fail (obj->ops->transform != NULL);
-
- if (!obj->ops->transform (obj, m))
+ if (!dia_object_transform (obj, m)) {
dia_context_add_message (ctx,
- _("Failed to apply transformation for '%s'"),
- obj->type->name);
+ _("Failed to apply transformation for '%s'"),
+ obj->type->name);
+ }
}
@@ -244,7 +250,10 @@ use_position (DiaObject *obj, xmlNodePtr node, DiaContext *ctx)
str = xmlGetProp(node, (const xmlChar *)"transform");
if (str) {
- DiaMatrix *m = dia_svg_parse_transform ((char *) str, user_scale);
+ graphene_matrix_t *graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+ DiaMatrix *m = g_new0 (DiaMatrix, 1);
+
+ dia_matrix_from_graphene (m, graphene_matrix);
if (m) {
if (obj->ops->transform) {
@@ -276,7 +285,7 @@ use_position (DiaObject *obj, xmlNodePtr node, DiaContext *ctx)
pr = g_ptr_array_index (props, 3);
pr->real_data *= m->yy;
- obj->ops->set_props (obj, props);
+ dia_object_set_properties (obj, props);
prop_list_free (props);
}
g_clear_pointer (&m, g_free);
@@ -432,137 +441,151 @@ _set_pattern_from_key (DiaObject *obj,
}
-/*!
- * \brief apply SVG style to object
+/**
+ * apply_style
+ *
+ * Apply SVG style to object
+ *
* Styling with SVG is a complicated thing. The style can be given with:
* - single attributes on the node
* - a style attribute on the node
* - accumulation from parent objects/groups
* - a reference to further information in single or style attribute
* - inheritance from object type, class, id or a combination thereof
- * This method uses all of this information to apply the best style approximation
- * possible with DIa's rendering model.
- * \ingroup SvgImport
+ *
+ * This method uses all of this information to apply the best style
+ * approximation possible with Dia's rendering model.
*/
static void
-apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht, gboolean init)
+apply_style (DiaObject *obj,
+ xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ gboolean init)
{
- DiaSvgStyle *gs;
- GPtrArray *props;
- LinestyleProperty *lsprop;
- ColorProperty *cprop;
- RealProperty *rprop;
- BoolProperty *bprop;
- EnumProperty *eprop;
- real scale = 1.0;
+ DiaSvgStyle *gs;
+ GPtrArray *props;
+ LinestyleProperty *lsprop;
+ ColorProperty *cprop;
+ RealProperty *rprop;
+ BoolProperty *bprop;
+ EnumProperty *eprop;
+ real scale = 1.0;
- xmlChar *str = xmlGetProp(node, (const xmlChar *)"transform");
- if (str) {
- DiaMatrix *m = dia_svg_parse_transform ((char *)str, user_scale);
- if (m) {
- transform_length (&scale, m);
- g_clear_pointer (&m, g_free);
- }
- xmlFree(str);
- }
- gs = g_new0(DiaSvgStyle, 1);
- /* SVG defaults */
- dia_svg_style_init (gs, parent_style);
- _node_css_parse_style (node, gs, user_scale, style_ht);
- dia_svg_parse_style(node, gs, user_scale);
- props = prop_list_from_descs(svg_style_prop_descs, pdtpp_true);
- g_assert(props->len == 7);
-
- cprop = g_ptr_array_index(props,0);
- if (gs->stroke == DIA_SVG_COLOUR_DEFAULT) {
- if (init) /* no stroke */
- cprop->color_data = get_colour(0xFFFFFF, 0.0);
- else /* leave it alone */
- cprop->common.experience |= PXP_NOTSET; /* no overwrite */
- } else if (gs->stroke == DIA_SVG_COLOUR_NONE) /* transparent */
- cprop->color_data = get_colour(0xFFFFFF, 0.0);
- else if (gs->stroke == DIA_SVG_COLOUR_FOREGROUND)
- cprop->color_data = attributes_get_foreground();
- else if (gs->stroke == DIA_SVG_COLOUR_BACKGROUND)
- cprop->color_data = attributes_get_background();
- else
- cprop->color_data = get_colour(gs->stroke, gs->stroke_opacity);
-
- rprop = g_ptr_array_index(props,1);
- rprop->real_data = gs->line_width * scale;
-
- lsprop = g_ptr_array_index(props,2);
- if (gs->linestyle != LINESTYLE_DEFAULT)
- lsprop->style = gs->linestyle;
- else if (init)
- lsprop->style = LINESTYLE_SOLID;
- else
- lsprop->common.experience |= PXP_NOTSET; /* no overwrite */
- lsprop->dash = gs->dashlength * scale;
-
- cprop = g_ptr_array_index(props,3);
- if (gs->fill == DIA_SVG_COLOUR_DEFAULT) {
- if (init)
- cprop->color_data = get_colour(0x000000, gs->fill_opacity); /* black */
- else
- cprop->common.experience |= PXP_NOTSET; /* no overwrite */
- } else if (gs->fill == DIA_SVG_COLOUR_NONE) /* transparent */
- cprop->color_data = get_colour(0x000000, 0.0);
- else if (gs->fill == DIA_SVG_COLOUR_FOREGROUND)
- cprop->color_data = attributes_get_foreground();
- else if (gs->fill == DIA_SVG_COLOUR_BACKGROUND)
- cprop->color_data = attributes_get_background();
- else
- cprop->color_data = get_colour(gs->fill, gs->fill_opacity);
-
- bprop = g_ptr_array_index(props,4);
- if(gs->fill == DIA_SVG_COLOUR_NONE || gs->fill_opacity == 0) {
- bprop->bool_data = FALSE;
- } else {
- if (init)
- bprop->bool_data = TRUE;
- else
- bprop->common.experience |= PXP_NOTSET; /* no overwrite */
- }
- /* apply pattern, gradient if any */
- str = xmlGetProp(node, (const xmlChar *)"fill");
- if (str) {
- const char *left = strstr ((const char*)str, "url(#");
- const char *right = strrchr ((const char*)str, ')');
- if (left && right) {
- char *key = g_strndup (left + 5, right - left - 5);
- _set_pattern_from_key (obj, bprop, pattern_ht, key);
- g_clear_pointer (&key, g_free);
- }
- xmlFree(str);
- } else if (gs->fill == DIA_SVG_COLOUR_NONE) {
- /* check the style again, it might contain a pattern */
- str = xmlGetProp(node, (const xmlChar*)"style");
- if (str) {
- const char *left = strstr ((const char*)str, "fill:url(#");
- const char *right = left ? strrchr (left, ')') : NULL;
- if (left && right) {
- char *key = g_strndup (left + 10, right - left - 10);
- _set_pattern_from_key (obj, bprop, pattern_ht, key);
- g_clear_pointer (&key, g_free);
- }
- xmlFree (str);
- }
+ xmlChar *str = xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ graphene_matrix_t *graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+ DiaMatrix *m = g_new0 (DiaMatrix, 1);
+
+ dia_matrix_from_graphene (m, graphene_matrix);
+
+ if (m) {
+ transform_length (&scale, m);
+ g_clear_pointer (&m, g_free);
+ g_clear_pointer (&graphene_matrix, graphene_matrix_free);
+ }
+
+ xmlFree(str);
+ }
+ gs = g_new0(DiaSvgStyle, 1);
+ /* SVG defaults */
+ dia_svg_style_init (gs, parent_style);
+ _node_css_parse_style (node, gs, user_scale, style_ht);
+ dia_svg_parse_style(node, gs, user_scale);
+ props = prop_list_from_descs(svg_style_prop_descs, pdtpp_true);
+ g_assert(props->len == 7);
+
+ cprop = g_ptr_array_index(props,0);
+ if (gs->stroke == DIA_SVG_COLOUR_DEFAULT) {
+ if (init) /* no stroke */
+ cprop->color_data = get_colour(0xFFFFFF, 0.0);
+ else /* leave it alone */
+ cprop->common.experience |= PXP_NOTSET; /* no overwrite */
+ } else if (gs->stroke == DIA_SVG_COLOUR_NONE) /* transparent */
+ cprop->color_data = get_colour(0xFFFFFF, 0.0);
+ else if (gs->stroke == DIA_SVG_COLOUR_FOREGROUND)
+ cprop->color_data = attributes_get_foreground();
+ else if (gs->stroke == DIA_SVG_COLOUR_BACKGROUND)
+ cprop->color_data = attributes_get_background();
+ else
+ cprop->color_data = get_colour(gs->stroke, gs->stroke_opacity);
+
+ rprop = g_ptr_array_index(props,1);
+ rprop->real_data = gs->line_width * scale;
+
+ lsprop = g_ptr_array_index(props,2);
+ if (gs->linestyle != LINESTYLE_DEFAULT)
+ lsprop->style = gs->linestyle;
+ else if (init)
+ lsprop->style = LINESTYLE_SOLID;
+ else
+ lsprop->common.experience |= PXP_NOTSET; /* no overwrite */
+ lsprop->dash = gs->dashlength * scale;
+
+ cprop = g_ptr_array_index(props,3);
+ if (gs->fill == DIA_SVG_COLOUR_DEFAULT) {
+ if (init)
+ cprop->color_data = get_colour(0x000000, gs->fill_opacity); /* black */
+ else
+ cprop->common.experience |= PXP_NOTSET; /* no overwrite */
+ } else if (gs->fill == DIA_SVG_COLOUR_NONE) /* transparent */
+ cprop->color_data = get_colour(0x000000, 0.0);
+ else if (gs->fill == DIA_SVG_COLOUR_FOREGROUND)
+ cprop->color_data = attributes_get_foreground();
+ else if (gs->fill == DIA_SVG_COLOUR_BACKGROUND)
+ cprop->color_data = attributes_get_background();
+ else
+ cprop->color_data = get_colour(gs->fill, gs->fill_opacity);
+
+ bprop = g_ptr_array_index(props,4);
+ if(gs->fill == DIA_SVG_COLOUR_NONE || gs->fill_opacity == 0) {
+ bprop->bool_data = FALSE;
+ } else {
+ if (init)
+ bprop->bool_data = TRUE;
+ else
+ bprop->common.experience |= PXP_NOTSET; /* no overwrite */
+ }
+
+ /* apply pattern, gradient if any */
+ str = xmlGetProp(node, (const xmlChar *)"fill");
+ if (str) {
+ const char *left = strstr ((const char*)str, "url(#");
+ const char *right = strrchr ((const char*)str, ')');
+ if (left && right) {
+ char *key = g_strndup (left + 5, right - left - 5);
+ _set_pattern_from_key (obj, bprop, pattern_ht, key);
+ g_clear_pointer (&key, g_free);
+ }
+ xmlFree(str);
+ } else if (gs->fill == DIA_SVG_COLOUR_NONE) {
+ /* check the style again, it might contain a pattern */
+ str = xmlGetProp(node, (const xmlChar*)"style");
+ if (str) {
+ const char *left = strstr ((const char*)str, "fill:url(#");
+ const char *right = left ? strrchr (left, ')') : NULL;
+ if (left && right) {
+ char *key = g_strndup (left + 10, right - left - 10);
+ _set_pattern_from_key (obj, bprop, pattern_ht, key);
+ g_clear_pointer (&key, g_free);
}
+ xmlFree (str);
+ }
+ }
- eprop = g_ptr_array_index(props,5);
- if (gs->linejoin != LINEJOIN_DEFAULT)
- eprop->enum_data = gs->linejoin;
- else
- eprop->common.experience |= PXP_NOTSET;
+ eprop = g_ptr_array_index(props,5);
+ if (gs->linejoin != LINEJOIN_DEFAULT)
+ eprop->enum_data = gs->linejoin;
+ else
+ eprop->common.experience |= PXP_NOTSET;
- eprop = g_ptr_array_index(props,6);
- if (gs->linecap != LINECAPS_DEFAULT)
- eprop->enum_data = gs->linecap;
- else
- eprop->common.experience |= PXP_NOTSET;
+ eprop = g_ptr_array_index(props,6);
+ if (gs->linecap != LINECAPS_DEFAULT)
+ eprop->enum_data = gs->linecap;
+ else
+ eprop->common.experience |= PXP_NOTSET;
dia_object_set_properties (obj, props);
@@ -570,6 +593,7 @@ apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style,
g_clear_pointer (&gs, g_free);
}
+
/*!
* \brief Elements (poly, path) can be closed style, too.
*
@@ -597,8 +621,10 @@ _node_closed_by_style (xmlNodePtr node, DiaSvgStyle *parent_style)
}
-/*!
- * \brief Read a SVG path element
+/**
+ * read_path_svg:
+ *
+ * Read a SVG path element
*
* This function parses a SVG path element into a Dia object. All
* the heavy lifting is done with dia_svg_parse_path() which is called multiple
@@ -611,118 +637,126 @@ _node_closed_by_style (xmlNodePtr node, DiaSvgStyle *parent_style)
* is not directly supported by Dia and also not especially useful.
* For path elements it is just an easy transformation of all the
* single points, so it is done here.
- *
- * \ingroup SvgImport
*/
static GList *
-read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, DiaContext *ctx)
+read_path_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ DiaContext *ctx)
{
- DiaObjectType *otype;
- DiaObject *new_obj;
- Handle *h1, *h2;
- BezierCreateData *bcd;
- xmlChar *str;
- char *pathdata, *unparsed = NULL;
- GArray *bezpoints = NULL;
- gboolean closed = FALSE;
- gint i;
- DiaMatrix *matrix = NULL;
- Point current_point = {0.0, 0.0};
- gboolean use_stdpath = FALSE;
- gboolean closed_by_style;
-
- str = xmlGetProp(node, (const xmlChar *)"transform");
- if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
- xmlFree (str);
+ DiaObjectType *otype;
+ DiaObject *new_obj;
+ Handle *h1, *h2;
+ BezierCreateData *bcd;
+ xmlChar *str;
+ char *pathdata, *unparsed = NULL;
+ GArray *bezpoints = NULL;
+ gboolean closed = FALSE;
+ gint i;
+ DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
+ Point current_point = {0.0, 0.0};
+ gboolean use_stdpath = FALSE;
+ gboolean closed_by_style;
+
+ str = xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+
+ xmlFree (str);
+ }
+
+ closed_by_style = _node_closed_by_style (node, parent_style);
+ str = xmlGetProp(node, (const xmlChar *)"d");
+ pathdata = (char *)str;
+ bezpoints = g_array_new(FALSE, FALSE, sizeof(BezPoint));
+ g_array_set_size(bezpoints, 0);
+ do {
+ int first = bezpoints->len;
+ if (!dia_svg_parse_path (bezpoints, pathdata, &unparsed, &closed, ¤t_point))
+ break;
+
+ if (!closed) {
+ /* expensive way to possibly close the path */
+ closed = closed_by_style;
+ /* if we close it here add an explicit line-to */
+ if (closed) {
+ BezPoint bp;
+
+ bp.type = BEZ_LINE_TO;
+ bp.p1 = g_array_index(bezpoints, BezPoint, first).p1;
+ g_array_append_val (bezpoints, bp);
+ }
}
+ if (unparsed) {
+ use_stdpath = TRUE;
+ } else if (bezpoints && bezpoints->len > 0) {
+ /* A stray 'z' can produce extra runs without adding any new BEZ_MOVE_TO.
+ * To have the optimum representation with Dia's objects we check again.
+ */
+ if (use_stdpath) {
+ int move_tos = 0;
+ for (i = 0; i < bezpoints->len; ++i)
+ if (g_array_index(bezpoints, BezPoint, i).type == BEZ_MOVE_TO)
+ ++move_tos;
+ use_stdpath = (move_tos > 1);
+ }
- closed_by_style = _node_closed_by_style (node, parent_style);
- str = xmlGetProp(node, (const xmlChar *)"d");
- pathdata = (char *)str;
- bezpoints = g_array_new(FALSE, FALSE, sizeof(BezPoint));
- g_array_set_size(bezpoints, 0);
- do {
- int first = bezpoints->len;
- if (!dia_svg_parse_path (bezpoints, pathdata, &unparsed, &closed, ¤t_point))
+ if (g_array_index(bezpoints, BezPoint, 0).type != BEZ_MOVE_TO) {
+ dia_context_add_message(ctx, _("Invalid path data.\n"
+ "svg:path data must start with moveto."));
break;
+ } else if (use_stdpath) {
+ otype = object_get_type("Standard - Path");
+ } else if (!closed) {
+ otype = object_get_type("Standard - BezierLine");
+ } else if (bezpoints->len < 3) { /* error path: invalid input or parsing error? */
+ /* Our beziergon can not handle less than three points
+ * So line-to the first point again...
+ */
+ BezPoint bpz = g_array_index(bezpoints, BezPoint, 0);
+ bpz.type = BEZ_LINE_TO;
+ g_array_append_val(bezpoints, bpz);
+ otype = object_get_type("Standard - Beziergon");
+ } else {
+ otype = object_get_type("Standard - Beziergon");
+ }
- if (!closed) {
- /* expensive way to possibly close the path */
- closed = closed_by_style;
- /* if we close it here add an explicit line-to */
- if (closed) {
- BezPoint bp;
-
- bp.type = BEZ_LINE_TO;
- bp.p1 = g_array_index(bezpoints, BezPoint, first).p1;
- g_array_append_val (bezpoints, bp);
- }
+ if (otype == NULL){
+ dia_context_add_message(ctx, _("Can't find standard object"));
+ break;
}
- if (unparsed) {
- use_stdpath = TRUE;
- } else if (bezpoints && bezpoints->len > 0) {
- /* A stray 'z' can produce extra runs without adding any new BEZ_MOVE_TO.
- * To have the optimum representation with Dia's objects we check again.
- */
- if (use_stdpath) {
- int move_tos = 0;
- for (i = 0; i < bezpoints->len; ++i)
- if (g_array_index(bezpoints, BezPoint, i).type == BEZ_MOVE_TO)
- ++move_tos;
- use_stdpath = (move_tos > 1);
- }
- if (g_array_index(bezpoints, BezPoint, 0).type != BEZ_MOVE_TO) {
- dia_context_add_message(ctx, _("Invalid path data.\n"
- "svg:path data must start with moveto."));
- break;
- } else if (use_stdpath) {
- otype = object_get_type("Standard - Path");
- } else if (!closed) {
- otype = object_get_type("Standard - BezierLine");
- } else if (bezpoints->len < 3) { /* error path: invalid input or parsing error? */
- /* Our beziergon can not handle less than three points
- * So line-to the first point again...
- */
- BezPoint bpz = g_array_index(bezpoints, BezPoint, 0);
- bpz.type = BEZ_LINE_TO;
- g_array_append_val(bezpoints, bpz);
- otype = object_get_type("Standard - Beziergon");
- } else {
- otype = object_get_type("Standard - Beziergon");
- }
- if (otype == NULL){
- dia_context_add_message(ctx, _("Can't find standard object"));
- break;
- }
- bcd = g_new(BezierCreateData, 1);
- bcd->num_points = bezpoints->len;
- bcd->points = &(g_array_index(bezpoints, BezPoint, 0));
- /* dia_svg_parse_path does not scale to the user coordinate system, do it here */
- for (i = 0; i < bcd->num_points; ++i) {
- bcd->points[i].p1.x /= user_scale;
- bcd->points[i].p1.y /= user_scale;
- bcd->points[i].p2.x /= user_scale;
- 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)
- reset_arrows (new_obj);
- g_clear_pointer (&bcd, g_free);
- apply_style(new_obj, node, parent_style, style_ht, pattern_ht, TRUE);
- list = g_list_append (list, new_obj);
-
- g_array_set_size (bezpoints, 0);
+ bcd = g_new(BezierCreateData, 1);
+ bcd->num_points = bezpoints->len;
+ bcd->points = &(g_array_index(bezpoints, BezPoint, 0));
+ /* dia_svg_parse_path does not scale to the user coordinate system, do it here */
+ for (i = 0; i < bcd->num_points; ++i) {
+ bcd->points[i].p1.x /= user_scale;
+ bcd->points[i].p1.y /= user_scale;
+ bcd->points[i].p2.x /= user_scale;
+ 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);
}
- pathdata = unparsed;
- unparsed = NULL;
- } while (pathdata);
+ new_obj = otype->ops->create(NULL, bcd, &h1, &h2);
+ if (!closed)
+ reset_arrows (new_obj);
+ g_clear_pointer (&bcd, g_free);
+ apply_style(new_obj, node, parent_style, style_ht, pattern_ht, TRUE);
+ list = g_list_append (list, new_obj);
+
+ g_array_set_size (bezpoints, 0);
+ }
+ pathdata = unparsed;
+ unparsed = NULL;
+ } while (pathdata);
if (bezpoints) {
g_array_free (bezpoints, TRUE);
@@ -737,250 +771,281 @@ read_path_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
return list;
}
-/*!
- * \brief Read a SVG text element
- * \ingroup SvgImport
+
+/**
+ * read_text_svg:
+ *
+ * Read a SVG text element
*/
static GList *
-read_text_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, DiaContext *ctx)
+read_text_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ DiaContext *ctx)
{
- DiaObjectType *otype = object_get_type("Standard - Text");
- DiaObject *new_obj;
- Handle *h1, *h2;
- Point point;
- GPtrArray *props;
- TextProperty *prop;
- xmlChar *str = NULL;
- gchar *multiline = NULL;
- DiaSvgStyle *gs;
- gboolean any_tspan = FALSE;
- DiaMatrix *matrix = NULL;
- real font_height = 0.0;
- gboolean preserve_space = xmlNodeGetSpacePreserve (node) > 0;
-
- str = xmlGetProp(node, (const xmlChar *)"transform");
- if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
- xmlFree (str);
- }
+ DiaObjectType *otype = object_get_type ("Standard - Text");
+ DiaObject *new_obj;
+ Handle *h1, *h2;
+ Point point;
+ GPtrArray *props;
+ TextProperty *prop;
+ xmlChar *str = NULL;
+ gchar *multiline = NULL;
+ DiaSvgStyle *gs;
+ gboolean any_tspan = FALSE;
+ DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
+ real font_height = 0.0;
+ gboolean preserve_space = xmlNodeGetSpacePreserve (node) > 0;
- gs = g_new(DiaSvgStyle, 1);
- dia_svg_style_init (gs, parent_style);
+ str = xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
- point.x = _node_get_real (node, "x", 0.0);
- point.y = _node_get_real (node, "y", 0.0);
+ dia_matrix_from_graphene (matrix, graphene_matrix);
- /* text property handling is special, don't use apply_style() */
- _node_css_parse_style (node, gs, user_scale, style_ht);
+ xmlFree (str);
+ }
- /* font-size can be given in the style (with absolute unit) or
- * with it's own attribute. The latter is preferred - also by
- * Dia's own export.
- */
- str = xmlGetProp(node, (const xmlChar *)"font-size");
- if (str) {
- font_height = get_value_as_cm((char *) str, NULL);
- xmlFree(str);
- }
+ gs = g_new(DiaSvgStyle, 1);
+ dia_svg_style_init (gs, parent_style);
- /* parse from <text/> before looking at the first <tspan/> */
- dia_svg_parse_style(node, gs, user_scale);
-
- {
- xmlNode *tspan = node->children;
- GString *paragraph = g_string_sized_new(512);
- while (tspan) {
- if (xmlStrcmp (tspan->name, (const xmlChar*)"tspan") == 0) {
- xmlChar *line = xmlNodeGetContent(tspan);
- if (any_tspan) { /* every other line needs separation */
- g_string_append(paragraph, "\n");
- } else { /* only first time with user scale - but w/o matrix - that shall be
- * in effect from the context? */
- dia_svg_parse_style(tspan, gs, user_scale);
- point.x = _node_get_real (tspan, "x", point.x);
- point.y = _node_get_real (tspan, "y", point.y);
- }
- g_string_append(paragraph, (gchar*)line);
- xmlFree(line);
- any_tspan = TRUE;
- }
- tspan = tspan->next;
+ point.x = _node_get_real (node, "x", 0.0);
+ point.y = _node_get_real (node, "y", 0.0);
+
+ /* text property handling is special, don't use apply_style() */
+ _node_css_parse_style (node, gs, user_scale, style_ht);
+
+ /* font-size can be given in the style (with absolute unit) or
+ * with it's own attribute. The latter is preferred - also by
+ * Dia's own export.
+ */
+ str = xmlGetProp(node, (const xmlChar *)"font-size");
+ if (str) {
+ font_height = get_value_as_cm((char *) str, NULL);
+ xmlFree(str);
+ }
+
+ /* parse from <text/> before looking at the first <tspan/> */
+ dia_svg_parse_style(node, gs, user_scale);
+
+ {
+ xmlNode *tspan = node->children;
+ GString *paragraph = g_string_sized_new(512);
+ while (tspan) {
+ if (xmlStrcmp (tspan->name, (const xmlChar*)"tspan") == 0) {
+ xmlChar *line = xmlNodeGetContent(tspan);
+ if (any_tspan) { /* every other line needs separation */
+ g_string_append(paragraph, "\n");
+ } else { /* only first time with user scale - but w/o matrix - that shall be
+ * in effect from the context? */
+ dia_svg_parse_style(tspan, gs, user_scale);
+ point.x = _node_get_real (tspan, "x", point.x);
+ point.y = _node_get_real (tspan, "y", point.y);
+ }
+ g_string_append(paragraph, (gchar*)line);
+ xmlFree(line);
+ any_tspan = TRUE;
}
- multiline = paragraph->str;
- g_string_free (paragraph, FALSE);
- str = NULL;
- }
- if (!any_tspan) {
- str = xmlNodeGetContent(node);
- /* so no valid multiline */
- g_clear_pointer (&multiline, g_free);
- multiline = NULL;
+ tspan = tspan->next;
}
- if(str || multiline) {
- new_obj = otype->ops->create(&point, otype->default_user_data,
- &h1, &h2);
- list = g_list_append (list, new_obj);
+ multiline = paragraph->str;
+ g_string_free (paragraph, FALSE);
+ str = NULL;
+ }
+ if (!any_tspan) {
+ str = xmlNodeGetContent(node);
+ /* so no valid multiline */
+ g_clear_pointer (&multiline, g_free);
+ multiline = NULL;
+ }
+ if(str || multiline) {
+ new_obj = otype->ops->create(&point, otype->default_user_data, &h1, &h2);
+ list = g_list_append (list, new_obj);
- props = prop_list_from_descs(svg_text_prop_descs, pdtpp_true);
- g_assert(props->len == 1);
+ props = prop_list_from_descs(svg_text_prop_descs, pdtpp_true);
+ g_assert(props->len == 1);
- if(gs->font == NULL) {
- gs->font = dia_font_new_from_legacy_name("Courier");
- }
- prop = g_ptr_array_index(props, 0);
- g_clear_pointer (&prop->text_data, g_free);
- prop->text_data = str ? g_strdup((char *) str) : multiline;
- if (!preserve_space)
- prop->text_data = g_strstrip (prop->text_data); /* modifies in-place */
- xmlFree(str);
- prop->attr.alignment = gs->alignment;
- prop->attr.position.x = point.x;
- prop->attr.position.y = point.y;
- /* FIXME: looks like a leak but without this an imported svg is
- * crashing on release */
- prop->attr.font = g_object_ref (gs->font);
- if (font_height > 0.0) {
- /* font-size should be the line-height according to SVG spec,
- * but see node_set_text_style() - round-trip first */
- real font_scale = dia_font_get_height (prop->attr.font) / dia_font_get_size (prop->attr.font);
- prop->attr.height = font_height * font_scale;
- } else {
- prop->attr.height = gs->font_height;
- }
- /* when operating with default values foreground and background are intentionally swapped
- * to avoid getting white text by default */
- switch (gs->fill) {
+ if(gs->font == NULL) {
+ gs->font = dia_font_new_from_legacy_name("Courier");
+ }
+ prop = g_ptr_array_index(props, 0);
+ g_clear_pointer (&prop->text_data, g_free);
+ prop->text_data = str ? g_strdup((char *) str) : multiline;
+ if (!preserve_space) {
+ prop->text_data = g_strstrip (prop->text_data); /* modifies in-place */
+ }
+ xmlFree(str);
+ prop->attr.alignment = gs->alignment;
+ prop->attr.position.x = point.x;
+ prop->attr.position.y = point.y;
+ /* FIXME: looks like a leak but without this an imported svg is
+ * crashing on release */
+ prop->attr.font = g_object_ref (gs->font);
+ if (font_height > 0.0) {
+ /* font-size should be the line-height according to SVG spec,
+ * but see node_set_text_style() - round-trip first */
+ real font_scale = dia_font_get_height (prop->attr.font) / dia_font_get_size (prop->attr.font);
+ prop->attr.height = font_height * font_scale;
+ } else {
+ prop->attr.height = gs->font_height;
+ }
+ /* when operating with default values foreground and background are intentionally swapped
+ * to avoid getting white text by default */
+ switch (gs->fill) {
case DIA_SVG_COLOUR_NONE :
/* don't use -1 which would be almost white */
case DIA_SVG_COLOUR_TEXT :
case DIA_SVG_COLOUR_BACKGROUND :
- prop->attr.color = attributes_get_foreground();
- break;
+ prop->attr.color = attributes_get_foreground();
+ break;
case DIA_SVG_COLOUR_DEFAULT: /* black */
- prop->attr.color = get_colour(0x000000, gs->fill_opacity);
- break;
+ prop->attr.color = get_colour(0x000000, gs->fill_opacity);
+ break;
case DIA_SVG_COLOUR_FOREGROUND :
- prop->attr.color = attributes_get_background();
- break;
- default :
- prop->attr.color = get_colour (gs->fill, gs->fill_opacity);
- break;
- }
- new_obj->ops->set_props(new_obj, props);
- prop_list_free (props);
- if (matrix)
- _transform_object (new_obj, matrix, ctx);
+ prop->attr.color = attributes_get_background();
+ break;
+ default:
+ prop->attr.color = get_colour (gs->fill, gs->fill_opacity);
+ break;
}
- g_clear_object (&gs->font);
- g_clear_pointer (&gs, g_free);
- g_clear_pointer (&matrix, g_free);
+ dia_object_set_properties (new_obj, props);
+ prop_list_free (props);
+ if (matrix) {
+ _transform_object (new_obj, matrix, ctx);
+ }
+ }
+ g_clear_object (&gs->font);
+ g_clear_pointer (&gs, g_free);
+ g_clear_pointer (&matrix, g_free);
- return list;
+ return list;
}
-/*!
- * \brief Read a polygon or a polyline
- * Create a _Polyline or _Polygon from the SVG element at node.
- * \ingroup SvgImport
+
+/**
+ * read_poly_svg:
+ *
+ * Read a polygon or a polyline
+ *
+ * Create a #Polyline or #Polygon from the SVG element at node.
*/
static GList *
-read_poly_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, char *object_type)
+read_poly_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ char *object_type)
{
- DiaObjectType *otype;
- DiaObject *new_obj;
- Handle *h1, *h2;
- MultipointCreateData *pcd;
- Point *points;
- GArray *arr = g_array_new(FALSE, FALSE, sizeof(real));
- real val, *rarr;
- xmlChar *str;
- char *tmp;
- int i;
- DiaMatrix *matrix = NULL;
-
- str = xmlGetProp(node, (const xmlChar *)"transform");
- if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
- xmlFree (str);
- }
+ DiaObjectType *otype;
+ DiaObject *new_obj;
+ Handle *h1, *h2;
+ MultipointCreateData *pcd;
+ Point *points;
+ GArray *arr = g_array_new (FALSE, FALSE, sizeof (double));
+ double val, *rarr;
+ xmlChar *str;
+ char *tmp;
+ int i;
+ DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
- /* Uh, oh, no : apparently a fill="" in a group above make this a polygon */
- if (_node_closed_by_style (node, parent_style))
- otype = object_get_type("Standard - Polygon");
- else
- otype = object_get_type(object_type);
+ str = xmlGetProp(node, (const xmlChar *)"transform");
+ if (str) {
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
- str = xmlGetProp(node, (const xmlChar *)"points");
- if (!str) {
- g_warning ("SVG: '%s' without points", node->name);
- g_clear_pointer (&matrix, g_free);
- return list;
- }
- tmp = (char *) str;
- while (tmp[0] != '\0') {
- /* skip junk */
- while (tmp[0] != '\0' && !g_ascii_isdigit(tmp[0]) && tmp[0]!='.'&&tmp[0]!='-')
- tmp++;
- if (tmp[0] == '\0') break;
- val = get_value_as_cm(tmp, &tmp);
- g_array_append_val(arr, val);
- }
- xmlFree(str);
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+ xmlFree (str);
+ }
- /* If an odd number of coordinates is provided, then the element is in error, cut off below */
- points = g_malloc0(arr->len/2*sizeof(Point));
-
- pcd = g_new(MultipointCreateData, 1);
- pcd->num_points = arr->len/2;
- rarr = (real *)arr->data;
- 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);
+ /* Uh, oh, no : apparently a fill="" in a group above make this a polygon */
+ if (_node_closed_by_style (node, parent_style))
+ otype = object_get_type("Standard - Polygon");
+ else
+ otype = object_get_type(object_type);
+
+ str = xmlGetProp(node, (const xmlChar *)"points");
+ if (!str) {
+ g_warning ("SVG: '%s' without points", node->name);
g_clear_pointer (&matrix, g_free);
+ return list;
+ }
+ tmp = (char *) str;
+ while (tmp[0] != '\0') {
+ /* skip junk */
+ while (tmp[0] != '\0' && !g_ascii_isdigit(tmp[0]) && tmp[0]!='.'&&tmp[0]!='-')
+tmp++;
+ if (tmp[0] == '\0') break;
+ val = get_value_as_cm(tmp, &tmp);
+ g_array_append_val(arr, val);
+ }
+ xmlFree(str);
- pcd->points = points;
- new_obj = otype->ops->create(NULL, pcd,
- &h1, &h2);
- reset_arrows (new_obj);
- apply_style(new_obj, node, parent_style, style_ht, pattern_ht, TRUE);
- list = g_list_append (list, new_obj);
- g_clear_pointer (&points, g_free);
- g_clear_pointer (&pcd, g_free);
+ /* If an odd number of coordinates is provided, then the element is in error, cut off below */
+ points = g_malloc0(arr->len/2*sizeof(Point));
- return list;
+ pcd = g_new(MultipointCreateData, 1);
+ pcd->num_points = arr->len/2;
+ rarr = (real *)arr->data;
+ 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);
+ g_clear_pointer (&matrix, g_free);
+
+ pcd->points = points;
+ new_obj = otype->ops->create (NULL, pcd, &h1, &h2);
+ reset_arrows (new_obj);
+ apply_style(new_obj, node, parent_style, style_ht, pattern_ht, TRUE);
+ list = g_list_append (list, new_obj);
+ g_clear_pointer (&points, g_free);
+ g_clear_pointer (&pcd, g_free);
+
+ return list;
}
-/*!
- * \brief Read an ellipse or circle from SVG
+
+/**
+ * read_ellipse_svg:
+ *
+ * Read an ellipse or circle from SVG
+ *
* Creates only _Ellipse objects, but could set the 'circle property'.
- * \ingroup SvgImport
*/
static GList *
-read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, DiaContext *ctx)
+read_ellipse_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ DiaContext *ctx)
{
xmlChar *str;
real width, height;
- DiaObjectType *otype = object_get_type("Standard - Ellipse");
+ DiaObjectType *otype = object_get_type ("Standard - Ellipse");
DiaObject *new_obj;
Handle *h1, *h2;
GPtrArray *props;
Point start;
DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
str = xmlGetProp(node, (const xmlChar *)"transform");
if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+
xmlFree (str);
}
@@ -1004,7 +1069,7 @@ read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
props = make_element_props(start.x-(width/2), start.y-(height/2),
width, height);
- new_obj->ops->set_props(new_obj, props);
+ dia_object_set_properties(new_obj, props);
if (matrix) {
_transform_object (new_obj, matrix, ctx);
g_clear_pointer (&matrix, g_free);
@@ -1013,27 +1078,37 @@ read_ellipse_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
return g_list_append (list, new_obj);
}
-/*!
- * \brief Read a line element from SVG
- * \ingroup SvgImport
+
+/**
+ * read_line_svg:
+ *
+ * Read a line element from SVG
*/
static GList *
-read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, DiaContext *ctx)
+read_line_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ DiaContext *ctx)
{
xmlChar *str;
- DiaObjectType *otype = object_get_type("Standard - Line");
+ DiaObjectType *otype = object_get_type ("Standard - Line");
DiaObject *new_obj;
Handle *h1, *h2;
PointProperty *ptprop;
GPtrArray *props;
Point start, end;
DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
str = xmlGetProp(node, (const xmlChar *)"transform");
if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+
xmlFree (str);
}
@@ -1054,7 +1129,7 @@ read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
ptprop = g_ptr_array_index(props,1);
ptprop->point_data = end;
- new_obj->ops->set_props(new_obj, props);
+ dia_object_set_properties (new_obj, props);
reset_arrows (new_obj);
prop_list_free(props);
@@ -1069,17 +1144,22 @@ read_line_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
return g_list_append (list, new_obj);
}
-/*!
- * \brief Read a rectangle element from SVG
- * \ingroup SvgImport
+
+/**
+ * read_rect_svg:
+ *
+ * Read a rectangle element from SVG
*/
static GList *
-read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, DiaContext *ctx)
+read_rect_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ DiaContext *ctx)
{
xmlChar *str;
- real width, height;
+ double width, height;
DiaObjectType *otype = object_get_type("Standard - Box");
DiaObject *new_obj;
Handle *h1, *h2;
@@ -1087,12 +1167,17 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
RealProperty *rprop;
GPtrArray *props;
Point start,end;
- real corner_radius = 0.0;
+ double corner_radius = 0.0;
DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
str = xmlGetProp(node, (const xmlChar *)"transform");
if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+
xmlFree (str);
}
@@ -1139,10 +1224,10 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
rprop = g_ptr_array_index(props,2);
rprop->real_data = corner_radius;
- new_obj->ops->set_props(new_obj, props);
- prop_list_free(props);
- props = make_element_props(start.x,start.y,width,height);
- new_obj->ops->set_props(new_obj, props);
+ dia_object_set_properties (new_obj, props);
+ prop_list_free (props);
+ props = make_element_props (start.x,start.y,width,height);
+ dia_object_set_properties (new_obj, props);
apply_style(new_obj, node, parent_style, style_ht, pattern_ht, TRUE);
prop_list_free(props);
@@ -1154,24 +1239,36 @@ read_rect_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
return list;
}
-/*!
- * \brief Read SVG image element
- * The result is an _Image object in the list.
- * \ingroup SvgImport
+
+/**
+ * read_image_svg:
+ *
+ * Read SVG image element
+ *
+ * The result is an #Image object in the list.
*/
static GList *
-read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
- GHashTable *style_ht, GHashTable *pattern_ht,
- GList *list, const gchar *filename_svg, DiaContext *ctx)
+read_image_svg (xmlNodePtr node,
+ DiaSvgStyle *parent_style,
+ GHashTable *style_ht,
+ GHashTable *pattern_ht,
+ GList *list,
+ const char *filename_svg,
+ DiaContext *ctx)
{
xmlChar *str;
real x, y, width, height;
DiaObject *new_obj = NULL;
DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
str = xmlGetProp(node, (const xmlChar *)"transform");
if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+
xmlFree (str);
}
@@ -1215,26 +1312,27 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
g_clear_pointer (&dir, g_free);
filename = absfn;
}
+
/* Importing svg as "Misc - Diagram" should produce better results than GdkPixbuf rendering */
if (filename && g_strrstr (filename, ".svg")) {
- Handle *h1, *h2;
- Point point = {x, y};
- DiaObjectType *otype = object_get_type("Misc - Diagram");
-
- if (otype) {
- GPtrArray *props = g_ptr_array_new ();
- new_obj = otype->ops->create (&point, otype->default_user_data, &h1, &h2);
- prop_list_add_filename (props, "diagram_file", filename);
- if (new_obj) {
- new_obj->ops->set_props (new_obj, props);
- point.x += width;
- point.y += height;
- new_obj->ops->move_handle (new_obj, h2, &point, NULL, HANDLE_MOVE_USER_FINAL, 0);
- }
- prop_list_free (props);
- }
+ Handle *h1, *h2;
+ Point point = {x, y};
+ DiaObjectType *otype = object_get_type ("Misc - Diagram");
+
+ if (otype) {
+ GPtrArray *props = g_ptr_array_new ();
+ new_obj = otype->ops->create (&point, otype->default_user_data, &h1, &h2);
+ prop_list_add_filename (props, "diagram_file", filename);
+ if (new_obj) {
+ dia_object_set_properties (new_obj, props);
+ point.x += width;
+ point.y += height;
+ dia_object_move_handle (new_obj, h2, &point, NULL, HANDLE_MOVE_USER_FINAL, 0);
+ }
+ prop_list_free (props);
+ }
} else {
- new_obj = create_standard_image(x, y, width, height, filename ? filename : "<broken>");
+ new_obj = create_standard_image (x, y, width, height, filename ? filename : "<broken>");
}
g_clear_pointer (&filename, g_free);
}
@@ -1270,6 +1368,7 @@ read_gradient (xmlNodePtr node, DiaSvgStyle *parent_gs, GHashTable *pattern_ht,
guint flags = 0;
real old_scale = user_scale;
DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
DiaSvgStyle gradient_gs;
str = xmlGetProp (node, (const xmlChar *)"gradientUnits");
@@ -1289,12 +1388,18 @@ read_gradient (xmlNodePtr node, DiaSvgStyle *parent_gs, GHashTable *pattern_ht,
xmlFree (str);
}
/* this should not be user_scaled */
- if ((flags & DIA_PATTERN_USER_SPACE) == 0)
+ if ((flags & DIA_PATTERN_USER_SPACE) == 0) {
user_scale = 1.0;
+ }
+
str = xmlGetProp (node, (const xmlChar *)"gradientTransform");
if (str) {
- matrix = dia_svg_parse_transform ((char *)str, user_scale);
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) str, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
}
+
if (xmlStrcmp(node->name, (const xmlChar *)"linearGradient")==0) {
Point p1 = {_node_get_real (node, "x1", 0.0), _node_get_real (node, "y1", 0.0)};
Point p2 = {_node_get_real (node, "x2", 1.0), _node_get_real (node, "y2", 0.0)};
@@ -1581,6 +1686,7 @@ read_items (xmlNodePtr startnode,
GList *moreitems;
DiaSvgStyle *group_gs;
DiaMatrix *matrix = NULL;
+ graphene_matrix_t *graphene_matrix = NULL;
xmlChar *trans;
/* We need to have/apply the groups style before the objects style */
@@ -1591,8 +1697,12 @@ read_items (xmlNodePtr startnode,
trans = xmlGetProp (node, (xmlChar *)"transform");
if (trans) {
- matrix = dia_svg_parse_transform ((char *)trans, user_scale);
- xmlFree (trans);
+ matrix = g_new0 (DiaMatrix, 1);
+ graphene_matrix = dia_svg_parse_transform ((char *) trans, user_scale);
+
+ dia_matrix_from_graphene (matrix, graphene_matrix);
+
+ xmlFree (trans);
}
moreitems = read_items (node->xmlChildrenNode, group_gs,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]