[librsvg] rsvg-handle.c: Move more RsvgHandle methods here



commit 323cb2798dcf9e9cd42cfaf66e502e113dd81fdb
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Dec 5 19:45:44 2017 -0600

    rsvg-handle.c: Move more RsvgHandle methods here

 rsvg-base.c   |  562 --------------------------------------------------------
 rsvg-handle.c |  565 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 565 insertions(+), 562 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index e3edd3f..2841615 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -1111,137 +1111,6 @@ rsvg_SAX_handler_struct_init (void)
     }
 }
 
-/* http://www.ietf.org/rfc/rfc2396.txt */
-
-static gboolean
-rsvg_path_is_uri (char const *path)
-{
-    char const *p;
-
-    if (path == NULL)
-        return FALSE;
-
-    if (strlen (path) < 4)
-        return FALSE;
-
-    if ((path[0] < 'a' || path[0] > 'z') &&
-        (path[0] < 'A' || path[0] > 'Z')) {
-        return FALSE;
-    }
-
-    for (p = &path[1];
-           (*p >= 'a' && *p <= 'z') ||
-        (*p >= 'A' && *p <= 'Z') ||
-        (*p >= '0' && *p <= '9') ||
-         *p == '+' ||
-         *p == '-' ||
-         *p == '.';
-        p++);
-
-    if (strlen (p) < 3)
-        return FALSE;
-
-    return (p[0] == ':' && p[1] == '/' && p[2] == '/');
-}
-
-static gchar *
-rsvg_get_base_uri_from_filename (const gchar * filename)
-{
-    gchar *current_dir;
-    gchar *absolute_filename;
-    gchar *base_uri;
-
-    if (g_path_is_absolute (filename))
-        return g_filename_to_uri (filename, NULL, NULL);
-
-    current_dir = g_get_current_dir ();
-    absolute_filename = g_build_filename (current_dir, filename, NULL);
-    base_uri = g_filename_to_uri (absolute_filename, NULL, NULL);
-    g_free (absolute_filename);
-    g_free (current_dir);
-
-    return base_uri;
-}
-
-/**
- * rsvg_handle_set_base_uri:
- * @handle: A #RsvgHandle
- * @base_uri: The base uri
- *
- * Set the base URI for this SVG. This can only be called before rsvg_handle_write()
- * has been called.
- *
- * Since: 2.9
- */
-void
-rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri)
-{
-    gchar *uri;
-    GFile *file;
-
-    g_return_if_fail (handle != NULL);
-
-    if (base_uri == NULL)
-       return;
-
-    if (rsvg_path_is_uri (base_uri))
-        uri = g_strdup (base_uri);
-    else
-        uri = rsvg_get_base_uri_from_filename (base_uri);
-
-    file = g_file_new_for_uri (uri ? uri : "data:");
-    rsvg_handle_set_base_gfile (handle, file);
-    g_object_unref (file);
-    g_free (uri);
-}
-
-/**
- * rsvg_handle_set_base_gfile:
- * @handle: a #RsvgHandle
- * @base_file: a #GFile
- *
- * Set the base URI for @handle from @file.
- * Note: This function may only be called before rsvg_handle_write()
- * or rsvg_handle_read_stream_sync() has been called.
- *
- * Since: 2.32
- */
-void
-rsvg_handle_set_base_gfile (RsvgHandle *handle,
-                            GFile      *base_file)
-{
-    RsvgHandlePrivate *priv;
-
-    g_return_if_fail (RSVG_IS_HANDLE (handle));
-    g_return_if_fail (G_IS_FILE (base_file));
-
-    priv = handle->priv;
-
-    g_object_ref (base_file);
-    if (priv->base_gfile)
-        g_object_unref (priv->base_gfile);
-    priv->base_gfile = base_file;
-
-    g_free (priv->base_uri);
-    priv->base_uri = g_file_get_uri (base_file);
-}
-
-/**
- * rsvg_handle_get_base_uri:
- * @handle: A #RsvgHandle
- *
- * Gets the base uri for this #RsvgHandle.
- *
- * Returns: the base uri, possibly null
- * Since: 2.8
- */
-const char *
-rsvg_handle_get_base_uri (RsvgHandle * handle)
-{
-    g_return_val_if_fail (handle, NULL);
-    return handle->priv->base_uri;
-}
-
 /**
  * rsvg_error_quark:
  *
@@ -1356,321 +1225,6 @@ rsvg_drawing_ctx_free (RsvgDrawingCtx * handle)
 }
 
 /**
- * rsvg_handle_get_metadata:
- * @handle: An #RsvgHandle
- *
- * Returns the SVG's metadata in UTF-8 or %NULL. You must make a copy
- * of this metadata if you wish to use it after @handle has been freed.
- *
- * Returns: (nullable): The SVG's title
- *
- * Since: 2.9
- *
- * Deprecated: 2.36
- */
-const char *
-rsvg_handle_get_metadata (RsvgHandle * handle)
-{
-    g_return_val_if_fail (handle, NULL);
-
-    if (handle->priv->metadata)
-        return handle->priv->metadata->str;
-    else
-        return NULL;
-}
-
-/**
- * rsvg_handle_get_title:
- * @handle: An #RsvgHandle
- *
- * Returns the SVG's title in UTF-8 or %NULL. You must make a copy
- * of this title if you wish to use it after @handle has been freed.
- *
- * Returns: (nullable): The SVG's title
- *
- * Since: 2.4
- *
- * Deprecated: 2.36
- */
-const char *
-rsvg_handle_get_title (RsvgHandle * handle)
-{
-    g_return_val_if_fail (handle, NULL);
-
-    if (handle->priv->title)
-        return handle->priv->title->str;
-    else
-        return NULL;
-}
-
-/**
- * rsvg_handle_get_desc:
- * @handle: An #RsvgHandle
- *
- * Returns the SVG's description in UTF-8 or %NULL. You must make a copy
- * of this description if you wish to use it after @handle has been freed.
- *
- * Returns: (nullable): The SVG's description
- *
- * Since: 2.4
- *
- * Deprecated: 2.36
- */
-const char *
-rsvg_handle_get_desc (RsvgHandle * handle)
-{
-    g_return_val_if_fail (handle, NULL);
-
-    if (handle->priv->desc)
-        return handle->priv->desc->str;
-    else
-        return NULL;
-}
-
-/**
- * rsvg_handle_get_dimensions:
- * @handle: A #RsvgHandle
- * @dimension_data: (out): A place to store the SVG's size
- *
- * Get the SVG's size. Do not call from within the size_func callback, because an infinite loop will occur.
- *
- * Since: 2.14
- */
-void
-rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_data)
-{
-    /* 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: (out): A place to store the SVG's size
- * @id: (nullable): 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;
-    RsvgNode *sself = NULL;
-    RsvgBbox bbox;
-    RsvgLength root_width, root_height;
-    RsvgViewBox root_vbox;
-
-    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));
-
-    if (id && *id) {
-        sself = rsvg_defs_lookup (handle->priv->defs, id);
-
-        if (rsvg_node_is_same (sself, handle->priv->treebase))
-            id = NULL;
-    } else {
-        sself = handle->priv->treebase;
-    }
-
-    if (!sself && id)
-        return FALSE;
-
-    if (!handle->priv->treebase)
-        return FALSE;
-
-    g_assert (rsvg_node_get_type (handle->priv->treebase) == RSVG_NODE_TYPE_SVG);
-
-    bbox.rect.x = bbox.rect.y = 0;
-    bbox.rect.width = bbox.rect.height = 1;
-
-    rsvg_node_svg_get_size (handle->priv->treebase, &root_width, &root_height);
-    root_vbox = rsvg_node_svg_get_view_box (handle->priv->treebase);
-
-    if (!id) {
-        if ((root_width.unit == LENGTH_UNIT_PERCENT || root_height.unit == LENGTH_UNIT_PERCENT) && 
!root_vbox.active)
-            handle_subelement = TRUE;
-        else
-            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) {
-            cairo_destroy (cr);
-            cairo_surface_destroy (target);
-
-            return FALSE;
-        }
-
-        g_assert (sself != NULL);
-        rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, sself);
-
-        rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0);
-        bbox = RSVG_CAIRO_RENDER (draw->render)->bbox;
-
-        rsvg_drawing_ctx_free (draw);
-        cairo_destroy (cr);
-        cairo_surface_destroy (target);
-
-        dimension_data->width = bbox.rect.width;
-        dimension_data->height = bbox.rect.height;
-    } else {
-        bbox.rect.width = root_vbox.rect.width;
-        bbox.rect.height = root_vbox.rect.height;
-
-        dimension_data->width = (int) (rsvg_length_hand_normalize (&root_width, handle->priv->dpi_x,
-                                                                   bbox.rect.width, 12) + 0.5);
-        dimension_data->height = (int) (rsvg_length_hand_normalize (&root_height, handle->priv->dpi_y,
-                                                                    bbox.rect.height, 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_handle_get_position_sub:
- * @handle: A #RsvgHandle
- * @position_data: (out): A place to store the SVG fragment's position.
- * @id: An element's id within the SVG.
- * For example, if you have a layer called "layer1" for that you want to get
- * the position, pass "##layer1" as the id.
- *
- * Get the position 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_position_sub (RsvgHandle * handle, RsvgPositionData * position_data, const char *id)
-{
-    RsvgDrawingCtx             *draw;
-    RsvgNode                   *node;
-    RsvgBbox                    bbox;
-    RsvgDimensionData    dimension_data;
-    cairo_surface_t            *target = NULL;
-    cairo_t                            *cr = NULL;
-    gboolean                    ret = FALSE;
-
-    g_return_val_if_fail (handle, FALSE);
-    g_return_val_if_fail (position_data, FALSE);
-
-    if (!handle->priv->treebase)
-        return FALSE;
-
-    /* Short-cut when no id is given. */
-    if (NULL == id || '\0' == *id) {
-        position_data->x = 0;
-        position_data->y = 0;
-        return TRUE;
-    }
-
-    memset (position_data, 0, sizeof (*position_data));
-    memset (&dimension_data, 0, sizeof (dimension_data));
-
-    node = rsvg_defs_lookup (handle->priv->defs, id);
-    if (!node) {
-        return FALSE;
-    } else if (rsvg_node_is_same (node, handle->priv->treebase)) {
-        /* Root node. */
-        position_data->x = 0;
-        position_data->y = 0;
-        return 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)
-        goto bail;
-
-    g_assert (node != NULL);
-    rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, node);
-
-    rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0);
-    bbox = RSVG_CAIRO_RENDER (draw->render)->bbox;
-
-    rsvg_drawing_ctx_free (draw);
-
-    position_data->x = bbox.rect.x;
-    position_data->y = bbox.rect.y;
-    dimension_data.width = bbox.rect.width;
-    dimension_data.height = bbox.rect.height;
-
-    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);
-
-    ret = TRUE;
-
-bail:
-    if (cr)
-        cairo_destroy (cr);
-    if (target)
-        cairo_surface_destroy (target);
-
-    return ret;
-}
-
-/**
- * rsvg_handle_has_sub:
- * @handle: a #RsvgHandle
- * @id: an element's id within the SVG
- *
- * Checks whether the element @id exists in the SVG document.
- *
- * Returns: %TRUE if @id exists in the SVG document
- *
- * Since: 2.22
- */
-gboolean
-rsvg_handle_has_sub (RsvgHandle * handle,
-                     const char *id)
-{
-    g_return_val_if_fail (handle, FALSE);
-
-    if (G_UNLIKELY (!id || !id[0]))
-      return FALSE;
-
-    return rsvg_defs_lookup (handle->priv->defs, id) != NULL;
-}
-
-/**
  * rsvg_set_default_dpi:
  * @dpi: Dots Per Inch (aka Pixels Per Inch)
  *
@@ -1711,106 +1265,6 @@ rsvg_set_default_dpi_x_y (double dpi_x, double dpi_y)
         rsvg_internal_dpi_y = dpi_y;
 }
 
-/**
- * rsvg_handle_set_dpi:
- * @handle: An #RsvgHandle
- * @dpi: Dots Per Inch (aka Pixels Per Inch)
- *
- * Sets the DPI for the outgoing pixbuf. Common values are
- * 75, 90, and 300 DPI. Passing a number <= 0 to @dpi will
- * reset the DPI to whatever the default value happens to be.
- *
- * Since: 2.8
- */
-void
-rsvg_handle_set_dpi (RsvgHandle * handle, double dpi)
-{
-    rsvg_handle_set_dpi_x_y (handle, dpi, dpi);
-}
-
-/**
- * rsvg_handle_set_dpi_x_y:
- * @handle: An #RsvgHandle
- * @dpi_x: Dots Per Inch (aka Pixels Per Inch)
- * @dpi_y: Dots Per Inch (aka Pixels Per Inch)
- *
- * Sets the DPI for the outgoing pixbuf. Common values are
- * 75, 90, and 300 DPI. Passing a number <= 0 to #dpi_x or @dpi_y will
- * reset the DPI to whatever the default value happens to be.
- *
- * Since: 2.8
- */
-void
-rsvg_handle_set_dpi_x_y (RsvgHandle * handle, double dpi_x, double dpi_y)
-{
-    g_return_if_fail (handle != NULL);
-
-    if (dpi_x <= 0.)
-        handle->priv->dpi_x = rsvg_internal_dpi_x;
-    else
-        handle->priv->dpi_x = dpi_x;
-
-    if (dpi_y <= 0.)
-        handle->priv->dpi_y = rsvg_internal_dpi_y;
-    else
-        handle->priv->dpi_y = dpi_y;
-}
-
-/**
- * rsvg_handle_set_size_callback:
- * @handle: An #RsvgHandle
- * @size_func: (nullable): A sizing function, or %NULL
- * @user_data: User data to pass to @size_func, or %NULL
- * @user_data_destroy: Destroy function for @user_data, or %NULL
- *
- * Sets the sizing function for the @handle.  This function is called right
- * after the size of the image has been loaded.  The size of the image is passed
- * in to the function, which may then modify these values to set the real size
- * of the generated pixbuf.  If the image has no associated size, then the size
- * arguments are set to -1.
- *
- * Deprecated: Set up a cairo matrix and use rsvg_handle_render_cairo() instead.
- * You can call rsvg_handle_get_dimensions() to figure out the size of your SVG,
- * and then scale it to the desired size via Cairo.  For example, the following
- * code renders an SVG at a specified size, scaled proportionally from whatever
- * original size it may have had:
- *
- * |[<!-- language="C" -->
- * void
- * render_scaled_proportionally (RsvgHandle *handle, cairo_t cr, int width, int height)
- * {
- *     RsvgDimensionData dimensions;
- *     double x_factor, y_factor;
- *     double scale_factor;
- *
- *     rsvg_handle_get_dimensions (handle, &dimensions);
- *
- *     x_factor = (double) width / dimensions.width;
- *     y_factor = (double) height / dimensions.height;
- *
- *     scale_factor = MIN (x_factor, y_factor);
- *
- *     cairo_scale (cr, scale_factor, scale_factor);
- *
- *     rsvg_handle_render_cairo (handle, cr);
- * }
- * ]|
- **/
-void
-rsvg_handle_set_size_callback (RsvgHandle * handle,
-                               RsvgSizeFunc size_func,
-                               gpointer user_data, GDestroyNotify user_data_destroy)
-{
-    g_return_if_fail (handle != NULL);
-
-    if (handle->priv->user_data_destroy)
-        (*handle->priv->user_data_destroy) (handle->priv->user_data);
-
-    handle->priv->size_func = size_func;
-    handle->priv->user_data = user_data;
-    handle->priv->user_data_destroy = user_data_destroy;
-}
-
 #define GZ_MAGIC_0 ((guchar) 0x1f)
 #define GZ_MAGIC_1 ((guchar) 0x8b)
 
