From 09a6bcfffc24f5abdc8709403bab7ae1e01563f1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 May 2024 13:15:17 +0200 Subject: Add `Image` rotation support Co-authored-by: DKolter <68352124+DKolter@users.noreply.github.com> --- core/src/rotation.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 core/src/rotation.rs (limited to 'core/src/rotation.rs') diff --git a/core/src/rotation.rs b/core/src/rotation.rs new file mode 100644 index 00000000..821aa494 --- /dev/null +++ b/core/src/rotation.rs @@ -0,0 +1,37 @@ +//! Control the rotation of some content (like an image) with the `RotationLayout` within a +//! space. +use crate::Size; + +/// The strategy used to rotate the content. +/// +/// This is used to control the behavior of the layout when the content is rotated +/// by a certain angle. +#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] +pub enum RotationLayout { + /// The layout is kept exactly as it was before the rotation. + /// + /// This is especially useful when used for animations, as it will avoid the + /// layout being shifted or resized when smoothly i.e. an icon. + Keep, + /// The layout is adjusted to fit the rotated content. + /// + /// This allows you to rotate an image and have the layout adjust to fit the new + /// size of the image. + Change, +} + +impl RotationLayout { + /// Applies the rotation to the layout while respecting the [`RotationLayout`] strategy. + /// The rotation is given in radians. + pub fn apply_to_size(&self, size: Size, rotation: f32) -> Size { + match self { + Self::Keep => size, + Self::Change => Size { + width: (size.width * rotation.cos()).abs() + + (size.height * rotation.sin()).abs(), + height: (size.width * rotation.sin()).abs() + + (size.height * rotation.cos()).abs(), + }, + } + } +} -- cgit From a57313b23ecb9843856ca0ea08635b6121fcb2cb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 May 2024 15:21:22 +0200 Subject: Simplify image rotation API and its internals --- core/src/rotation.rs | 71 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 20 deletions(-) (limited to 'core/src/rotation.rs') diff --git a/core/src/rotation.rs b/core/src/rotation.rs index 821aa494..ebb85f3c 100644 --- a/core/src/rotation.rs +++ b/core/src/rotation.rs @@ -1,37 +1,68 @@ -//! Control the rotation of some content (like an image) with the `RotationLayout` within a -//! space. -use crate::Size; +//! Control the rotation of some content (like an image) within a space. +use crate::{Radians, Size}; /// The strategy used to rotate the content. /// /// This is used to control the behavior of the layout when the content is rotated /// by a certain angle. -#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] -pub enum RotationLayout { - /// The layout is kept exactly as it was before the rotation. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Rotation { + /// The element will float while rotating. The layout will be kept exactly as it was + /// before the rotation. /// /// This is especially useful when used for animations, as it will avoid the /// layout being shifted or resized when smoothly i.e. an icon. - Keep, - /// The layout is adjusted to fit the rotated content. + /// + /// This is the default. + Floating(Radians), + /// The element will be solid while rotating. The layout will be adjusted to fit + /// the rotated content. /// /// This allows you to rotate an image and have the layout adjust to fit the new /// size of the image. - Change, + Solid(Radians), } -impl RotationLayout { - /// Applies the rotation to the layout while respecting the [`RotationLayout`] strategy. - /// The rotation is given in radians. - pub fn apply_to_size(&self, size: Size, rotation: f32) -> Size { +impl Rotation { + /// Returns the angle of the [`Rotation`] in [`Radians`]. + pub fn radians(self) -> Radians { + match self { + Rotation::Floating(radians) | Rotation::Solid(radians) => radians, + } + } + + /// Rotates the given [`Size`]. + pub fn apply(self, size: Size) -> Size { match self { - Self::Keep => size, - Self::Change => Size { - width: (size.width * rotation.cos()).abs() - + (size.height * rotation.sin()).abs(), - height: (size.width * rotation.sin()).abs() - + (size.height * rotation.cos()).abs(), - }, + Self::Floating(_) => size, + Self::Solid(rotation) => { + let radians = f32::from(rotation); + + Size { + width: (size.width * radians.cos()).abs() + + (size.height * radians.sin()).abs(), + height: (size.width * radians.sin()).abs() + + (size.height * radians.cos()).abs(), + } + } } } } + +impl Default for Rotation { + fn default() -> Self { + Self::Floating(Radians(0.0)) + } +} + +impl From for Rotation { + fn from(radians: Radians) -> Self { + Self::Floating(radians) + } +} + +impl From for Rotation { + fn from(radians: f32) -> Self { + Self::Floating(Radians(radians)) + } +} -- cgit From efc55b655bfce98fc32e698cf3c2007e27be941a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 May 2024 17:14:20 +0200 Subject: Create `ferris` example to showcase `ContentFit` and `Rotation` --- core/src/rotation.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src/rotation.rs') diff --git a/core/src/rotation.rs b/core/src/rotation.rs index ebb85f3c..f36ef089 100644 --- a/core/src/rotation.rs +++ b/core/src/rotation.rs @@ -1,5 +1,5 @@ //! Control the rotation of some content (like an image) within a space. -use crate::{Radians, Size}; +use crate::{Degrees, Radians, Size}; /// The strategy used to rotate the content. /// @@ -31,6 +31,11 @@ impl Rotation { } } + /// Returns the angle of the [`Rotation`] in [`Degrees`]. + pub fn degrees(self) -> Degrees { + Degrees(self.radians().0.to_degrees()) + } + /// Rotates the given [`Size`]. pub fn apply(self, size: Size) -> Size { match self { -- cgit From eac5bcb64f17dfbb52b64ea4f95693462986bb69 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 07:04:57 +0200 Subject: Fix `Image::bounds` when rotation present in `iced_graphics` --- core/src/rotation.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'core/src/rotation.rs') diff --git a/core/src/rotation.rs b/core/src/rotation.rs index f36ef089..00a8c302 100644 --- a/core/src/rotation.rs +++ b/core/src/rotation.rs @@ -36,20 +36,12 @@ impl Rotation { Degrees(self.radians().0.to_degrees()) } - /// Rotates the given [`Size`]. + /// Applies the [`Rotation`] to the given [`Size`], returning + /// the minimum [`Size`] containing the rotated one. pub fn apply(self, size: Size) -> Size { match self { Self::Floating(_) => size, - Self::Solid(rotation) => { - let radians = f32::from(rotation); - - Size { - width: (size.width * radians.cos()).abs() - + (size.height * radians.sin()).abs(), - height: (size.width * radians.sin()).abs() - + (size.height * radians.cos()).abs(), - } - } + Self::Solid(rotation) => size.rotate(rotation), } } } -- cgit From 4010e3983d40e24a5d7b590d8fec9801651199ce Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 07:23:55 +0200 Subject: Add `spin` mode to `ferris` example :crab: --- core/src/rotation.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'core/src/rotation.rs') diff --git a/core/src/rotation.rs b/core/src/rotation.rs index 00a8c302..afa8d79e 100644 --- a/core/src/rotation.rs +++ b/core/src/rotation.rs @@ -31,6 +31,13 @@ impl Rotation { } } + /// Returns a mutable reference to the angle of the [`Rotation`] in [`Radians`]. + pub fn radians_mut(&mut self) -> &mut Radians { + match self { + Rotation::Floating(radians) | Rotation::Solid(radians) => radians, + } + } + /// Returns the angle of the [`Rotation`] in [`Degrees`]. pub fn degrees(self) -> Degrees { Degrees(self.radians().0.to_degrees()) -- cgit