[librsvg: 7/15] Normalize the Filter element into a ResolvedFilter as early as possible
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 7/15] Normalize the Filter element into a ResolvedFilter as early as possible
- Date: Thu, 8 Apr 2021 22:52:27 +0000 (UTC)
commit 4487bc25bb583310a0bc30c6281f99c0b0814ea8
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Apr 8 14:06:32 2021 -0500
Normalize the Filter element into a ResolvedFilter as early as possible
This finally lets us remove all the length normalization while running the
filter primitives.
src/filter.rs | 17 +++++++++++++++--
src/filters/context.rs | 17 ++++++-----------
src/filters/mod.rs | 9 ++++++++-
3 files changed, 29 insertions(+), 14 deletions(-)
---
diff --git a/src/filter.rs b/src/filter.rs
index 7ea31c81..a1568bfc 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -26,6 +26,13 @@ pub struct Filter {
primitive_units: CoordUnits,
}
+/// A <filter> element definition in user-space coordinates.
+pub struct ResolvedFilter {
+ pub rect: Rect,
+ pub filter_units: CoordUnits,
+ pub primitive_units: CoordUnits,
+}
+
impl Default for Filter {
/// Constructs a new `Filter` with default properties.
fn default() -> Self {
@@ -49,7 +56,7 @@ impl Filter {
self.primitive_units
}
- pub fn get_rect(&self, values: &ComputedValues, params: &ViewParams) -> Rect {
+ pub fn resolve(&self, values: &ComputedValues, params: &ViewParams) -> ResolvedFilter {
// With filterunits == ObjectBoundingBox, lengths represent fractions or percentages of the
// referencing node. No units are allowed (it's checked during attribute parsing).
let (x, y, w, h) = if self.filter_units == CoordUnits::ObjectBoundingBox {
@@ -68,7 +75,13 @@ impl Filter {
)
};
- Rect::new(x, y, x + w, y + h)
+ let rect = Rect::new(x, y, x + w, y + h);
+
+ ResolvedFilter {
+ rect,
+ filter_units: self.filter_units,
+ primitive_units: self.primitive_units,
+ }
}
}
diff --git a/src/filters/context.rs b/src/filters/context.rs
index adc97732..ee705a13 100644
--- a/src/filters/context.rs
+++ b/src/filters/context.rs
@@ -5,7 +5,7 @@ use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
-use crate::filter::Filter;
+use crate::filter::ResolvedFilter;
use crate::paint_server::UserSpacePaintSource;
use crate::parsers::CustomIdent;
use crate::properties::ComputedValues;
@@ -100,7 +100,7 @@ pub struct FilterContext {
impl FilterContext {
/// Creates a new `FilterContext`.
pub fn new(
- filter: &Filter,
+ filter: &ResolvedFilter,
computed_from_node_being_filtered: &ComputedValues,
stroke_paint: UserSpacePaintSource,
fill_paint: UserSpacePaintSource,
@@ -113,8 +113,7 @@ impl FilterContext {
// However, with userSpaceOnUse it's still possible to create images with a filter.
let bbox_rect = node_bbox.rect.unwrap_or_default();
- let filter_units = filter.get_filter_units();
- let affine = match filter_units {
+ let affine = match filter.filter_units {
CoordUnits::UserSpaceOnUse => draw_transform,
CoordUnits::ObjectBoundingBox => Transform::new_unchecked(
bbox_rect.width(),
@@ -127,8 +126,7 @@ impl FilterContext {
.post_transform(&draw_transform),
};
- let primitive_units = filter.get_primitive_units();
- let paffine = match primitive_units {
+ let paffine = match filter.primitive_units {
CoordUnits::UserSpaceOnUse => draw_transform,
CoordUnits::ObjectBoundingBox => Transform::new_unchecked(
bbox_rect.width(),
@@ -148,13 +146,10 @@ impl FilterContext {
}
let effects_region = {
- let params = draw_ctx.push_coord_units(filter_units);
- let filter_rect = filter.get_rect(&computed_from_node_being_filtered, ¶ms);
-
let mut bbox = BoundingBox::new();
let other_bbox = BoundingBox::new()
.with_transform(affine)
- .with_rect(filter_rect);
+ .with_rect(filter.rect);
// At this point all of the previous viewbox and matrix business gets converted to pixel
// coordinates in the final surface, because bbox is created with an identity transform.
@@ -178,7 +173,7 @@ impl FilterContext {
background_surface: OnceCell::new(),
stroke_paint_surface: OnceCell::new(),
fill_paint_surface: OnceCell::new(),
- primitive_units,
+ primitive_units: filter.primitive_units,
effects_region,
_affine: affine,
paffine,
diff --git a/src/filters/mod.rs b/src/filters/mod.rs
index d278421c..3c78f5ad 100644
--- a/src/filters/mod.rs
+++ b/src/filters/mod.rs
@@ -259,8 +259,15 @@ pub fn render(
.resolve(acquired_nodes, values.fill_opacity().0, values.color().0)?
.to_user_space(&node_bbox, draw_ctx, values);
+ let resolved_filter = {
+ // This is in a temporary scope so we don't leave the coord_units pushed during
+ // the execution of all the filter primitives.
+ let params = draw_ctx.push_coord_units(filter.get_filter_units());
+ filter.resolve(values, ¶ms)
+ };
+
if let Ok(mut filter_ctx) = FilterContext::new(
- &filter,
+ &resolved_filter,
computed_from_node_being_filtered,
stroke_paint_source,
fill_paint_source,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]