[librsvg: 3/11] Normalize gradients before setting them on the cr
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 3/11] Normalize gradients before setting them on the cr
- Date: Tue, 1 Dec 2020 18:24:44 +0000 (UTC)
commit 068aa558f0b2eab3e45bfe2b858169a0de533389
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Nov 30 21:01:47 2020 -0600
Normalize gradients before setting them on the cr
This introduces a Gradient struct again, which is in user-space
units. It gets constructed from ResolvedGradient.to_user_space().
src/drawing_ctx.rs | 61 ++++++++-------------------------------
src/gradient.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 49 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 9fe4175d..19e2dc6d 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -20,7 +20,7 @@ use crate::error::{AcquireError, RenderingError};
use crate::filter::FilterValue;
use crate::filters;
use crate::float_eq_cairo::ApproxEqCairo;
-use crate::gradient::{GradientUnits, ResolvedGradient, ResolvedGradientVariant, SpreadMethod};
+use crate::gradient::{Gradient, GradientVariant, SpreadMethod};
use crate::marker;
use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
use crate::paint_server::{PaintServer, PaintSource};
@@ -933,62 +933,26 @@ impl DrawingCtx {
Ok(child_surface)
}
- fn set_gradient(
- self: &mut DrawingCtx,
- gradient: &ResolvedGradient,
- _acquired_nodes: &mut AcquiredNodes<'_>,
- opacity: UnitInterval,
- values: &ComputedValues,
- bbox: &BoundingBox,
- ) -> Result<bool, RenderingError> {
- let GradientUnits(units) = gradient.get_units();
- let transform = if let Ok(t) = bbox.rect_to_transform(units) {
- t
- } else {
- return Ok(false);
- };
-
- let params = self.push_coord_units(units);
-
- let g = match gradient.get_variant() {
- ResolvedGradientVariant::Linear { x1, y1, x2, y2 } => {
- cairo::Gradient::clone(&cairo::LinearGradient::new(
- x1.normalize(values, ¶ms),
- y1.normalize(values, ¶ms),
- x2.normalize(values, ¶ms),
- y2.normalize(values, ¶ms),
- ))
+ fn set_gradient(self: &mut DrawingCtx, gradient: &Gradient, opacity: UnitInterval) {
+ let g = match gradient.variant {
+ GradientVariant::Linear { x1, y1, x2, y2 } => {
+ cairo::Gradient::clone(&cairo::LinearGradient::new(x1, y1, x2, y2))
}
- ResolvedGradientVariant::Radial {
+ GradientVariant::Radial {
cx,
cy,
r,
fx,
fy,
fr,
- } => {
- let n_cx = cx.normalize(values, ¶ms);
- let n_cy = cy.normalize(values, ¶ms);
- let n_r = r.normalize(values, ¶ms);
- let n_fx = fx.normalize(values, ¶ms);
- let n_fy = fy.normalize(values, ¶ms);
- let n_fr = fr.normalize(values, ¶ms);
-
- cairo::Gradient::clone(&cairo::RadialGradient::new(
- n_fx, n_fy, n_fr, n_cx, n_cy, n_r,
- ))
- }
+ } => cairo::Gradient::clone(&cairo::RadialGradient::new(fx, fy, fr, cx, cy, r)),
};
- let transform = transform.pre_transform(&gradient.get_transform());
- if let Some(m) = transform.invert() {
- g.set_matrix(m.into())
- }
+ g.set_matrix(gradient.transform.into());
+ g.set_extend(cairo::Extend::from(gradient.spread));
- g.set_extend(cairo::Extend::from(gradient.get_spread()));
-
- for stop in gradient.get_stops() {
+ for stop in &gradient.stops {
let UnitInterval(stop_offset) = stop.offset;
let UnitInterval(o) = opacity;
let UnitInterval(stop_opacity) = stop.opacity;
@@ -1004,8 +968,6 @@ impl DrawingCtx {
let cr = self.cr.clone();
cr.set_source(&g);
-
- Ok(true)
}
fn set_pattern(
@@ -1193,7 +1155,8 @@ impl DrawingCtx {
match paint_source {
PaintSource::Gradient(g, c) => {
- if self.set_gradient(&g, acquired_nodes, opacity, values, bbox)? {
+ if let Some(gradient) = g.to_user_space(bbox, self, values) {
+ self.set_gradient(&gradient, opacity);
Ok(true)
} else if let Some(c) = c {
self.set_color(c, opacity, current_color)
diff --git a/src/gradient.rs b/src/gradient.rs
index e0f28931..3cbca442 100644
--- a/src/gradient.rs
+++ b/src/gradient.rs
@@ -7,14 +7,17 @@ use markup5ever::{
use std::cell::RefCell;
use crate::attributes::Attributes;
+use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeStack};
+use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::{Parse, ParseValue};
+use crate::properties::ComputedValues;
use crate::property_defs::StopColor;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;
@@ -139,6 +142,25 @@ pub enum ResolvedGradientVariant {
},
}
+/// Parameters specific to each gradient type, after normalizing to user-space units.
+pub enum GradientVariant {
+ Linear {
+ x1: f64,
+ y1: f64,
+ x2: f64,
+ y2: f64,
+ },
+
+ Radial {
+ cx: f64,
+ cy: f64,
+ r: f64,
+ fx: f64,
+ fy: f64,
+ fr: f64,
+ },
+}
+
impl UnresolvedVariant {
fn into_resolved(self) -> ResolvedGradientVariant {
assert!(self.is_resolved());
@@ -341,6 +363,15 @@ pub struct ResolvedGradient {
variant: ResolvedGradientVariant,
}
+/// Gradient normalized to user-space units.
+pub struct Gradient {
+ pub transform: Transform,
+ pub spread: SpreadMethod,
+ pub stops: Vec<ColorStop>,
+
+ pub variant: GradientVariant,
+}
+
impl UnresolvedGradient {
fn into_resolved(self) -> ResolvedGradient {
assert!(self.is_resolved());
@@ -683,6 +714,60 @@ impl ResolvedGradient {
pub fn get_variant(&self) -> &ResolvedGradientVariant {
&self.variant
}
+
+ pub fn to_user_space(
+ &self,
+ bbox: &BoundingBox,
+ draw_ctx: &DrawingCtx,
+ values: &ComputedValues,
+ ) -> Option<Gradient> {
+ let units = self.units.0;
+ let transform = if let Ok(t) = bbox.rect_to_transform(units) {
+ t
+ } else {
+ return None;
+ };
+
+ let params = draw_ctx.push_coord_units(units);
+
+ let transform = if let Some(m) = transform.pre_transform(&self.transform).invert() {
+ m
+ } else {
+ return None;
+ };
+
+ let variant = match self.variant {
+ ResolvedGradientVariant::Linear { x1, y1, x2, y2 } => GradientVariant::Linear {
+ x1: x1.normalize(values, ¶ms),
+ y1: y1.normalize(values, ¶ms),
+ x2: x2.normalize(values, ¶ms),
+ y2: y2.normalize(values, ¶ms),
+ },
+
+ ResolvedGradientVariant::Radial {
+ cx,
+ cy,
+ r,
+ fx,
+ fy,
+ fr,
+ } => GradientVariant::Radial {
+ cx: cx.normalize(values, ¶ms),
+ cy: cy.normalize(values, ¶ms),
+ r: r.normalize(values, ¶ms),
+ fx: fx.normalize(values, ¶ms),
+ fy: fy.normalize(values, ¶ms),
+ fr: fr.normalize(values, ¶ms),
+ },
+ };
+
+ Some(Gradient {
+ transform,
+ spread: self.spread,
+ stops: self.stops.clone(),
+ variant,
+ })
+ }
}
#[cfg(test)]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]