[dia] [gradient] svg: import gradients and set them on objects
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] [gradient] svg: import gradients and set them on objects
- Date: Tue, 24 Dec 2013 14:28:34 +0000 (UTC)
commit d69490c77e1012a7dea361d65b800c01a2ca2f5d
Author: Hans Breuer <hans breuer org>
Date: Tue Dec 24 15:18:08 2013 +0100
[gradient] svg: import gradients and set them on objects
Step 5 of 7 for gradient support in Dia: parse gradient information from
SVG and set the pattern property for respective objects.
plug-ins/svg/svg-import.c | 138 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 137 insertions(+), 1 deletions(-)
---
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 2674541..c24b75d 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -48,10 +48,14 @@
#include "group.h"
#include "font.h"
#include "attributes.h"
+#include "pattern.h"
static gboolean import_svg (xmlDocPtr doc, DiagramData *dia, DiaContext *ctx, void* user_data);
static GPtrArray *make_element_props(real xpos, real ypos, real width, real height);
+/* ToDo: allow to put patterns into defs_ht to get rid of global variable */
+GHashTable *_pattern_ht = NULL;
+
/* TODO: use existing implementation in dia source */
static Color
get_colour(gint32 c, real opacity)
@@ -474,6 +478,24 @@ apply_style(DiaObject *obj, xmlNodePtr node, DiaSvgStyle *parent_style,
} else {
bprop->bool_data = TRUE;
}
+ /* 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) {
+ gchar *key = g_strndup (left + 5, right - left - 5);
+ DiaPattern *pattern = g_hash_table_lookup (_pattern_ht, key);
+ if (pattern) {
+ dia_object_set_pattern (obj, pattern);
+ /* activate "show_background" */
+ bprop->bool_data = TRUE;
+ }
+ g_free (key);
+ }
+ xmlFree(str);
+ }
eprop = g_ptr_array_index(props,5);
if (gs->linejoin != DIA_SVG_LINEJOIN_DEFAULT)
@@ -1147,6 +1169,109 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style, GHashTable *style_ht,
return list;
}
+/*!
+ * \brief Parse gradient including stop-colors
+ *
+ * Parse a radial or linear gradient and into a DiaPattern.
+ * Missing attribute handling for:
+ * - gradientTransform
+ * - style inheritance (would require to parse stop-color and stop-opacity
+ * outside of this function)
+ */
+static DiaPattern *
+read_gradient (xmlNodePtr node, DiaContext *ctx)
+{
+ DiaPattern *pat;
+ xmlNode *child;
+ xmlChar *str;
+ guint flags = 0;
+ real old_scale = user_scale;
+
+ str = xmlGetProp (node, (const xmlChar *)"gradientUnits");
+ if (str) {
+ if (xmlStrcmp(str, (const xmlChar *)"userSpaceOnUse")==0)
+ flags |= DIA_PATTERN_USER_SPACE;
+ xmlFree (str);
+ }
+ str = xmlGetProp (node, (const xmlChar *)"spreadMethod");
+ if (str) {
+ if (xmlStrcmp(str, (const xmlChar *)"pad")==0)
+ flags |= DIA_PATTERN_EXTEND_PAD;
+ else if (xmlStrcmp(str, (const xmlChar *)"reflect")==0)
+ flags |= DIA_PATTERN_EXTEND_REFLECT;
+ if (xmlStrcmp(str, (const xmlChar *)"repeat")==0)
+ flags |= DIA_PATTERN_EXTEND_REPEAT;
+ xmlFree (str);
+ }
+ /* this should not be user_scaled */
+ if ((flags & DIA_PATTERN_USER_SPACE) == 0)
+ user_scale = 1.0;
+ if (xmlStrcmp(node->name, (const xmlChar *)"linearGradient")==0) {
+ pat = dia_pattern_new (DIA_LINEAR_GRADIENT, flags,
+ _node_get_real (node, "x1", 0.0), _node_get_real (node, "y1", 0.0));
+ dia_pattern_set_point (pat, _node_get_real (node, "x2", 1.0), _node_get_real (node, "y2", 0.0));
+ } else {
+ real cx = _node_get_real (node, "cx", 0.5);
+ real cy = _node_get_real (node, "cy", 0.5);
+ pat = dia_pattern_new (DIA_RADIAL_GRADIENT, flags, cx, cy);
+ dia_pattern_set_radius (pat, _node_get_real (node, "r", 0.5));
+ dia_pattern_set_point (pat, _node_get_real (node, "fx", cx), _node_get_real (node, "fy", cy));
+ }
+ /* restore previous user scale */
+ user_scale = old_scale;
+
+ /* if there is a single color on the gradient
+ * - parse it to initialize currentColor
+ * - use it as fall-back color for the whole gradient?
+ */
+ {
+ DiaSvgStyle gs;
+ dia_svg_style_init (&gs, NULL);
+ dia_svg_parse_style (node, &gs, user_scale);
+ /* not stop-color, but should be better than nothing */
+ }
+
+ /* stops and focal point can be defined by reference */
+ 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");
+ if (str) {
+ DiaPattern *pattern = g_hash_table_lookup (_pattern_ht, (const char*)str+1);
+ if (pattern)
+ dia_pattern_set_pattern (pat, pattern);
+ xmlFree (str);
+ }
+
+ child = node->children;
+ while (child) {
+ if (xmlStrcmp(child->name, (const xmlChar *)"stop")==0) {
+ Color color = color_black;
+ real offset = 0.0;
+ str = xmlGetProp(child, (const xmlChar *)"stop-color");
+ if (str) {
+ dia_svg_parse_color((const gchar*)str, &color);
+ xmlFree(str);
+ }
+ str = xmlGetProp(child, (const xmlChar *)"offset");
+ if (str) {
+ if (strrchr (str, '%'))
+ offset = g_ascii_strtod ((const char*)str, NULL) / 100.0;
+ else
+ offset = g_ascii_strtod ((const char*)str, NULL);
+ xmlFree(str);
+ }
+ str = xmlGetProp(child, (const xmlChar *)"stop-opacity");
+ if (str) {
+ color.alpha = g_ascii_strtod ((const char*)str, NULL);
+ xmlFree(str);
+ }
+ dia_pattern_add_color (pat, offset, &color);
+ }
+ child = child->next;
+ }
+
+ return pat;
+}
/*!
* \brief Parse the CSS style block of the SVG
@@ -1169,7 +1294,7 @@ read_style (xmlNodePtr node, GHashTable *ht)
g_regex_match (regex, (gchar *)str, 0, &info);
while (g_match_info_matches (info)) {
/* Use the _last_ key before { and val between {}
- * To the left there might be refernenced parents in the tree restricting
+ * To the left there might be referenced parents in the tree restricting
* the effect of the key but that's just too complicated for Dia's SVG ...
*/
gchar *key = g_match_info_fetch (info, 1);
@@ -1411,6 +1536,15 @@ read_items (xmlNodePtr startnode,
items = read_image_svg(node, parent_gs, style_ht, items, filename_svg);
if (items)
obj = g_list_last(items)->data;
+ } else if(!xmlStrcmp(node->name, (const xmlChar *)"linearGradient") ||
+ !xmlStrcmp(node->name, (const xmlChar *)"radialGradient")) {
+ xmlChar *val = xmlGetProp (node, (const xmlChar *)"id");
+ if (val) {
+ DiaPattern *pat = read_gradient (node, ctx);
+ if (pat)
+ g_hash_table_insert (_pattern_ht, g_strdup(val), pat);
+ xmlFree (val);
+ }
} else if(!xmlStrcmp(node->name, (const xmlChar *)"defs")) {
/* everything below must have a name to make a difference */
GList *list, *defs = read_items (node->xmlChildrenNode, parent_gs, defs_ht, style_ht, filename_svg,
ctx);
@@ -1737,8 +1871,10 @@ import_svg (xmlDocPtr doc, DiagramData *dia,
{
GHashTable *defs_ht = g_hash_table_new (g_str_hash, g_str_equal);
GHashTable *style_ht = g_hash_table_new (g_str_hash, g_str_equal);
+ _pattern_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
items = read_items (root->xmlChildrenNode, NULL, defs_ht, style_ht,
dia_context_get_filename(ctx), ctx);
+ g_hash_table_destroy (_pattern_ht);
g_hash_table_destroy (style_ht);
g_hash_table_destroy (defs_ht);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]