diff --git a/core/src/image.rs b/core/src/image.rs index 267bb0ee..65342dae 100644 --- a/core/src/image.rs +++ b/core/src/image.rs @@ -16,22 +16,17 @@ pub struct Image { /// The handle of the image. pub handle: H, - /// The clip bounds of the [`Image`]. - /// - /// Anything outside this [`Rectangle`] will not be drawn. - pub clip_bounds: Rectangle, - - /// The border radius of the [`Image`]. - /// - /// Currently, this will only be applied to the `clip_bounds`. - pub border_radius: border::Radius, - /// The filter method of the image. pub filter_method: FilterMethod, /// The rotation to be applied to the image; on its center. pub rotation: Radians, + /// The border radius of the [`Image`]. + /// + /// Currently, this will only be applied to the `clip_bounds`. + pub border_radius: border::Radius, + /// The opacity of the image. /// /// 0 means transparent. 1 means opaque. @@ -49,10 +44,9 @@ impl Image { pub fn new(handle: impl Into) -> Self { Self { handle: handle.into(), - clip_bounds: Rectangle::INFINITE, - border_radius: border::Radius::default(), filter_method: FilterMethod::default(), rotation: Radians(0.0), + border_radius: border::Radius::default(), opacity: 1.0, snap: false, } @@ -307,5 +301,10 @@ pub trait Renderer: crate::Renderer { fn measure_image(&self, handle: &Self::Handle) -> Size; /// Draws an [`Image`] inside the provided `bounds`. - fn draw_image(&mut self, image: Image, bounds: Rectangle); + fn draw_image( + &mut self, + image: Image, + bounds: Rectangle, + clip_bounds: Rectangle, + ); } diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs index 8b3fbb0c..87b6ed19 100644 --- a/core/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -217,7 +217,13 @@ impl image::Renderer for () { Size::default() } - fn draw_image(&mut self, _image: Image, _bounds: Rectangle) {} + fn draw_image( + &mut self, + _image: Image, + _bounds: Rectangle, + _clip_bounds: Rectangle, + ) { + } } impl svg::Renderer for () { @@ -225,5 +231,11 @@ impl svg::Renderer for () { Size::default() } - fn draw_svg(&mut self, _svg: svg::Svg, _bounds: Rectangle) {} + fn draw_svg( + &mut self, + _svg: svg::Svg, + _bounds: Rectangle, + _clip_bounds: Rectangle, + ) { + } } diff --git a/core/src/svg.rs b/core/src/svg.rs index ac19b223..4a25b7e7 100644 --- a/core/src/svg.rs +++ b/core/src/svg.rs @@ -155,5 +155,5 @@ pub trait Renderer: crate::Renderer { fn measure_svg(&self, handle: &Handle) -> Size; /// Draws an SVG with the given [`Handle`], an optional [`Color`] filter, and inside the provided `bounds`. - fn draw_svg(&mut self, svg: Svg, bounds: Rectangle); + fn draw_svg(&mut self, svg: Svg, bounds: Rectangle, clip_bounds: Rectangle); } diff --git a/graphics/src/image.rs b/graphics/src/image.rs index 171edd80..6f74b721 100644 --- a/graphics/src/image.rs +++ b/graphics/src/image.rs @@ -7,21 +7,32 @@ use crate::core::image; use crate::core::svg; /// A raster or vector image. +#[allow(missing_docs)] #[derive(Debug, Clone, PartialEq)] pub enum Image { /// A raster image. - Raster(image::Image, Rectangle), + Raster { + image: image::Image, + bounds: Rectangle, + clip_bounds: Rectangle, + }, /// A vector image. - Vector(svg::Svg, Rectangle), + Vector { + svg: svg::Svg, + bounds: Rectangle, + clip_bounds: Rectangle, + }, } impl Image { /// Returns the bounds of the [`Image`]. pub fn bounds(&self) -> Rectangle { match self { - Image::Raster(image, bounds) => bounds.rotate(image.rotation), - Image::Vector(svg, bounds) => bounds.rotate(svg.rotation), + Image::Raster { image, bounds, .. } => { + bounds.rotate(image.rotation) + } + Image::Vector { svg, bounds, .. } => bounds.rotate(svg.rotation), } } } diff --git a/renderer/src/fallback.rs b/renderer/src/fallback.rs index 9f2d3c09..01e49390 100644 --- a/renderer/src/fallback.rs +++ b/renderer/src/fallback.rs @@ -158,8 +158,17 @@ where delegate!(self, renderer, renderer.measure_image(handle)) } - fn draw_image(&mut self, image: Image, bounds: Rectangle) { - delegate!(self, renderer, renderer.draw_image(image, bounds)); + fn draw_image( + &mut self, + image: Image, + bounds: Rectangle, + clip_bounds: Rectangle, + ) { + delegate!( + self, + renderer, + renderer.draw_image(image, bounds, clip_bounds) + ); } } @@ -172,8 +181,13 @@ where delegate!(self, renderer, renderer.measure_svg(handle)) } - fn draw_svg(&mut self, svg: Svg, bounds: Rectangle) { - delegate!(self, renderer, renderer.draw_svg(svg, bounds)); + fn draw_svg( + &mut self, + svg: Svg, + bounds: Rectangle, + clip_bounds: Rectangle, + ) { + delegate!(self, renderer, renderer.draw_svg(svg, bounds, clip_bounds)); } } diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index 2b829b0f..69423361 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -550,7 +550,7 @@ impl Engine { ) { match image { #[cfg(feature = "image")] - Image::Raster(raster, bounds) => { + Image::Raster { image, bounds, .. } => { let physical_bounds = *bounds * _transformation; if !_clip_bounds.intersects(&physical_bounds) { @@ -561,7 +561,7 @@ impl Engine { .then_some(_clip_mask as &_); let center = physical_bounds.center(); - let radians = f32::from(raster.rotation); + let radians = f32::from(image.rotation); let transform = into_transform(_transformation).post_rotate_at( radians.to_degrees(), @@ -570,17 +570,17 @@ impl Engine { ); self.raster_pipeline.draw( - &raster.handle, - raster.filter_method, + &image.handle, + image.filter_method, *bounds, - raster.opacity, + image.opacity, _pixels, transform, clip_mask, ); } #[cfg(feature = "svg")] - Image::Vector(svg, bounds) => { + Image::Vector { svg, bounds, .. } => { let physical_bounds = *bounds * _transformation; if !_clip_bounds.intersects(&physical_bounds) { diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index a1c0d8a6..a45d9522 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -307,7 +307,11 @@ impl geometry::frame::Backend for Frame { image.rotation += external_rotation; - self.images.push(graphics::Image::Raster(image, bounds)); + self.images.push(graphics::Image::Raster { + image, + bounds, + clip_bounds: self.clip_bounds, + }); } fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into) { @@ -318,7 +322,11 @@ impl geometry::frame::Backend for Frame { svg.rotation += external_rotation; - self.images.push(Image::Vector(svg, bounds)); + self.images.push(Image::Vector { + svg, + bounds, + clip_bounds: self.clip_bounds, + }); } } diff --git a/tiny_skia/src/layer.rs b/tiny_skia/src/layer.rs index 37be9c68..951f4b14 100644 --- a/tiny_skia/src/layer.rs +++ b/tiny_skia/src/layer.rs @@ -117,11 +117,19 @@ impl Layer { pub fn draw_image(&mut self, image: Image, transformation: Transformation) { match image { - Image::Raster(raster, bounds) => { - self.draw_raster(raster, bounds, transformation); + Image::Raster { + image, + bounds, + clip_bounds, + } => { + self.draw_raster(image, bounds, clip_bounds, transformation); } - Image::Vector(svg, bounds) => { - self.draw_svg(svg, bounds, transformation); + Image::Vector { + svg, + bounds, + clip_bounds, + } => { + self.draw_svg(svg, bounds, clip_bounds, transformation); } } } @@ -130,17 +138,18 @@ impl Layer { &mut self, image: core::Image, bounds: Rectangle, + clip_bounds: Rectangle, transformation: Transformation, ) { - let image = Image::Raster( - core::Image { - clip_bounds: image.clip_bounds * transformation, + let image = Image::Raster { + image: core::Image { border_radius: image.border_radius * transformation.scale_factor(), ..image }, - bounds * transformation, - ); + bounds: bounds * transformation, + clip_bounds: clip_bounds * transformation, + }; self.images.push(image); } @@ -149,9 +158,14 @@ impl Layer { &mut self, svg: Svg, bounds: Rectangle, + clip_bounds: Rectangle, transformation: Transformation, ) { - let svg = Image::Vector(svg, bounds * transformation); + let svg = Image::Vector { + svg, + bounds: bounds * transformation, + clip_bounds: clip_bounds * transformation, + }; self.images.push(svg); } diff --git a/tiny_skia/src/lib.rs b/tiny_skia/src/lib.rs index fe24078b..159f8155 100644 --- a/tiny_skia/src/lib.rs +++ b/tiny_skia/src/lib.rs @@ -364,9 +364,14 @@ impl core::image::Renderer for Renderer { self.engine.raster_pipeline.dimensions(handle) } - fn draw_image(&mut self, image: core::Image, bounds: Rectangle) { + fn draw_image( + &mut self, + image: core::Image, + bounds: Rectangle, + clip_bounds: Rectangle, + ) { let (layer, transformation) = self.layers.current_mut(); - layer.draw_raster(image, bounds, transformation); + layer.draw_raster(image, bounds, clip_bounds, transformation); } } @@ -379,9 +384,14 @@ impl core::svg::Renderer for Renderer { self.engine.vector_pipeline.viewport_dimensions(handle) } - fn draw_svg(&mut self, svg: core::Svg, bounds: Rectangle) { + fn draw_svg( + &mut self, + svg: core::Svg, + bounds: Rectangle, + clip_bounds: Rectangle, + ) { let (layer, transformation) = self.layers.current_mut(); - layer.draw_svg(svg, bounds, transformation); + layer.draw_svg(svg, bounds, clip_bounds, transformation); } } diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 872d9fe1..f82adedb 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -431,8 +431,14 @@ impl geometry::frame::Backend for Frame { self.transforms.current.transform_rectangle(bounds); image.rotation += external_rotation; + image.border_radius = + image.border_radius * self.transforms.current.scale().0; - self.images.push(Image::Raster(image, bounds)); + self.images.push(Image::Raster { + image, + bounds, + clip_bounds: self.clip_bounds, + }); } fn draw_svg(&mut self, bounds: Rectangle, svg: impl Into) { @@ -443,7 +449,11 @@ impl geometry::frame::Backend for Frame { svg.rotation += external_rotation; - self.images.push(Image::Vector(svg, bounds)); + self.images.push(Image::Vector { + svg, + bounds, + clip_bounds: self.clip_bounds, + }); } } diff --git a/wgpu/src/image/mod.rs b/wgpu/src/image/mod.rs index 21164741..ba98f443 100644 --- a/wgpu/src/image/mod.rs +++ b/wgpu/src/image/mod.rs @@ -261,7 +261,11 @@ impl State { for image in images { match &image { #[cfg(feature = "image")] - Image::Raster(image, bounds) => { + Image::Raster { + image, + bounds, + clip_bounds, + } => { if let Some((atlas_entry, bind_group)) = cache .upload_raster(device, encoder, belt, &image.handle) { @@ -283,7 +287,7 @@ impl State { add_instances( *bounds, - image.clip_bounds, + *clip_bounds, image.border_radius, f32::from(image.rotation), image.opacity, @@ -304,7 +308,11 @@ impl State { Image::Raster { .. } => continue, #[cfg(feature = "svg")] - Image::Vector(svg, bounds) => { + Image::Vector { + svg, + bounds, + clip_bounds, + } => { if let Some((atlas_entry, bind_group)) = cache .upload_vector( device, @@ -334,7 +342,7 @@ impl State { add_instances( *bounds, - Rectangle::INFINITE, + *clip_bounds, border::radius(0), f32::from(svg.rotation), svg.opacity, diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index cfa634a4..f7ee2a3a 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -128,11 +128,19 @@ impl Layer { pub fn draw_image(&mut self, image: Image, transformation: Transformation) { match image { - Image::Raster(image, bounds) => { - self.draw_raster(image, bounds, transformation); + Image::Raster { + image, + bounds, + clip_bounds, + } => { + self.draw_raster(image, bounds, clip_bounds, transformation); } - Image::Vector(svg, bounds) => { - self.draw_svg(svg, bounds, transformation); + Image::Vector { + svg, + bounds, + clip_bounds, + } => { + self.draw_svg(svg, bounds, clip_bounds, transformation); } } } @@ -141,17 +149,18 @@ impl Layer { &mut self, image: core::Image, bounds: Rectangle, + clip_bounds: Rectangle, transformation: Transformation, ) { - let image = Image::Raster( - core::Image { - clip_bounds: image.clip_bounds * transformation, + let image = Image::Raster { + image: core::Image { border_radius: image.border_radius * transformation.scale_factor(), ..image }, - bounds * transformation, - ); + bounds: bounds * transformation, + clip_bounds: clip_bounds * transformation, + }; self.images.push(image); } @@ -160,9 +169,14 @@ impl Layer { &mut self, svg: Svg, bounds: Rectangle, + clip_bounds: Rectangle, transformation: Transformation, ) { - let svg = Image::Vector(svg, bounds * transformation); + let svg = Image::Vector { + svg, + bounds: bounds * transformation, + clip_bounds: clip_bounds * transformation, + }; self.images.push(svg); } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index f78998bb..e0a7e969 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -777,9 +777,14 @@ impl core::image::Renderer for Renderer { self.image_cache.borrow_mut().measure_image(handle) } - fn draw_image(&mut self, image: core::Image, bounds: Rectangle) { + fn draw_image( + &mut self, + image: core::Image, + bounds: Rectangle, + clip_bounds: Rectangle, + ) { let (layer, transformation) = self.layers.current_mut(); - layer.draw_raster(image, bounds, transformation); + layer.draw_raster(image, bounds, clip_bounds, transformation); } } @@ -789,9 +794,14 @@ impl core::svg::Renderer for Renderer { self.image_cache.borrow_mut().measure_svg(handle) } - fn draw_svg(&mut self, svg: core::Svg, bounds: Rectangle) { + fn draw_svg( + &mut self, + svg: core::Svg, + bounds: Rectangle, + clip_bounds: Rectangle, + ) { let (layer, transformation) = self.layers.current_mut(); - layer.draw_svg(svg, bounds, transformation); + layer.draw_svg(svg, bounds, clip_bounds, transformation); } } diff --git a/widget/src/image.rs b/widget/src/image.rs index 709915aa..e40c9b6d 100644 --- a/widget/src/image.rs +++ b/widget/src/image.rs @@ -337,7 +337,6 @@ pub fn draw( renderer.draw_image( image::Image { handle: handle.clone(), - clip_bounds: bounds, border_radius, filter_method, rotation: rotation.radians(), @@ -345,6 +344,7 @@ pub fn draw( snap: true, }, drawing_bounds, + bounds, ); } diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs index e9b153e5..2fab9013 100644 --- a/widget/src/image/viewer.rs +++ b/widget/src/image/viewer.rs @@ -314,7 +314,7 @@ where _style: &renderer::Style, layout: Layout<'_>, _cursor: mouse::Cursor, - _viewport: &Rectangle, + viewport: &Rectangle, ) { let state = tree.state.downcast_ref::(); let bounds = layout.bounds(); @@ -348,7 +348,6 @@ where renderer.draw_image( Image { handle: self.handle.clone(), - clip_bounds: Rectangle::INFINITE, border_radius: border::Radius::default(), filter_method: self.filter_method, rotation: Radians(0.0), @@ -356,6 +355,7 @@ where snap: true, }, drawing_bounds, + *viewport, ); }); }; diff --git a/widget/src/svg.rs b/widget/src/svg.rs index dabe499f..9ed3d870 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -240,25 +240,16 @@ where let style = theme.style(&self.class, status); - let render = |renderer: &mut Renderer| { - renderer.draw_svg( - svg::Svg { - handle: self.handle.clone(), - color: style.color, - rotation: self.rotation.radians(), - opacity: self.opacity, - }, - drawing_bounds, - ); - }; - - if adjusted_fit.width > bounds.width - || adjusted_fit.height > bounds.height - { - renderer.with_layer(bounds, render); - } else { - render(renderer); - } + renderer.draw_svg( + svg::Svg { + handle: self.handle.clone(), + color: style.color, + rotation: self.rotation.radians(), + opacity: self.opacity, + }, + drawing_bounds, + bounds, + ); } }