[librsvg: 5/8] Pass the color_interpolation_filters directly to FilterContext.get_input()
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 5/8] Pass the color_interpolation_filters directly to FilterContext.get_input()
- Date: Thu, 11 Mar 2021 03:13:21 +0000 (UTC)
commit 99afdceda6fab95cae8c543dd0bc71fd69080c14
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Mar 10 20:43:39 2021 -0600
Pass the color_interpolation_filters directly to FilterContext.get_input()
There was a convoluted scheme to get the value of
color_interpolation_filters in the main filters::render(), and hack it
into the FilterContext with with_linear_rgb().
It is easier if filter primitives request their inputs in the color
space that they need.
I've added comments where the spec explicitly says that a primitive
should *not* use the value of the color_interpolation_filters
property.
I've also added a comment to morphology.rs, since the spec is not
clear about it, but a) using the value from the ComputedValues makes a
test fail; b) the original code has feMorphology's implementation of
is_affected_by_color_interpolation_filters() set to false anyway.
I've regenerated the reference for svg1.1/filters-displace-02-f.svg -
it fails when the code works as per the spec (it didn't before, as it
converted both `in` and `in2` to the color_interpolation_filters color
space when it should only do that for `in2`, while `in` should remain
in its original color space. I can't make much sense of the
difference between the new result and the original PNG from the SVG1.1
test suite.
src/filters/blend.rs | 12 ++++--
src/filters/color_matrix.rs | 10 +++--
src/filters/component_transfer.rs | 8 +++-
src/filters/composite.rs | 12 ++++--
src/filters/context.rs | 30 ++++---------
src/filters/convolve_matrix.rs | 10 +++--
src/filters/displacement_map.rs | 24 +++++++++--
src/filters/gaussian_blur.rs | 10 +++--
src/filters/lighting.rs | 17 ++++----
src/filters/merge.rs | 35 ++++++++++++---
src/filters/mod.rs | 47 ++++++---------------
src/filters/morphology.rs | 16 ++++++-
src/filters/offset.rs | 15 ++++++-
src/filters/tile.rs | 15 ++++++-
.../reftests/svg1.1/filters-displace-02-f-ref.png | Bin 7658 -> 7511 bytes
15 files changed, 165 insertions(+), 96 deletions(-)
---
diff --git a/src/filters/blend.rs b/src/filters/blend.rs
index 9ff0d41d..8728a5d6 100755
--- a/src/filters/blend.rs
+++ b/src/filters/blend.rs
@@ -5,7 +5,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
-use crate::node::Node;
+use crate::node::{CascadedValues, Node};
use crate::parsers::{Parse, ParseValue};
use crate::xml::Attributes;
@@ -75,13 +75,17 @@ impl SetAttributes for FeBlend {
impl FilterRender for FeBlend {
fn render(
&self,
- _node: &Node,
+ node: &Node,
ctx: &FilterContext,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
- let input_2 = ctx.get_input(acquired_nodes, draw_ctx, &self.in2)?;
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
+ let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1, cif)?;
+ let input_2 = ctx.get_input(acquired_nodes, draw_ctx, &self.in2, cif)?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/color_matrix.rs b/src/filters/color_matrix.rs
index 9cdb0ca1..31ecdf2e 100644
--- a/src/filters/color_matrix.rs
+++ b/src/filters/color_matrix.rs
@@ -6,7 +6,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
-use crate::node::Node;
+use crate::node::{CascadedValues, Node};
use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
use crate::surface_utils::{
iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
@@ -142,12 +142,16 @@ impl SetAttributes for FeColorMatrix {
impl FilterRender for FeColorMatrix {
fn render(
&self,
- _node: &Node,
+ node: &Node,
ctx: &FilterContext,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
+ let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1, cif)?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/component_transfer.rs b/src/filters/component_transfer.rs
index 75d7a85e..62923bd7 100644
--- a/src/filters/component_transfer.rs
+++ b/src/filters/component_transfer.rs
@@ -7,7 +7,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
-use crate::node::{Node, NodeBorrow};
+use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
use crate::surface_utils::{
iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
@@ -294,9 +294,13 @@ impl FilterRender for FeComponentTransfer {
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
let functions = get_parameters(node)?;
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1, cif)?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/composite.rs b/src/filters/composite.rs
index 0929d571..ae92b180 100644
--- a/src/filters/composite.rs
+++ b/src/filters/composite.rs
@@ -5,7 +5,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
-use crate::node::Node;
+use crate::node::{CascadedValues, Node};
use crate::parsers::{Parse, ParseValue};
use crate::xml::Attributes;
@@ -76,13 +76,17 @@ impl SetAttributes for FeComposite {
impl FilterRender for FeComposite {
fn render(
&self,
- _node: &Node,
+ node: &Node,
ctx: &FilterContext,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
- let input_2 = ctx.get_input(acquired_nodes, draw_ctx, &self.in2)?;
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
+ let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1, cif)?;
+ let input_2 = ctx.get_input(acquired_nodes, draw_ctx, &self.in2, cif)?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/context.rs b/src/filters/context.rs
index c5bf35be..172ff894 100644
--- a/src/filters/context.rs
+++ b/src/filters/context.rs
@@ -8,6 +8,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::filter::Filter;
use crate::parsers::CustomIdent;
use crate::properties::ComputedValues;
+use crate::property_defs::ColorInterpolationFilters;
use crate::rect::{IRect, Rect};
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::transform::Transform;
@@ -70,11 +71,6 @@ pub struct FilterContext {
primitive_units: CoordUnits,
/// The filter effects region.
effects_region: Rect,
- /// Whether the currently rendered filter primitive uses linear RGB for color operations.
- ///
- /// This affects `get_input()` and `store_result()` which should perform linearization and
- /// unlinearization respectively when this is set to `true`.
- processing_linear_rgb: bool,
/// The filter element affine matrix.
///
@@ -174,7 +170,6 @@ impl FilterContext {
fill_paint_surface: OnceCell::new(),
primitive_units,
effects_region,
- processing_linear_rgb: false,
_affine: affine,
paffine,
}
@@ -310,8 +305,6 @@ impl FilterContext {
}
/// Retrieves the filter input surface according to the SVG rules.
- ///
- /// Does not take `processing_linear_rgb` into account.
fn get_input_raw(
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
@@ -369,11 +362,14 @@ impl FilterContext {
}
/// Retrieves the filter input surface according to the SVG rules.
+ ///
+ /// The surface will be converted to the color space specified by `color_interpolation_filters`.
pub fn get_input(
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
in_: &Input,
+ color_interpolation_filters: ColorInterpolationFilters,
) -> Result<FilterInput, FilterError> {
let raw = self.get_input_raw(acquired_nodes, draw_ctx, in_)?;
@@ -386,11 +382,12 @@ impl FilterContext {
}) => (surface, *bounds),
};
- let surface = if self.processing_linear_rgb {
- surface.to_linear_rgb(bounds)
- } else {
- surface.to_srgb(bounds)
+ let surface = match color_interpolation_filters {
+ ColorInterpolationFilters::Auto => Ok(surface.clone()),
+ ColorInterpolationFilters::LinearRgb => surface.to_linear_rgb(bounds),
+ ColorInterpolationFilters::Srgb => surface.to_srgb(bounds),
};
+
surface
.map_err(FilterError::CairoError)
.map(|surface| match raw {
@@ -400,15 +397,6 @@ impl FilterContext {
}
})
}
-
- /// Calls the given closure with linear RGB processing enabled.
- #[inline]
- pub fn with_linear_rgb<T, F: FnOnce(&mut FilterContext) -> T>(&mut self, f: F) -> T {
- self.processing_linear_rgb = true;
- let rv = f(self);
- self.processing_linear_rgb = false;
- rv
- }
}
impl FilterInput {
diff --git a/src/filters/convolve_matrix.rs b/src/filters/convolve_matrix.rs
index 40449942..4d6723b1 100644
--- a/src/filters/convolve_matrix.rs
+++ b/src/filters/convolve_matrix.rs
@@ -6,7 +6,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
-use crate::node::Node;
+use crate::node::{CascadedValues, Node};
use crate::parsers::{
NonNegative, NumberList, NumberListLength, NumberOptionalNumber, Parse, ParseValue,
};
@@ -124,14 +124,18 @@ impl SetAttributes for FeConvolveMatrix {
impl FilterRender for FeConvolveMatrix {
fn render(
&self,
- _node: &Node,
+ node: &Node,
ctx: &FilterContext,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
#![allow(clippy::many_single_char_names)]
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
+ let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1, cif)?;
let mut bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/displacement_map.rs b/src/filters/displacement_map.rs
index 6bd557ed..42d00e55 100644
--- a/src/filters/displacement_map.rs
+++ b/src/filters/displacement_map.rs
@@ -5,8 +5,9 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
-use crate::node::Node;
+use crate::node::{CascadedValues, Node};
use crate::parsers::{Parse, ParseValue};
+use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::{iterators::Pixels, shared_surface::ExclusiveImageSurface};
use crate::xml::Attributes;
@@ -73,13 +74,28 @@ impl SetAttributes for FeDisplacementMap {
impl FilterRender for FeDisplacementMap {
fn render(
&self,
- _node: &Node,
+ node: &Node,
ctx: &FilterContext,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
- let displacement_input = ctx.get_input(acquired_nodes, draw_ctx, &self.in2)?;
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
+ // https://www.w3.org/TR/filter-effects/#feDisplacementMapElement
+ // "The color-interpolation-filters property only applies to
+ // the in2 source image and does not apply to the in source
+ // image. The in source image must remain in its current color
+ // space.
+
+ let input_1 = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &self.in1,
+ ColorInterpolationFilters::Auto,
+ )?;
+ let displacement_input = ctx.get_input(acquired_nodes, draw_ctx, &self.in2, cif)?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/gaussian_blur.rs b/src/filters/gaussian_blur.rs
index 5fe342b2..a752255c 100644
--- a/src/filters/gaussian_blur.rs
+++ b/src/filters/gaussian_blur.rs
@@ -7,7 +7,7 @@ use nalgebra::{DMatrix, Dynamic, VecStorage};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
-use crate::node::Node;
+use crate::node::{CascadedValues, Node};
use crate::parsers::{NonNegative, NumberOptionalNumber, ParseValue};
use crate::rect::IRect;
use crate::surface_utils::{
@@ -190,12 +190,16 @@ fn gaussian_blur(
impl FilterRender for FeGaussianBlur {
fn render(
&self,
- _node: &Node,
+ node: &Node,
ctx: &FilterContext,
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ let cascaded = CascadedValues::new_from_node(node);
+ let values = cascaded.get();
+ let cif = values.color_interpolation_filters();
+
+ let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1, cif)?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/lighting.rs b/src/filters/lighting.rs
index 81132bd9..db97b2dd 100644
--- a/src/filters/lighting.rs
+++ b/src/filters/lighting.rs
@@ -461,7 +461,14 @@ macro_rules! impl_lighting_filter {
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ let light = Light::new(node)?;
+
+ let input_1 = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &self.in1,
+ light.color_interpolation_filters,
+ )?;
let mut bounds = self
.base
.get_bounds(ctx)?
@@ -494,18 +501,12 @@ macro_rules! impl_lighting_filter {
let (ox, oy) = scale.unwrap_or((1.0, 1.0));
- let light = Light::new(node)?;
-
let source = light.source.transform(ctx.paffine());
- // The generated color values are in the color space determined by
- // color-interpolation-filters.
- let surface_type = SurfaceType::from(light.color_interpolation_filters);
-
let mut surface = ExclusiveImageSurface::new(
input_surface.width(),
input_surface.height(),
- surface_type,
+ SurfaceType::from(light.color_interpolation_filters),
)?;
{
diff --git a/src/filters/merge.rs b/src/filters/merge.rs
index 0ba0d8b1..35c598f8 100644
--- a/src/filters/merge.rs
+++ b/src/filters/merge.rs
@@ -3,8 +3,9 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
-use crate::node::{Node, NodeBorrow};
+use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::ParseValue;
+use crate::property_defs::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::xml::Attributes;
@@ -21,6 +22,7 @@ pub struct FeMerge {
#[derive(Clone, Debug, Default, PartialEq)]
pub struct FeMergeNode {
in1: Input,
+ color_interpolation_filters: ColorInterpolationFilters,
}
impl Default for FeMerge {
@@ -63,7 +65,12 @@ impl FeMergeNode {
bounds: IRect,
output_surface: Option<SharedImageSurface>,
) -> Result<SharedImageSurface, FilterError> {
- let input = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ let input = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &self.in1,
+ self.color_interpolation_filters,
+ )?;
if output_surface.is_none() {
return Ok(input.surface().clone());
@@ -89,7 +96,12 @@ impl FilterRender for FeMerge {
// Compute the filter bounds, taking each feMergeNode's input into account.
let mut bounds = self.base.get_bounds(ctx)?;
for merge_node in ¶meters {
- let input = ctx.get_input(acquired_nodes, draw_ctx, &merge_node.in1)?;
+ let input = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &merge_node.in1,
+ merge_node.color_interpolation_filters,
+ )?;
bounds = bounds.add_input(&input);
}
@@ -137,8 +149,15 @@ fn get_parameters(node: &Node) -> Result<Vec<FeMergeNode>, FilterError> {
return Err(FilterError::ChildNodeInError);
}
+ let cascaded = CascadedValues::new_from_node(&child);
+ let values = cascaded.get();
+ let color_interpolation_filters = values.color_interpolation_filters();
+
if let Element::FeMergeNode(ref merge_node) = *elt {
- merge_nodes.push(merge_node.element_impl.clone());
+ merge_nodes.push(FeMergeNode {
+ color_interpolation_filters,
+ ..merge_node.element_impl.clone()
+ });
}
}
@@ -158,7 +177,7 @@ mod tests {
<filter id="filter">
<feMerge id="merge">
<feMergeNode in="SourceGraphic"/>
- <feMergeNode in="SourceAlpha"/>
+ <feMergeNode in="SourceAlpha" color-interpolation-filters="sRGB"/>
</feMerge>
</filter>
</svg>
@@ -173,10 +192,12 @@ mod tests {
¶ms[..],
vec![
FeMergeNode {
- in1: Input::SourceGraphic
+ in1: Input::SourceGraphic,
+ color_interpolation_filters: Default::default(),
},
FeMergeNode {
- in1: Input::SourceAlpha
+ in1: Input::SourceAlpha,
+ color_interpolation_filters: ColorInterpolationFilters::Srgb,
},
]
);
diff --git a/src/filters/mod.rs b/src/filters/mod.rs
index e69b6d97..cdcb89f0 100644
--- a/src/filters/mod.rs
+++ b/src/filters/mod.rs
@@ -11,7 +11,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::{ElementError, ParseError, RenderingError};
use crate::length::*;
-use crate::node::{CascadedValues, Node, NodeBorrow};
+use crate::node::{Node, NodeBorrow};
use crate::parsers::{CustomIdent, Parse, ParseValue};
use crate::properties::ComputedValues;
use crate::property_defs::ColorInterpolationFilters;
@@ -258,45 +258,24 @@ pub fn render(
!in_error
})
// Keep only filter primitives (those that implement the Filter trait)
- .filter(|c| c.borrow_element().as_filter_effect().is_some())
- // Check if the node wants linear RGB.
- .map(|c| {
- let linear_rgb = {
- let cascaded = CascadedValues::new_from_node(&c);
- let values = cascaded.get();
+ .filter(|c| c.borrow_element().as_filter_effect().is_some());
- values.color_interpolation_filters() == ColorInterpolationFilters::LinearRgb
- };
-
- (c, linear_rgb)
- });
-
- for (c, linear_rgb) in primitives {
+ for c in primitives {
let elt = c.borrow_element();
let filter = elt.as_filter_effect().unwrap();
- let mut render = |filter_ctx: &mut FilterContext| {
- if let Err(err) = filter
- .render(&c, filter_ctx, acquired_nodes, draw_ctx)
- .and_then(|result| filter_ctx.store_result(result))
- {
- rsvg_log!("(filter primitive {} returned an error: {})", c, err);
-
- // Exit early on Cairo errors. Continue rendering otherwise.
- if let FilterError::CairoError(status) = err {
- return Err(status);
- }
- }
-
- Ok(())
- };
-
let start = Instant::now();
- if filter.is_affected_by_color_interpolation_filters() && linear_rgb {
- filter_ctx.with_linear_rgb(render)?;
- } else {
- render(&mut filter_ctx)?;
+ if let Err(err) = filter
+ .render(&c, &mut filter_ctx, acquired_nodes, draw_ctx)
+ .and_then(|result| filter_ctx.store_result(result))
+ {
+ rsvg_log!("(filter primitive {} returned an error: {})", c, err);
+
+ // Exit early on Cairo errors. Continue rendering otherwise.
+ if let FilterError::CairoError(status) = err {
+ return Err(RenderingError::from(status));
+ }
}
let elapsed = start.elapsed();
diff --git a/src/filters/morphology.rs b/src/filters/morphology.rs
index c88efbea..ce135681 100644
--- a/src/filters/morphology.rs
+++ b/src/filters/morphology.rs
@@ -9,6 +9,7 @@ use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::Node;
use crate::parsers::{NonNegative, NumberOptionalNumber, Parse, ParseValue};
+use crate::property_defs::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::surface_utils::{
iterators::{PixelRectangle, Pixels},
@@ -74,7 +75,20 @@ impl FilterRender for FeMorphology {
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ // Although https://www.w3.org/TR/filter-effects/#propdef-color-interpolation-filters does not
mention
+ // feMorphology as being one of the primitives that does *not* use that property,
+ // the SVG1.1 test for filters-morph-01-f.svg fails if we pass the value from the ComputedValues
here (that
+ // document does not specify the color-interpolation-filters property, so it defaults to linearRGB).
+ // So, we pass Auto, which will get resolved to SRGB, and that makes that test pass.
+ //
+ // I suppose erosion/dilation doesn't care about the color space of the source image?
+
+ let input_1 = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &self.in1,
+ ColorInterpolationFilters::Auto,
+ )?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/offset.rs b/src/filters/offset.rs
index 213a5c77..3b899d4b 100644
--- a/src/filters/offset.rs
+++ b/src/filters/offset.rs
@@ -5,6 +5,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::node::Node;
use crate::parsers::ParseValue;
+use crate::property_defs::ColorInterpolationFilters;
use crate::xml::Attributes;
use super::context::{FilterContext, FilterOutput, FilterResult};
@@ -55,7 +56,19 @@ impl FilterRender for FeOffset {
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ // https://www.w3.org/TR/filter-effects/#ColorInterpolationFiltersProperty
+ //
+ // "Note: The color-interpolation-filters property just has an
+ // effect on filter operations. Therefore, it has no effect on
+ // filter primitives like feOffset"
+ //
+ // This is why we pass Auto here.
+ let input_1 = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &self.in1,
+ ColorInterpolationFilters::Auto,
+ )?;
let bounds = self
.base
.get_bounds(ctx)?
diff --git a/src/filters/tile.rs b/src/filters/tile.rs
index 986eeff7..7d086082 100644
--- a/src/filters/tile.rs
+++ b/src/filters/tile.rs
@@ -2,6 +2,7 @@ use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::node::Node;
+use crate::property_defs::ColorInterpolationFilters;
use crate::xml::Attributes;
use super::context::{FilterContext, FilterInput, FilterOutput, FilterResult};
@@ -39,7 +40,19 @@ impl FilterRender for FeTile {
acquired_nodes: &mut AcquiredNodes<'_>,
draw_ctx: &mut DrawingCtx,
) -> Result<FilterResult, FilterError> {
- let input_1 = ctx.get_input(acquired_nodes, draw_ctx, &self.in1)?;
+ // https://www.w3.org/TR/filter-effects/#ColorInterpolationFiltersProperty
+ //
+ // "Note: The color-interpolation-filters property just has an
+ // effect on filter operations. Therefore, it has no effect on
+ // filter primitives like [...], feTile"
+ //
+ // This is why we pass Auto here.
+ let input_1 = ctx.get_input(
+ acquired_nodes,
+ draw_ctx,
+ &self.in1,
+ ColorInterpolationFilters::Auto,
+ )?;
// feTile doesn't consider its inputs in the filter primitive subregion calculation.
let bounds = self.base.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
diff --git a/tests/fixtures/reftests/svg1.1/filters-displace-02-f-ref.png
b/tests/fixtures/reftests/svg1.1/filters-displace-02-f-ref.png
index 784f35ce..f8790b9e 100644
Binary files a/tests/fixtures/reftests/svg1.1/filters-displace-02-f-ref.png and
b/tests/fixtures/reftests/svg1.1/filters-displace-02-f-ref.png differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]