[librsvg: 26/30] pattern: calculate transforms inside UserSpacePattern
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 26/30] pattern: calculate transforms inside UserSpacePattern
- Date: Mon, 28 Dec 2020 20:06:30 +0000 (UTC)
commit b1a327838975c05faa0dd7240d10f8c71bf1d052
Author: Paolo Borelli <pborelli gnome org>
Date: Sun Dec 27 15:33:52 2020 +0100
pattern: calculate transforms inside UserSpacePattern
As described in the preexisting FIXME comment, calculate the
transforms in the pattern code instead of doing it in drawing_ctx.
src/drawing_ctx.rs | 83 ++++++++++------------------------------------------
src/pattern.rs | 86 +++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 81 insertions(+), 88 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 33b2d129..f2962cd5 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -25,7 +25,7 @@ use crate::marker;
use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
use crate::paint_server::{PaintServer, UserSpacePaintSource};
use crate::path_builder::*;
-use crate::pattern::{PatternContentUnits, PatternUnits, UserSpacePattern};
+use crate::pattern::UserSpacePattern;
use crate::properties::ComputedValues;
use crate::property_defs::{
ClipRule, FillRule, Filter, MixBlendMode, Opacity, Overflow, PaintTarget, ShapeRendering,
@@ -981,88 +981,37 @@ impl DrawingCtx {
acquired_nodes: &mut AcquiredNodes<'_>,
opacity: UnitInterval,
) -> Result<bool, RenderingError> {
- // Work out the size of the rectangle so it takes into account the object bounding box
- let (bbwscale, bbhscale) = match pattern.units {
- PatternUnits(CoordUnits::ObjectBoundingBox) => pattern.bbox.rect.unwrap().size(),
- PatternUnits(CoordUnits::UserSpaceOnUse) => (1.0, 1.0),
- };
+ if approx_eq!(f64, pattern.width, 0.0) || approx_eq!(f64, pattern.height, 0.0) {
+ return Ok(false);
+ }
let taffine = self.get_transform().pre_transform(&pattern.transform);
let mut scwscale = (taffine.xx.powi(2) + taffine.xy.powi(2)).sqrt();
let mut schscale = (taffine.yx.powi(2) + taffine.yy.powi(2)).sqrt();
- let scaled_width = pattern.rect.width() * bbwscale;
- let scaled_height = pattern.rect.height() * bbhscale;
-
- if approx_eq!(f64, scaled_width, 0.0) || approx_eq!(f64, scaled_height, 0.0) {
- return Ok(false);
- }
-
- let pw: i32 = (scaled_width * scwscale) as i32;
- let ph: i32 = (scaled_height * schscale) as i32;
+ let pw: i32 = (pattern.width * scwscale) as i32;
+ let ph: i32 = (pattern.height * schscale) as i32;
if pw < 1 || ph < 1 {
return Ok(false);
}
- scwscale = f64::from(pw) / scaled_width;
- schscale = f64::from(ph) / scaled_height;
-
- // Create the pattern coordinate system
- let mut affine = match pattern.units {
- PatternUnits(CoordUnits::ObjectBoundingBox) => {
- let bbrect = pattern.bbox.rect.unwrap();
- Transform::new_translate(
- bbrect.x0 + pattern.rect.x0 * bbrect.width(),
- bbrect.y0 + pattern.rect.y0 * bbrect.height(),
- )
- }
-
- PatternUnits(CoordUnits::UserSpaceOnUse) => {
- Transform::new_translate(pattern.rect.x0, pattern.rect.y0)
- }
- };
+ scwscale = f64::from(pw) / pattern.width;
+ schscale = f64::from(ph) / pattern.height;
// Apply the pattern transform
- affine = affine.post_transform(&pattern.transform);
-
- let mut caffine: Transform;
-
- // Create the pattern contents coordinate system
- let _params = if let Some(vbox) = pattern.vbox {
- // If there is a vbox, use that
- let r = pattern
- .preserve_aspect_ratio
- .compute(&vbox, &Rect::from_size(scaled_width, scaled_height));
-
- let sw = r.width() / vbox.width();
- let sh = r.height() / vbox.height();
- let x = r.x0 - vbox.x0 * sw;
- let y = r.y0 - vbox.y0 * sh;
-
- caffine = Transform::new_scale(sw, sh).pre_translate(x, y);
-
- self.push_view_box(vbox.width(), vbox.height())
+ let (affine, caffine) = if scwscale.approx_eq_cairo(1.0) && schscale.approx_eq_cairo(1.0) {
+ (pattern.coord_transform, pattern.content_transform)
} else {
- let PatternContentUnits(content_units) = pattern.content_units;
-
- caffine = if content_units == CoordUnits::ObjectBoundingBox {
- // If coords are in terms of the bounding box, use them
- let (bbw, bbh) = pattern.bbox.rect.unwrap().size();
- Transform::new_scale(bbw, bbh)
- } else {
- Transform::identity()
- };
-
- self.push_coord_units(content_units)
+ (
+ pattern
+ .coord_transform
+ .pre_scale(1.0 / scwscale, 1.0 / schscale),
+ pattern.content_transform.post_scale(scwscale, schscale),
+ )
};
- if !scwscale.approx_eq_cairo(1.0) || !schscale.approx_eq_cairo(1.0) {
- caffine = caffine.post_scale(scwscale, schscale);
- affine = affine.pre_scale(1.0 / scwscale, 1.0 / schscale);
- }
-
// Draw to another surface
let cr_save = self.cr.clone();
diff --git a/src/pattern.rs b/src/pattern.rs
index 05d57783..83a0836e 100644
--- a/src/pattern.rs
+++ b/src/pattern.rs
@@ -7,7 +7,7 @@ use crate::aspect_ratio::*;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId, NodeStack};
-use crate::drawing_ctx::DrawingCtx;
+use crate::drawing_ctx::{DrawingCtx, ViewParams};
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
@@ -105,13 +105,11 @@ pub struct ResolvedPattern {
/// Pattern normalized to user-space units.
pub struct UserSpacePattern {
- pub units: PatternUnits,
- pub content_units: PatternContentUnits,
- pub bbox: BoundingBox,
- pub vbox: Option<ViewBox>,
- pub preserve_aspect_ratio: AspectRatio,
+ pub width: f64,
+ pub height: f64,
pub transform: Transform,
- pub rect: Rect,
+ pub coord_transform: Transform,
+ pub content_transform: Transform,
pub node_with_children: Node,
}
@@ -315,6 +313,15 @@ impl ResolvedPattern {
}
}
+ fn get_rect(&self, values: &ComputedValues, params: &ViewParams) -> Rect {
+ let x = self.x.normalize(&values, ¶ms);
+ let y = self.y.normalize(&values, ¶ms);
+ let w = self.width.normalize(&values, ¶ms);
+ let h = self.height.normalize(&values, ¶ms);
+
+ Rect::new(x, y, x + w, y + h)
+ }
+
pub fn to_user_space(
&self,
bbox: &BoundingBox,
@@ -325,25 +332,62 @@ impl ResolvedPattern {
let params = draw_ctx.push_coord_units(self.units.0);
- let x = self.x.normalize(&values, ¶ms);
- let y = self.y.normalize(&values, ¶ms);
- let w = self.width.normalize(&values, ¶ms);
- let h = self.height.normalize(&values, ¶ms);
+ let rect = self.get_rect(values, ¶ms);
+ let bbrect = bbox.rect.unwrap();
+
+ // Create the pattern coordinate system
+ let (width, height, coord_transform) = match self.units {
+ PatternUnits(CoordUnits::ObjectBoundingBox) => (
+ rect.width() * bbrect.width(),
+ rect.height() * bbrect.height(),
+ Transform::new_translate(
+ bbrect.x0 + rect.x0 * bbrect.width(),
+ bbrect.y0 + rect.y0 * bbrect.height(),
+ ),
+ ),
+ PatternUnits(CoordUnits::UserSpaceOnUse) => (
+ rect.width(),
+ rect.height(),
+ Transform::new_translate(rect.x0, rect.y0),
+ ),
+ };
+
+ let coord_transform = coord_transform.post_transform(&self.transform);
+
+ // Create the pattern contents coordinate system
+ let content_transform = if let Some(vbox) = self.vbox {
+ // If there is a vbox, use that
+ let r = self
+ .preserve_aspect_ratio
+ .compute(&vbox, &Rect::from_size(width, height));
+
+ let sw = r.width() / vbox.width();
+ let sh = r.height() / vbox.height();
+ let x = r.x0 - vbox.x0 * sw;
+ let y = r.y0 - vbox.y0 * sh;
+
+ let _params = draw_ctx.push_view_box(vbox.width(), vbox.height());
- let rect = Rect::new(x, y, x + w, y + h);
+ Transform::new_scale(sw, sh).pre_translate(x, y)
+ } else {
+ let PatternContentUnits(content_units) = self.content_units;
+
+ let _params = draw_ctx.push_coord_units(content_units);
- // FIXME: eventually UserSpacePattern should contain fewer fields; we should be able
- // to figure out all the transforms in advance and just put them there, rather than
- // leaving that responsibility to DrawingCtx.set_pattern().
+ match content_units {
+ CoordUnits::ObjectBoundingBox => {
+ Transform::new_scale(bbrect.width(), bbrect.height())
+ }
+ CoordUnits::UserSpaceOnUse => Transform::identity(),
+ }
+ };
Some(UserSpacePattern {
- units: self.units,
- content_units: self.content_units,
- vbox: self.vbox,
- bbox: *bbox,
- preserve_aspect_ratio: self.preserve_aspect_ratio,
+ width,
+ height,
transform: self.transform,
- rect,
+ coord_transform,
+ content_transform,
node_with_children,
})
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]