[librsvg: 11/15] New API function rsvg_handle_get_intrinsic_size_in_pixels()




commit 33a7c326e63d64dba1eec65ae594ed65d8b5b0cb
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Oct 27 16:51:43 2020 -0600

    New API function rsvg_handle_get_intrinsic_size_in_pixels()

 doc/rsvg-sections.txt          |  1 +
 librsvg/c_api.rs               | 38 ++++++++++++++++++++++++++
 librsvg/lib.rs                 |  1 +
 librsvg/rsvg.h                 | 60 ++++++++++++++++++++++++++++++++++++++++++
 tests/api.c                    | 49 ++++++++++++++++++++++++++++++++++
 tests/fixtures/api/no-size.svg |  1 +
 tests/fixtures/api/size.svg    |  1 +
 7 files changed, 151 insertions(+)
---
diff --git a/doc/rsvg-sections.txt b/doc/rsvg-sections.txt
index ee7b9ed4..c0d8828a 100644
--- a/doc/rsvg-sections.txt
+++ b/doc/rsvg-sections.txt
@@ -70,6 +70,7 @@ RSVG_TYPE_HANDLE_FLAGS
 <FILE>rsvg-cairo</FILE>
 <TITLE>Using RSVG with cairo</TITLE>
 rsvg_handle_get_intrinsic_dimensions
+rsvg_handle_get_intrinsic_size_in_pixels
 rsvg_handle_render_document
 rsvg_handle_get_geometry_for_layer
 rsvg_handle_render_layer
diff --git a/librsvg/c_api.rs b/librsvg/c_api.rs
index 9cbc8dd6..af922a6b 100644
--- a/librsvg/c_api.rs
+++ b/librsvg/c_api.rs
@@ -1060,6 +1060,13 @@ impl CHandle {
         Ok(handle.get_intrinsic_dimensions())
     }
 
