[librsvg: 9/15] Add C version of rsvg_handle_render_layer()



commit c2c79030ebe0b10079a8b4bbc520fa5bfbcdb969
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Jul 29 13:12:40 2019 -0500

    Add C version of rsvg_handle_render_layer()

 doc/rsvg-sections.txt         |  3 ++-
 librsvg/rsvg-cairo.h          | 16 +++++++++++++++
 librsvg/rsvg-handle.c         | 21 +++++++++++++++++++
 librsvg/rsvg.h                |  8 --------
 librsvg_crate/src/lib.rs      | 30 +++++++++++++++++++++++++++
 rsvg_internals/src/c_api.rs   | 32 +++++++++++++++++++++++++++++
 tests/api.c                   | 47 +++++++++++++++++++++++++++++++++++++++++++
 tests/fixtures/api/layers.svg |  5 +++++
 8 files changed, 153 insertions(+), 9 deletions(-)
---
diff --git a/doc/rsvg-sections.txt b/doc/rsvg-sections.txt
index 53c7f304..07661222 100644
--- a/doc/rsvg-sections.txt
+++ b/doc/rsvg-sections.txt
@@ -26,7 +26,6 @@ rsvg_handle_get_dimensions
 rsvg_handle_get_dimensions_sub
 rsvg_handle_get_position_sub
 rsvg_handle_get_intrinsic_dimensions
-rsvg_handle_get_geometry_for_element
 rsvg_handle_has_sub
 rsvg_handle_get_title
 rsvg_handle_get_desc
@@ -70,6 +69,8 @@ RSVG_TYPE_HANDLE_FLAGS
 <SECTION>
 <FILE>rsvg-cairo</FILE>
 <TITLE>Using RSVG with cairo</TITLE>
+rsvg_handle_get_geometry_for_layer
+rsvg_handle_render_layer
 rsvg_handle_render_cairo
 rsvg_handle_render_cairo_sub
 </SECTION>
diff --git a/librsvg/rsvg-cairo.h b/librsvg/rsvg-cairo.h
index 3a75c629..c70f83cc 100644
--- a/librsvg/rsvg-cairo.h
+++ b/librsvg/rsvg-cairo.h
@@ -39,6 +39,22 @@ gboolean    rsvg_handle_render_cairo     (RsvgHandle *handle, cairo_t *cr);
 RSVG_API
 gboolean    rsvg_handle_render_cairo_sub (RsvgHandle *handle, cairo_t *cr, const char *id);
 
+RSVG_API
+gboolean rsvg_handle_get_geometry_for_layer (RsvgHandle     *handle,
+                                             const char     *id,
+                                             const RsvgRectangle *viewport,
+                                             RsvgRectangle  *out_ink_rect,
+                                             RsvgRectangle  *out_logical_rect,
+                                             GError        **error);
+
+RSVG_API
+gboolean rsvg_handle_render_layer (RsvgHandle           *handle,
+                                   cairo_t              *cr,
+                                   const char           *id,
+                                   const RsvgRectangle  *viewport,
+                                   GError              **error);
+
+
 G_END_DECLS
 
 #endif
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 5b32dc04..42be2e67 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -388,6 +388,12 @@ extern gboolean rsvg_rust_handle_get_geometry_for_layer (RsvgHandle     *handle,
                                                          RsvgRectangle  *out_ink_rect,
                                                          RsvgRectangle  *out_logical_rect,
                                                          GError        **error);
+extern gboolean rsvg_rust_handle_render_layer (RsvgHandle           *handle,
+                                               cairo_t              *cr,
+                                               const char           *id,
+                                               const RsvgRectangle  *viewport,
+                                               GError              **error);
+
 
 
 /* Implemented in rsvg_internals/src/c_api.rs */
@@ -1285,6 +1291,21 @@ rsvg_handle_get_geometry_for_layer (RsvgHandle     *handle,
                                                     error);
 }
 
