summaryrefslogtreecommitdiffstats
path: root/widget/src/svg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'widget/src/svg.rs')
-rw-r--r--widget/src/svg.rs65
1 files changed, 50 insertions, 15 deletions
diff --git a/widget/src/svg.rs b/widget/src/svg.rs
index eb142189..21946af8 100644
--- a/widget/src/svg.rs
+++ b/widget/src/svg.rs
@@ -5,8 +5,8 @@ use crate::core::renderer;
use crate::core::svg;
use crate::core::widget::Tree;
use crate::core::{
- Color, ContentFit, Element, Layout, Length, Rectangle, Size, Theme, Vector,
- Widget,
+ Color, ContentFit, Element, Layout, Length, Point, Rectangle,
+ RotationLayout, Size, Theme, Widget,
};
use std::path::PathBuf;
@@ -29,6 +29,8 @@ where
height: Length,
content_fit: ContentFit,
class: Theme::Class<'a>,
+ rotation: f32,
+ rotation_layout: RotationLayout,
}
impl<'a, Theme> Svg<'a, Theme>
@@ -43,6 +45,8 @@ where
height: Length::Shrink,
content_fit: ContentFit::Contain,
class: Theme::default(),
+ rotation: 0.0,
+ rotation_layout: RotationLayout::Change,
}
}
@@ -95,6 +99,18 @@ where
self.class = class.into();
self
}
+
+ /// Rotates the [`Svg`] by the given angle in radians.
+ pub fn rotation(mut self, degrees: f32) -> Self {
+ self.rotation = degrees;
+ self
+ }
+
+ /// Sets the [`RotationLayout`] of the [`Svg`].
+ pub fn rotation_layout(mut self, rotation_layout: RotationLayout) -> Self {
+ self.rotation_layout = rotation_layout;
+ self
+ }
}
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
@@ -120,11 +136,16 @@ where
let Size { width, height } = renderer.measure_svg(&self.handle);
let image_size = Size::new(width as f32, height as f32);
+ // The rotated size of the svg
+ let rotated_size = self
+ .rotation_layout
+ .apply_to_size(image_size, self.rotation);
+
// The size to be available to the widget prior to `Shrink`ing
- let raw_size = limits.resolve(self.width, self.height, image_size);
+ let raw_size = limits.resolve(self.width, self.height, rotated_size);
// The uncropped size of the image when fit to the bounds above
- let full_size = self.content_fit.fit(image_size, raw_size);
+ let full_size = self.content_fit.fit(rotated_size, raw_size);
// Shrink the widget to fit the resized image, if requested
let final_size = Size {
@@ -153,23 +174,35 @@ where
) {
let Size { width, height } = renderer.measure_svg(&self.handle);
let image_size = Size::new(width as f32, height as f32);
+ let rotated_size = self
+ .rotation_layout
+ .apply_to_size(image_size, self.rotation);
let bounds = layout.bounds();
- let adjusted_fit = self.content_fit.fit(image_size, bounds.size());
+ let adjusted_fit = self.content_fit.fit(rotated_size, bounds.size());
+ let scale = Size::new(
+ adjusted_fit.width / rotated_size.width,
+ adjusted_fit.height / rotated_size.height,
+ );
+
let is_mouse_over = cursor.is_over(bounds);
let render = |renderer: &mut Renderer| {
- let offset = Vector::new(
- (bounds.width - adjusted_fit.width).max(0.0) / 2.0,
- (bounds.height - adjusted_fit.height).max(0.0) / 2.0,
- );
-
- let drawing_bounds = Rectangle {
- width: adjusted_fit.width,
- height: adjusted_fit.height,
- ..bounds
+ let position = match self.content_fit {
+ ContentFit::None => Point::new(
+ bounds.position().x
+ + (rotated_size.width - image_size.width) / 2.0,
+ bounds.position().y
+ + (rotated_size.height - image_size.height) / 2.0,
+ ),
+ _ => Point::new(
+ bounds.center_x() - image_size.width / 2.0,
+ bounds.center_y() - image_size.height / 2.0,
+ ),
};
+ let drawing_bounds = Rectangle::new(position, image_size);
+
let status = if is_mouse_over {
Status::Hovered
} else {
@@ -181,7 +214,9 @@ where
renderer.draw_svg(
self.handle.clone(),
style.color,
- drawing_bounds + offset,
+ drawing_bounds,
+ self.rotation,
+ scale,
);
};