Fix kernelUnitLength handling

parent 25bc1bbb
......@@ -253,6 +253,9 @@ impl Filter for ConvolveMatrix {
.scale(bounds, 1.0 / ox, 1.0 / oy)
.map_err(FilterError::IntermediateSurfaceCreation)?;
let new_surface = SharedImageSurface::new(new_surface)
.map_err(FilterError::BadIntermediateSurfaceStatus)?;
input_surface = new_surface;
bounds = new_bounds;
}
......@@ -338,15 +341,19 @@ impl Filter for ConvolveMatrix {
if let Some((ox, oy)) = scale {
// Scale the output surface back.
output_surface = output_surface
.scale_to(
ctx.source_graphic().width(),
ctx.source_graphic().height(),
original_bounds,
ox,
oy,
)
.map_err(FilterError::IntermediateSurfaceCreation)?;
output_surface = SharedImageSurface::new(
output_surface
.scale_to(
ctx.source_graphic().width(),
ctx.source_graphic().height(),
original_bounds,
ox,
oy,
)
.map_err(FilterError::IntermediateSurfaceCreation)?,
).map_err(FilterError::BadIntermediateSurfaceStatus)?;
bounds = original_bounds;
}
Ok(FilterResult {
......
......@@ -151,10 +151,15 @@ impl Filter for DiffuseLighting {
.scale(bounds, 1.0 / ox, 1.0 / oy)
.map_err(FilterError::IntermediateSurfaceCreation)?;
let new_surface = SharedImageSurface::new(new_surface)
.map_err(FilterError::BadIntermediateSurfaceStatus)?;
input_surface = new_surface;
bounds = new_bounds;
}
let (ox, oy) = scale.unwrap_or((1.0, 1.0));
let mut output_surface = ImageSurface::create(
cairo::Format::ARgb32,
input_surface.width(),
......@@ -165,9 +170,14 @@ impl Filter for DiffuseLighting {
{
let mut output_data = output_surface.get_data().unwrap();
for (x, y, _pixel) in Pixels::new(&input_surface, bounds) {
for (x, y, pixel) in Pixels::new(&input_surface, bounds) {
let normal = normal(&input_surface, bounds, x, y, surface_scale);
let light_vector = light_source.vector(&input_surface, x, y, surface_scale, ctx);
let scaled_x = f64::from(x) * ox;
let scaled_y = f64::from(y) * oy;
let z = f64::from(pixel.a) / 255.0 * surface_scale;
let light_vector = light_source.vector(scaled_x, scaled_y, z, ctx);
let light_color = light_source.color(lighting_color, &light_vector, ctx);
let n_dot_l = normal.dot(&light_vector);
......@@ -189,15 +199,19 @@ impl Filter for DiffuseLighting {
if let Some((ox, oy)) = scale {
// Scale the output surface back.
output_surface = output_surface
.scale_to(
ctx.source_graphic().width(),
ctx.source_graphic().height(),
original_bounds,
ox,
oy,
)
.map_err(FilterError::IntermediateSurfaceCreation)?;
output_surface = SharedImageSurface::new(
output_surface
.scale_to(
ctx.source_graphic().width(),
ctx.source_graphic().height(),
original_bounds,
ox,
oy,
)
.map_err(FilterError::IntermediateSurfaceCreation)?,
).map_err(FilterError::BadIntermediateSurfaceStatus)?;
bounds = original_bounds;
}
Ok(FilterResult {
......
......@@ -11,7 +11,6 @@ use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers;
use property_bag::PropertyBag;
use surface_utils::shared_surface::SharedImageSurface;
use util::clamp;
/// A light source node (`feDistantLight`, `fePointLight` or `feSpotLight`).
......@@ -74,14 +73,7 @@ impl LightSource {
/// Returns the unit (or null) vector from the image sample to the light.
#[inline]
pub fn vector(
&self,
surface: &SharedImageSurface,
x: u32,
y: u32,
surface_scale: f64,
ctx: &FilterContext,
) -> Vector<f64> {
pub fn vector(&self, x: f64, y: f64, z: f64, ctx: &FilterContext) -> Vector<f64> {
match self {
LightSource::Distant { azimuth, elevation } => {
let azimuth = azimuth.get().to_radians();
......@@ -103,17 +95,11 @@ impl LightSource {
z: light_z,
..
} => {
let (light_x_, light_y_) =
let (light_x, light_y) =
ctx.paffine().transform_point(light_x.get(), light_y.get());
let light_z_ = ctx.transform_dist(light_z.get());
let z = f64::from(surface.get_pixel(x, y).a) / 255.0;
let light_z = ctx.transform_dist(light_z.get());
let mut v = vector![
light_x_ - f64::from(x),
light_y_ - f64::from(y),
light_z_ - z * surface_scale
];
let mut v = vector![light_x - x, light_y - y, light_z - z];
let _ = normalize(&mut v);
v
}
......
......@@ -169,10 +169,15 @@ impl Filter for SpecularLighting {
.scale(bounds, 1.0 / ox, 1.0 / oy)
.map_err(FilterError::IntermediateSurfaceCreation)?;
let new_surface = SharedImageSurface::new(new_surface)
.map_err(FilterError::BadIntermediateSurfaceStatus)?;
input_surface = new_surface;
bounds = new_bounds;
}
let (ox, oy) = scale.unwrap_or((1.0, 1.0));
let mut output_surface = ImageSurface::create(
cairo::Format::ARgb32,
input_surface.width(),
......@@ -183,9 +188,14 @@ impl Filter for SpecularLighting {
{
let mut output_data = output_surface.get_data().unwrap();
for (x, y, _pixel) in Pixels::new(&input_surface, bounds) {
for (x, y, pixel) in Pixels::new(&input_surface, bounds) {
let normal = normal(&input_surface, bounds, x, y, surface_scale);
let light_vector = light_source.vector(&input_surface, x, y, surface_scale, ctx);
let scaled_x = f64::from(x) / ox;
let scaled_y = f64::from(y) / oy;
let z = f64::from(pixel.a) / 255.0 * surface_scale;
let light_vector = light_source.vector(scaled_x, scaled_y, z, ctx);
let light_color = light_source.color(lighting_color, &light_vector, ctx);
let mut h = light_vector + vector![0.0, 0.0, 1.0];
......@@ -211,15 +221,19 @@ impl Filter for SpecularLighting {
if let Some((ox, oy)) = scale {
// Scale the output surface back.
output_surface = output_surface
.scale_to(
ctx.source_graphic().width(),
ctx.source_graphic().height(),
original_bounds,
ox,
oy,
)
.map_err(FilterError::IntermediateSurfaceCreation)?;
output_surface = SharedImageSurface::new(
output_surface
.scale_to(
ctx.source_graphic().width(),
ctx.source_graphic().height(),
original_bounds,
ox,
oy,
)
.map_err(FilterError::IntermediateSurfaceCreation)?,
).map_err(FilterError::BadIntermediateSurfaceStatus)?;
bounds = original_bounds;
}
Ok(FilterResult {
......
......@@ -163,7 +163,7 @@ impl SharedImageSurface {
bounds: IRect,
x: f64,
y: f64,
) -> Result<SharedImageSurface, cairo::Status> {
) -> Result<ImageSurface, cairo::Status> {
let output_surface = ImageSurface::create(cairo::Format::ARgb32, width, height)?;
{
......@@ -181,7 +181,7 @@ impl SharedImageSurface {
cr.paint();
}
Ok(SharedImageSurface::new(output_surface)?)
Ok(output_surface)
}
/// Returns a scaled version of a surface and bounds.
......@@ -191,9 +191,9 @@ impl SharedImageSurface {
bounds: IRect,
x: f64,
y: f64,
) -> Result<(SharedImageSurface, IRect), cairo::Status> {
) -> Result<(ImageSurface, IRect), cairo::Status> {
let new_width = (f64::from(self.width) * x).ceil() as i32;
let new_height = (f64::from(self.height) * x).ceil() as i32;
let new_height = (f64::from(self.height) * y).ceil() as i32;
let new_bounds = bounds.scale(x, y);
Ok((
......
<svg id="svg-root" width="100%" height="100%"
viewBox="0 0 480 360" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- The test checks that kernelUnitLength is handled properly by filters which support it. -->
<filter id="convolve-matrix">
<feConvolveMatrix kernelUnitLength="2 1" x="0" y="0" width="25" height="25" edgeMode="wrap" order="5" targetX="0" targetY="0" kernelMatrix="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"/>
</filter>
<filter id="pointLightA" filterUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<feDiffuseLighting kernelUnitLength="2" in="SourceGraphic" diffuseConstant="1" surfaceScale="10" lighting-color="white">
<fePointLight x="0" y="0" z="10"/>
</feDiffuseLighting>
</filter>
<filter id="spotLightD" filterUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<feDiffuseLighting kernelUnitLength="0.25" in="SourceGraphic" diffuseConstant="1" surfaceScale="10" lighting-color="white">
<feSpotLight x="25" y="0" z="35" pointsAtX="25" pointsAtY="30" pointsAtZ="0" specularExponent="0" limitingConeAngle="30"/>
</feDiffuseLighting>
</filter>
<g transform="translate(30 20)" filter="url(#convolve-matrix)">
<rect fill="red" x="1" y="1" width="50" height="50"/>
<rect fill="green" x="6" y="6" width="40" height="40"/>
</g>
<g transform="translate(30 60)">
<image xlink:href="svg1.1/images/bumpMap2.png" width="50" height="30" filter="url(#pointLightA)"/>
<rect transform="translate(70, 0)" width="50" height="30" filter="url(#spotLightD)"/>
</g>
</svg>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment