[librsvg: 6/13] Minimal implementation of a public SvgHandle::set_stylesheet() API



commit 7eeac4566845094de13bbae099e4846b013c4898
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Jan 23 18:36:10 2020 -0600

    Minimal implementation of a public SvgHandle::set_stylesheet() API

 librsvg_crate/src/lib.rs     |  4 ++++
 librsvg_crate/tests/api.rs   | 48 ++++++++++++++++++++++++++++++++++++++++++++
 rsvg_internals/src/css.rs    |  2 +-
 rsvg_internals/src/handle.rs |  8 ++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)
---
diff --git a/librsvg_crate/src/lib.rs b/librsvg_crate/src/lib.rs
index d33cdef1..6583ca2c 100644
--- a/librsvg_crate/src/lib.rs
+++ b/librsvg_crate/src/lib.rs
@@ -365,6 +365,10 @@ impl SvgHandle {
     pub fn has_element_with_id(&self, id: &str) -> Result<bool, RenderingError> {
         self.0.has_sub(id)
     }
+
+    pub fn set_stylesheet(&mut self, css: &str) -> Result<(), LoadingError> {
+        self.0.set_stylesheet(css)
+    }
 }
 
 /// Can render an `SvgHandle` to a Cairo context.
diff --git a/librsvg_crate/tests/api.rs b/librsvg_crate/tests/api.rs
index 1052ff9e..548a13a1 100644
--- a/librsvg_crate/tests/api.rs
+++ b/librsvg_crate/tests/api.rs
@@ -173,3 +173,51 @@ fn untransformed_element() {
 
     compare_to_surface(&output_surf, &reference_surf, "untransformed_element");
 }
+
+#[test]
+fn set_stylesheet() {
+    // This has a rectangle which we style from a user-supplied stylesheet.
+    let mut svg = load_svg(
+        br##"<?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="20" width="30" height="40" fill="black"/>
+</svg>
+"##,
+    );
+
+    svg.set_stylesheet("rect { fill: #00ff00; }").expect("should be a valid stylesheet");
+
+    let renderer = CairoRenderer::new(&svg);
+
+    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
+
+    let res = {
+        let cr = cairo::Context::new(&output);
+        let viewport = cairo::Rectangle {
+            x: 0.0,
+            y: 0.0,
+            width: 100.0,
+            height: 100.0,
+        };
+
+        renderer.render_document(&cr, &viewport)
+    };
+
+    let output_surf = res
+        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
+        .unwrap();
+
+    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
+
+    {
+        let cr = cairo::Context::new(&reference_surf);
+
+        cr.rectangle(10.0, 20.0, 30.0, 40.0);
+        cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
+        cr.fill();
+    }
+
+    let reference_surf = SharedImageSurface::wrap(reference_surf, SurfaceType::SRgb).unwrap();
+
+    compare_to_surface(&output_surf, &reference_surf, "set_stylesheet");
+}
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index 8b4e5cb6..7226f3a7 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -651,7 +651,7 @@ impl Stylesheet {
     ///
     /// The `base_url` is required for `@import` rules, so that librsvg
     /// can determine if the requested path is allowed.
-    fn parse(&mut self, buf: &str, base_url: Option<&Url>) -> Result<(), LoadingError> {
+    pub fn parse(&mut self, buf: &str, base_url: Option<&Url>) -> Result<(), LoadingError> {
         let mut input = ParserInput::new(buf);
         let mut parser = Parser::new(&mut input);
 
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 6d9e6ac1..f887f0db 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -9,6 +9,7 @@ use locale_config::{LanguageRange, Locale};
 
 use crate::allowed_url::{AllowedUrl, Href};
 use crate::bbox::BoundingBox;
+use crate::css::{Origin, Stylesheet};
 use crate::document::Document;
 use crate::dpi::Dpi;
 use crate::drawing_ctx::DrawingCtx;
@@ -581,6 +582,13 @@ impl Handle {
     pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
         self.document.get_intrinsic_dimensions()
     }
+
+    pub fn set_stylesheet(&mut self, css: &str) -> Result<(), LoadingError> {
+        let mut stylesheet = Stylesheet::new(Origin::User);
+        stylesheet.parse(css, None)?;
+        self.document.cascade(&[stylesheet]);
+        Ok(())
+    }
 }
 
 fn check_cairo_context(cr: &cairo::Context) -> Result<(), RenderingError> {


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