diff options
author | Dom Lachowicz <doml@src.gnome.org> | 2004-08-14 14:01:03 +0000 |
---|---|---|
committer | Dom Lachowicz <doml@src.gnome.org> | 2004-08-14 14:01:03 +0000 |
commit | 04c949a0dc30c258a8e32aaa5d861167b2fe2d0e (patch) | |
tree | 8dc397e06857e545ea2d0daf2625747a8db7d465 | |
parent | 1a07cca1788d8e3ab823e684bfc25842f3fac5b3 (diff) | |
download | librsvg-04c949a0dc30c258a8e32aaa5d861167b2fe2d0e.tar.gz |
backport significant amount from HEAD
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | rsvg-filter.c | 101 | ||||
-rw-r--r-- | rsvg-mask.c | 90 | ||||
-rw-r--r-- | rsvg-paint-server.c | 19 | ||||
-rw-r--r-- | rsvg-private.h | 12 | ||||
-rw-r--r-- | rsvg-shapes.c | 211 | ||||
-rw-r--r-- | rsvg-styles.c | 88 | ||||
-rw-r--r-- | rsvg-styles.h | 5 | ||||
-rw-r--r-- | rsvg-text.c | 14 | ||||
-rw-r--r-- | rsvg.c | 51 |
11 files changed, 269 insertions, 336 deletions
@@ -1,3 +1,13 @@ +2004-08-13 Dom Lachowicz <cinamod@hotmail.com> + + * rsvg-styles.c: Fix memory leak in the new "state stack thingie". + * rsvg.c: Use a GMemChunk to (marginally) speed up state allocation + +2004-08-13 Caleb Moore <c.moore@student.unsw.edu.au> + + * prettymuch-everywhere: Huge number of small bugfixes + * rsvg-styles.c: rewrote the whole state stack thingie + 2004-07-23 Caleb Moore <c.moore@student.unsw.edu.au> * rsvg-shapes.c, rsvg-mask.c: ClipPaths now partially working diff --git a/configure.in b/configure.in index b5b4abfa..4391ca10 100644 --- a/configure.in +++ b/configure.in @@ -19,8 +19,8 @@ AC_SUBST(POPT_REQUIRED) dnl =========================================================================== LIBRSVG_MAJOR_VERSION=2 -LIBRSVG_MINOR_VERSION=8 -LIBRSVG_MICRO_VERSION=0 +LIBRSVG_MINOR_VERSION=7 +LIBRSVG_MICRO_VERSION=90 AC_SUBST(LIBRSVG_MAJOR_VERSION) AC_SUBST(LIBRSVG_MINOR_VERSION) AC_SUBST(LIBRSVG_MICRO_VERSION) diff --git a/rsvg-filter.c b/rsvg-filter.c index 5ab99dba..5de70908 100644 --- a/rsvg-filter.c +++ b/rsvg-filter.c @@ -37,6 +37,9 @@ #define M_PI 3.14159265358979323846 #endif /* M_PI */ +/* probably poor form, but it saves us from whacking it in the header file */ +void rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path); + #define PERFECTBLUR 0 /*************************************************************/ @@ -169,9 +172,9 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, return output; } -static GdkPixbuf * -gdk_pixbuf_new_cleared (GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, - int width, int height) +GdkPixbuf * +_rsvg_pixbuf_new_cleared (GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, + int width, int height) { GdkPixbuf *pb; guchar *data; @@ -432,6 +435,9 @@ rsvg_filter_render (RsvgFilter * self, GdkPixbuf * source, GdkPixbuf * output, bounds = rsvg_filter_primitive_get_bounds (NULL, ctx); + if (rsvg_state_current (context)->clippath) + rsvg_clip_image(ctx->lastresult.result, rsvg_state_current (context)->clippath); + rsvg_alpha_blt (ctx->lastresult.result, bounds.x1, bounds.y1, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1, output, bounds.x1, bounds.y1); context->bbox.x0 = bounds.x1; @@ -501,9 +507,9 @@ pixbuf_get_alpha (GdkPixbuf * pb) pbsize = gdk_pixbuf_get_width (pb) * gdk_pixbuf_get_height (pb); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, - gdk_pixbuf_get_width (pb), - gdk_pixbuf_get_height (pb)); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, + gdk_pixbuf_get_width (pb), + gdk_pixbuf_get_height (pb)); data = gdk_pixbuf_get_pixels (output); pbdata = gdk_pixbuf_get_pixels (pb); @@ -906,7 +912,7 @@ rsvg_filter_primitive_blend_render (RsvgFilterPrimitive * self, in = rsvg_filter_get_in (self->in, ctx); in2 = rsvg_filter_get_in (bself->in2, ctx); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in)); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in)); rsvg_filter_blend(bself->mode, in, in2, output, boundarys); @@ -1130,7 +1136,7 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); for (y = boundarys.y1; y < boundarys.y2; y++) @@ -1513,6 +1519,12 @@ box_blur (GdkPixbuf *in, GdkPixbuf *output, GdkPixbuf *intermediate, gint kw, rowstride = gdk_pixbuf_get_rowstride (in); + if (kw > boundarys.x2 - boundarys.x1) + kw = boundarys.x2 - boundarys.x1; + + if (kh > boundarys.y2 - boundarys.y1) + kh = boundarys.y2 - boundarys.y1; + if (kw >= 1) { @@ -1709,10 +1721,10 @@ fast_blur (GdkPixbuf *in, GdkPixbuf *output, gfloat sx, kx = floor(sx * 3*sqrt(2*M_PI)/4 + 0.5); ky = floor(sy * 3*sqrt(2*M_PI)/4 + 0.5); - intermediate1 = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, + intermediate1 = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in)); - intermediate2 = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, + intermediate2 = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in)); @@ -1745,7 +1757,7 @@ rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, op = rsvg_filter_get_result (self->in, ctx); in = op.result; - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in)); @@ -1899,7 +1911,7 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); @@ -2051,7 +2063,7 @@ rsvg_filter_primitive_merge_render (RsvgFilterPrimitive * self, mself = (RsvgFilterPrimitiveMerge *) self; boundarys = rsvg_filter_primitive_get_bounds (self, ctx); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height); for (i = 0; i < mself->nodes->len; i++) { @@ -2152,14 +2164,26 @@ rsvg_start_filter_primitive_merge_node (RsvgHandle * ctx, RsvgPropertyBag * atts) { const char *value; + int needdefault = 1; + if (!(ctx && ctx->currentsubfilter)) + return; + if (rsvg_property_bag_size (atts)) { /* see bug 145149 - sodipodi generates bad SVG... */ - if (ctx && ctx->currentsubfilter && (value = rsvg_property_bag_lookup (atts, "in"))) - g_ptr_array_add (((RsvgFilterPrimitiveMerge *) (ctx-> - currentsubfilter))-> - nodes, g_string_new (value)); + if ((value = rsvg_property_bag_lookup (atts, "in"))) + { + needdefault = 0; + g_ptr_array_add (((RsvgFilterPrimitiveMerge *) + (ctx->currentsubfilter))-> + nodes, g_string_new (value)); + } } + + if (needdefault) + g_ptr_array_add (((RsvgFilterPrimitiveMerge *) + (ctx->currentsubfilter))-> + nodes, g_string_new ("none")); } /*************************************************************/ @@ -2212,7 +2236,7 @@ rsvg_filter_primitive_colour_matrix_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); for (y = boundarys.y1; y < boundarys.y2; y++) @@ -2561,7 +2585,7 @@ rsvg_filter_primitive_component_transfer_render (RsvgFilterPrimitive * rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); @@ -2830,7 +2854,7 @@ rsvg_filter_primitive_erode_render (RsvgFilterPrimitive * self, kx = cself->rx * ctx->paffine[0]; ky = cself->ry * ctx->paffine[3]; - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); @@ -3020,7 +3044,7 @@ rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); if (bself->mode == COMPOSITE_MODE_ARITHMETIC) @@ -3274,7 +3298,7 @@ rsvg_filter_primitive_flood_render (RsvgFilterPrimitive * self, height = ctx->height; width = ctx->width; - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); rowstride = gdk_pixbuf_get_rowstride (output); output_pixels = gdk_pixbuf_get_pixels (output); @@ -3438,7 +3462,7 @@ rsvg_filter_primitive_displacement_map_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); @@ -3849,7 +3873,7 @@ rsvg_filter_primitive_turbulence_render (RsvgFilterPrimitive * self, tileWidth = (boundarys.x2 - boundarys.x1); tileHeight = (boundarys.y2 - boundarys.y1); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); for (y = 0; y < tileHeight; y++) @@ -4016,30 +4040,19 @@ rsvg_filter_primitive_image_render_in (RsvgFilterPrimitive * self, boundarys = rsvg_filter_primitive_get_bounds (self, context); - img = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, context->width, context->height); + img = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, context->width, context->height); save = ctx->pixbuf; ctx->pixbuf = img; for (i = 0; i < 6; i++) - ctx->state[ctx->n_state - 1].affine[i] = context->paffine[i]; - - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_current(ctx)->affine[i] = context->paffine[i]; + + rsvg_state_push(ctx); rsvg_defs_drawable_draw (drawable, ctx, 0); - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); ctx->pixbuf = save; return img; @@ -4104,7 +4117,7 @@ rsvg_filter_primitive_image_render (RsvgFilterPrimitive * self, boundarys = rsvg_filter_primitive_get_bounds (self, ctx); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height); img = rsvg_filter_primitive_image_render_in (self, ctx); if (img == NULL) @@ -4677,7 +4690,7 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); @@ -4874,7 +4887,7 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, rowstride = gdk_pixbuf_get_rowstride (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height); output_pixels = gdk_pixbuf_get_pixels (output); @@ -5075,7 +5088,7 @@ rsvg_filter_primitive_tile_render (RsvgFilterPrimitive * self, in_pixels = gdk_pixbuf_get_pixels (in); - output = gdk_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height); + output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, ctx->width, ctx->height); rowstride = gdk_pixbuf_get_rowstride (output); output_pixels = gdk_pixbuf_get_pixels (output); diff --git a/rsvg-mask.c b/rsvg-mask.c index da5f31e0..0a292871 100644 --- a/rsvg-mask.c +++ b/rsvg-mask.c @@ -36,6 +36,7 @@ rsvg_mask_free (RsvgDefVal * self) { RsvgMask *z = (RsvgMask *)self; g_ptr_array_free(z->super.children, TRUE); + rsvg_state_finalize (&z->super.super.state); g_free (z); } @@ -53,34 +54,16 @@ rsvg_mask_render (RsvgMask *self, GdkPixbuf *tos, GdkPixbuf *nos, RsvgHandle *ct drawable = (RsvgDefsDrawable*)self; - mask = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8, - gdk_pixbuf_get_width(tos), - gdk_pixbuf_get_height(tos)); - - gdk_pixbuf_fill(mask, 0x00000000); + mask = _rsvg_pixbuf_new_cleared(GDK_COLORSPACE_RGB, 1, 8, + gdk_pixbuf_get_width(tos), + gdk_pixbuf_get_height(tos)); save = ctx->pixbuf; ctx->pixbuf = mask; - -/* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; - + rsvg_state_push(ctx); rsvg_defs_drawable_draw (drawable, ctx, 0); - - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); - - + rsvg_state_pop(ctx); ctx->pixbuf = save; @@ -92,7 +75,7 @@ rsvg_mask_render (RsvgMask *self, GdkPixbuf *tos, GdkPixbuf *nos, RsvgHandle *ct if (!gdk_pixbuf_get_has_alpha (nos)) { - g_warning ("push/pop transparency group on non-alpha buffer nyi"); + g_warning (_("push/pop transparency group on non-alpha buffer nyi")); return; } @@ -148,32 +131,19 @@ rsvg_defs_drawable_mask_draw (RsvgDefsDrawable * self, RsvgHandle *ctx, RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self; guint i; - /* combine state definitions */ - if (ctx->n_state > 1) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); + rsvg_state_reinherit_top(ctx, &self->state, 0); if (state->opacity != 0xff || state->filter) rsvg_push_discrete_layer (ctx); for (i = 0; i < group->children->len; i++) { - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); rsvg_defs_drawable_draw (g_ptr_array_index(group->children, i), ctx, 0); - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } if (state->opacity != 0xff || state->filter) @@ -201,7 +171,7 @@ rsvg_new_mask (void) void rsvg_start_mask (RsvgHandle *ctx, RsvgPropertyBag *atts) { - const char *id = NULL, *value; + const char *id = NULL, *klazz = NULL, *value; RsvgMask *mask; double font_size; @@ -250,16 +220,24 @@ rsvg_start_mask (RsvgHandle *ctx, RsvgPropertyBag *atts) font_size); if ((value = rsvg_property_bag_lookup (atts, "id"))) id = value; + if ((value = rsvg_property_bag_lookup (atts, "class"))) + klazz = value; } + + rsvg_parse_style_attrs (ctx, rsvg_state_current (ctx), "mask", klazz, id, atts); + mask->super.super.parent = (RsvgDefsDrawable *)ctx->current_defs_group; ctx->current_defs_group = &mask->super; + + rsvg_state_clone (&mask->super.super.state, rsvg_state_current (ctx)); /* set up the defval stuff */ mask->super.super.super.type = RSVG_DEF_MASK; mask->super.super.super.free = &rsvg_mask_free; mask->super.super.draw = &rsvg_defs_drawable_mask_draw; + rsvg_defs_set (ctx->defs, id, &mask->super.super.super); } @@ -308,6 +286,7 @@ rsvg_clip_path_free (RsvgDefVal * self) { RsvgClipPath *z = (RsvgClipPath *)self; g_ptr_array_free(z->super.children, TRUE); + rsvg_state_finalize (&z->super.super.state); g_free (z); } @@ -320,10 +299,8 @@ rsvg_clip_path_render (RsvgClipPath * self, RsvgHandle *ctx) ArtSVP *svp, *svpx; svpx = NULL; - - /* combine state definitions */ - if (ctx->n_state > 1) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); + + rsvg_state_reinherit_top(ctx, &self->super.super.state, 0); if (self->units == objectBoundingBox) { @@ -337,16 +314,7 @@ rsvg_clip_path_render (RsvgClipPath * self, RsvgHandle *ctx) for (i = 0; i < group->children->len; i++) { - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); svp = rsvg_defs_drawable_draw_as_svp (g_ptr_array_index(group->children, i), ctx, 0); @@ -365,9 +333,7 @@ rsvg_clip_path_render (RsvgClipPath * self, RsvgHandle *ctx) svpx = svp; } - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } return svpx; @@ -388,7 +354,7 @@ rsvg_new_clip_path (void) void rsvg_start_clip_path (RsvgHandle *ctx, RsvgPropertyBag *atts) { - const char *id = NULL, *value = NULL; + const char *id = NULL, *klazz = NULL, *value = NULL; RsvgClipPath *clip_path; double font_size; @@ -406,9 +372,13 @@ rsvg_start_clip_path (RsvgHandle *ctx, RsvgPropertyBag *atts) } if ((value = rsvg_property_bag_lookup (atts, "id"))) id = value; + if ((value = rsvg_property_bag_lookup (atts, "class"))) + klazz = value; } - rsvg_parse_style_pairs (ctx, rsvg_state_current(ctx), atts); + rsvg_parse_style_attrs (ctx, rsvg_state_current (ctx), "clipPath", klazz, id, atts); + + rsvg_state_clone (&clip_path->super.super.state, rsvg_state_current (ctx)); clip_path->super.super.parent = (RsvgDefsDrawable *)ctx->current_defs_group; diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c index 133bff07..40830f40 100644 --- a/rsvg-paint-server.c +++ b/rsvg-paint-server.c @@ -561,21 +561,14 @@ rsvg_paint_server_pattern_render (RsvgPaintServer *self, ArtRender *ar, if (maxy > gdk_pixbuf_get_height(hctx->pixbuf)) yoffset = -maxy; - render = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1, 8, - gdk_pixbuf_get_width(hctx->pixbuf), - gdk_pixbuf_get_height(hctx->pixbuf)); - - gdk_pixbuf_fill(render, 0x00000000); + render = _rsvg_pixbuf_new_cleared(GDK_COLORSPACE_RGB, 1, 8, + gdk_pixbuf_get_width(hctx->pixbuf), + gdk_pixbuf_get_height(hctx->pixbuf)); save = hctx->pixbuf; hctx->pixbuf = render; - /* push the state stack */ - if (hctx->n_state == hctx->n_state_max) - hctx->state = g_renew (RsvgState, hctx->state, - hctx->n_state_max <<= 1); - rsvg_state_init (&hctx->state[hctx->n_state]); - hctx->n_state++; + rsvg_state_push(ctx->ctx); caffine[4] += xoffset; caffine[5] += yoffset; @@ -592,9 +585,7 @@ rsvg_paint_server_pattern_render (RsvgPaintServer *self, ArtRender *ar, else rsvg_defs_drawable_draw ((RsvgDefsDrawable *)pattern->gfallback, hctx, 2); - /* pop the state stack */ - hctx->n_state--; - rsvg_state_finalize (&hctx->state[hctx->n_state]); + rsvg_state_pop(ctx->ctx); hctx->pixbuf = save; diff --git a/rsvg-private.h b/rsvg-private.h index 03559753..0c374ec7 100644 --- a/rsvg-private.h +++ b/rsvg-private.h @@ -32,6 +32,7 @@ #include <libxml/xmlmemory.h> #include <pango/pango.h> #include <libart_lgpl/art_rect.h> +#include <glib/gslist.h> G_BEGIN_DECLS @@ -62,9 +63,8 @@ struct RsvgHandle { ArtIRect bbox; /* stack; there is a state for each element */ - RsvgState *state; - int n_state; - int n_state_max; + + GSList * state; RsvgDefs *defs; guint in_defs; @@ -100,6 +100,8 @@ struct RsvgHandle { void * currentfilter; void * currentsubfilter; + GMemChunk * state_allocator; + /* virtual fns */ gboolean (* write) (RsvgHandle *handle, const guchar *buf, @@ -181,6 +183,10 @@ void rsvg_handle_set_base_uri (RsvgHandle *handle, gboolean rsvg_eval_switch_attributes (RsvgPropertyBag *atts, gboolean * p_has_cond); +GdkPixbuf * +_rsvg_pixbuf_new_cleared (GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, + int width, int height); + G_END_DECLS #endif diff --git a/rsvg-shapes.c b/rsvg-shapes.c index 3b468987..aee8f6a4 100644 --- a/rsvg-shapes.c +++ b/rsvg-shapes.c @@ -512,21 +512,10 @@ static void rsvg_defs_drawable_path_draw (RsvgDefsDrawable * self, RsvgHandle *ctx, int dominate) { - RsvgState *state = rsvg_state_current (ctx); RsvgDefsDrawablePath *path = (RsvgDefsDrawablePath*)self; - /* combine state definitions */ - - rsvg_state_clone (state, &self->state); - if (ctx->n_state > 1) - { - if (dominate) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); - else - rsvg_state_reinherit(state, &ctx->state[ctx->n_state - 2]); - } + rsvg_state_reinherit_top(ctx, &self->state, dominate); - /* always want to render inside of a <use/> */ rsvg_render_path (ctx, path->d); } @@ -535,21 +524,10 @@ static ArtSVP * rsvg_defs_drawable_path_draw_as_svp (RsvgDefsDrawable * self, RsvgHandle *ctx, int dominate) { - RsvgState *state = rsvg_state_current (ctx); RsvgDefsDrawablePath *path = (RsvgDefsDrawablePath*)self; - /* combine state definitions */ - - rsvg_state_clone (state, &self->state); - if (ctx->n_state > 1) - { - if (dominate) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); - else - rsvg_state_reinherit(state, &ctx->state[ctx->n_state - 2]); - } + rsvg_state_reinherit_top(ctx, &self->state, dominate); - /* always want to render inside of a <use/> */ return rsvg_render_path_as_svp (ctx, path->d); } @@ -567,57 +545,21 @@ static void rsvg_defs_drawable_group_draw (RsvgDefsDrawable * self, RsvgHandle *ctx, int dominate) { - - RsvgState *state = rsvg_state_current (ctx); RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self; guint i; - double tempaffine[6]; - for (i = 0; i < 6; i++) - { - tempaffine[i] = ctx->state[ctx->n_state - 1].affine[i]; - } - - /* combine state definitions */ - rsvg_state_clone (state, &self->state); - if (ctx->n_state > 1) - { - /*This is a special domination mode for patterns, the style - is simply reinherited, wheras the transform is totally overridden*/ - if (dominate == 2) - { - for (i = 0; i < 6; i++) - { - state->affine[i] = tempaffine[i]; - } - } - else if (dominate) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); - else - rsvg_state_reinherit(state, &ctx->state[ctx->n_state - 2]); - } + rsvg_state_reinherit_top(ctx, &self->state, dominate); rsvg_push_discrete_layer (ctx); for (i = 0; i < group->children->len; i++) { - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); rsvg_defs_drawable_draw (g_ptr_array_index(group->children, i), ctx, 0); - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } rsvg_pop_discrete_layer (ctx); @@ -627,49 +569,17 @@ static ArtSVP * rsvg_defs_drawable_group_draw_as_svp (RsvgDefsDrawable * self, RsvgHandle *ctx, int dominate) { - RsvgState *state = rsvg_state_current (ctx); RsvgDefsDrawableGroup *group = (RsvgDefsDrawableGroup*)self; guint i; - double tempaffine[6]; ArtSVP *svp1, *svp2, *svp3; svp1 = NULL; - for (i = 0; i < 6; i++) - { - tempaffine[i] = ctx->state[ctx->n_state - 1].affine[i]; - } - /* combine state definitions */ - rsvg_state_clone (state, &self->state); - if (ctx->n_state > 1) - { - /*This is a special domination mode for patterns, the style - is simply reinherited, wheras the transform is totally overridden*/ - if (dominate == 2) - { - for (i = 0; i < 6; i++) - { - state->affine[i] = tempaffine[i]; - } - } - else if (dominate) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); - else - rsvg_state_reinherit(state, &ctx->state[ctx->n_state - 2]); - } + rsvg_state_reinherit_top(ctx, &self->state, dominate); for (i = 0; i < group->children->len; i++) { - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); svp2 = rsvg_defs_drawable_draw_as_svp (g_ptr_array_index(group->children, i), ctx, 0); @@ -679,10 +589,8 @@ rsvg_defs_drawable_group_draw_as_svp (RsvgDefsDrawable * self, RsvgHandle *ctx, art_free(svp1); svp1 = svp3; } - - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + + rsvg_state_pop(ctx); } return svp1; } @@ -702,45 +610,45 @@ rsvg_defs_drawable_use_draw (RsvgDefsDrawable * self, RsvgHandle *ctx, RsvgState *state = rsvg_state_current (ctx); RsvgDefsDrawableUse *use = (RsvgDefsDrawableUse*)self; - /* combine state definitions */ - - rsvg_state_clone (state, &self->state); - if (ctx->n_state > 1) - { - if (dominate) - rsvg_state_dominate(state, &ctx->state[ctx->n_state - 2]); - else - rsvg_state_reinherit(state, &ctx->state[ctx->n_state - 2]); - } - + rsvg_state_reinherit_top(ctx, &self->state, dominate); + if (state->opacity != 0xff || rsvg_needs_discrete_layer(state)) rsvg_push_discrete_layer (ctx); - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); rsvg_defs_drawable_draw (use->child, ctx, 1); - - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + + rsvg_state_pop(ctx); if (state->opacity != 0xff || rsvg_needs_discrete_layer(state)) rsvg_pop_discrete_layer (ctx); +} + +static ArtSVP * +rsvg_defs_drawable_use_draw_as_svp (RsvgDefsDrawable * self, RsvgHandle *ctx, + int dominate) +{ + RsvgDefsDrawableUse *use = (RsvgDefsDrawableUse*)self; + ArtSVP * svp; + + rsvg_state_reinherit_top(ctx, &self->state, dominate); + + rsvg_state_push(ctx); + + svp = rsvg_defs_drawable_draw_as_svp (use->child, ctx, 1); + + rsvg_state_pop(ctx); + + return svp; } static void rsvg_defs_drawable_group_pack (RsvgDefsDrawableGroup *self, RsvgDefsDrawable *child) { + if (self == NULL) + return; RsvgDefsDrawableGroup *z = (RsvgDefsDrawableGroup *)self; g_ptr_array_add(z->children, child); } @@ -1832,7 +1740,9 @@ rsvg_affine_image(GdkPixbuf *img, GdkPixbuf *intermediate, } } -static void +void rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path); + +void rsvg_clip_image(GdkPixbuf *intermediate, ArtSVP *path) { gint intstride; @@ -2038,6 +1948,8 @@ rsvg_start_use (RsvgHandle *ctx, RsvgPropertyBag *atts) xlink_href = value; } + rsvg_parse_style_attrs (ctx, state, "use", klazz, id, atts); + /* < 0 is an error, 0 disables rendering. TODO: handle positive values correctly */ if (got_width || got_height) if (width <= 0. || height <= 0.) @@ -2055,33 +1967,25 @@ rsvg_start_use (RsvgHandle *ctx, RsvgPropertyBag *atts) RsvgDefsDrawableUse * use; use = g_new (RsvgDefsDrawableUse, 1); use->child = drawable; - rsvg_parse_style_attrs (ctx, state, "use", klazz, id, atts); rsvg_state_clone (&use->super.state, state); use->super.super.type = RSVG_DEF_PATH; use->super.super.free = rsvg_defs_drawable_use_free; use->super.draw = rsvg_defs_drawable_use_draw; + use->super.draw_as_svp = rsvg_defs_drawable_use_draw_as_svp; art_affine_translate(affine, x, y); art_affine_multiply(use->super.state.affine, affine, use->super.state.affine); - art_affine_multiply(use->super.state.personal_affine, affine, use->super.state.personal_affine); + art_affine_multiply(use->super.state.personal_affine, affine, use->super.state.personal_affine); + + rsvg_defs_set (ctx->defs, id, &use->super.super); + + use->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group; + if (use->super.parent != NULL) + rsvg_defs_drawable_group_pack((RsvgDefsDrawableGroup *)use->super.parent, + &use->super); if (!ctx->in_defs) - { - rsvg_defs_drawable_draw (&use->super, ctx, 1); - use->super.super.free(&use->super.super); - break; - } - else - { - rsvg_defs_set (ctx->defs, id, &use->super.super); - - use->super.parent = (RsvgDefsDrawable *)ctx->current_defs_group; - if (use->super.parent != NULL) - rsvg_defs_drawable_group_pack((RsvgDefsDrawableGroup *)use->super.parent, - &use->super); - - - break; - } + rsvg_defs_drawable_draw (&use->super, ctx, 0); + break; } default: g_warning (_("Unhandled defs entry/type %s %d\n"), id, @@ -2246,16 +2150,7 @@ rsvg_marker_render (RsvgMarker *self, gdouble x, gdouble y, gdouble orient, gdou art_affine_multiply(affine, affine, taffine); - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, - ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); for (i = 0; i < 6; i++) { @@ -2265,9 +2160,7 @@ rsvg_marker_render (RsvgMarker *self, gdouble x, gdouble y, gdouble orient, gdou rsvg_defs_drawable_draw (self->contents, ctx, 2); - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } RsvgDefVal * diff --git a/rsvg-styles.c b/rsvg-styles.c index 755b0926..98c6b5c9 100644 --- a/rsvg-styles.c +++ b/rsvg-styles.c @@ -335,7 +335,6 @@ rsvg_state_dominate (RsvgState *dst, const RsvgState *src) dst->dash.dash[i] = src->dash.dash[i]; } art_affine_multiply (dst->affine, dst->personal_affine, src->affine); - dst->clippath = src->clippath; } @@ -1259,7 +1258,7 @@ rsvg_lookup_apply_css_style (RsvgHandle *ctx, const char * target) if (value != NULL) { - rsvg_parse_style (ctx, &ctx->state[ctx->n_state - 1], + rsvg_parse_style (ctx, rsvg_state_current(ctx), value); return TRUE; } @@ -1397,7 +1396,7 @@ rsvg_push_discrete_layer (RsvgHandle *ctx) art_u8 *pixels; int width, height, rowstride; - state = &ctx->state[ctx->n_state - 1]; + state = rsvg_state_current(ctx); pixbuf = ctx->pixbuf; rsvg_state_clip_path_assure(ctx); @@ -1530,9 +1529,8 @@ rsvg_compile_bg(RsvgHandle *ctx, RsvgState *topstate) lastintermediate = gdk_pixbuf_copy(topstate->save_pixbuf); - for (i = ctx->n_state - 1; i >= 0; i--) + for (i = 0; (state = g_slist_nth_data(ctx->state, i)) != NULL; i++) { - state = &ctx->state[i]; if (state == topstate) { foundstate = 1; @@ -1674,24 +1672,20 @@ rsvg_needs_discrete_layer(RsvgState *state) RsvgState * rsvg_state_current (RsvgHandle *ctx) { - if (ctx->n_state > 0) - return &ctx->state[ctx->n_state - 1]; - return NULL; + return g_slist_nth_data(ctx->state, 0); } RsvgState * rsvg_state_parent (RsvgHandle *ctx) { - if (ctx->n_state > 1) - return &ctx->state[ctx->n_state - 2]; - return NULL; + return g_slist_nth_data(ctx->state, 1); } double rsvg_state_current_font_size (RsvgHandle *ctx) { - if (ctx->n_state > 0) - return ctx->state[ctx->n_state - 1].font_size; + if (rsvg_state_current(ctx) != NULL) + return rsvg_state_current(ctx)->font_size; else return 12.0; } @@ -1744,13 +1738,18 @@ rsvg_state_clip_path_assure(RsvgHandle * ctx) if (state->clip_path_ref && !state->clip_path_loaded) { + rsvg_state_push(ctx); + tmppath = rsvg_clip_path_render (state->clip_path_ref, ctx); + + rsvg_state_pop(ctx); + state->clip_path_loaded = TRUE; } else return; - if (state->clippath) + if (state->clippath != NULL && tmppath != NULL) { tmppath2 = art_svp_intersect(tmppath, state->clippath); art_free(tmppath); @@ -1759,3 +1758,64 @@ rsvg_state_clip_path_assure(RsvgHandle * ctx) else state->clippath = tmppath; } + +void +rsvg_state_push(RsvgHandle * ctx) +{ + RsvgState * data; + RsvgState * baseon; + + baseon = (RsvgState *)g_slist_nth_data(ctx->state, 0); + data = g_chunk_new(RsvgState, ctx->state_allocator); + + if (baseon) + rsvg_state_inherit(data, baseon); + else + rsvg_state_init(data); + + ctx->state = g_slist_prepend(ctx->state, data); +} + +void +rsvg_state_pop(RsvgHandle * ctx) +{ + RsvgState * toremove = g_slist_nth_data(ctx->state, 0); + rsvg_state_finalize (toremove); + ctx->state = g_slist_remove(ctx->state, toremove); + g_mem_chunk_free(ctx->state_allocator, toremove); +} + +void +rsvg_state_reinherit_top(RsvgHandle * ctx, RsvgState * state, int dominate) +{ + double tempaffine[6]; + gint i; + RsvgState * baseon; + + baseon = rsvg_state_parent(ctx); + + for (i = 0; i < 6; i++) + { + tempaffine[i] = rsvg_state_current(ctx)->affine[i]; + } + + /* combine state definitions */ + rsvg_state_clone (rsvg_state_current(ctx), state); + + if (baseon) + { + /*This is a special domination mode for patterns, the style + is simply left as is, wheras the transform is totally overridden*/ + if (dominate == 2) + { + for (i = 0; i < 6; i++) + { + rsvg_state_current(ctx)->affine[i] = tempaffine[i]; + } + } + else if (dominate) + rsvg_state_dominate(rsvg_state_current(ctx), baseon); + else + rsvg_state_reinherit(rsvg_state_current(ctx), baseon); + } +} diff --git a/rsvg-styles.h b/rsvg-styles.h index a6958288..15378666 100644 --- a/rsvg-styles.h +++ b/rsvg-styles.h @@ -185,6 +185,11 @@ double rsvg_state_current_font_size (RsvgHandle *ctx); void rsvg_state_clip_path_assure(RsvgHandle * ctx); +void rsvg_state_pop(RsvgHandle * ctx); +void rsvg_state_push(RsvgHandle * ctx); + +void rsvg_state_reinherit_top(RsvgHandle * ctx, RsvgState * state, int dominate); + G_END_DECLS #endif /* RSVG_STYLES_H */ diff --git a/rsvg-text.c b/rsvg-text.c index c7fc8385..7c33807f 100644 --- a/rsvg-text.c +++ b/rsvg-text.c @@ -293,15 +293,7 @@ rsvg_text_handler_start (RsvgSaxHandler *self, const xmlChar *name, RsvgSaxHandlerText *z = (RsvgSaxHandlerText *)self; RsvgHandle *ctx = z->ctx; - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, ctx->n_state_max <<= 1); - if (ctx->n_state) - rsvg_state_clone (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); /* this should be the only thing starting inside of text */ if (!strcmp ((char *)name, "tspan")) @@ -330,9 +322,7 @@ rsvg_text_handler_end (RsvgSaxHandler *self, const xmlChar *name) } } - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } void @@ -1058,9 +1058,7 @@ rsvg_desc_handler_end (RsvgSaxHandler *self, const xmlChar *name) } } - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } static void @@ -1135,9 +1133,7 @@ rsvg_title_handler_end (RsvgSaxHandler *self, const xmlChar *name) } } - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + rsvg_state_pop(ctx); } static void @@ -1173,17 +1169,7 @@ rsvg_start_element (void *data, const xmlChar *name, } else { - /* push the state stack */ - if (ctx->n_state == ctx->n_state_max) - ctx->state = g_renew (RsvgState, ctx->state, ctx->n_state_max <<= 1); - if (ctx->n_state) - { - rsvg_state_inherit (&ctx->state[ctx->n_state], - &ctx->state[ctx->n_state - 1]); - } - else - rsvg_state_init (ctx->state); - ctx->n_state++; + rsvg_state_push(ctx); if (!strcmp ((char *)name, "svg")) { @@ -1315,9 +1301,8 @@ rsvg_end_element (void *data, const xmlChar *name) ctx->in_defs--; rsvg_pop_def_group(ctx); } - /* pop the state stack */ - ctx->n_state--; - rsvg_state_finalize (&ctx->state[ctx->n_state]); + + rsvg_state_pop(ctx); } } @@ -1475,18 +1460,23 @@ rsvg_handle_close_impl (RsvgHandle *handle, return TRUE; } +static void +rsvg_state_free_func(gpointer data, gpointer user_data) +{ + RsvgHandle * ctx = (RsvgHandle *)user_data; + rsvg_state_finalize((RsvgState *)data); + g_mem_chunk_free(ctx->state_allocator, data); +} + void rsvg_handle_free_impl (RsvgHandle *handle) { - int i; - if (handle->pango_context != NULL) g_object_unref (handle->pango_context); rsvg_defs_free (handle->defs); - for (i = 0; i < handle->n_state; i++) - rsvg_state_finalize (&handle->state[i]); - g_free (handle->state); + g_slist_foreach(handle->state, rsvg_state_free_func, (gpointer)handle); + g_slist_free (handle->state); g_hash_table_foreach (handle->entities, rsvg_ctx_free_helper, NULL); g_hash_table_destroy (handle->entities); @@ -1506,6 +1496,8 @@ rsvg_handle_free_impl (RsvgHandle *handle) if (handle->base_uri) g_free (handle->base_uri); + g_mem_chunk_destroy(handle->state_allocator); + g_free (handle); } @@ -1569,9 +1561,7 @@ rsvg_handle_new (void) void rsvg_handle_init (RsvgHandle * handle) { - handle->n_state = 0; - handle->n_state_max = 16; - handle->state = g_new (RsvgState, handle->n_state_max); + handle->state = NULL; handle->defs = rsvg_defs_new (); handle->handler_nest = 0; handle->entities = g_hash_table_new (g_str_hash, g_str_equal); @@ -1586,6 +1576,11 @@ rsvg_handle_init (RsvgHandle * handle) handle->current_defs_group = NULL; handle->title = g_string_new (NULL); handle->desc = g_string_new (NULL); + + /* should this be G_ALLOC_ONLY? */ + handle->state_allocator = g_mem_chunk_create (RsvgState, 256, G_ALLOC_AND_FREE); + + rsvg_state_push(handle); } /** |