@@ -2081,22 +1535,6 @@ rsvg_handle_read_stream_sync (RsvgHandle   *handle,
 }
 
 /**
- * _rsvg_handle_internal_set_testing:
- * @handle: a #RsvgHandle
- * @testing: Whether to enable testing mode
- *
- * Do not call this function.  This is intended for librsvg's internal
- * test suite only.
- **/
-void
-rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
-{
-    g_return_if_fail (RSVG_IS_HANDLE (handle));
-
-    handle->priv->is_testing = testing ? TRUE : FALSE;
-}
-
-/**
  * rsvg_init:
  *
  * Initializes librsvg
diff --git a/rsvg-handle.c b/rsvg-handle.c
index 00a80e6..f0ac86a 100644
--- a/rsvg-handle.c
+++ b/rsvg-handle.c
@@ -112,9 +112,12 @@
  */
 
 #include "config.h"
+#include <string.h>
 
 #include "rsvg-private.h"
 #include "rsvg-defs.h"
+#include "rsvg-cairo-render.h"
+#include "rsvg-structure.h"
 
 enum {
     PROP_0,
@@ -570,3 +573,565 @@ rsvg_handle_new_from_stream_sync (GInputStream   *input_stream,
 
     return handle;
 }
+
+/* http://www.ietf.org/rfc/rfc2396.txt */
+
+static gboolean
+path_is_uri (char const *path)
+{
+    char const *p;
+
+    if (path == NULL)
+        return FALSE;
+
+    if (strlen (path) < 4)
+        return FALSE;
+
+    if ((path[0] < 'a' || path[0] > 'z') &&
+        (path[0] < 'A' || path[0] > 'Z')) {
+        return FALSE;
+    }
+
+    for (p = &path[1];
+           (*p >= 'a' && *p <= 'z') ||
+        (*p >= 'A' && *p <= 'Z') ||
+        (*p >= '0' && *p <= '9') ||
+         *p == '+' ||
+         *p == '-' ||
+         *p == '.';
+        p++);
+
+    if (strlen (p) < 3)
+        return FALSE;
+
+    return (p[0] == ':' && p[1] == '/' && p[2] == '/');
+}
+
+static gchar *
+get_base_uri_from_filename (const gchar * filename)
+{
+    gchar *current_dir;
+    gchar *absolute_filename;
+    gchar *base_uri;
+
+    if (g_path_is_absolute (filename))
+        return g_filename_to_uri (filename, NULL, NULL);
+
+    current_dir = g_get_current_dir ();
+    absolute_filename = g_build_filename (current_dir, filename, NULL);
+    base_uri = g_filename_to_uri (absolute_filename, NULL, NULL);
+    g_free (absolute_filename);
+    g_free (current_dir);
+
+    return base_uri;
+}
+
+/**
+ * rsvg_handle_set_base_uri:
+ * @handle: A #RsvgHandle
+ * @base_uri: The base uri
+ *
+ * Set the base URI for this SVG. This can only be called before rsvg_handle_write()
+ * has been called.
+ *
+ * Since: 2.9
+ */
+void
+rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri)
+{
+    gchar *uri;
+    GFile *file;
+
+    g_return_if_fail (handle != NULL);
+
+    if (base_uri == NULL)
+        return;
+
+    if (path_is_uri (base_uri))
+        uri = g_strdup (base_uri);
+    else
+        uri = get_base_uri_from_filename (base_uri);
+
+    file = g_file_new_for_uri (uri ? uri : "data:");
+    rsvg_handle_set_base_gfile (handle, file);
+    g_object_unref (file);
+    g_free (uri);
+}
+
+/**
+ * rsvg_handle_set_base_gfile:
+ * @handle: a #RsvgHandle
+ * @base_file: a #GFile
+ *
+ * Set the base URI for @handle from @file.
+ * Note: This function may only be called before rsvg_handle_write()
+ * or rsvg_handle_read_stream_sync() has been called.
+ *
+ * Since: 2.32
+ */
+void
+rsvg_handle_set_base_gfile (RsvgHandle *handle,
+                            GFile      *base_file)
+{
+    RsvgHandlePrivate *priv;
+
+    g_return_if_fail (RSVG_IS_HANDLE (handle));
+    g_return_if_fail (G_IS_FILE (base_file));
+
+    priv = handle->priv;
+
+    g_object_ref (base_file);
+    if (priv->base_gfile)
+        g_object_unref (priv->base_gfile);
+    priv->base_gfile = base_file;
+
+    g_free (priv->base_uri);
+    priv->base_uri = g_file_get_uri (base_file);
+}
+
+/**
+ * rsvg_handle_get_base_uri:
+ * @handle: A #RsvgHandle
+ *
+ * Gets the base uri for this #RsvgHandle.
+ *
+ * Returns: the base uri, possibly null
+ * Since: 2.8
+ */
+const char *
+rsvg_handle_get_base_uri (RsvgHandle * handle)
+{
+    g_return_val_if_fail (handle, NULL);
+    return handle->priv->base_uri;
+}
+
+/**
+ * rsvg_handle_get_metadata:
+ * @handle: An #RsvgHandle
+ *
+ * Returns the SVG's metadata in UTF-8 or %NULL. You must make a copy
+ * of this metadata if you wish to use it after @handle has been freed.
+ *
+ * Returns: (nullable): The SVG's title
+ *
+ * Since: 2.9
+ *
+ * Deprecated: 2.36
+ */
+const char *
+rsvg_handle_get_metadata (RsvgHandle * handle)
+{
+    g_return_val_if_fail (handle, NULL);
+
+    if (handle->priv->metadata)
+        return handle->priv->metadata->str;
+    else
+        return NULL;
+}
+
+/**
+ * rsvg_handle_get_title:
+ * @handle: An #RsvgHandle
+ *
+ * Returns the SVG's title in UTF-8 or %NULL. You must make a copy
+ * of this title if you wish to use it after @handle has been freed.
+ *
+ * Returns: (nullable): The SVG's title
+ *
+ * Since: 2.4
+ *
+ * Deprecated: 2.36
+ */
+const char *
+rsvg_handle_get_title (RsvgHandle * handle)
+{
+    g_return_val_if_fail (handle, NULL);
+
+    if (handle->priv->title)
+        return handle->priv->title->str;
+    else
+        return NULL;
+}
+
+/**
+ * rsvg_handle_get_desc:
+ * @handle: An #RsvgHandle
+ *
+ * Returns the SVG's description in UTF-8 or %NULL. You must make a copy
+ * of this description if you wish to use it after @handle has been freed.
+ *
+ * Returns: (nullable): The SVG's description
+ *
+ * Since: 2.4
+ *
+ * Deprecated: 2.36
+ */
+const char *
+rsvg_handle_get_desc (RsvgHandle * handle)
+{
+    g_return_val_if_fail (handle, NULL);
+
+    if (handle->priv->desc)
+        return handle->priv->desc->str;
+    else
+        return NULL;
+}
+
+/**
+ * rsvg_handle_get_dimensions:
+ * @handle: A #RsvgHandle
+ * @dimension_data: (out): A place to store the SVG's size
+ *
+ * Get the SVG's size. Do not call from within the size_func callback, because an infinite loop will occur.
+ *
+ * Since: 2.14
+ */
+void
+rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_data)
+{
+    /* 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: (out): A place to store the SVG's size
+ * @id: (nullable): 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;
+    RsvgNode *sself = NULL;
+    RsvgBbox bbox;
+    RsvgLength root_width, root_height;
+    RsvgViewBox root_vbox;
+
+    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));
+
+    if (id && *id) {
+        sself = rsvg_defs_lookup (handle->priv->defs, id);
+
+        if (rsvg_node_is_same (sself, handle->priv->treebase))
+            id = NULL;
+    } else {
+        sself = handle->priv->treebase;
+    }
+
+    if (!sself && id)
+        return FALSE;
+
+    if (!handle->priv->treebase)
+        return FALSE;
+
+    g_assert (rsvg_node_get_type (handle->priv->treebase) == RSVG_NODE_TYPE_SVG);
+
+    bbox.rect.x = bbox.rect.y = 0;
+    bbox.rect.width = bbox.rect.height = 1;
+
+    rsvg_node_svg_get_size (handle->priv->treebase, &root_width, &root_height);
+    root_vbox = rsvg_node_svg_get_view_box (handle->priv->treebase);
+
+    if (!id) {
+        if ((root_width.unit == LENGTH_UNIT_PERCENT || root_height.unit == LENGTH_UNIT_PERCENT) && 
!root_vbox.active)
+            handle_subelement = TRUE;
+        else
+            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) {
+            cairo_destroy (cr);
+            cairo_surface_destroy (target);
+
+            return FALSE;
+        }
+
+        g_assert (sself != NULL);
+        rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, sself);
+
+        rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0);
+        bbox = RSVG_CAIRO_RENDER (draw->render)->bbox;
+
+        rsvg_drawing_ctx_free (draw);
+        cairo_destroy (cr);
+        cairo_surface_destroy (target);
+
+        dimension_data->width = bbox.rect.width;
+        dimension_data->height = bbox.rect.height;
+    } else {
+        bbox.rect.width = root_vbox.rect.width;
+        bbox.rect.height = root_vbox.rect.height;
+
+        dimension_data->width = (int) (rsvg_length_hand_normalize (&root_width, handle->priv->dpi_x,
+                                                                   bbox.rect.width, 12) + 0.5);
+        dimension_data->height = (int) (rsvg_length_hand_normalize (&root_height, handle->priv->dpi_y,
+                                                                    bbox.rect.height, 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_handle_get_position_sub:
+ * @handle: A #RsvgHandle
+ * @position_data: (out): A place to store the SVG fragment's position.
+ * @id: An element's id within the SVG.
+ * For example, if you have a layer called "layer1" for that you want to get
+ * the position, pass "##layer1" as the id.
+ *
+ * Get the position 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_position_sub (RsvgHandle * handle, RsvgPositionData * position_data, const char *id)
+{
+    RsvgDrawingCtx             *draw;
+    RsvgNode                   *node;
+    RsvgBbox                    bbox;
+    RsvgDimensionData    dimension_data;
+    cairo_surface_t            *target = NULL;
+    cairo_t                            *cr = NULL;
+    gboolean                    ret = FALSE;
+
+    g_return_val_if_fail (handle, FALSE);
+    g_return_val_if_fail (position_data, FALSE);
+
+    if (!handle->priv->treebase)
+        return FALSE;
+
+    /* Short-cut when no id is given. */
+    if (NULL == id || '\0' == *id) {
+        position_data->x = 0;
+        position_data->y = 0;
+        return TRUE;
+    }
+
+    memset (position_data, 0, sizeof (*position_data));
+    memset (&dimension_data, 0, sizeof (dimension_data));
+
+    node = rsvg_defs_lookup (handle->priv->defs, id);
+    if (!node) {
+        return FALSE;
+    } else if (rsvg_node_is_same (node, handle->priv->treebase)) {
+        /* Root node. */
+        position_data->x = 0;
+        position_data->y = 0;
+        return 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)
+        goto bail;
+
+    g_assert (node != NULL);
+    rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, node);
+
+    rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->treebase, 0);
+    bbox = RSVG_CAIRO_RENDER (draw->render)->bbox;
+
+    rsvg_drawing_ctx_free (draw);
+
+    position_data->x = bbox.rect.x;
+    position_data->y = bbox.rect.y;
+    dimension_data.width = bbox.rect.width;
+    dimension_data.height = bbox.rect.height;
+
+    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);
+
+    ret = TRUE;
+
+bail:
+    if (cr)
+        cairo_destroy (cr);
+    if (target)
+        cairo_surface_destroy (target);
+
+    return ret;
+}
+
+/**
+ * rsvg_handle_has_sub:
+ * @handle: a #RsvgHandle
+ * @id: an element's id within the SVG
+ *
+ * Checks whether the element @id exists in the SVG document.
+ *
+ * Returns: %TRUE if @id exists in the SVG document
+ *
+ * Since: 2.22
+ */
+gboolean
+rsvg_handle_has_sub (RsvgHandle * handle,
+                     const char *id)
+{
+    g_return_val_if_fail (handle, FALSE);
+
+    if (G_UNLIKELY (!id || !id[0]))
+      return FALSE;
+
+    return rsvg_defs_lookup (handle->priv->defs, id) != NULL;
+}
+
+/**
+ * rsvg_handle_set_dpi:
+ * @handle: An #RsvgHandle
+ * @dpi: Dots Per Inch (aka Pixels Per Inch)
+ *
+ * Sets the DPI for the outgoing pixbuf. Common values are
+ * 75, 90, and 300 DPI. Passing a number <= 0 to @dpi will
+ * reset the DPI to whatever the default value happens to be.
+ *
+ * Since: 2.8
+ */
+void
+rsvg_handle_set_dpi (RsvgHandle * handle, double dpi)
+{
+    rsvg_handle_set_dpi_x_y (handle, dpi, dpi);
+}
+
+/**
+ * rsvg_handle_set_dpi_x_y:
+ * @handle: An #RsvgHandle
+ * @dpi_x: Dots Per Inch (aka Pixels Per Inch)
+ * @dpi_y: Dots Per Inch (aka Pixels Per Inch)
+ *
+ * Sets the DPI for the outgoing pixbuf. Common values are
+ * 75, 90, and 300 DPI. Passing a number <= 0 to #dpi_x or @dpi_y will
+ * reset the DPI to whatever the default value happens to be.
+ *
+ * Since: 2.8
+ */
+void
+rsvg_handle_set_dpi_x_y (RsvgHandle * handle, double dpi_x, double dpi_y)
+{
+    g_return_if_fail (handle != NULL);
+
+    if (dpi_x <= 0.)
+        handle->priv->dpi_x = rsvg_internal_dpi_x;
+    else
+        handle->priv->dpi_x = dpi_x;
+
+    if (dpi_y <= 0.)
+        handle->priv->dpi_y = rsvg_internal_dpi_y;
+    else
+        handle->priv->dpi_y = dpi_y;
+}
+
+/**
+ * rsvg_handle_set_size_callback:
+ * @handle: An #RsvgHandle
+ * @size_func: (nullable): A sizing function, or %NULL
+ * @user_data: User data to pass to @size_func, or %NULL
+ * @user_data_destroy: Destroy function for @user_data, or %NULL
+ *
+ * Sets the sizing function for the @handle.  This function is called right
+ * after the size of the image has been loaded.  The size of the image is passed
+ * in to the function, which may then modify these values to set the real size
+ * of the generated pixbuf.  If the image has no associated size, then the size
+ * arguments are set to -1.
+ *
+ * Deprecated: Set up a cairo matrix and use rsvg_handle_render_cairo() instead.
+ * You can call rsvg_handle_get_dimensions() to figure out the size of your SVG,
+ * and then scale it to the desired size via Cairo.  For example, the following
+ * code renders an SVG at a specified size, scaled proportionally from whatever
+ * original size it may have had:
+ *
+ * |[<!-- language="C" -->
+ * void
+ * render_scaled_proportionally (RsvgHandle *handle, cairo_t cr, int width, int height)
+ * {
+ *     RsvgDimensionData dimensions;
+ *     double x_factor, y_factor;
+ *     double scale_factor;
+ *
+ *     rsvg_handle_get_dimensions (handle, &dimensions);
+ *
+ *     x_factor = (double) width / dimensions.width;
+ *     y_factor = (double) height / dimensions.height;
+ *
+ *     scale_factor = MIN (x_factor, y_factor);
+ *
+ *     cairo_scale (cr, scale_factor, scale_factor);
+ *
+ *     rsvg_handle_render_cairo (handle, cr);
+ * }
+ * ]|
+ **/
+void
+rsvg_handle_set_size_callback (RsvgHandle * handle,
+                               RsvgSizeFunc size_func,
+                               gpointer user_data, GDestroyNotify user_data_destroy)
+{
+    g_return_if_fail (handle != NULL);
+
+    if (handle->priv->user_data_destroy)
+        (*handle->priv->user_data_destroy) (handle->priv->user_data);
+
+    handle->priv->size_func = size_func;
+    handle->priv->user_data = user_data;
+    handle->priv->user_data_destroy = user_data_destroy;
+}
+
+/**
+ * _rsvg_handle_internal_set_testing:
+ * @handle: a #RsvgHandle
+ * @testing: Whether to enable testing mode
+ *
+ * Do not call this function.  This is intended for librsvg's internal
+ * test suite only.
+ **/
+void
+rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
+{
+    g_return_if_fail (RSVG_IS_HANDLE (handle));
+
+    handle->priv->is_testing = testing ? TRUE : FALSE;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]