+    fn get_intrinsic_size_in_pixels(&self) -> Result<Option<(f64, f64)>, RenderingError> {
+        let handle = self.get_handle_ref()?;
+        let inner = self.inner.borrow();
+
+        Ok(handle.get_intrinsic_size_in_pixels(inner.dpi.into()))
+    }
+
     fn set_testing(&self, is_testing: bool) {
         let mut inner = self.inner.borrow_mut();
         inner.is_testing = is_testing;
@@ -1874,6 +1881,37 @@ pub unsafe extern "C" fn rsvg_handle_get_intrinsic_dimensions(
     set_out_param(out_has_viewbox, out_viewbox, &r);
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_get_intrinsic_size_in_pixels(
+    handle: *const RsvgHandle,
+    out_width: *mut f64,
+    out_height: *mut f64,
+) -> glib_sys::gboolean {
+    rsvg_return_val_if_fail! {
+        rsvg_handle_get_intrinsic_size_in_pixels => false.to_glib();
+
+        is_rsvg_handle(handle),
+    }
+
+    let rhandle = get_rust_handle(handle);
+
+    let dim = rhandle
+        .get_intrinsic_size_in_pixels()
+        .unwrap_or_else(|_| panic!("API called out of order"));
+
+    let (w, h) = dim.unwrap_or((0.0, 0.0));
+
+    if !out_width.is_null() {
+        *out_width = w;
+    }
+
+    if !out_height.is_null() {
+        *out_height = h;
+    }
+
+    dim.is_some().to_glib()
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_handle_render_document(
     handle: *const RsvgHandle,
diff --git a/librsvg/lib.rs b/librsvg/lib.rs
index d6beaf21..8f647f8a 100644
--- a/librsvg/lib.rs
+++ b/librsvg/lib.rs
@@ -12,6 +12,7 @@ pub use crate::c_api::{
     rsvg_handle_get_geometry_for_element,
     rsvg_handle_get_geometry_for_layer,
     rsvg_handle_get_intrinsic_dimensions,
+    rsvg_handle_get_intrinsic_size_in_pixels,
     rsvg_handle_get_pixbuf_sub,
     rsvg_handle_get_position_sub,
     rsvg_handle_has_sub,
diff --git a/librsvg/rsvg.h b/librsvg/rsvg.h
index 7bead03c..11b02931 100644
--- a/librsvg/rsvg.h
+++ b/librsvg/rsvg.h
@@ -889,6 +889,66 @@ void rsvg_handle_get_intrinsic_dimensions (RsvgHandle *handle,
                                            gboolean   *out_has_viewbox,
                                            RsvgRectangle *out_viewbox);
 
+/**
+ * rsvg_handle_get_intrinsic_size_in_pixels:
+ * @handle: An #RsvgHandle
+ * @out_width: (out)(optional): Will be set to the computed width
+ * @out_height: (out)(optional): Will be set to the computed height
+ *
+ * Converts an SVG document's intrinsic dimensions to pixels, and returns the result.
+ *
+ * This function is able to extract the size in pixels from an SVG document if the
+ * document has both <literal>width</literal> and <literal>height</literal> attributes
+ * with physical units (px, in, cm, mm, pt, pc) or font-based units (em, ex).  For
+ * physical units, the dimensions are normalized to pixels using the dots-per-inch (DPI)
+ * value set previously with rsvg_handle_set_dpi().  For font-based units, this function
+ * uses the computed value of the `font-size` property for the toplevel
+ * <literal>&lt;svg&gt;</literal> element.  In those cases, this function returns %TRUE.
+ *
+ * This function is not able to extract the size in pixels directly from the intrinsic
+ * dimensions of the SVG document if the <literal>width</literal> or
+ * <literal>height</literal> are in percentage units (or if they do not exist, in which
+ * case the SVG spec mandates that they default to 100%), as these require a
+ * <firstterm>viewport</firstterm> to be resolved to a final size.  In this case, the
+ * function returns %FALSE.
+ *
+ * For example, the following document fragment has intrinsic dimensions that will resolve
+ * to 20x30 pixels.
+ *
+ * |[
+ * <svg xmlns="http://www.w3.org/2000/svg"; width="20" height="30"/>
+ * ]|
+ *
+ * Similarly, if the DPI is set to 96, this document will resolve to 192x288 pixels (i.e. 96*2 x 96*3).
+ *
+ * |[
+ * <svg xmlns="http://www.w3.org/2000/svg"; width="2in" height="3in"/>
+ * ]|
+ *
+ * The dimensions of the following documents cannot be resolved to pixels directly, and
+ * this function would return %FALSE for them:
+ *
+ * |[
+ * <!-- Needs a viewport against which to compute the percentages. -->
+ * <svg xmlns="http://www.w3.org/2000/svg"; width="100%" height="100%"/>
+ *
+ * <!-- Does not have intrinsic width/height, just a 1:2 aspect ratio which
+ *      needs to be fitted within a viewport. -->
+ * <svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 0 100 200"/>
+ * ]|
+ *
+ *
+ * Returns: %TRUE if the dimensions could be converted directly to pixels; in this case
+ * @out_width and @out_height will be set accordingly.  If the dimensions cannot be converted
+ * to pixels, returns %FALSE and puts 0.0 in both @out_width and @out_height.
+ *
+ * Since: 2.52
+ */
+RSVG_API
+gboolean rsvg_handle_get_intrinsic_size_in_pixels (RsvgHandle *handle,
+                                                   gdouble    *out_width,
+                                                   gdouble    *out_height);
+
 /* GIO APIs */
 
 /**
diff --git a/tests/api.c b/tests/api.c
index c344d32b..d4f53b88 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -968,6 +968,53 @@ get_intrinsic_dimensions (void)
     g_object_unref (handle);
 }
 
+static void
+get_intrinsic_size_in_pixels_yes (void)
+{
+    char *filename = get_test_filename ("size.svg");
+    GError *error = NULL;
+    gdouble width, height;
+
+    RsvgHandle *handle = rsvg_handle_new_from_file (filename, &error);
+    g_free (filename);
+
+    g_assert_nonnull (handle);
+    g_assert_no_error (error);
+
+    rsvg_handle_set_dpi (handle, 96.0);
+
+    /* Test optional parameters */
+    g_assert (rsvg_handle_get_intrinsic_size_in_pixels (handle, NULL, NULL));
+
+    /* Test the actual result */
+    g_assert (rsvg_handle_get_intrinsic_size_in_pixels (handle, &width, &height));
+    g_assert_cmpfloat (width, ==, 192.0);
+    g_assert_cmpfloat (height, ==, 288.0);
+
+    g_object_unref (handle);
+}
+
+static void
+get_intrinsic_size_in_pixels_no (void)
+{
+    char *filename = get_test_filename ("no-size.svg");
+    GError *error = NULL;
+    gdouble width, height;
+
+    RsvgHandle *handle = rsvg_handle_new_from_file (filename, &error);
+    g_free (filename);
+
+    g_assert_nonnull (handle);
+    g_assert_no_error (error);
+
+    rsvg_handle_set_dpi (handle, 96.0);
+    g_assert (!rsvg_handle_get_intrinsic_size_in_pixels (handle, &width, &height));
+    g_assert_cmpfloat (width, ==, 0.0);
+    g_assert_cmpfloat (height, ==, 0.0);
+
+    g_object_unref (handle);
+}
+
 static void
 render_document (void)
 {
@@ -1630,6 +1677,8 @@ add_api_tests (void)
     g_test_add_func ("/api/can_draw_to_non_image_surface", can_draw_to_non_image_surface);
     g_test_add_func ("/api/render_cairo_sub", render_cairo_sub);
     g_test_add_func ("/api/get_intrinsic_dimensions", get_intrinsic_dimensions);
+    g_test_add_func ("/api/get_intrinsic_size_in_pixels/yes", get_intrinsic_size_in_pixels_yes);
+    g_test_add_func ("/api/get_intrinsic_size_in_pixels/no", get_intrinsic_size_in_pixels_no);
     g_test_add_func ("/api/render_document", render_document);
     g_test_add_func ("/api/get_geometry_for_layer", get_geometry_for_layer);
     g_test_add_func ("/api/render_layer", render_layer);
diff --git a/tests/fixtures/api/no-size.svg b/tests/fixtures/api/no-size.svg
new file mode 100644
index 00000000..1a45cb32
--- /dev/null
+++ b/tests/fixtures/api/no-size.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="100%" height="100%"/>
diff --git a/tests/fixtures/api/size.svg b/tests/fixtures/api/size.svg
new file mode 100644
index 00000000..25c1e0bf
--- /dev/null
+++ b/tests/fixtures/api/size.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="2in" height="3in"/>


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