[dia] [gradient] svg: stop-(color|opacity) from style and gradientTransform
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] [gradient] svg: stop-(color|opacity) from style and gradientTransform
- Date: Wed, 1 Jan 2014 11:51:07 +0000 (UTC)
commit 24505d75bc63dccec4b23abc54e1bee26cafd98e
Author: Hans Breuer <hans breuer org>
Date: Thu Dec 26 20:50:41 2013 +0100
[gradient] svg: stop-(color|opacity) from style and gradientTransform
Now stop-color and stop-opacity are read by dia_svg_parse_style() not only
for our own SVG round-trip. Also included initial gradientTransform, not
passed down to DiaPattern yet. Finally some stop-color offset clipping.
lib/dia_svg.c | 28 +++++++++++++++-
lib/dia_svg.h | 3 ++
lib/pattern.c | 5 ++-
plug-ins/svg/svg-import.c | 78 +++++++++++++++++++++++++-------------------
4 files changed, 78 insertions(+), 36 deletions(-)
---
diff --git a/lib/dia_svg.c b/lib/dia_svg.c
index e3a5106..6766557 100644
--- a/lib/dia_svg.c
+++ b/lib/dia_svg.c
@@ -74,6 +74,9 @@ dia_svg_style_init(DiaSvgStyle *gs, DiaSvgStyle *parent_style)
gs->font = (parent_style && parent_style->font) ? dia_font_ref(parent_style->font) : NULL;
gs->font_height = parent_style ? parent_style->font_height : 0.8;
gs->alignment = parent_style ? parent_style->alignment : ALIGN_LEFT;
+
+ gs->stop_color = parent_style ? parent_style->stop_color : 0x000000; /* default black */
+ gs->stop_opacity = parent_style ? parent_style->stop_opacity : 1.0;
}
/*!
@@ -99,6 +102,8 @@ dia_svg_style_copy(DiaSvgStyle *dest, DiaSvgStyle *src)
dest->font = src->font ? dia_font_ref(src->font) : NULL;
dest->font_height = src->font_height;
dest->alignment = src->alignment;
+ dest->stop_color = src->stop_color;
+ dest->stop_opacity = src->stop_opacity;
}
static const struct _SvgNamedColor {
@@ -634,6 +639,16 @@ dia_svg_parse_style_string (DiaSvgStyle *s, real user_scale, const gchar *str)
} else if (!strncmp("fill-opacity:", ptr, 13)) {
ptr += 13;
s->fill_opacity = g_ascii_strtod(ptr, &ptr);
+ } else if (!strncmp("stop-color:", ptr, 11)) {
+ ptr += 11;
+ while (ptr[0] != '\0' && g_ascii_isspace(ptr[0])) ptr++;
+ if (ptr[0] == '\0') break;
+
+ if (!_parse_color (&s->stop_color, ptr))
+ s->stop_color = DIA_SVG_COLOUR_NONE;
+ } else if (!strncmp("stop-opacity:", ptr, 13)) {
+ ptr += 13;
+ s->stop_opacity = g_ascii_strtod(ptr, &ptr);
} else if (!strncmp("opacity", ptr, 7)) {
real opacity;
ptr += 7;
@@ -757,6 +772,17 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
s->fill_opacity *= opacity;
xmlFree(str);
}
+ str = xmlGetProp(node, (const xmlChar *)"stop-color");
+ if (str) {
+ if (!_parse_color (&s->stop_color, (char *) str) && strcmp ((const char *) str, "inherit") != 0)
+ s->stop_color = DIA_SVG_COLOUR_NONE;
+ xmlFree(str);
+ }
+ str = xmlGetProp(node, (const xmlChar *)"stop-opacity");
+ if (str) {
+ s->stop_opacity = g_ascii_strtod((char *) str, NULL);
+ xmlFree(str);
+ }
str = xmlGetProp(node, (const xmlChar *)"fill");
if (str) {
if (!_parse_color (&s->fill, (char *) str) && strcmp ((const char *) str, "inherit") != 0)
@@ -778,7 +804,7 @@ dia_svg_parse_style(xmlNodePtr node, DiaSvgStyle *s, real user_scale)
if (str) {
s->stroke_opacity = g_ascii_strtod((char *) str, NULL);
xmlFree(str);
- }
+ }
str = xmlGetProp(node, (const xmlChar *)"stroke-width");
if (str) {
s->line_width = g_ascii_strtod((char *) str, NULL);
diff --git a/lib/dia_svg.h b/lib/dia_svg.h
index be53176..87bbe5c 100644
--- a/lib/dia_svg.h
+++ b/lib/dia_svg.h
@@ -57,6 +57,9 @@ struct _DiaSvgStyle {
DiaFont *font;
real font_height;
Alignment alignment;
+
+ gint32 stop_color;
+ real stop_opacity;
};
void dia_svg_style_init (DiaSvgStyle *gs, DiaSvgStyle *parent_style);
diff --git a/lib/pattern.c b/lib/pattern.c
index a7f93e5..5260254 100644
--- a/lib/pattern.c
+++ b/lib/pattern.c
@@ -194,10 +194,13 @@ void
dia_pattern_add_color (DiaPattern *self, real pos, const Color *color)
{
ColorStop stop;
+ real former = 0.0;
g_return_if_fail (self != NULL && color != NULL);
stop.color = *color;
- stop.offset = pos;
+ if (self->stops->len > 0)
+ former = g_array_index (self->stops, ColorStop, self->stops->len - 1).offset;
+ stop.offset = MAX(pos, former);
g_array_append_val (self->stops, stop);
}
diff --git a/plug-ins/svg/svg-import.c b/plug-ins/svg/svg-import.c
index 4972008..abd8a1d 100644
--- a/plug-ins/svg/svg-import.c
+++ b/plug-ins/svg/svg-import.c
@@ -1196,18 +1196,18 @@ read_image_svg(xmlNodePtr node, DiaSvgStyle *parent_style,
*
* 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)
+ * - gradients via CSS
*/
static DiaPattern *
-read_gradient (xmlNodePtr node, GHashTable *pattern_ht, DiaContext *ctx)
+read_gradient (xmlNodePtr node, DiaSvgStyle *parent_gs, GHashTable *pattern_ht, DiaContext *ctx)
{
DiaPattern *pat;
xmlNode *child;
xmlChar *str;
guint flags = 0;
real old_scale = user_scale;
+ DiaMatrix *matrix = NULL;
+ DiaSvgStyle gradient_gs;
str = xmlGetProp (node, (const xmlChar *)"gradientUnits");
if (str) {
@@ -1228,30 +1228,41 @@ read_gradient (xmlNodePtr node, GHashTable *pattern_ht, DiaContext *ctx)
/* this should not be user_scaled */
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);
+ }
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));
+ 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)};
+ if (matrix) {
+ transform_point (&p1, matrix);
+ transform_point (&p2, matrix);
+ }
+ pat = dia_pattern_new (DIA_LINEAR_GRADIENT, flags, p1.x, p1.y);
+ dia_pattern_set_point (pat, p2.x, p2.y);
} 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));
+ Point c = {_node_get_real (node, "cx", 0.5), _node_get_real (node, "cy", 0.5)};
+ Point f = {_node_get_real (node, "fx", c.x), _node_get_real (node, "fy", c.y)};
+ real r = _node_get_real (node, "r", 0.5);
+ if (matrix) {
+ transform_point (&c, matrix);
+ transform_point (&f, matrix);
+ transform_length (&r, matrix);
+ }
+ pat = dia_pattern_new (DIA_RADIAL_GRADIENT, flags, c.x, c.y);
+ dia_pattern_set_radius (pat, r);
+ dia_pattern_set_point (pat, f.x, f.y);
}
/* restore previous user scale */
user_scale = old_scale;
- /* if there is a single color on the gradient
+ /* if there are single stop value on the gradient
+ * - use it as default stop-color and stop-opacity
* - 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 */
- }
+ dia_svg_style_init (&gradient_gs, parent_gs);
+ dia_svg_parse_style (node, &gradient_gs, user_scale);
/* stops and focal point can be defined by reference */
str = xmlGetProp(node, (const xmlChar *)"xlink:href");
@@ -1267,13 +1278,13 @@ read_gradient (xmlNodePtr node, GHashTable *pattern_ht, DiaContext *ctx)
child = node->children;
while (child) {
if (xmlStrcmp(child->name, (const xmlChar *)"stop")==0) {
- Color color = color_black;
+ DiaSvgStyle gs;
+ Color color;
real offset = 0.0;
- str = xmlGetProp(child, (const xmlChar *)"stop-color");
- if (str) {
- dia_svg_parse_color((const gchar*)str, &color);
- xmlFree(str);
- }
+
+ dia_svg_style_init (&gs, &gradient_gs);
+ dia_svg_parse_style (child, &gs, user_scale);
+
str = xmlGetProp(child, (const xmlChar *)"offset");
if (str) {
if (strrchr (str, '%'))
@@ -1282,15 +1293,13 @@ read_gradient (xmlNodePtr node, GHashTable *pattern_ht, DiaContext *ctx)
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);
- }
+ color = get_colour (gs.stop_color, gs.stop_opacity);
dia_pattern_add_color (pat, offset, &color);
}
child = child->next;
}
+ if (matrix)
+ g_free (matrix);
return pat;
}
@@ -1567,8 +1576,9 @@ read_items (xmlNodePtr startnode,
!xmlStrcmp(node->name, (const xmlChar *)"radialGradient") ||
!xmlStrcmp(node->name, (const xmlChar *)"style") ||
!xmlStrcmp(node->name, (const xmlChar *)"pattern") ||
+ !xmlStrcmp(node->name, (const xmlChar *)"mask") ||
!xmlStrcmp(node->name, (const xmlChar *)"defs")) {
- /* read_defs was already handling these */
+ /* read_defs was already handling these, mostly;) */
} else if(!xmlStrcmp(node->name, (const xmlChar *)"use")) {
xmlChar *key = xmlGetNsProp (node, (const xmlChar *)"href", (const xmlChar *)"xlink");
@@ -1713,7 +1723,7 @@ read_defs (xmlNodePtr startnode,
!xmlStrcmp(node->name, (const xmlChar *)"radialGradient")) {
xmlChar *val = xmlGetProp (node, (const xmlChar *)"id");
if (val) {
- DiaPattern *pat = read_gradient (node, pattern_ht, ctx);
+ DiaPattern *pat = read_gradient (node, parent_gs, pattern_ht, ctx);
if (pat)
g_hash_table_insert (pattern_ht, g_strdup(val), pat);
xmlFree (val);
@@ -1726,7 +1736,7 @@ read_defs (xmlNodePtr startnode,
/* Commonly seen in <defs/> are
* clipPath, font, filter, linearGradient, mask, marker, pattern, radialGradient, style
- * all not supported as of this writing.
+ * mostly not supported as of this writing.
* Less commonly used are normal objects which could be supported here.
*/
for (list = defs; list != NULL; list = g_list_next (list)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]