summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--rsvg-base.c165
-rw-r--r--rsvg-cairo-draw.c32
-rw-r--r--rsvg-cairo-render.c2
-rw-r--r--rsvg-css.c100
-rw-r--r--rsvg-css.h3
-rw-r--r--rsvg-mask.c40
-rw-r--r--rsvg-mask.h3
-rw-r--r--rsvg-private.h29
-rw-r--r--rsvg-structure.c47
-rw-r--r--rsvg-structure.h2
-rw-r--r--rsvg.c3
12 files changed, 356 insertions, 75 deletions
diff --git a/ChangeLog b/ChangeLog
index b0347982..21db6168 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-10-22 Caleb Moore <c.moore@student.unsw.edu.au>
+
+ * a_lot_of_places: implemented a system of late normalizations of lengths. Now used in masks and svgs
+ * rsvg-base.c: find out the size of the contents of an SVG if there is nothing else to go on.
+
2005-10-20 Dom Lachowicz <cinamod@hotmail.com>
* configure.in: Prioritize the cairo backend over the libart one; disable the libart backend until it builds again
diff --git a/rsvg-base.c b/rsvg-base.c
index fddd0ee1..3fda9c18 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -1040,6 +1040,133 @@ rsvg_handle_new (void)
return handle;
}
+typedef struct {
+ RsvgRender super;
+ RsvgBbox bbox;
+} RsvgBboxRender;
+
+static void
+rsvg_bbox_render_path (RsvgDrawingCtx *ctx, const RsvgBpathDef *bpath_def)
+{
+ RsvgState *state = rsvg_state_current (ctx);
+ RsvgBpath *bpath;
+ RsvgBboxRender *render = (RsvgBboxRender *)ctx->render;
+ RsvgBbox bbox;
+ int i;
+
+ rsvg_bbox_init(&bbox, state->affine);
+ bbox.w = bbox.h = bbox.virgin = 0;
+
+ for (i=0; i < bpath_def->n_bpath; i++) {
+ bpath = &bpath_def->bpath[i];
+
+ switch (bpath->code) {
+ case RSVG_MOVETO:
+ case RSVG_MOVETO_OPEN:
+ case RSVG_CURVETO:
+ case RSVG_LINETO:
+ bbox.x = bpath->x3;
+ bbox.y = bpath->y3;
+ rsvg_bbox_insert(&render->bbox, &bbox);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void rsvg_bbox_render_image (RsvgDrawingCtx *ctx,
+ const GdkPixbuf * pixbuf,
+ double pixbuf_x, double pixbuf_y,
+ double w, double h)
+{
+ RsvgState *state = rsvg_state_current (ctx);
+ RsvgBboxRender *render = (RsvgBboxRender *)ctx->render;
+ RsvgBbox bbox;
+
+ rsvg_bbox_init(&bbox, state->affine);
+ bbox.x = pixbuf_x;
+ bbox.y = pixbuf_y;
+ bbox.w = w;
+ bbox.h = h;
+ bbox.virgin = 0;
+
+ rsvg_bbox_insert(&render->bbox, &bbox);
+}
+
+
+static void
+rsvg_bbox_render_free (RsvgRender * self)
+{
+ g_free (self);
+}
+
+static void
+rsvg_bbox_push_discrete_layer (RsvgDrawingCtx *ctx) {}
+
+static void
+rsvg_bbox_pop_discrete_layer (RsvgDrawingCtx *ctx) {}
+
+static void
+rsvg_bbox_add_clipping_rect (RsvgDrawingCtx *ctx,
+ double x, double y,
+ double w, double h){}
+
+static RsvgBboxRender *
+rsvg_bbox_render_new()
+{
+ RsvgBboxRender * render = g_new0(RsvgBboxRender, 1);
+ double affine[6];
+
+ render->super.free = rsvg_bbox_render_free;
+ render->super.render_image = rsvg_bbox_render_image;
+ render->super.render_path = rsvg_bbox_render_path;
+ render->super.pop_discrete_layer =
+ rsvg_bbox_pop_discrete_layer;
+ render->super.push_discrete_layer =
+ rsvg_bbox_push_discrete_layer;
+ render->super.add_clipping_rect =
+ rsvg_bbox_add_clipping_rect;
+ render->super.get_image_of_node = NULL;
+ _rsvg_affine_identity(affine);
+ rsvg_bbox_init(&render->bbox, affine);
+
+ return render;
+}
+
+static RsvgBbox
+_rsvg_find_bbox (RsvgHandle *handle)
+{
+ RsvgDrawingCtx * ctx = g_new(RsvgDrawingCtx, 1);
+ RsvgBbox output;
+ RsvgBboxRender * render = rsvg_bbox_render_new();
+ ctx->render = (RsvgRender *)render;
+
+ ctx->state = NULL;
+
+ ctx->state_allocator = g_mem_chunk_create (RsvgState, 256, G_ALLOC_AND_FREE);
+
+ ctx->defs = handle->defs;
+ ctx->base_uri = g_strdup(handle->base_uri);
+ ctx->dpi_x = handle->dpi_x;
+ ctx->dpi_y = handle->dpi_y;
+ ctx->vb.w = 512;
+ ctx->vb.h = 512;
+ ctx->pango_context = NULL;
+
+ rsvg_state_push(ctx);
+ _rsvg_affine_identity(rsvg_state_current(ctx)->affine);
+
+ rsvg_state_push(ctx);
+ _rsvg_node_draw_children ((RsvgNode *)handle->treebase, ctx, 0);
+ rsvg_state_pop(ctx);
+
+ output = render->bbox;
+ rsvg_render_free(ctx->render);
+ g_free(ctx);
+ return output;
+}
+
void
rsvg_handle_get_dimensions(RsvgHandle * handle, RsvgDimensionData * output)
{
@@ -1053,8 +1180,21 @@ rsvg_handle_get_dimensions(RsvgHandle * handle, RsvgDimensionData * output)
if (sself->hasw && sself->hash)
{
- output->width = sself->w;
- output->height = sself->h;
+ RsvgBbox bbox;
+ if (sself->w.factor == 'p' || sself->h.factor == 'p')
+ {
+ if (sself->has_vbox && sself->vbw > 0. && sself->vbh > 0.)
+ {
+ bbox.w = sself->vbw;
+ bbox.h = sself->vbh;
+ }
+ else
+ bbox = _rsvg_find_bbox(handle);
+ }
+ output->width = _rsvg_css_hand_normalize_length_struct(&sself->w, handle->dpi_x,
+ bbox.w, 12);
+ output->height = _rsvg_css_hand_normalize_length_struct(&sself->h, handle->dpi_y,
+ bbox.h, 12);
}
else if (sself->has_vbox && sself->vbw > 0. && sself->vbh > 0.)
{
@@ -1063,8 +1203,10 @@ rsvg_handle_get_dimensions(RsvgHandle * handle, RsvgDimensionData * output)
}
else
{
- output->width = 512;
- output->height = 512;
+ RsvgBbox bbox;
+ bbox = _rsvg_find_bbox(handle);
+ output->width = bbox.w;
+ output->height = bbox.h;
}
output->em = output->width;
@@ -1486,3 +1628,18 @@ void rsvg_bbox_clip(RsvgBbox * dst, RsvgBbox * src)
dst->h = ymax - ymin;
}
+void _rsvg_push_view_box(RsvgDrawingCtx *ctx, double w, double h)
+{
+ RsvgViewBox * vb = g_new(RsvgViewBox, 1);
+ *vb = ctx->vb;
+ ctx->vb_stack = g_slist_prepend(ctx->vb_stack, vb);
+ ctx->vb.w = w;
+ ctx->vb.h = h;
+}
+
+void _rsvg_pop_view_box(RsvgDrawingCtx *ctx)
+{
+ ctx->vb = *((RsvgViewBox *)ctx->vb_stack->data);
+ g_free(ctx->vb_stack->data);
+ ctx->vb_stack = g_slist_remove_link(ctx->vb_stack, ctx->vb_stack);
+}
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 9ac9531d..24d6b757 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -633,7 +633,19 @@ rsvg_cairo_generate_mask(cairo_t *cr,
guint32 width = render->width, height = render->height;
guint32 rowstride = width * 4, row, i;
double affinesave[6];
+ double sx, sy, sw, sh;
+ if (self->maskunits == objectBoundingBox)
+ _rsvg_push_view_box(ctx, 1, 1);
+
+ sx = _rsvg_css_normalize_length_struct(&self->x, ctx, 'h');
+ sy = _rsvg_css_normalize_length_struct(&self->y, ctx, 'v');
+ sw = _rsvg_css_normalize_length_struct(&self->width, ctx, 'h');
+ sh = _rsvg_css_normalize_length_struct(&self->height, ctx, 'v');
+
+ if (self->maskunits == objectBoundingBox)
+ _rsvg_pop_view_box(ctx);
+
pixels = g_new0(guint8, height * rowstride);
surface = cairo_image_surface_create_for_data (pixels,
CAIRO_FORMAT_ARGB32,
@@ -646,13 +658,12 @@ rsvg_cairo_generate_mask(cairo_t *cr,
if (self->maskunits == objectBoundingBox)
rsvg_cairo_add_clipping_rect (ctx,
- self->x * bbox->w + bbox->x,
- self->y * bbox->h + bbox->y,
- self->width * bbox->w,
- self->height * bbox->h);
+ sx * bbox->w + bbox->x,
+ sy * bbox->h + bbox->y,
+ sw * bbox->w,
+ sh * bbox->h);
else
- rsvg_cairo_add_clipping_rect (ctx, self->x, self->y,
- self->width, self->height);
+ rsvg_cairo_add_clipping_rect (ctx, sx, sy, sw, sh);
/* Horribly dirty hack to have the bbox premultiplied to everything */
if (self->contentunits == objectBoundingBox)
@@ -669,6 +680,7 @@ rsvg_cairo_generate_mask(cairo_t *cr,
_rsvg_affine_multiply(self->super.state->affine,
bbtransform,
self->super.state->affine);
+ _rsvg_push_view_box(ctx, 1, 1);
}
rsvg_state_push(ctx);
@@ -676,9 +688,11 @@ rsvg_cairo_generate_mask(cairo_t *cr,
rsvg_state_pop(ctx);
if (self->contentunits == objectBoundingBox)
- for (i = 0; i < 6; i++)
- self->super.state->affine[i] = affinesave[i];
-
+ {
+ _rsvg_pop_view_box(ctx);
+ for (i = 0; i < 6; i++)
+ self->super.state->affine[i] = affinesave[i];
+ }
render->cr = save_cr;
diff --git a/rsvg-cairo-render.c b/rsvg-cairo-render.c
index f3f7549f..4414ff8d 100644
--- a/rsvg-cairo-render.c
+++ b/rsvg-cairo-render.c
@@ -94,6 +94,8 @@ rsvg_cairo_new_drawing_ctx (cairo_t *cr, RsvgHandle *handle)
draw->base_uri = g_strdup(handle->base_uri);
draw->dpi_x = handle->dpi_x;
draw->dpi_y = handle->dpi_y;
+ draw->vb.w = data.em;
+ draw->vb.h = data.ex;
draw->pango_context = NULL;
rsvg_state_push(draw);
diff --git a/rsvg-css.c b/rsvg-css.c
index 90d55930..a80ff1f9 100644
--- a/rsvg-css.c
+++ b/rsvg-css.c
@@ -25,6 +25,8 @@
#include "config.h"
#include "rsvg-css.h"
+#include "rsvg-private.h"
+#include "rsvg-styles.h"
#include <glib.h>
#include <stdio.h>
@@ -90,7 +92,7 @@ rsvg_css_parse_vbox (const char * vbox, double * x, double * y,
* Returns: returns the length.
**/
double
-rsvg_css_parse_length (const char *str, gdouble pixels_per_inch,
+rsvg_css_parse_length (const char *str, gint *in,
gint *percent, gint *em, gint *ex)
{
double length = 0.0;
@@ -114,15 +116,27 @@ rsvg_css_parse_length (const char *str, gdouble pixels_per_inch,
if (p && (strcmp(p, "px") != 0))
{
if (!strcmp(p, "pt"))
- length *= (pixels_per_inch / POINTS_PER_INCH);
+ {
+ length /= POINTS_PER_INCH;
+ *in = TRUE;
+ }
else if (!strcmp(p, "in"))
- length *= pixels_per_inch;
+ *in = TRUE;
else if (!strcmp(p, "cm"))
- length *= (pixels_per_inch / CM_PER_INCH);
+ {
+ length /= CM_PER_INCH;
+ *in = TRUE;
+ }
else if (!strcmp(p, "mm"))
- length *= (pixels_per_inch / MM_PER_INCH);
+ {
+ length /= MM_PER_INCH;
+ *in = TRUE;
+ }
else if (!strcmp(p, "pc"))
- length *= (pixels_per_inch / PICA_PER_INCH);
+ {
+ length /= PICA_PER_INCH;
+ *in = TRUE;
+ }
else if (!strcmp(p, "em"))
*em = TRUE;
else if (!strcmp(p, "ex"))
@@ -137,6 +151,72 @@ rsvg_css_parse_length (const char *str, gdouble pixels_per_inch,
return length;
}
+RsvgLength
+_rsvg_css_parse_length_struct(const char *str)
+{
+ RsvgLength out;
+ gint percent, em, ex, in;
+ percent = em = ex = in = FALSE;
+
+ out.length = rsvg_css_parse_length (str, &in, &percent, &em, &ex);
+ if (percent)
+ out.factor = 'p';
+ else if (em)
+ out.factor = 'm';
+ else if (ex)
+ out.factor = 'x';
+ else if (in)
+ out.factor = 'i';
+ else
+ out.factor = '\0';
+ return out;
+}
+
+double
+_rsvg_css_normalize_length_struct(const RsvgLength * in, RsvgDrawingCtx * ctx,
+ char dir)
+{
+ if (in->factor == '\0')
+ return in->length;
+ else if (in->factor == 'p')
+ {
+ if (dir == 'h')
+ return in->length * ctx->vb.w;
+ if (dir == 'v')
+ return in->length * ctx->vb.h;
+ }
+ else if (in->factor == 'm')
+ return in->length * rsvg_state_current(ctx)->font_size;
+ else if (in->factor == 'x')
+ return in->length * rsvg_state_current(ctx)->font_size / 2.;
+ else if (in->factor == 'i')
+ {
+ if (dir == 'h')
+ return in->length * ctx->dpi_x;
+ if (dir == 'v')
+ return in->length * ctx->dpi_y;
+ }
+ return 0;
+}
+
+double
+_rsvg_css_hand_normalize_length_struct(const RsvgLength * in, gdouble pixels_per_inch,
+ gdouble width_or_height, gdouble font_size)
+{
+ if (in->factor == '\0')
+ return in->length;
+ else if (in->factor == 'p')
+ return in->length * width_or_height;
+ else if (in->factor == 'm')
+ return in->length * font_size;
+ else if (in->factor == 'x')
+ return in->length * font_size / 2.;
+ else if (in->factor == 'i')
+ return in->length * pixels_per_inch;
+
+ return 0;
+}
+
/**
* rsvg_css_parse_normalized_length: Parse CSS2 length to a pixel value.
* @str: Original string.
@@ -152,16 +232,18 @@ rsvg_css_parse_normalized_length(const char *str, gdouble pixels_per_inch,
gdouble width_or_height, gdouble font_size)
{
double length;
- gint percent, em, ex;
- percent = em = ex = FALSE;
+ gint percent, em, ex, in;
+ percent = em = ex = in = FALSE;
- length = rsvg_css_parse_length (str, pixels_per_inch, &percent, &em, &ex);
+ length = rsvg_css_parse_length (str, &in, &percent, &em, &ex);
if (percent)
return length * width_or_height;
else if (em)
return length * font_size;
else if (ex)
return (length * font_size) / 2.;
+ else if (in)
+ return length * pixels_per_inch;
else
return length;
}
diff --git a/rsvg-css.h b/rsvg-css.h
index ef1f1dc9..55079d8d 100644
--- a/rsvg-css.h
+++ b/rsvg-css.h
@@ -45,7 +45,7 @@ G_BEGIN_DECLS
int rsvg_css_parse_aspect_ratio(const char * str);
double
-rsvg_css_parse_length (const char *str, gdouble pixels_per_inch,
+rsvg_css_parse_length (const char *str, gint *in,
gint *percent, gint *em, gint *ex);
double
@@ -105,6 +105,7 @@ rsvg_css_parse_number_list(const char * in_str, guint * out_list_len);
gboolean
rsvg_css_parse_overflow(const char * str, gboolean * inherit);
+
G_END_DECLS
#endif /* RSVG_CSS_H */
diff --git a/rsvg-mask.c b/rsvg-mask.c
index 82b56468..535886a1 100644
--- a/rsvg-mask.c
+++ b/rsvg-mask.c
@@ -33,20 +33,14 @@ rsvg_mask_set_atts (RsvgNode * self, RsvgHandle *ctx, RsvgPropertyBag *atts)
{
const char *id = NULL, *klazz = NULL, *value;
RsvgMask *mask;
- double font_size, xscale = 1., yscale = 1.;
-
- font_size = rsvg_state_current_font_size (ctx);
mask = (RsvgMask *)self;
if (rsvg_property_bag_size (atts))
{
if ((value = rsvg_property_bag_lookup (atts, "maskUnits")))
{
- if (!strcmp (value, "userSpaceOnUse")){
+ if (!strcmp (value, "userSpaceOnUse"))
mask->maskunits = userSpaceOnUse;
- xscale = (gdouble)ctx->width;
- yscale = (gdouble)ctx->height;
- }
else
mask->maskunits = objectBoundingBox;
}
@@ -58,29 +52,13 @@ rsvg_mask_set_atts (RsvgNode * self, RsvgHandle *ctx, RsvgPropertyBag *atts)
mask->contentunits = userSpaceOnUse;
}
if ((value = rsvg_property_bag_lookup (atts, "x")))
- mask->x =
- rsvg_css_parse_normalized_length (value,
- ctx->dpi_x,
- xscale,
- font_size);
+ mask->x = _rsvg_css_parse_length_struct (value);
if ((value = rsvg_property_bag_lookup (atts, "y")))
- mask->y =
- rsvg_css_parse_normalized_length (value,
- ctx->dpi_y,
- yscale,
- font_size);
+ mask->y = _rsvg_css_parse_length_struct (value);
if ((value = rsvg_property_bag_lookup (atts, "width")))
- mask->width =
- rsvg_css_parse_normalized_length (value,
- ctx->dpi_x,
- xscale,
- font_size);
+ mask->width = _rsvg_css_parse_length_struct (value);
if ((value = rsvg_property_bag_lookup (atts, "height")))
- mask->height =
- rsvg_css_parse_normalized_length (value,
- ctx->dpi_y,
- yscale,
- font_size);
+ mask->height = _rsvg_css_parse_length_struct (value);
if ((value = rsvg_property_bag_lookup (atts, "id")))
{
id = value;
@@ -102,10 +80,10 @@ rsvg_new_mask (void)
_rsvg_node_init(&mask->super);
mask->maskunits = objectBoundingBox;
mask->contentunits = userSpaceOnUse;
- mask->x = 0;
- mask->y = 0;
- mask->width = 1;
- mask->height = 1;
+ mask->x = _rsvg_css_parse_length_struct ("0");
+ mask->y = _rsvg_css_parse_length_struct ("0");
+ mask->width = _rsvg_css_parse_length_struct ("1");
+ mask->height = _rsvg_css_parse_length_struct ("1");
mask->super.type = RSVG_NODE_MASK;
mask->super.set_atts = rsvg_mask_set_atts;
return &mask->super;
diff --git a/rsvg-mask.h b/rsvg-mask.h
index 13ccba0b..46eacd5b 100644
--- a/rsvg-mask.h
+++ b/rsvg-mask.h
@@ -27,6 +27,7 @@
#include "rsvg.h"
#include "rsvg-defs.h"
+#include "rsvg-css.h"
#include "rsvg-styles.h"
#include "rsvg-shapes.h"
#include <libxml/SAX.h>
@@ -39,7 +40,7 @@ typedef struct _RsvgMask RsvgMask;
struct _RsvgMask {
RsvgNode super;
- double x, y, width, height;
+ RsvgLength x, y, width, height;
RsvgMaskUnits maskunits;
RsvgMaskUnits contentunits;
};
diff --git a/rsvg-private.h b/rsvg-private.h
index f9aecc67..8bb6f136 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -65,7 +65,6 @@ typedef struct _RsvgIRect RsvgIRect;
# endif /* G_PI */
#endif /* M_PI */
-
struct RsvgSaxHandler {
void (*free) (RsvgSaxHandler *self);
void (*start_element) (RsvgSaxHandler *self, const xmlChar *name, RsvgPropertyBag *atts);
@@ -122,6 +121,10 @@ struct RsvgHandle {
void * gzipped_data; /* really a GsfOutput */
};
+typedef struct{
+ double w, h;
+} RsvgViewBox;
+
/*Contextual information for the drawing phase*/
struct RsvgDrawingCtx {
@@ -132,8 +135,9 @@ struct RsvgDrawingCtx {
gchar * base_uri;
GMemChunk * state_allocator;
PangoContext *pango_context;
- double dpi_x;
- double dpi_y;
+ double dpi_x, dpi_y;
+ RsvgViewBox vb;
+ GSList * vb_stack;
};
/*Abstract base class for context for our backends (one as yet)*/
@@ -152,6 +156,12 @@ struct RsvgRender {
double w, double h);
};
+
+typedef struct{
+ double length;
+ char factor;
+} RsvgLength;
+
struct _RsvgIRect {
int x0, y0, x1, y1;
};
@@ -331,6 +341,19 @@ void rsvg_bbox_init(RsvgBbox * self, double * affine);
void rsvg_bbox_insert(RsvgBbox * dst, RsvgBbox * src);
void rsvg_bbox_clip(RsvgBbox * dst, RsvgBbox * src);
+double
+_rsvg_css_normalize_length_struct(const RsvgLength * in, RsvgDrawingCtx * ctx,
+ char dir);
+double
+_rsvg_css_hand_normalize_length_struct(const RsvgLength * in, gdouble pixels_per_inch,
+ gdouble width_or_height, gdouble font_size);
+
+RsvgLength
+_rsvg_css_parse_length_struct(const char *str);
+
+void _rsvg_push_view_box(RsvgDrawingCtx *ctx, double w, double h);
+void _rsvg_pop_view_box(RsvgDrawingCtx *ctx);
+
G_END_DECLS
#endif
diff --git a/rsvg-structure.c b/rsvg-structure.c
index e65779cb..ed2433e6 100644
--- a/rsvg-structure.c
+++ b/rsvg-structure.c
@@ -204,11 +204,12 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
-symbol->y);
_rsvg_affine_multiply(state->affine, affine, state->affine);
+ _rsvg_push_view_box(ctx, symbol->width, symbol->height);
+ rsvg_push_discrete_layer (ctx);
if (!state->overflow ||
(!state->has_overflow && child->state->overflow))
- rsvg_push_discrete_layer (ctx);
- rsvg_add_clipping_rect (ctx, symbol->x, symbol->y,
- symbol->width, symbol->height);
+ rsvg_add_clipping_rect (ctx, symbol->x, symbol->y,
+ symbol->width, symbol->height);
} else {
_rsvg_affine_translate(affine, use->x, use->y);
_rsvg_affine_multiply(state->affine, affine, state->affine);
@@ -219,6 +220,8 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
_rsvg_node_draw_children(child, ctx, 1);
rsvg_state_pop(ctx);
rsvg_pop_discrete_layer (ctx);
+ if (symbol->has_vbox)
+ _rsvg_pop_view_box(ctx);
}
}
@@ -240,8 +243,14 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
RsvgState *state;
gdouble affine[6], affine_old[6], affine_new[6];
guint i;
+ double nx, ny, nw, nh;
sself = (RsvgNodeSvg *)self;
+ nx = _rsvg_css_normalize_length_struct(&sself->x, ctx, 'h');
+ ny = _rsvg_css_normalize_length_struct(&sself->y, ctx, 'v');
+ nw = _rsvg_css_normalize_length_struct(&sself->w, ctx, 'h');
+ nh = _rsvg_css_normalize_length_struct(&sself->h, ctx, 'v');
+
rsvg_state_reinherit_top(ctx, self->state, dominate);
state = rsvg_state_current (ctx);
@@ -251,7 +260,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
if (sself->has_vbox && sself->hasw && sself->hash)
{
- double x = sself->x, y = sself->y, w = sself->w, h = sself->h;
+ double x = nx, y = ny, w = nw, h = nh;
rsvg_preserve_aspect_ratio(sself->preserve_aspect_ratio,
sself->vbw, sself->vbh,
&w, &h, &x, &y);
@@ -263,6 +272,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
affine[5] = y - sself->vby * h / sself->vbh;
_rsvg_affine_multiply(state->affine, affine,
state->affine);
+ _rsvg_push_view_box(ctx, sself->vbw, sself->vbh);
}
else
{
@@ -270,10 +280,11 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
affine[1] = 0;
affine[2] = 0;
affine[3] = 1;
- affine[4] = sself->x;
- affine[5] = sself->y;
+ affine[4] = nx;
+ affine[5] = ny;
_rsvg_affine_multiply(state->affine, affine,
state->affine);
+ _rsvg_push_view_box(ctx, nw, nh);
}
for (i = 0; i < 6; i++)
affine_new[i] = state->affine[i];
@@ -286,7 +297,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
{
for (i = 0; i < 6; i++)
state->affine[i] = affine_old[i];
- rsvg_add_clipping_rect(ctx, sself->x, sself->y, sself->w, sself->h);
+ rsvg_add_clipping_rect(ctx, nx, ny, nw, nh);
for (i = 0; i < 6; i++)
state->affine[i] = affine_new[i];
}
@@ -300,6 +311,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx *ctx,
}
rsvg_pop_discrete_layer (ctx);
+ _rsvg_pop_view_box(ctx);
}
static void
@@ -329,22 +341,22 @@ rsvg_node_svg_set_atts (RsvgNode * self, RsvgHandle *ctx, RsvgPropertyBag *atts)
svg->preserve_aspect_ratio = rsvg_css_parse_aspect_ratio (value);
if ((value = rsvg_property_bag_lookup (atts, "width")))
{
- svg->w = rsvg_css_parse_normalized_length (value, ctx->dpi_x, ctx->width, 1);
- svg->hasw = (svg->w > 0);
+ svg->w = _rsvg_css_parse_length_struct (value);
+ svg->hasw = svg->w.length > 0;
if (!svg->has_vbox)
- ctx->width = svg->w;
+ ctx->width = svg->w.length;
}
if ((value = rsvg_property_bag_lookup (atts, "height")))
{
- svg->h = rsvg_css_parse_normalized_length (value, ctx->dpi_y, ctx->height, 1);
- svg->hash = (svg->h > 0);
+ svg->h = _rsvg_css_parse_length_struct (value);
+ svg->hash = svg->h.length > 0;
if (!svg->has_vbox)
- ctx->height = svg->h;
+ ctx->height = svg->h.length;
}
if ((value = rsvg_property_bag_lookup (atts, "x")))
- svg->x = rsvg_css_parse_normalized_length (value, ctx->dpi_x, ctx->width, 1);
+ svg->x = _rsvg_css_parse_length_struct (value);
if ((value = rsvg_property_bag_lookup (atts, "y")))
- svg->y = rsvg_css_parse_normalized_length (value, ctx->dpi_y, ctx->height, 1);
+ svg->y = _rsvg_css_parse_length_struct (value);
if ((value = rsvg_property_bag_lookup (atts, "id")))
{
id = value;
@@ -361,7 +373,10 @@ rsvg_new_svg (void)
_rsvg_node_init(&svg->super);
svg->has_vbox = FALSE;
svg->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
- svg->x = 0; svg->y = 0; svg->w = -1; svg->h = -1;
+ svg->x = _rsvg_css_parse_length_struct ("0");
+ svg->y = _rsvg_css_parse_length_struct ("0");
+ svg->w = _rsvg_css_parse_length_struct ("0");
+ svg->h = _rsvg_css_parse_length_struct ("0");
svg->hasw = svg->hash = FALSE;
svg->vbx = 0; svg->vby = 0; svg->vbw = 0; svg->vbh = 0;
svg->super.type = RSVG_NODE_PATH;
diff --git a/rsvg-structure.h b/rsvg-structure.h
index c6a72516..e92acb5c 100644
--- a/rsvg-structure.h
+++ b/rsvg-structure.h
@@ -67,7 +67,7 @@ struct _RsvgNodeUse {
struct _RsvgNodeSvg {
RsvgNode super;
gint preserve_aspect_ratio;
- gdouble x, y, w, h;
+ RsvgLength x, y, w, h;
int hasw :1;
int hash :1;
gdouble vbx, vby, vbw, vbh;
diff --git a/rsvg.c b/rsvg.c
index 0b944a7c..1fed7ae0 100644
--- a/rsvg.c
+++ b/rsvg.c
@@ -77,6 +77,9 @@ rsvg_new_drawing_ctx(RsvgHandle * handle)
draw->base_uri = g_strdup(handle->base_uri);
draw->dpi_x = handle->dpi_x;
draw->dpi_y = handle->dpi_y;
+ draw->vb.w = data.w;
+ draw->vb.h = data.h;
+ draw->vb_stack = NULL;
draw->pango_context = NULL;
rsvg_state_push(draw);