diff --git a/core/src/rectangle.rs b/core/src/rectangle.rs index ee1e3807..7ed3d2df 100644 --- a/core/src/rectangle.rs +++ b/core/src/rectangle.rs @@ -27,6 +27,34 @@ impl Rectangle { && self.y <= point.y && point.y <= self.y + self.height } + + /// Computes the intersection with the given [`Rectangle`]. + /// + /// [`Rectangle`]: struct.Rectangle.html + pub fn intersection( + &self, + other: &Rectangle, + ) -> Option> { + let x = self.x.max(other.x); + let y = self.y.max(other.y); + + let lower_right_x = (self.x + self.width).min(other.x + other.width); + let lower_right_y = (self.y + self.height).min(other.y + other.height); + + let width = lower_right_x - x; + let height = lower_right_y - y; + + if width > 0.0 && height > 0.0 { + Some(Rectangle { + x, + y, + width, + height, + }) + } else { + None + } + } } impl std::ops::Mul for Rectangle { @@ -41,3 +69,25 @@ impl std::ops::Mul for Rectangle { } } } + +impl From> for Rectangle { + fn from(rectangle: Rectangle) -> Rectangle { + Rectangle { + x: rectangle.x as f32, + y: rectangle.y as f32, + width: rectangle.width as f32, + height: rectangle.height as f32, + } + } +} + +impl From> for Rectangle { + fn from(rectangle: Rectangle) -> Rectangle { + Rectangle { + x: rectangle.x as u32, + y: rectangle.y as u32, + width: rectangle.width.ceil() as u32, + height: rectangle.height.ceil() as u32, + } + } +} diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index 29adcfb6..af61804e 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -240,25 +240,18 @@ impl Renderer { offset, content, } => { - let x = bounds.x - layer.offset.x as f32; - let y = bounds.y - layer.offset.y as f32; - let width = (bounds.width + x).min(bounds.width); - let height = (bounds.height + y).min(bounds.height); + let layer_bounds: Rectangle = layer.bounds.into(); - // Only draw visible content on-screen - // TODO: Also, check for parent layer bounds to avoid further - // drawing in some circumstances. - if width > 0.0 && height > 0.0 { - let clip_layer = Layer::new( - Rectangle { - x: x.max(0.0).floor() as u32, - y: y.max(0.0).floor() as u32, - width: width.ceil() as u32, - height: height.ceil() as u32, - }, - layer.offset + *offset, - ); + let clip = Rectangle { + x: bounds.x - layer.offset.x as f32, + y: bounds.y - layer.offset.y as f32, + ..*bounds + }; + // Only draw visible content + if let Some(clip_bounds) = layer_bounds.intersection(&clip) { + let clip_layer = + Layer::new(clip_bounds.into(), layer.offset + *offset); let new_layer = Layer::new(layer.bounds, layer.offset); layers.push(clip_layer);