Simplify image rotation API and its internals
This commit is contained in:
parent
09a6bcfffc
commit
a57313b23e
23 changed files with 219 additions and 225 deletions
|
|
@ -65,6 +65,12 @@ impl From<u8> for Radians {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Radians> for f32 {
|
||||
fn from(radians: Radians) -> Self {
|
||||
radians.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Radians> for f64 {
|
||||
fn from(radians: Radians) -> Self {
|
||||
Self::from(radians.0)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::Size;
|
|||
/// in CSS, see [Mozilla's docs][1], or run the `tour` example
|
||||
///
|
||||
/// [1]: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum ContentFit {
|
||||
/// Scale as big as it can be without needing to crop or hide parts.
|
||||
///
|
||||
|
|
@ -23,6 +23,7 @@ pub enum ContentFit {
|
|||
/// This is a great fit for when you need to display an image without losing
|
||||
/// any part of it, particularly when the image itself is the focus of the
|
||||
/// screen.
|
||||
#[default]
|
||||
Contain,
|
||||
|
||||
/// Scale the image to cover all of the bounding box, cropping if needed.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! Load and draw raster graphics.
|
||||
pub use bytes::Bytes;
|
||||
|
||||
use crate::{Rectangle, Size};
|
||||
use crate::{Radians, Rectangle, Size};
|
||||
|
||||
use rustc_hash::FxHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
|
@ -173,7 +173,6 @@ pub trait Renderer: crate::Renderer {
|
|||
handle: Self::Handle,
|
||||
filter_method: FilterMethod,
|
||||
bounds: Rectangle,
|
||||
rotation: f32,
|
||||
scale: Size,
|
||||
rotation: Radians,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ pub use pixels::Pixels;
|
|||
pub use point::Point;
|
||||
pub use rectangle::Rectangle;
|
||||
pub use renderer::Renderer;
|
||||
pub use rotation::RotationLayout;
|
||||
pub use rotation::Rotation;
|
||||
pub use shadow::Shadow;
|
||||
pub use shell::Shell;
|
||||
pub use size::Size;
|
||||
|
|
|
|||
|
|
@ -227,3 +227,19 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Mul<Vector<T>> for Rectangle<T>
|
||||
where
|
||||
T: std::ops::Mul<Output = T> + Copy,
|
||||
{
|
||||
type Output = Rectangle<T>;
|
||||
|
||||
fn mul(self, scale: Vector<T>) -> Self {
|
||||
Rectangle {
|
||||
x: self.x * scale.x,
|
||||
y: self.y * scale.y,
|
||||
width: self.width * scale.x,
|
||||
height: self.height * scale.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use crate::renderer::{self, Renderer};
|
|||
use crate::svg;
|
||||
use crate::text::{self, Text};
|
||||
use crate::{
|
||||
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
||||
Background, Color, Font, Pixels, Point, Radians, Rectangle, Size,
|
||||
Transformation,
|
||||
};
|
||||
|
||||
impl Renderer for () {
|
||||
|
|
@ -171,8 +172,7 @@ impl image::Renderer for () {
|
|||
_handle: Self::Handle,
|
||||
_filter_method: image::FilterMethod,
|
||||
_bounds: Rectangle,
|
||||
_rotation: f32,
|
||||
_scale: Size,
|
||||
_rotation: Radians,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -187,8 +187,7 @@ impl svg::Renderer for () {
|
|||
_handle: svg::Handle,
|
||||
_color: Option<Color>,
|
||||
_bounds: Rectangle,
|
||||
_rotation: f32,
|
||||
_scale: Size,
|
||||
_rotation: Radians,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
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(),
|
||||
},
|
||||
Rotation::Floating(radians) | Rotation::Solid(radians) => radians,
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotates the given [`Size`].
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Rotation {
|
||||
fn default() -> Self {
|
||||
Self::Floating(Radians(0.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Radians> for Rotation {
|
||||
fn from(radians: Radians) -> Self {
|
||||
Self::Floating(radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Rotation {
|
||||
fn from(radians: f32) -> Self {
|
||||
Self::Floating(Radians(radians))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,3 +113,17 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Mul<Vector<T>> for Size<T>
|
||||
where
|
||||
T: std::ops::Mul<Output = T> + Copy,
|
||||
{
|
||||
type Output = Size<T>;
|
||||
|
||||
fn mul(self, scale: Vector<T>) -> Self::Output {
|
||||
Size {
|
||||
width: self.width * scale.x,
|
||||
height: self.height * scale.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//! Load and draw vector graphics.
|
||||
use crate::{Color, Rectangle, Size};
|
||||
use crate::{Color, Radians, Rectangle, Size};
|
||||
|
||||
use rustc_hash::FxHasher;
|
||||
use std::borrow::Cow;
|
||||
|
|
@ -100,7 +100,6 @@ pub trait Renderer: crate::Renderer {
|
|||
handle: Handle,
|
||||
color: Option<Color>,
|
||||
bounds: Rectangle,
|
||||
rotation: f32,
|
||||
scale: Size,
|
||||
rotation: Radians,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ impl<T> Vector<T> {
|
|||
impl Vector {
|
||||
/// The zero [`Vector`].
|
||||
pub const ZERO: Self = Self::new(0.0, 0.0);
|
||||
|
||||
/// The unit [`Vector`].
|
||||
pub const UNIT: Self = Self::new(0.0, 0.0);
|
||||
}
|
||||
|
||||
impl<T> std::ops::Add for Vector<T>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue