[librsvg: 13/15] fe*Lighting - Separate steps for extracting the light source from nodes, and transforming it
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 13/15] fe*Lighting - Separate steps for extracting the light source from nodes, and transforming it
- Date: Tue, 9 Mar 2021 20:51:37 +0000 (UTC)
commit 88cfbf7a816535f3f47a39a63ad3d2f4075e3561
Author: Federico Mena Quintero <federico gnome org>
Date: Tue Mar 9 13:27:40 2021 -0600
fe*Lighting - Separate steps for extracting the light source from nodes, and transforming it
src/filters/lighting.rs | 54 +++++++++++++++++++++++++++++++++++++------------
1 file changed, 41 insertions(+), 13 deletions(-)
---
diff --git a/src/filters/lighting.rs b/src/filters/lighting.rs
index 36466d85..7bcdb4e4 100644
--- a/src/filters/lighting.rs
+++ b/src/filters/lighting.rs
@@ -26,6 +26,13 @@ use crate::transform::Transform;
use crate::util::clamp;
use crate::xml::Attributes;
+/// A light source before applying affine transformations, straight out of the SVG.
+enum UntransformedLightSource {
+ Distant(FeDistantLight),
+ Point(FePointLight),
+ Spot(FeSpotLight),
+}
+
/// A light source with affine transformations applied.
pub enum LightSource {
Distant {
@@ -43,14 +50,24 @@ pub enum LightSource {
},
}
+impl UntransformedLightSource {
+ fn transform(&self, paffine: Transform) -> LightSource {
+ match *self {
+ UntransformedLightSource::Distant(ref l) => l.transform(),
+ UntransformedLightSource::Point(ref l) => l.transform(paffine),
+ UntransformedLightSource::Spot(ref l) => l.transform(paffine),
+ }
+ }
+}
+
struct Light {
- source: LightSource,
+ source: UntransformedLightSource,
lighting_color: cssparser::RGBA,
color_interpolation_filters: ColorInterpolationFilters,
}
impl Light {
- pub fn new(node: &Node, paffine: Transform) -> Result<Light, FilterError> {
+ pub fn new(node: &Node) -> Result<Light, FilterError> {
let mut sources = node.children().rev().filter(|c| {
c.is_element()
&& matches!(
@@ -72,9 +89,11 @@ impl Light {
}
let source = match *elt {
- Element::FeDistantLight(ref l) => l.transform(),
- Element::FePointLight(ref l) => l.transform(paffine),
- Element::FeSpotLight(ref l) => l.transform(paffine),
+ Element::FeDistantLight(ref l) => {
+ UntransformedLightSource::Distant(l.element_impl.clone())
+ }
+ Element::FePointLight(ref l) => UntransformedLightSource::Point(l.element_impl.clone()),
+ Element::FeSpotLight(ref l) => UntransformedLightSource::Spot(l.element_impl.clone()),
_ => unreachable!(),
};
@@ -95,8 +114,14 @@ impl Light {
/// Returns the color and unit (or null) vector from the image sample to the light.
#[inline]
- pub fn color_and_vector(&self, x: f64, y: f64, z: f64) -> (cssparser::RGBA, Vector3<f64>) {
- let vector = match self.source {
+ pub fn color_and_vector(
+ &self,
+ source: &LightSource,
+ x: f64,
+ y: f64,
+ z: f64,
+ ) -> (cssparser::RGBA, Vector3<f64>) {
+ let vector = match *source {
LightSource::Distant { azimuth, elevation } => {
let azimuth = azimuth.to_radians();
let elevation = elevation.to_radians();
@@ -113,7 +138,7 @@ impl Light {
}
};
- let color = match self.source {
+ let color = match *source {
LightSource::Spot {
direction,
specular_exponent,
@@ -146,7 +171,7 @@ impl Light {
}
}
-#[derive(Default)]
+#[derive(Clone, Default)]
pub struct FeDistantLight {
azimuth: f64,
elevation: f64,
@@ -177,7 +202,7 @@ impl SetAttributes for FeDistantLight {
impl Draw for FeDistantLight {}
-#[derive(Default)]
+#[derive(Clone, Default)]
pub struct FePointLight {
x: f64,
y: f64,
@@ -212,7 +237,7 @@ impl SetAttributes for FePointLight {
impl Draw for FePointLight {}
-#[derive(Default)]
+#[derive(Clone, Default)]
pub struct FeSpotLight {
x: f64,
y: f64,
@@ -464,7 +489,9 @@ macro_rules! impl_lighting_filter {
let (ox, oy) = scale.unwrap_or((1.0, 1.0));
- let light = Light::new(node, ctx.paffine())?;
+ 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.
@@ -489,7 +516,8 @@ macro_rules! impl_lighting_filter {
let scaled_y = f64::from(y) * oy;
let z = f64::from(pixel.a) / 255.0 * self.surface_scale;
- let (color, vector) = light.color_and_vector(scaled_x, scaled_y, z);
+ let (color, vector) =
+ light.color_and_vector(&source, scaled_x, scaled_y, z);
// compute the factor just once for the three colors
let factor = self.compute_factor(normal, vector);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]