librsvg r1190 - trunk
- From: doml svn gnome org
- To: svn-commits-list gnome org
- Subject: librsvg r1190 - trunk
- Date: Sat, 22 Nov 2008 16:44:34 +0000 (UTC)
Author: doml
Date: Sat Nov 22 16:44:34 2008
New Revision: 1190
URL: http://svn.gnome.org/viewvc/librsvg?rev=1190&view=rev
Log:
2008-11-22 Dominic Lachowicz <domlachowicz gmail com>
* rsvg-cairo-render.h: Feature request:
rsvg_handle_get_dimensions_sub()
(#555682). Patches from Hagen Schink (troja84 gmail com) and
Robert Staudinger (robert staudinger gmail com)
* librsvg.def:
* rsvg-private.h:
* ChangeLog:
* rsvg-structure.c:
* rsvg-base.c:
* rsvg-css.c:
* rsvg.h:
* rsvg-dimensions.c:
* Makefile.am:
* rsvg-cairo-render.c:
* rsvg-gobject.c: ditto
Added:
trunk/rsvg-dimensions.c
Modified:
trunk/ChangeLog
trunk/Makefile.am
trunk/librsvg.def
trunk/rsvg-base.c
trunk/rsvg-cairo-render.c
trunk/rsvg-cairo-render.h
trunk/rsvg-css.c
trunk/rsvg-gobject.c
trunk/rsvg-private.h
trunk/rsvg-structure.c
trunk/rsvg.h
Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am (original)
+++ trunk/Makefile.am Sat Nov 22 16:44:34 2008
@@ -8,7 +8,7 @@
lib_LTLIBRARIES = librsvg-2.la
bin_PROGRAMS = rsvg-convert $(target_rsvg_view)
-noinst_PROGRAMS = test-performance
+noinst_PROGRAMS = test-performance rsvg-dimensions
man_MANS = rsvg.1
@@ -109,6 +109,11 @@
test_performance_DEPENDENCIES = $(DEPS)
test_performance_LDADD = $(LDADDS) $(libm)
+rsvg_dimensions_SOURCES=rsvg-dimensions.c
+rsvg_dimensions_LDFLAGS =
+rsvg_dimensions_DEPENDENCIES = $(DEPS)
+rsvg_dimensions_LDADD = $(LDADDS) $(libm)
+
rsvg_view_SOURCES = \
test-display.c
rsvg_view_LDFLAGS =
Modified: trunk/librsvg.def
==============================================================================
--- trunk/librsvg.def (original)
+++ trunk/librsvg.def Sat Nov 22 16:44:34 2008
@@ -15,6 +15,7 @@
rsvg_handle_get_base_uri
rsvg_handle_set_base_uri
rsvg_handle_get_dimensions
+rsvg_handle_get_dimensions_sub
rsvg_handle_get_title
rsvg_handle_get_desc
rsvg_handle_get_metadata
Modified: trunk/rsvg-base.c
==============================================================================
--- trunk/rsvg-base.c (original)
+++ trunk/rsvg-base.c Sat Nov 22 16:44:34 2008
@@ -42,6 +42,7 @@
#include "rsvg-filter.h"
#include "rsvg-mask.h"
#include "rsvg-marker.h"
+#include "rsvg-cairo-render.h"
#include <libxml/uri.h>
@@ -1224,132 +1225,6 @@
return NULL;
}
-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->drawsub_stack = NULL;
- ctx->ptrs = NULL;
- ctx->render = (RsvgRender *) render;
-
- ctx->state = NULL;
-
- ctx->defs = handle->priv->defs;
- ctx->base_uri = g_strdup (handle->priv->base_uri);
- ctx->dpi_x = handle->priv->dpi_x;
- ctx->dpi_y = handle->priv->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_node_draw_children ((RsvgNode *) handle->priv->treebase, ctx, 0);
- rsvg_state_pop (ctx);
-
- output = render->bbox;
- rsvg_render_free (ctx->render);
- g_free (ctx);
- return output;
-}
-
/**
* rsvg_handle_get_dimensions
* @handle: A #RsvgHandle
@@ -1362,43 +1237,135 @@
void
rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_data)
{
- RsvgNodeSvg *sself;
+ /* This function is probably called from the cairo_render functions.
+ * To prevent an infinite loop we are saving the state.
+ */
+ if (!handle->priv->in_loop) {
+ handle->priv->in_loop = TRUE;
+ rsvg_handle_get_dimensions_sub (handle, dimension_data, NULL);
+ handle->priv->in_loop = FALSE;
+ } else {
+ /* Called within the size function, so return a standard size */
+ dimension_data->em = dimension_data->width = 1;
+ dimension_data->ex = dimension_data->height = 1;
+ }
+}
+
+/**
+ * rsvg_handle_get_dimensions_sub
+ * @handle: A #RsvgHandle
+ * @dimension_data: A place to store the SVG's size
+ * @id: An element's id within the SVG, or NULL to get the dimension of the whole SVG.
+ * For example, if you have a layer called "layer1" for that you want to get the dimension,
+ * pass "#layer1" as the id.
+ *
+ * Get the size of a subelement of the SVG file. Do not call from within the size_func callback, because an infinite loop will occur.
+ *
+ * Since: 2.22
+ */
+gboolean
+rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimension_data, const char *id)
+{
+ cairo_t *cr;
+ cairo_surface_t *target;
+ RsvgDrawingCtx *draw;
+ RsvgCairoRender *render;
+ RsvgNodeSvg *root = NULL;
+ RsvgNode *sself = NULL;
RsvgBbox bbox;
- g_return_if_fail (handle);
- g_return_if_fail (dimension_data);
+ gboolean handle_subelement = TRUE;
+
+ g_return_val_if_fail (handle, FALSE);
+ g_return_val_if_fail (dimension_data, FALSE);
memset (dimension_data, 0, sizeof (RsvgDimensionData));
- sself = (RsvgNodeSvg *) handle->priv->treebase;
- if (!sself)
- return;
+ if (id && *id) {
+ sself = (RsvgNode *) rsvg_defs_lookup (handle->priv->defs, id);
+
+ if (sself == (RsvgNode *) handle->priv->treebase)
+ id = NULL;
+ }
+ else
+ sself = (RsvgNode *) handle->priv->treebase;
+
+ if (!sself && id)
+ return FALSE;
+
+ root = (RsvgNodeSvg *) handle->priv->treebase;
+
+ if (!root)
+ return FALSE;
bbox.x = bbox.y = 0;
bbox.w = bbox.h = 1;
- if (sself->w.factor == 'p' || sself->h.factor == 'p') {
- if (sself->vbox.active && sself->vbox.w > 0. && sself->vbox.h > 0.) {
- bbox.w = sself->vbox.w;
- bbox.h = sself->vbox.h;
- } else
- bbox = _rsvg_find_bbox (handle);
- }
+ if (!id && (root->w.factor == 'p' || root->h.factor == 'p')
+ && root->vbox.active && root->vbox.w > 0. && root->vbox.h > 0.)
+ handle_subelement = TRUE;
+ else if (!id && root->w.length != -1 && root->h.length != -1)
+ handle_subelement = FALSE;
+
+ if (handle_subelement == TRUE) {
+ target = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+ 1, 1);
+ cr = cairo_create (target);
+
+ draw = rsvg_cairo_new_drawing_ctx (cr, handle);
+
+ if (!draw)
+ return FALSE;
+
+ while (sself != NULL) {
+ draw->drawsub_stack = g_slist_prepend (draw->drawsub_stack, sself);
+ sself = sself->parent;
+ }
+
+ rsvg_state_push (draw);
+ cairo_save (cr);
- dimension_data->width = (int) (_rsvg_css_hand_normalize_length (&sself->w, handle->priv->dpi_x,
- bbox.w + bbox.x * 2, 12) + 0.5);
- dimension_data->height = (int) (_rsvg_css_hand_normalize_length (&sself->h, handle->priv->dpi_y,
- bbox.h + bbox.y * 2,
- 12) + 0.5);
+ rsvg_node_draw ((RsvgNode *) handle->priv->treebase, draw, 0);
+ render = (RsvgCairoRender *) draw->render;
+
+ bbox.x = render->bbox.x;
+ bbox.y = render->bbox.y;
+ bbox.w = render->bbox.w;
+ bbox.h = render->bbox.h;
+
+ cairo_restore (cr);
+ rsvg_state_pop (draw);
+ rsvg_drawing_ctx_free (draw);
+ cairo_destroy (cr);
+ cairo_surface_destroy (target);
+
+ dimension_data->width = (int) (_rsvg_css_hand_normalize_length_sub (&root->w, bbox.w, handle->priv->dpi_x,
+ bbox.w + bbox.x * 2, 12) + 0.5);
+ dimension_data->height = (int) (_rsvg_css_hand_normalize_length_sub (&root->h, bbox.h, handle->priv->dpi_y,
+ bbox.h + bbox.y * 2,
+ 12) + 0.5);
+ } else {
+ bbox.w = root->vbox.w;
+ bbox.h = root->vbox.h;
+ dimension_data->width = (int) (_rsvg_css_hand_normalize_length (&root->w, handle->priv->dpi_x,
+ bbox.w + bbox.x * 2, 12) + 0.5);
+ dimension_data->height = (int) (_rsvg_css_hand_normalize_length (&root->h, handle->priv->dpi_y,
+ bbox.h + bbox.y * 2,
+ 12) + 0.5);
+ }
+
dimension_data->em = dimension_data->width;
dimension_data->ex = dimension_data->height;
if (handle->priv->size_func)
(*handle->priv->size_func) (&dimension_data->width, &dimension_data->height,
handle->priv->user_data);
+
+ return TRUE;
}
+
/**
* rsvg_set_default_dpi
* @dpi: Dots Per Inch (aka Pixels Per Inch)
Modified: trunk/rsvg-cairo-render.c
==============================================================================
--- trunk/rsvg-cairo-render.c (original)
+++ trunk/rsvg-cairo-render.c Sat Nov 22 16:44:34 2008
@@ -107,7 +107,7 @@
*y1 = ceil (t > y11 ? t : y11);
}
-static RsvgDrawingCtx *
+RsvgDrawingCtx *
rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle)
{
RsvgDimensionData data;
Modified: trunk/rsvg-cairo-render.h
==============================================================================
--- trunk/rsvg-cairo-render.h (original)
+++ trunk/rsvg-cairo-render.h Sat Nov 22 16:44:34 2008
@@ -51,6 +51,7 @@
RsvgCairoRender *rsvg_cairo_render_new (cairo_t * cr, double width, double height);
void rsvg_cairo_render_rsvg_handle (cairo_t * cr, RsvgHandle * handle);
+RsvgDrawingCtx *rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle);
G_END_DECLS
Modified: trunk/rsvg-css.c
==============================================================================
--- trunk/rsvg-css.c (original)
+++ trunk/rsvg-css.c Sat Nov 22 16:44:34 2008
@@ -252,6 +252,25 @@
return 0;
}
+double
+_rsvg_css_hand_normalize_length_sub (const RsvgLength * in, gdouble length,
+ gdouble pixels_per_inch, gdouble width_or_height,
+ gdouble font_size)
+{
+ if (in->factor == '\0')
+ return length;
+ else if (in->factor == 'p')
+ return length * width_or_height;
+ else if (in->factor == 'm')
+ return length * font_size;
+ else if (in->factor == 'x')
+ return length * font_size / 2.;
+ else if (in->factor == 'i')
+ return length * pixels_per_inch;
+
+ return 0;
+}
+
gboolean
rsvg_css_param_match (const char *str, const char *param_name)
{
Added: trunk/rsvg-dimensions.c
==============================================================================
--- (empty file)
+++ trunk/rsvg-dimensions.c Sat Nov 22 16:44:34 2008
@@ -0,0 +1,128 @@
+
+/*
+ * License: Public Domain.
+ * Author: Robert Staudinger <robsta gnome org>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <rsvg.h>
+
+static void
+show_help (GOptionContext *context)
+{
+ char *help;
+ help = g_option_context_get_help (context, TRUE, NULL);
+ perror (help);
+ g_free (help), help = NULL;
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GOptionContext *context;
+ char const *fragment;
+ char const **filenames;
+ char const *file;
+ RsvgHandle *handle;
+ RsvgDimensionData dimensions;
+ GError *error;
+ int exit_code;
+ int i;
+
+ GOptionEntry options[] = {
+ { "fragment", 'f', 0, G_OPTION_ARG_STRING, &fragment, "The SVG fragment to address.", "<string>" },
+ { G_OPTION_REMAINING, 0, G_OPTION_FLAG_FILENAME, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, "[FILE...]" },
+ { NULL }
+ };
+
+ rsvg_init ();
+
+ fragment = NULL;
+ filenames = NULL;
+
+ context = g_option_context_new ("- SVG measuring tool.");
+ g_option_context_add_main_entries (context, options, NULL);
+
+ /* No args? */
+ if (argc < 2) {
+ show_help (context);
+ exit_code = EXIT_SUCCESS;
+ goto bail1;
+ }
+
+ error = NULL;
+ g_option_context_parse (context, &argc, &argv, &error);
+ if (error) {
+ show_help (context);
+ g_warning (error->message);
+ exit_code = EXIT_FAILURE;
+ goto bail2;
+ }
+
+ /* Invalid / missing args? */
+ if (filenames == NULL) {
+ show_help (context);
+ exit_code = EXIT_FAILURE;
+ goto bail2;
+ }
+
+ g_option_context_free (context), context = NULL;
+
+ for (i = 0; NULL != (file = filenames[i]); i++) {
+
+ error = NULL;
+ handle = rsvg_handle_new_from_file (file, &error);
+ if (error) {
+ g_warning (error->message);
+ exit_code = EXIT_FAILURE;
+ goto bail2;
+ }
+
+ if (fragment && handle) {
+ gboolean have_fragment;
+ have_fragment = rsvg_handle_get_dimensions_sub (handle,
+ &dimensions, fragment);
+ if (!have_fragment) {
+ g_warning ("%s: fragment `'%s' not found.",
+ file, fragment);
+ exit_code = EXIT_FAILURE;
+ goto bail3;
+ }
+
+ printf ("%s, fragment `%s': %dx%d, em=%f, ex=%f\n",
+ file, fragment,
+ dimensions.width, dimensions.height,
+ dimensions.em, dimensions.ex);
+
+ } else if (handle) {
+ rsvg_handle_get_dimensions (handle, &dimensions);
+ printf ("%s: %dx%d, em=%f, ex=%f\n", file,
+ dimensions.width, dimensions.height,
+ dimensions.em, dimensions.ex);
+ } else {
+ g_warning ("Could not open file `%s'", file);
+ exit_code = EXIT_FAILURE;
+ goto bail2;
+ }
+
+ g_object_unref (G_OBJECT (handle)), handle = NULL;
+ }
+
+ exit_code = EXIT_SUCCESS;
+
+bail3:
+ if (handle)
+ g_object_unref (G_OBJECT (handle)), handle = NULL;
+bail2:
+ if (context)
+ g_option_context_free (context), context = NULL;
+ if (error)
+ g_error_free (error), error = NULL;
+bail1:
+ rsvg_term ();
+ return exit_code;
+}
+
Modified: trunk/rsvg-gobject.c
==============================================================================
--- trunk/rsvg-gobject.c (original)
+++ trunk/rsvg-gobject.c Sat Nov 22 16:44:34 2008
@@ -63,6 +63,7 @@
self->priv->first_write = TRUE;
self->priv->is_disposed = FALSE;
+ self->priv->in_loop = FALSE;
}
static void
Modified: trunk/rsvg-private.h
==============================================================================
--- trunk/rsvg-private.h (original)
+++ trunk/rsvg-private.h Sat Nov 22 16:44:34 2008
@@ -167,6 +167,7 @@
gboolean first_write;
gboolean is_gzipped;
void *gzipped_data; /* really a GsfOutput */
+ gboolean in_loop; /* see get_dimension() */
};
typedef struct {
@@ -345,6 +346,9 @@
double _rsvg_css_normalize_length (const RsvgLength * in, RsvgDrawingCtx * ctx, char dir);
double _rsvg_css_hand_normalize_length (const RsvgLength * in, gdouble pixels_per_inch,
gdouble width_or_height, gdouble font_size);
+double _rsvg_css_hand_normalize_length_sub (const RsvgLength * in, gdouble length,
+ gdouble pixels_per_inch, gdouble width_or_height,
+ gdouble font_size);
RsvgLength _rsvg_css_parse_length (const char *str);
Modified: trunk/rsvg-structure.c
==============================================================================
--- trunk/rsvg-structure.c (original)
+++ trunk/rsvg-structure.c Sat Nov 22 16:44:34 2008
@@ -345,9 +345,16 @@
svg->preserve_aspect_ratio = rsvg_css_parse_aspect_ratio (value);
if ((value = rsvg_property_bag_lookup (atts, "width")))
svg->w = _rsvg_css_parse_length (value);
+ else {
+ svg->w.length = -1;
+ svg->w.factor = '\0';
+ }
if ((value = rsvg_property_bag_lookup (atts, "height")))
svg->h = _rsvg_css_parse_length (value);
-
+ else {
+ svg->h.length = -1;
+ svg->h.factor = '\0';
+ }
/*
* x & y attributes have no effect on outermost svg
* http://www.w3.org/TR/SVG/struct.html#SVGElement
Modified: trunk/rsvg.h
==============================================================================
--- trunk/rsvg.h (original)
+++ trunk/rsvg.h Sat Nov 22 16:44:34 2008
@@ -118,6 +118,8 @@
void rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_data);
+gboolean rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimension_data, const char *id);
+
/* Accessibility API */
G_CONST_RETURN char *rsvg_handle_get_title (RsvgHandle * handle);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]