Skip to content

Commit

Permalink
Add inset types
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Nov 4, 2024
1 parent 4d621a3 commit 8133eb7
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
2 changes: 2 additions & 0 deletions dpi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Unreleased` header.

## Unreleased

- Added `Insets`, `LogicalInsets` and `PhysicalInsets` types.

## 0.1.1

- Derive `Debug`, `Copy`, `Clone`, `PartialEq`, `Serialize`, `Deserialize` traits for `PixelUnit`.
Expand Down
139 changes: 139 additions & 0 deletions dpi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,145 @@ impl<P: Pixel> From<LogicalPosition<P>> for Position {
}
}

/// The logical distance between the edges of two rectangles.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LogicalInsets<P> {
/// The distance to the top edge.
pub top: P,
/// The distance to the left edge.
pub left: P,
/// The distance to the bottom edge.
pub bottom: P,
/// The distance to the right edge.
pub right: P,
}

impl<P> LogicalInsets<P> {
#[inline]
pub const fn new(top: P,
left: P,
bottom: P,
right: P,) -> Self {
Self { top, left, bottom, right }
}
}

impl<P: Pixel> LogicalInsets<P> {
#[inline]
pub fn from_physical<T: Into<LogicalInsets<X>>, X: Pixel>(
physical: T,
scale_factor: f64,
) -> Self {
physical.into().to_logical(scale_factor)
}

#[inline]
pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalInsets<X> {
assert!(validate_scale_factor(scale_factor));
let top = self.top.into() * scale_factor;
let left = self.left.into() * scale_factor;
let bottom = self.bottom.into() * scale_factor;
let right = self.right.into() * scale_factor;
PhysicalInsets::new(top, left, bottom, right).cast()
}

#[inline]
pub fn cast<X: Pixel>(&self) -> LogicalInsets<X> {
LogicalInsets { top: self.top.cast(), left: self.left.cast(), bottom: self.bottom.cast(), right: self.right.cast() }
}
}

/// The physical distance between the edges of two rectangles.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PhysicalInsets<P> {
/// The distance to the top edge.
pub top: P,
/// The distance to the left edge.
pub left: P,
/// The distance to the bottom edge.
pub bottom: P,
/// The distance to the right edge.
pub right: P,
}

impl<P> PhysicalInsets<P> {
#[inline]
pub const fn new(top: P,
left: P,
bottom: P,
right: P,) -> Self {
Self { top, left, bottom, right }
}
}

impl<P: Pixel> PhysicalInsets<P> {
#[inline]
pub fn from_logical<T: Into<LogicalInsets<X>>, X: Pixel>(logical: T, scale_factor: f64) -> Self {
logical.into().to_physical(scale_factor)
}

#[inline]
pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalInsets<X> {
assert!(validate_scale_factor(scale_factor));
let width = self.width.into() / scale_factor;
let height = self.height.into() / scale_factor;
let top = self.top.into() / scale_factor;
let left = self.left.into() / scale_factor;
let bottom = self.bottom.into() / scale_factor;
let right = self.right.into() / scale_factor;
LogicalInsets::new(top, left, bottom, right).cast()
}

#[inline]
pub fn cast<X: Pixel>(&self) -> PhysicalInsets<X> {
PhysicalInsets { top: self.top.cast(), left: self.left.cast(), bottom: self.bottom.cast(), right: self.right.cast() }
}
}

/// Insets that are either physical or logical.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Insets {
Physical(PhysicalInsets<u32>),
Logical(LogicalInsets<f64>),
}

impl Insets {
pub fn new<S: Into<Self>>(insets: S) -> Self {
insets.into()
}

pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalInsets<P> {
match *self {
Self::Physical(insets) => insets.to_logical(scale_factor),
Self::Logical(insets) => insets.cast(),
}
}

pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalInsets<P> {
match *self {
Self::Physical(insets) => insets.cast(),
Self::Logical(insets) => insets.to_physical(scale_factor),
}
}
}

impl<P: Pixel> From<PhysicalInsets<P>> for Insets {
#[inline]
fn from(insets: PhysicalInsets<P>) -> Self {
Self::Physical(insets.cast())
}
}

impl<P: Pixel> From<LogicalInsets<P>> for Insets {
#[inline]
fn from(insets: LogicalInsets<P>) -> Self {
Self::Logical(insets.cast())
}
}

#[cfg(test)]
mod tests {
use std::collections::HashSet;
Expand Down

0 comments on commit 8133eb7

Please sign in to comment.