summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDom Lachowicz <doml@src.gnome.org>2003-01-27 16:35:43 +0000
committerDom Lachowicz <doml@src.gnome.org>2003-01-27 16:35:43 +0000
commit0ceb853801e73641f405e5e753fc09d0620b1760 (patch)
treee53a98471886bd72ae751f8532ce5202e2e3a705
parent0a0842ec0f34beed010707395cc98de7ac74e7cc (diff)
downloadlibrsvg-0ceb853801e73641f405e5e753fc09d0620b1760.tar.gz
fix crash wrt sodipodi and linear/radial Gradients. output still isn't correct, though...
-rw-r--r--ChangeLog6
-rw-r--r--rsvg-paint-server.c97
-rw-r--r--rsvg-paint-server.h8
-rw-r--r--rsvg-private.h3
-rw-r--r--rsvg.c78
5 files changed, 126 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index be44af86..0a7af1b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
-2003-01-25 Dom Lachowicz <cinamod@hotmail.com>
+2003-01-27 Dom Lachowicz <cinamod@hotmail.com>
+
+ * *: Fix a bunch of brokenness caused by Sodipodi's handling of gradients. Output still doesn't look quite right, though, unfortunately....
+
+2003-01-26 Dom Lachowicz <cinamod@hotmail.com>
* *: Support CSS id as well as class, style
diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c
index a2e9c2e9..ef0eda7d 100644
--- a/rsvg-paint-server.c
+++ b/rsvg-paint-server.c
@@ -24,6 +24,7 @@
#include "config.h"
#include "rsvg-paint-server.h"
+#include "rsvg-private.h"
#include <glib/gmem.h>
#include <glib/gmessages.h>
@@ -353,57 +354,87 @@ rsvg_paint_server_unref (RsvgPaintServer *ps)
}
RsvgRadialGradient *
-rsvg_clone_radial_gradient (const RsvgRadialGradient *grad)
+rsvg_clone_radial_gradient (const RsvgRadialGradient *grad, gboolean * shallow_cloned)
{
RsvgRadialGradient * clone = NULL;
int i;
- clone = g_new (RsvgRadialGradient, 1);
- clone->super.type = grad->super.type;
- clone->super.free = grad->super.free;
+ clone = g_new0 (RsvgRadialGradient, 1);
+ clone->super.type = RSVG_DEF_RADGRAD;
+ clone->super.free = rsvg_radial_gradient_free;
for (i = 0; i < 6; i++)
clone->affine[i] = grad->affine[i];
- clone->cx = grad->cx;
- clone->cy = grad->cy;
- clone->r = grad->r;
- clone->fx = grad->fx;
- clone->fy = grad->fy;
-
- clone->stops = g_new (RsvgGradientStops, 1);
- clone->stops->n_stop = grad->stops->n_stop;
- clone->stops->stop = g_new (RsvgGradientStop, clone->stops->n_stop);
-
- for (i = 0; i < grad->stops->n_stop; i++)
- clone->stops->stop[i] = grad->stops->stop[i];
+
+ if (grad->stops != NULL) {
+ clone->stops = g_new (RsvgGradientStops, 1);
+ clone->stops->n_stop = grad->stops->n_stop;
+ clone->stops->stop = g_new (RsvgGradientStop, grad->stops->n_stop);
+
+ for (i = 0; i < grad->stops->n_stop; i++)
+ clone->stops->stop[i] = grad->stops->stop[i];
+ } else {
+ clone->stops = NULL;
+ }
+
+ /* EVIL EVIL - sodipodi can base LinearGradients on
+ RadialGradients, and vice-versa. it is legal, though:
+ http://www.w3.org/TR/SVG11/pservers.html#LinearGradients
+ */
+ if (grad->super.type == RSVG_DEF_RADGRAD) {
+ clone->cx = grad->cx;
+ clone->cy = grad->cy;
+ clone->r = grad->r;
+ clone->fx = grad->fx;
+ clone->fy = grad->fy;
+
+ *shallow_cloned = FALSE;
+ } else {
+ *shallow_cloned = TRUE;
+ }
return clone;
}
RsvgLinearGradient *
-rsvg_clone_linear_gradient (const RsvgLinearGradient *grad)
+rsvg_clone_linear_gradient (const RsvgLinearGradient *grad, gboolean * shallow_cloned)
{
RsvgLinearGradient * clone = NULL;
int i;
- clone = g_new (RsvgLinearGradient, 1);
- clone->super.type = grad->super.type;
- clone->super.free = grad->super.free;
+ clone = g_new0 (RsvgLinearGradient, 1);
+ clone->super.type = RSVG_DEF_LINGRAD;
+ clone->super.free = rsvg_linear_gradient_free;
for (i = 0; i < 6; i++)
clone->affine[i] = grad->affine[i];
- clone->x1 = grad->x1;
- clone->y1 = grad->y1;
- clone->x2 = grad->x2;
- clone->y2 = grad->y2;
- clone->spread = grad->spread;
-
- clone->stops = g_new (RsvgGradientStops, 1);
- clone->stops->n_stop = grad->stops->n_stop;
- clone->stops->stop = g_new (RsvgGradientStop, clone->stops->n_stop);
-
- for (i = 0; i < grad->stops->n_stop; i++)
- clone->stops->stop[i] = grad->stops->stop[i];
-
+
+ if (grad->stops != NULL) {
+ clone->stops = g_new (RsvgGradientStops, 1);
+ clone->stops->n_stop = grad->stops->n_stop;
+ clone->stops->stop = g_new (RsvgGradientStop, grad->stops->n_stop);
+
+ for (i = 0; i < grad->stops->n_stop; i++)
+ clone->stops->stop[i] = grad->stops->stop[i];
+ } else {
+ clone->stops = NULL;
+ }
+
+ /* EVIL EVIL - sodipodi can base LinearGradients on
+ RadialGradients, and vice-versa. it is legal, though:
+ http://www.w3.org/TR/SVG11/pservers.html#LinearGradients
+ */
+ if (grad->super.type == RSVG_DEF_LINGRAD) {
+ clone->x1 = grad->x1;
+ clone->y1 = grad->y1;
+ clone->x2 = grad->x2;
+ clone->y2 = grad->y2;
+ clone->spread = grad->spread;
+
+ *shallow_cloned = FALSE;
+ } else {
+ *shallow_cloned = TRUE;
+ }
+
return clone;
}
diff --git a/rsvg-paint-server.h b/rsvg-paint-server.h
index cea56ac9..b060b08e 100644
--- a/rsvg-paint-server.h
+++ b/rsvg-paint-server.h
@@ -70,19 +70,19 @@ struct _RsvgGradientStops {
struct _RsvgLinearGradient {
RsvgDefVal super;
double affine[6]; /* user space to actual at time of gradient def */
+ RsvgGradientStops *stops;
double x1, y1;
double x2, y2;
ArtGradientSpread spread;
- RsvgGradientStops *stops;
};
struct _RsvgRadialGradient {
RsvgDefVal super;
double affine[6]; /* user space to actual at time of gradient def */
+ RsvgGradientStops *stops;
double cx, cy;
double r;
double fx, fy;
- RsvgGradientStops *stops;
};
/* Create a new paint server based on a specification string. */
@@ -100,10 +100,10 @@ void
rsvg_paint_server_unref (RsvgPaintServer *ps);
RsvgRadialGradient *
-rsvg_clone_radial_gradient (const RsvgRadialGradient *grad);
+rsvg_clone_radial_gradient (const RsvgRadialGradient *grad, gboolean * shallow_cloned);
RsvgLinearGradient *
-rsvg_clone_linear_gradient (const RsvgLinearGradient *grad);
+rsvg_clone_linear_gradient (const RsvgLinearGradient *grad, gboolean * shallow_cloned);
G_END_DECLS
diff --git a/rsvg-private.h b/rsvg-private.h
index 48c57ece..7d82c6b1 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -74,6 +74,9 @@ struct RsvgHandle {
double dpi;
};
+void rsvg_linear_gradient_free (RsvgDefVal *self);
+void rsvg_radial_gradient_free (RsvgDefVal *self);
+
G_END_DECLS
#endif
diff --git a/rsvg.c b/rsvg.c
index 074ae504..902dce30 100644
--- a/rsvg.c
+++ b/rsvg.c
@@ -382,7 +382,8 @@ rsvg_gradient_stop_handler_new (RsvgHandle *ctx, RsvgGradientStops **p_stops,
return &gstops->super;
}
-static void
+/* exported to the paint server via rsvg-private.h */
+void
rsvg_linear_gradient_free (RsvgDefVal *self)
{
RsvgLinearGradient *z = (RsvgLinearGradient *)self;
@@ -398,13 +399,13 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
RsvgState *state = &ctx->state[ctx->n_state - 1];
RsvgLinearGradient *grad = NULL;
int i;
- char *id = NULL;
+ const char *id = NULL;
double x1 = 0., y1 = 0., x2 = 0., y2 = 0.;
ArtGradientSpread spread = ART_GRADIENT_PAD;
const char * xlink_href = NULL;
- gboolean got_x1, got_x2, got_y1, got_y2, got_spread, cloned;
+ gboolean got_x1, got_x2, got_y1, got_y2, got_spread, cloned, shallow_cloned;
- got_x1 = got_x2 = got_y1 = got_y2 = got_spread = cloned = FALSE;
+ got_x1 = got_x2 = got_y1 = got_y2 = got_spread = cloned = shallow_cloned = FALSE;
/* 100% is the default */
x2 = rsvg_css_parse_normalized_length ("100%", ctx->dpi, (gdouble)ctx->width, state->font_size);
@@ -415,23 +416,37 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
for (i = 0; atts[i] != NULL; i += 2)
{
if (!strcmp ((char *)atts[i], "id"))
- id = (char *)atts[i + 1];
- else if (!strcmp ((char *)atts[i], "x1"))
+ id = (const char *)atts[i + 1];
+ else if (!strcmp ((char *)atts[i], "x1")) {
x1 = rsvg_css_parse_normalized_length ((char *)atts[i + 1], ctx->dpi, (gdouble)ctx->width, state->font_size);
- else if (!strcmp ((char *)atts[i], "y1"))
+ got_x1 = TRUE;
+ }
+ else if (!strcmp ((char *)atts[i], "y1")) {
y1 = rsvg_css_parse_normalized_length ((char *)atts[i + 1], ctx->dpi, (gdouble)ctx->height, state->font_size);
- else if (!strcmp ((char *)atts[i], "x2"))
+ got_y1 = TRUE;
+ }
+ else if (!strcmp ((char *)atts[i], "x2")) {
x2 = rsvg_css_parse_normalized_length ((char *)atts[i + 1], ctx->dpi, (gdouble)ctx->width, state->font_size);
- else if (!strcmp ((char *)atts[i], "y2"))
+ got_x2 = TRUE;
+ }
+ else if (!strcmp ((char *)atts[i], "y2")) {
y2 = rsvg_css_parse_normalized_length ((char *)atts[i + 1], ctx->dpi, (gdouble)ctx->height, state->font_size);
+ got_y2 = TRUE;
+ }
else if (!strcmp ((char *)atts[i], "spreadMethod"))
{
- if (!strcmp ((char *)atts[i + 1], "pad"))
+ if (!strcmp ((char *)atts[i + 1], "pad")) {
spread = ART_GRADIENT_PAD;
- else if (!strcmp ((char *)atts[i + 1], "reflect"))
+ got_spread = TRUE;
+ }
+ else if (!strcmp ((char *)atts[i + 1], "reflect")) {
spread = ART_GRADIENT_REFLECT;
- else if (!strcmp ((char *)atts[i + 1], "repeat"))
+ got_spread = TRUE;
+ }
+ else if (!strcmp ((char *)atts[i + 1], "repeat")) {
spread = ART_GRADIENT_REPEAT;
+ got_spread = TRUE;
+ }
}
else if (!strcmp ((char *)atts[i], "xlink:href"))
xlink_href = (const char *)atts[i + 1];
@@ -444,7 +459,7 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
if (parent != NULL)
{
cloned = TRUE;
- grad = rsvg_clone_linear_gradient (parent);
+ grad = rsvg_clone_linear_gradient (parent, &shallow_cloned);
ctx->handler = rsvg_gradient_stop_handler_new_clone (ctx, grad->stops, "linearGradient");
}
}
@@ -470,7 +485,8 @@ rsvg_start_linear_gradient (RsvgHandle *ctx, const xmlChar **atts)
grad->spread = (cloned && !got_spread) ? grad->spread : spread;
}
-static void
+/* exported to the paint server via rsvg-private.h */
+void
rsvg_radial_gradient_free (RsvgDefVal *self)
{
RsvgRadialGradient *z = (RsvgRadialGradient *)self;
@@ -486,12 +502,12 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts)
RsvgState *state = &ctx->state[ctx->n_state - 1];
RsvgRadialGradient *grad = NULL;
int i;
- char *id = NULL;
+ const char *id = NULL;
double cx = 0., cy = 0., r = 0., fx = 0., fy = 0.;
const char * xlink_href = NULL;
- gboolean got_cx, got_cy, got_r, got_fx, got_fy, cloned;
+ gboolean got_cx, got_cy, got_r, got_fx, got_fy, cloned, shallow_cloned;
- got_cx = got_cy = got_r = got_fx = got_fy = cloned = FALSE;
+ got_cx = got_cy = got_r = got_fx = got_fy = cloned = shallow_cloned = FALSE;
/* setup defaults */
cx = rsvg_css_parse_normalized_length ("50%", ctx->dpi, (gdouble)ctx->width, state->font_size);
@@ -504,7 +520,7 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts)
for (i = 0; atts[i] != NULL; i += 2)
{
if (!strcmp ((char *)atts[i], "id"))
- id = (char *)atts[i + 1];
+ id = (const char *)atts[i + 1];
else if (!strcmp ((char *)atts[i], "cx")) {
cx = rsvg_css_parse_normalized_length ((char *)atts[i + 1], ctx->dpi, (gdouble)ctx->width, state->font_size);
got_cx = TRUE;
@@ -538,7 +554,7 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts)
if (parent != NULL)
{
cloned = TRUE;
- grad = rsvg_clone_radial_gradient (parent);
+ grad = rsvg_clone_radial_gradient (parent, &shallow_cloned);
ctx->handler = rsvg_gradient_stop_handler_new_clone (ctx, grad->stops, "radialGradient");
}
}
@@ -547,13 +563,19 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts)
grad = g_new (RsvgRadialGradient, 1);
grad->super.type = RSVG_DEF_RADGRAD;
grad->super.free = rsvg_radial_gradient_free;
- ctx->handler = rsvg_gradient_stop_handler_new (ctx, &grad->stops, "radialGradient");
-
- if (!got_fx)
- fx = cx;
- if (!got_fy)
- fy = cy;
+ ctx->handler = rsvg_gradient_stop_handler_new (ctx, &grad->stops, "radialGradient");
+ }
+
+ if (!cloned || shallow_cloned) {
+ if (!got_fx) {
+ fx = cx;
+ got_fx = TRUE;
+ }
+ if (!got_fy) {
+ fy = cy;
+ got_fy = TRUE;
}
+ }
rsvg_defs_set (ctx->defs, id, &grad->super);
@@ -561,9 +583,9 @@ rsvg_start_radial_gradient (RsvgHandle *ctx, const xmlChar **atts)
grad->affine[i] = state->affine[i];
/* state inherits parent/cloned information unless it's explicity gotten */
- grad->cx = (cloned && !got_cx) ? grad->cx: cx;
- grad->cy = (cloned && !got_cy) ? grad->cy: cy;
- grad->r = (cloned && !got_r) ? grad->r : r;
+ grad->cx = (cloned && !got_cx) ? grad->cx : cx;
+ grad->cy = (cloned && !got_cy) ? grad->cy : cy;
+ grad->r = (cloned && !got_r) ? grad->r : r;
grad->fx = (cloned && !got_fx) ? grad->fx : fx;
grad->fy = (cloned && !got_fy) ? grad->fy : fy;
}