[librsvg] filters::render() - Take the computed values of the node being filtered, not the whole node



commit 580beabe535e6d852b4bc69b8ddc7d6ded49ceec
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Sep 20 19:11:04 2018 -0500

    filters::render() - Take the computed values of the node being filtered, not the whole node
    
    Some time soon I want to merge Artem Vorotnikov's work to replace the
    ubiquitous Rc<Node> with a Rc<NodeTrait>, to have a "real" inheritance
    scheme rather our awkward node.with_impl().
    
    In the meantime, it turns out that the filters code doesn't need the
    actual node that is being filtered; just a set of computed values to
    pass around while rendering the filter.  So, let's do that.

 rsvg_internals/src/drawing_ctx.rs     |  2 +-
 rsvg_internals/src/filters/context.rs | 40 ++++++++++++++++-------------------
 rsvg_internals/src/filters/image.rs   |  4 +---
 rsvg_internals/src/filters/mod.rs     | 12 +++++++----
 4 files changed, 28 insertions(+), 30 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 805baa08..076c047c 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -437,7 +437,7 @@ impl<'a> DrawingCtx<'a> {
 
                                 if !filter_node.is_in_error() {
                                     // FIXME: deal with out of memory here
-                                    Some(filters::render(&filter_node, node, &output, self))
+                                    Some(filters::render(&filter_node, values, &output, self))
                                 } else {
                                     rsvg_log!(
                                         "(ignoring filter element {} because it is in error)",
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index 905aa38a..b75a4a1e 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -10,6 +10,7 @@ use drawing_ctx::DrawingCtx;
 use length::Length;
 use node::RsvgNode;
 use paint_server::{self, PaintServer};
+use state::ComputedValues;
 use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
 use unitinterval::UnitInterval;
 
@@ -58,8 +59,8 @@ pub enum FilterInput {
 pub struct FilterContext {
     /// The <filter> node.
     node: RsvgNode,
-    /// The node which referenced this filter.
-    node_being_filtered: RsvgNode,
+    /// Values from the node which referenced this filter.
+    computed_from_node_being_filtered: ComputedValues,
     /// The source graphic surface.
     source_surface: SharedImageSurface,
     /// Output of the last filter primitive.
@@ -102,15 +103,14 @@ pub struct FilterContext {
 /// Computes and returns the filter effects region.
 fn compute_effects_region(
     filter_node: &RsvgNode,
-    target_node: &RsvgNode,
+    computed_from_target_node: &ComputedValues,
     draw_ctx: &mut DrawingCtx<'_>,
     affine: cairo::Matrix,
     width: f64,
     height: f64,
 ) -> BoundingBox {
     // Filters use the properties of the target node.
-    let cascaded = target_node.get_cascaded_values();
-    let values = cascaded.get();
+    let values = computed_from_target_node;
 
     let filter = filter_node.get_impl::<NodeFilter>().unwrap();
 
@@ -193,7 +193,7 @@ impl FilterContext {
     /// Creates a new `FilterContext`.
     pub fn new(
         filter_node: &RsvgNode,
-        node_being_filtered: &RsvgNode,
+        computed_from_node_being_filtered: &ComputedValues,
         source_surface: SharedImageSurface,
         draw_ctx: &mut DrawingCtx<'_>,
     ) -> Self {
@@ -246,14 +246,14 @@ impl FilterContext {
 
         Self {
             node: filter_node.clone(),
-            node_being_filtered: node_being_filtered.clone(),
+            computed_from_node_being_filtered: computed_from_node_being_filtered.clone(),
             source_surface,
             last_result: None,
             previous_results: HashMap::new(),
             background_surface: UnsafeCell::new(None),
             effects_region: compute_effects_region(
                 filter_node,
-                node_being_filtered,
+                computed_from_node_being_filtered,
                 draw_ctx,
                 affine,
                 f64::from(width),
@@ -265,10 +265,10 @@ impl FilterContext {
         }
     }
 
-    /// Returns the node that referenced this filter.
+    /// Returns the computed values from the node that referenced this filter.
     #[inline]
-    pub fn get_node_being_filtered(&self) -> RsvgNode {
-        self.node_being_filtered.clone()
+    pub fn get_computed_values_from_node_being_filtered(&self) -> &ComputedValues {
+        &self.computed_from_node_being_filtered
     }
 
     /// Returns the surface corresponding to the last filter primitive's result.
@@ -427,10 +427,6 @@ impl FilterContext {
     where
         for<'b> F: FnOnce(Box<Fn(&Length) -> f64 + 'b>) -> T,
     {
-        // Filters use the properties of the target node.
-        let cascaded = self.node_being_filtered.get_cascaded_values();
-        let values = cascaded.get();
-
         let filter = self.node.get_impl::<NodeFilter>().unwrap();
 
         // See comments in compute_effects_region() for how this works.
@@ -441,7 +437,11 @@ impl FilterContext {
             rv
         } else {
             f(Box::new(|length: &Length| {
-                length.normalize(values, &draw_ctx.get_view_params())
+                // Filters use the properties of the target node.
+                length.normalize(
+                    &self.computed_from_node_being_filtered,
+                    &draw_ctx.get_view_params(),
+                )
             }))
         }
     }
@@ -463,9 +463,6 @@ impl FilterContext {
         let cr = cairo::Context::new(&surface);
         draw_ctx.set_cairo_context(&cr);
 
-        let cascaded = self.node_being_filtered.get_cascaded_values();
-        let values = cascaded.get();
-
         let bbox = draw_ctx.get_bbox().clone();
 
         // FIXME: we are ignoring the following error; propagate it upstream
@@ -474,7 +471,7 @@ impl FilterContext {
             paint_server,
             &opacity,
             &bbox,
-            &values.color.0,
+            &self.computed_from_node_being_filtered.color.0,
         ).and_then(|had_paint_server| {
             if had_paint_server {
                 cr.paint();
@@ -505,8 +502,7 @@ impl FilterContext {
             }
         }
 
-        let cascaded = self.node_being_filtered.get_cascaded_values();
-        let values = cascaded.get();
+        let values = &self.computed_from_node_being_filtered;
 
         match *in_.unwrap() {
             Input::SourceGraphic => Ok(FilterInput::StandardInput(self.source_graphic().clone())),
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index 47177e04..6d7e103a 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -69,9 +69,7 @@ impl Image {
 
         draw_ctx.get_cairo_context().set_matrix(ctx.paffine());
 
-        let node_being_filtered = ctx.get_node_being_filtered();
-        let node_being_filtered_cascaded = node_being_filtered.get_cascaded_values();
-        let node_being_filtered_values = node_being_filtered_cascaded.get();
+        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();
 
         let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);
 
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index c3d70541..4cdccac3 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -14,7 +14,7 @@ use length::{Length, LengthDir, LengthUnit};
 use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
 use parsers::{parse_and_validate, ParseError};
 use property_bag::PropertyBag;
-use state::ColorInterpolationFilters;
+use state::{ColorInterpolationFilters, ComputedValues};
 use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
 
 mod bounds;
@@ -232,7 +232,7 @@ impl Deref for PrimitiveWithInput {
 /// Applies a filter and returns the resulting surface.
 pub fn render(
     filter_node: &RsvgNode,
-    node_being_filtered: &RsvgNode,
+    computed_from_node_being_filtered: &ComputedValues,
     source: &cairo::ImageSurface,
     draw_ctx: &mut DrawingCtx<'_>,
 ) -> cairo::ImageSurface {
@@ -254,8 +254,12 @@ pub fn render(
     }
     let source_surface = SharedImageSurface::new(source_surface, SurfaceType::SRgb).unwrap();
 
-    let mut filter_ctx =
-        FilterContext::new(filter_node, node_being_filtered, source_surface, draw_ctx);
+    let mut filter_ctx = FilterContext::new(
+        filter_node,
+        computed_from_node_being_filtered,
+        source_surface,
+        draw_ctx,
+    );
 
     // If paffine is non-invertible, we won't draw anything. Also bbox combining in bounds
     // computations will panic due to non-invertible martrix.


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