Add border radius support for image

This commit is contained in:
Héctor Ramón Jiménez 2025-10-25 22:53:44 +02:00
parent c896cd8d31
commit 44e68aa4b6
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
15 changed files with 256 additions and 188 deletions

View file

@ -19,6 +19,7 @@
pub mod viewer;
pub use viewer::Viewer;
use crate::core::border;
use crate::core::image;
use crate::core::layout;
use crate::core::mouse;
@ -59,6 +60,7 @@ pub struct Image<Handle = image::Handle> {
width: Length,
height: Length,
crop: Option<Rectangle<u32>>,
border_radius: border::Radius,
content_fit: ContentFit,
filter_method: FilterMethod,
rotation: Rotation,
@ -75,6 +77,7 @@ impl<Handle> Image<Handle> {
width: Length::Shrink,
height: Length::Shrink,
crop: None,
border_radius: border::Radius::default(),
content_fit: ContentFit::default(),
filter_method: FilterMethod::default(),
rotation: Rotation::default(),
@ -164,6 +167,18 @@ impl<Handle> Image<Handle> {
self.crop = Some(region);
self
}
/// Sets the [`border::Radius`] of the [`Image`].
///
/// Currently, it will only be applied around the rectangular bounding box
/// of the [`Image`].
pub fn border_radius(
mut self,
border_radius: impl Into<border::Radius>,
) -> Self {
self.border_radius = border_radius.into();
self
}
}
/// Computes the layout of an [`Image`].
@ -281,10 +296,6 @@ where
Rectangle::new(position + crop_offset, final_size)
}
fn must_clip(bounds: Rectangle, drawing_bounds: Rectangle) -> bool {
drawing_bounds.width > bounds.width || drawing_bounds.height > bounds.height
}
fn crop(size: Size<u32>, region: Option<Rectangle<u32>>) -> Size<f32> {
if let Some(region) = region {
Size::new(
@ -300,9 +311,9 @@ fn crop(size: Size<u32>, region: Option<Rectangle<u32>>) -> Size<f32> {
pub fn draw<Renderer, Handle>(
renderer: &mut Renderer,
layout: Layout<'_>,
viewport: &Rectangle,
handle: &Handle,
crop: Option<Rectangle<u32>>,
border_radius: border::Radius,
content_fit: ContentFit,
filter_method: FilterMethod,
rotation: Rotation,
@ -323,45 +334,11 @@ pub fn draw<Renderer, Handle>(
scale,
);
if must_clip(bounds, drawing_bounds) {
if let Some(bounds) = bounds.intersection(viewport) {
renderer.with_layer(bounds, |renderer| {
render(
renderer,
handle,
filter_method,
rotation,
opacity,
drawing_bounds,
);
});
}
} else {
render(
renderer,
handle,
filter_method,
rotation,
opacity,
drawing_bounds,
);
}
}
fn render<Renderer, Handle>(
renderer: &mut Renderer,
handle: &Handle,
filter_method: FilterMethod,
rotation: Rotation,
opacity: f32,
drawing_bounds: Rectangle,
) where
Renderer: image::Renderer<Handle = Handle>,
Handle: Clone,
{
renderer.draw_image(
image::Image {
handle: handle.clone(),
clip_bounds: bounds,
border_radius,
filter_method,
rotation: rotation.radians(),
opacity,
@ -411,14 +388,14 @@ where
_style: &renderer::Style,
layout: Layout<'_>,
_cursor: mouse::Cursor,
viewport: &Rectangle,
_viewport: &Rectangle,
) {
draw(
renderer,
layout,
viewport,
&self.handle,
self.crop,
self.border_radius,
self.content_fit,
self.filter_method,
self.rotation,

View file

@ -1,4 +1,5 @@
//! Zoom and pan on an image.
use crate::core::border;
use crate::core::image::{self, FilterMethod};
use crate::core::layout;
use crate::core::mouse;
@ -347,6 +348,8 @@ 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),
opacity: 1.0,