+gboolean
+rsvg_handle_render_layer (RsvgHandle           *handle,
+                          cairo_t              *cr,
+                          const char           *id,
+                          const RsvgRectangle  *viewport,
+                          GError              **error)
+{
+    g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
+    g_return_val_if_fail (cr != NULL, FALSE);
+    g_return_val_if_fail (viewport != NULL, FALSE);
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    return rsvg_rust_handle_render_layer (handle, cr, id, viewport, error);
+}
+
 /**
  * rsvg_handle_internal_set_testing:
  * @handle: a #RsvgHandle
diff --git a/librsvg/rsvg.h b/librsvg/rsvg.h
index 5cd2be90..476c3025 100644
--- a/librsvg/rsvg.h
+++ b/librsvg/rsvg.h
@@ -280,14 +280,6 @@ void rsvg_handle_get_intrinsic_dimensions (RsvgHandle *handle,
                                            gboolean   *out_has_viewbox,
                                            RsvgRectangle *out_viewbox);
 
-RSVG_API
-gboolean rsvg_handle_get_geometry_for_layer (RsvgHandle     *handle,
-                                             const char     *id,
-                                             const RsvgRectangle *viewport,
-                                             RsvgRectangle  *out_ink_rect,
-                                             RsvgRectangle  *out_logical_rect,
-                                             GError        **error);
-
 /* GIO APIs */
 
 /**
diff --git a/librsvg_crate/src/lib.rs b/librsvg_crate/src/lib.rs
index e904076c..3ab58117 100644
--- a/librsvg_crate/src/lib.rs
+++ b/librsvg_crate/src/lib.rs
@@ -455,6 +455,36 @@ impl<'a> CairoRenderer<'a> {
             .render_layer(cr, id, viewport, self.dpi, false)
     }
 
+    /// Computes the (ink_rect, logical_rect) of a single SVG element
+    ///
+    /// While `geometry_for_layer` computes the geometry of an SVG element subtree with
+    /// its transformation matrix, this other function will compute the element's geometry
+    /// as if it were being rendered under an identity transformation by itself.  That is,
+    /// the resulting geometry is as if the element got extracted by itself from the SVG.
+    ///
+    /// This function is the counterpart to `render_element`.
+    ///
+    /// Element IDs should look like an URL fragment identifier; for
+    /// example, pass `Some("#foo")` to get the geometry of the
+    /// element that has an `id="foo"` attribute.
+    ///
+    /// The "ink rectangle" is the bounding box that would be painted
+    /// for fully- stroked and filled elements.
+    ///
+    /// The "logical rectangle" just takes into account the unstroked
+    /// paths and text outlines.
+    ///
+    /// Note that these bounds are not minimum bounds; for example,
+    /// clipping paths are not taken into account.
+    ///
+    /// You can pass `None` for the `id` if you want to measure all
+    /// the elements in the SVG, i.e. to measure everything from the
+    /// root element.
+    ///
+    /// This operation is not constant-time, as it involves going through all
+    /// the child elements.
+    ///
+    /// FIXME: example
     pub fn geometry_for_element(
         &self,
         id: Option<&str>,
diff --git a/rsvg_internals/src/c_api.rs b/rsvg_internals/src/c_api.rs
index d876c31d..74701a4a 100644
--- a/rsvg_internals/src/c_api.rs
+++ b/rsvg_internals/src/c_api.rs
@@ -711,6 +711,16 @@ impl CHandle {
         handle.get_geometry_for_layer(id, viewport, self.dpi.get(), self.is_testing.get())
     }
 
+    fn render_layer(
+        &self,
+        cr: &cairo::Context,
+        id: Option<&str>,
+        viewport: &cairo::Rectangle,
+    ) -> Result<(), RenderingError> {
+        let handle = self.get_handle_ref()?;
+        handle.render_layer(cr, id, viewport, self.dpi.get(), self.is_testing.get())
+    }
+
     fn get_intrinsic_dimensions(&self) -> Result<IntrinsicDimensions, RenderingError> {
         let handle = self.get_handle_ref()?;
         Ok(handle.get_intrinsic_dimensions())
@@ -1282,6 +1292,28 @@ pub unsafe extern "C" fn rsvg_rust_handle_get_geometry_for_layer(
     }
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_render_layer(
+    handle: *mut RsvgHandle,
+    cr: *mut cairo_sys::cairo_t,
+    id: *const libc::c_char,
+    viewport: *const RsvgRectangle,
+    error: *mut *mut glib_sys::GError,
+) -> glib_sys::gboolean {
+    let rhandle = get_rust_handle(handle);
+    let cr = from_glib_none(cr);
+    let id: Option<String> = from_glib_none(id);
+
+    match rhandle.render_layer(&cr, id.as_ref().map(String::as_str), &(*viewport).into()) {
+        Ok(()) => true.to_glib(),
+
+        Err(e) => {
+            set_gerror(error, 0, &format!("{}", e));
+            false.to_glib()
+        }
+    }
+}
+
 /// Detects whether a `*const libc::c_char` is a path or a URI
 ///
 /// `rsvg_handle_new_from_file()` takes a `filename` argument, and advertises
diff --git a/tests/api.c b/tests/api.c
index bb18169b..54298d6c 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -983,6 +983,52 @@ get_geometry_for_layer (void)
     g_object_unref (handle);
 }
 
+static void
+render_layer (void)
+{
+    char *filename = get_test_filename ("layers.svg");
+    GError *error = NULL;
+
+    RsvgHandle *handle = rsvg_handle_new_from_file (filename, &error);
+    g_free (filename);
+
+    g_assert (handle != NULL);
+    g_assert (error == NULL);
+
+    cairo_surface_t *output = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 300, 300);
+    cairo_t *cr = cairo_create (output);
+
+    RsvgRectangle viewport = { 100.0, 100.0, 100.0, 100.0 };
+
+    g_assert (rsvg_handle_render_layer (handle, cr, "#bar", &viewport, &error));
+    g_assert (error == NULL);
+
+    cairo_destroy (cr);
+
+    cairo_surface_t *expected = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 300, 300);
+    cr = cairo_create (expected);
+
+    cairo_translate (cr, 100.0, 100.0);
+    cairo_rectangle (cr, 20.0, 20.0, 30.0, 30.0);
+    cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 1.0);
+    cairo_fill (cr);
+    cairo_destroy (cr);
+
+    cairo_surface_t *diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 300, 300);
+
+    TestUtilsBufferDiffResult result = {0, 0};
+    test_utils_compare_surfaces (output, expected, diff, &result);
+
+    if (result.pixels_changed && result.max_diff > 0) {
+        g_test_fail ();
+    }
+
+    cairo_surface_destroy (diff);
+    cairo_surface_destroy (expected);
+    cairo_surface_destroy (output);
+    g_object_unref (handle);
+}
+
 /* https://gitlab.gnome.org/GNOME/librsvg/issues/385 */
 static void
 no_write_before_close (void)
@@ -1206,6 +1252,7 @@ main (int argc, char **argv)
     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_geometry_for_layer", get_geometry_for_layer);
+    g_test_add_func ("/api/render_layer", render_layer);
     g_test_add_func ("/api/no_write_before_close", no_write_before_close);
     g_test_add_func ("/api/empty_write_close", empty_write_close);
     g_test_add_func ("/api/cannot_request_external_elements", cannot_request_external_elements);
diff --git a/tests/fixtures/api/layers.svg b/tests/fixtures/api/layers.svg
new file mode 100644
index 00000000..73fc5cb9
--- /dev/null
+++ b/tests/fixtures/api/layers.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; width="100" height="100">
+  <rect id="foo" x="10" y="10" width="30" height="30" fill="#00ff00"/>
+  <rect id="bar" x="20" y="20" width="30" height="30" fill="#0000ff"/>
+</svg>


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