diff options
author | Dom Lachowicz <doml@src.gnome.org> | 2003-01-27 16:35:43 +0000 |
---|---|---|
committer | Dom Lachowicz <doml@src.gnome.org> | 2003-01-27 16:35:43 +0000 |
commit | 0ceb853801e73641f405e5e753fc09d0620b1760 (patch) | |
tree | e53a98471886bd72ae751f8532ce5202e2e3a705 | |
parent | 0a0842ec0f34beed010707395cc98de7ac74e7cc (diff) | |
download | librsvg-0ceb853801e73641f405e5e753fc09d0620b1760.tar.gz |
fix crash wrt sodipodi and linear/radial Gradients. output still isn't correct, though...
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | rsvg-paint-server.c | 97 | ||||
-rw-r--r-- | rsvg-paint-server.h | 8 | ||||
-rw-r--r-- | rsvg-private.h | 3 | ||||
-rw-r--r-- | rsvg.c | 78 |
5 files changed, 126 insertions, 66 deletions
@@ -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 @@ -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; } |