diff --git a/dpi/CHANGELOG.md b/dpi/CHANGELOG.md new file mode 100644 index 0000000000..94fdfcdcb8 --- /dev/null +++ b/dpi/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +Please keep one empty line before and after all headers. (This is required for +`git` to produce a conflict when a release is made while a PR is open and the +PR's changelog entry would go into the wrong section). + +And please only add new entries to the top of this list, right below the `# +Unreleased` header. + +# Unreleased + +- Add `LogicalUnit`, `PhysicalUnit` and `PixelUnit` types and related functions. diff --git a/dpi/src/lib.rs b/dpi/src/lib.rs index aeb1038a88..0faf475f7f 100644 --- a/dpi/src/lib.rs +++ b/dpi/src/lib.rs @@ -35,8 +35,8 @@ //! //! ### Position and Size types //! -//! The [`PhysicalPosition`] / [`PhysicalSize`] types correspond with the actual pixels on the -//! device, and the [`LogicalPosition`] / [`LogicalSize`] types correspond to the physical pixels +//! The [`PhysicalPosition`] / [`PhysicalSize`] / [`PhysicalUnit`] types correspond with the actual pixels on the +//! device, and the [`LogicalPosition`] / [`LogicalSize`] / [`LogicalUnit`] types correspond to the physical pixels //! divided by the scale factor. //! //! The position and size types are generic over their exact pixel type, `P`, to allow the @@ -128,6 +128,238 @@ pub fn validate_scale_factor(scale_factor: f64) -> bool { scale_factor.is_sign_positive() && scale_factor.is_normal() } +/// A logical pixel unit. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct LogicalUnit
(pub P); + +impl
LogicalUnit
{
+ /// Represents a minimum logical unit of [`f64::MAX`].
+ pub const MIN: LogicalUnit {
+ #[inline]
+ pub fn from_physical {
+ fn from(v: X) -> LogicalUnit {
+ LogicalUnit::new(v.cast())
+ }
+}
+
+impl ) -> u8 {
+ v.0.cast()
+ }
+}
+
+impl ) -> u16 {
+ v.0.cast()
+ }
+}
+
+impl ) -> u32 {
+ v.0.cast()
+ }
+}
+
+impl ) -> i8 {
+ v.0.cast()
+ }
+}
+
+impl ) -> i16 {
+ v.0.cast()
+ }
+}
+
+impl ) -> i32 {
+ v.0.cast()
+ }
+}
+
+impl ) -> f32 {
+ v.0.cast()
+ }
+}
+
+impl ) -> f64 {
+ v.0.cast()
+ }
+}
+
+/// A physical pixel unit.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct PhysicalUnit (pub P);
+
+impl PhysicalUnit {
+ /// Represents a minimum physical unit of [`f64::MAX`].
+ pub const MIN: LogicalUnit {
+ #[inline]
+ pub fn from_logical {
+ fn from(v: X) -> PhysicalUnit {
+ PhysicalUnit::new(v.cast())
+ }
+}
+
+impl ) -> u8 {
+ v.0.cast()
+ }
+}
+
+impl ) -> u16 {
+ v.0.cast()
+ }
+}
+
+impl ) -> u32 {
+ v.0.cast()
+ }
+}
+
+impl ) -> i8 {
+ v.0.cast()
+ }
+}
+
+impl ) -> i16 {
+ v.0.cast()
+ }
+}
+
+impl ) -> i32 {
+ v.0.cast()
+ }
+}
+
+impl ) -> f32 {
+ v.0.cast()
+ }
+}
+
+impl ) -> f64 {
+ v.0.cast()
+ }
+}
+
+/// A pixel unit that's either physical or logical.
+pub enum PixelUnit {
+ Physical(PhysicalUnit {
+ match *self {
+ PixelUnit::Physical(unit) => unit.to_logical(scale_factor),
+ PixelUnit::Logical(unit) => unit.cast(),
+ }
+ }
+
+ pub fn to_physical {
+ match *self {
+ PixelUnit::Physical(unit) => unit.cast(),
+ PixelUnit::Logical(unit) => unit.to_physical(scale_factor),
+ }
+ }
+}
+
+impl ) -> PixelUnit {
+ PixelUnit::Physical(unit.cast())
+ }
+}
+
+impl ) -> PixelUnit {
+ PixelUnit::Logical(unit.cast())
+ }
+}
+
/// A position represented in logical pixels.
///
/// The position is stored as floats, so please be careful. Casting floats to integers truncates the
@@ -730,6 +962,43 @@ mod tests {
assert!(!validate_scale_factor(f64::NEG_INFINITY));
}
+ #[test]
+ fn test_logical_unity() {
+ let log_unit = LogicalUnit::new(1.0);
+ assert_eq!(log_unit.to_physical::