|
@@ -4,15 +4,8 @@
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
-fn validate_scale_factor(scale_factor: f64) -> bool {
|
|
|
|
- scale_factor.is_sign_positive() && scale_factor.is_normal()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/// A pixel definition. Must be created from a `f64` value.
|
|
|
|
pub trait Pixel: Copy + Into<f64> {
|
|
pub trait Pixel: Copy + Into<f64> {
|
|
- /// Creates the pixel from the `f64` value.
|
|
|
|
fn from_f64(f: f64) -> Self;
|
|
fn from_f64(f: f64) -> Self;
|
|
- /// Casts a pixel.
|
|
|
|
fn cast<P: Pixel>(self) -> P {
|
|
fn cast<P: Pixel>(self) -> P {
|
|
P::from_f64(self.into())
|
|
P::from_f64(self.into())
|
|
}
|
|
}
|
|
@@ -23,81 +16,87 @@ impl Pixel for u8 {
|
|
f.round() as u8
|
|
f.round() as u8
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for u16 {
|
|
impl Pixel for u16 {
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f.round() as u16
|
|
f.round() as u16
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for u32 {
|
|
impl Pixel for u32 {
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f.round() as u32
|
|
f.round() as u32
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for i8 {
|
|
impl Pixel for i8 {
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f.round() as i8
|
|
f.round() as i8
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for i16 {
|
|
impl Pixel for i16 {
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f.round() as i16
|
|
f.round() as i16
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for i32 {
|
|
impl Pixel for i32 {
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f.round() as i32
|
|
f.round() as i32
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for f32 {
|
|
impl Pixel for f32 {
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f as f32
|
|
f as f32
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
impl Pixel for f64 {
|
|
impl Pixel for f64 {
|
|
- #[allow(clippy::wrong_self_convention)]
|
|
|
|
fn from_f64(f: f64) -> Self {
|
|
fn from_f64(f: f64) -> Self {
|
|
f
|
|
f
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/// A position represented in physical pixels.
|
|
|
|
|
|
+/// Checks that the scale factor is a normal positive `f64`.
|
|
|
|
+///
|
|
|
|
+/// All functions that take a scale factor assert that this will return `true`. If you're sourcing scale factors from
|
|
|
|
+/// anywhere other than tao, it's recommended to validate them using this function before passing them to tao;
|
|
|
|
+/// otherwise, you risk panics.
|
|
|
|
+#[inline]
|
|
|
|
+pub fn validate_scale_factor(scale_factor: f64) -> bool {
|
|
|
|
+ scale_factor.is_sign_positive() && scale_factor.is_normal()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// A position represented in logical pixels.
|
|
|
|
+///
|
|
|
|
+/// The position is stored as floats, so please be careful. Casting floats to integers truncates the
|
|
|
|
+/// fractional part, which can cause noticeable issues. To help with that, an `Into<(i32, i32)>`
|
|
|
|
+/// implementation is provided which does the rounding for you.
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
-pub struct PhysicalPosition<P> {
|
|
|
|
- /// Vertical axis value.
|
|
|
|
|
|
+pub struct LogicalPosition<P> {
|
|
pub x: P,
|
|
pub x: P,
|
|
- /// Horizontal axis value.
|
|
|
|
pub y: P,
|
|
pub y: P,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<P: Pixel> PhysicalPosition<P> {
|
|
|
|
- /// Converts the physical position to a logical one, using the scale factor.
|
|
|
|
|
|
+impl<P> LogicalPosition<P> {
|
|
#[inline]
|
|
#[inline]
|
|
- pub fn to_logical<X: Pixel>(self, scale_factor: f64) -> LogicalPosition<X> {
|
|
|
|
- assert!(validate_scale_factor(scale_factor));
|
|
|
|
- let x = self.x.into() / scale_factor;
|
|
|
|
- let y = self.y.into() / scale_factor;
|
|
|
|
- LogicalPosition { x, y }.cast()
|
|
|
|
|
|
+ pub const fn new(x: P, y: P) -> Self {
|
|
|
|
+ LogicalPosition { x, y }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/// A position represented in logical pixels.
|
|
|
|
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
|
|
-pub struct LogicalPosition<P> {
|
|
|
|
- /// Vertical axis value.
|
|
|
|
- pub x: P,
|
|
|
|
- /// Horizontal axis value.
|
|
|
|
- pub y: P,
|
|
|
|
-}
|
|
|
|
|
|
+impl<P: Pixel> LogicalPosition<P> {
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn from_physical<T: Into<PhysicalPosition<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) -> PhysicalPosition<X> {
|
|
|
|
+ assert!(validate_scale_factor(scale_factor));
|
|
|
|
+ let x = self.x.into() * scale_factor;
|
|
|
|
+ let y = self.y.into() * scale_factor;
|
|
|
|
+ PhysicalPosition::new(x, y).cast()
|
|
|
|
+ }
|
|
|
|
|
|
-impl<T: Pixel> LogicalPosition<T> {
|
|
|
|
- /// Casts the logical size to another pixel type.
|
|
|
|
#[inline]
|
|
#[inline]
|
|
pub fn cast<X: Pixel>(&self) -> LogicalPosition<X> {
|
|
pub fn cast<X: Pixel>(&self) -> LogicalPosition<X> {
|
|
LogicalPosition {
|
|
LogicalPosition {
|
|
@@ -107,47 +106,122 @@ impl<T: Pixel> LogicalPosition<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/// A position that's either physical or logical.
|
|
|
|
-#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
-#[serde(tag = "type", content = "data")]
|
|
|
|
-pub enum Position {
|
|
|
|
- /// Physical position.
|
|
|
|
- Physical(PhysicalPosition<i32>),
|
|
|
|
- /// Logical position.
|
|
|
|
- Logical(LogicalPosition<f64>),
|
|
|
|
|
|
+impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalPosition<P> {
|
|
|
|
+ fn from((x, y): (X, X)) -> LogicalPosition<P> {
|
|
|
|
+ LogicalPosition::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-/// A size represented in physical pixels.
|
|
|
|
|
|
+impl<P: Pixel, X: Pixel> From<LogicalPosition<P>> for (X, X) {
|
|
|
|
+ fn from(pos: LogicalPosition<P>) -> Self {
|
|
|
|
+ (pos.x.cast(), pos.y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalPosition<P> {
|
|
|
|
+ fn from([x, y]: [X; 2]) -> LogicalPosition<P> {
|
|
|
|
+ LogicalPosition::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<LogicalPosition<P>> for [X; 2] {
|
|
|
|
+ fn from(pos: LogicalPosition<P>) -> Self {
|
|
|
|
+ [pos.x.cast(), pos.y.cast()]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// A position represented in physical pixels.
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
-pub struct PhysicalSize<T> {
|
|
|
|
- /// Width.
|
|
|
|
- pub width: T,
|
|
|
|
- /// Height.
|
|
|
|
- pub height: T,
|
|
|
|
|
|
+pub struct PhysicalPosition<P> {
|
|
|
|
+ pub x: P,
|
|
|
|
+ pub y: P,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P> PhysicalPosition<P> {
|
|
|
|
+ #[inline]
|
|
|
|
+ pub const fn new(x: P, y: P) -> Self {
|
|
|
|
+ PhysicalPosition { x, y }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: Pixel> PhysicalSize<T> {
|
|
|
|
- /// Converts the physical size to a logical one, applying the scale factor.
|
|
|
|
|
|
+impl<P: Pixel> PhysicalPosition<P> {
|
|
#[inline]
|
|
#[inline]
|
|
- pub fn to_logical<X: Pixel>(self, scale_factor: f64) -> LogicalSize<X> {
|
|
|
|
|
|
+ pub fn from_logical<T: Into<LogicalPosition<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) -> LogicalPosition<X> {
|
|
assert!(validate_scale_factor(scale_factor));
|
|
assert!(validate_scale_factor(scale_factor));
|
|
- let width = self.width.into() / scale_factor;
|
|
|
|
- let height = self.height.into() / scale_factor;
|
|
|
|
- LogicalSize { width, height }.cast()
|
|
|
|
|
|
+ let x = self.x.into() / scale_factor;
|
|
|
|
+ let y = self.y.into() / scale_factor;
|
|
|
|
+ LogicalPosition::new(x, y).cast()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn cast<X: Pixel>(&self) -> PhysicalPosition<X> {
|
|
|
|
+ PhysicalPosition {
|
|
|
|
+ x: self.x.cast(),
|
|
|
|
+ y: self.y.cast(),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalPosition<P> {
|
|
|
|
+ fn from((x, y): (X, X)) -> PhysicalPosition<P> {
|
|
|
|
+ PhysicalPosition::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<PhysicalPosition<P>> for (X, X) {
|
|
|
|
+ fn from(pos: PhysicalPosition<P>) -> Self {
|
|
|
|
+ (pos.x.cast(), pos.y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalPosition<P> {
|
|
|
|
+ fn from([x, y]: [X; 2]) -> PhysicalPosition<P> {
|
|
|
|
+ PhysicalPosition::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<PhysicalPosition<P>> for [X; 2] {
|
|
|
|
+ fn from(pos: PhysicalPosition<P>) -> Self {
|
|
|
|
+ [pos.x.cast(), pos.y.cast()]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// A size represented in logical pixels.
|
|
/// A size represented in logical pixels.
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
-pub struct LogicalSize<T> {
|
|
|
|
- /// Width.
|
|
|
|
- pub width: T,
|
|
|
|
- /// Height.
|
|
|
|
- pub height: T,
|
|
|
|
|
|
+pub struct LogicalSize<P> {
|
|
|
|
+ pub width: P,
|
|
|
|
+ pub height: P,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P> LogicalSize<P> {
|
|
|
|
+ #[inline]
|
|
|
|
+ pub const fn new(width: P, height: P) -> Self {
|
|
|
|
+ LogicalSize { width, height }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: Pixel> LogicalSize<T> {
|
|
|
|
- /// Casts the logical size to another pixel type.
|
|
|
|
|
|
+impl<P: Pixel> LogicalSize<P> {
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn from_physical<T: Into<PhysicalSize<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) -> PhysicalSize<X> {
|
|
|
|
+ assert!(validate_scale_factor(scale_factor));
|
|
|
|
+ let width = self.width.into() * scale_factor;
|
|
|
|
+ let height = self.height.into() * scale_factor;
|
|
|
|
+ PhysicalSize::new(width, height).cast()
|
|
|
|
+ }
|
|
|
|
+
|
|
#[inline]
|
|
#[inline]
|
|
pub fn cast<X: Pixel>(&self) -> LogicalSize<X> {
|
|
pub fn cast<X: Pixel>(&self) -> LogicalSize<X> {
|
|
LogicalSize {
|
|
LogicalSize {
|
|
@@ -157,12 +231,169 @@ impl<T: Pixel> LogicalSize<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalSize<P> {
|
|
|
|
+ fn from((x, y): (X, X)) -> LogicalSize<P> {
|
|
|
|
+ LogicalSize::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<LogicalSize<P>> for (X, X) {
|
|
|
|
+ fn from(size: LogicalSize<P>) -> Self {
|
|
|
|
+ (size.width.cast(), size.height.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalSize<P> {
|
|
|
|
+ fn from([x, y]: [X; 2]) -> LogicalSize<P> {
|
|
|
|
+ LogicalSize::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<LogicalSize<P>> for [X; 2] {
|
|
|
|
+ fn from(size: LogicalSize<P>) -> Self {
|
|
|
|
+ [size.width.cast(), size.height.cast()]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// A size represented in physical pixels.
|
|
|
|
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Serialize, Deserialize)]
|
|
|
|
+pub struct PhysicalSize<P> {
|
|
|
|
+ pub width: P,
|
|
|
|
+ pub height: P,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P> PhysicalSize<P> {
|
|
|
|
+ #[inline]
|
|
|
|
+ pub const fn new(width: P, height: P) -> Self {
|
|
|
|
+ PhysicalSize { width, height }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel> PhysicalSize<P> {
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn from_logical<T: Into<LogicalSize<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) -> LogicalSize<X> {
|
|
|
|
+ assert!(validate_scale_factor(scale_factor));
|
|
|
|
+ let width = self.width.into() / scale_factor;
|
|
|
|
+ let height = self.height.into() / scale_factor;
|
|
|
|
+ LogicalSize::new(width, height).cast()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #[inline]
|
|
|
|
+ pub fn cast<X: Pixel>(&self) -> PhysicalSize<X> {
|
|
|
|
+ PhysicalSize {
|
|
|
|
+ width: self.width.cast(),
|
|
|
|
+ height: self.height.cast(),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalSize<P> {
|
|
|
|
+ fn from((x, y): (X, X)) -> PhysicalSize<P> {
|
|
|
|
+ PhysicalSize::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<PhysicalSize<P>> for (X, X) {
|
|
|
|
+ fn from(size: PhysicalSize<P>) -> Self {
|
|
|
|
+ (size.width.cast(), size.height.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalSize<P> {
|
|
|
|
+ fn from([x, y]: [X; 2]) -> PhysicalSize<P> {
|
|
|
|
+ PhysicalSize::new(x.cast(), y.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel, X: Pixel> From<PhysicalSize<P>> for [X; 2] {
|
|
|
|
+ fn from(size: PhysicalSize<P>) -> Self {
|
|
|
|
+ [size.width.cast(), size.height.cast()]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/// A size that's either physical or logical.
|
|
/// A size that's either physical or logical.
|
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
-#[serde(tag = "type", content = "data")]
|
|
|
|
pub enum Size {
|
|
pub enum Size {
|
|
- /// Physical size.
|
|
|
|
Physical(PhysicalSize<u32>),
|
|
Physical(PhysicalSize<u32>),
|
|
- /// Logical size.
|
|
|
|
Logical(LogicalSize<f64>),
|
|
Logical(LogicalSize<f64>),
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+impl Size {
|
|
|
|
+ pub fn new<S: Into<Size>>(size: S) -> Size {
|
|
|
|
+ size.into()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalSize<P> {
|
|
|
|
+ match *self {
|
|
|
|
+ Size::Physical(size) => size.to_logical(scale_factor),
|
|
|
|
+ Size::Logical(size) => size.cast(),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalSize<P> {
|
|
|
|
+ match *self {
|
|
|
|
+ Size::Physical(size) => size.cast(),
|
|
|
|
+ Size::Logical(size) => size.to_physical(scale_factor),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel> From<PhysicalSize<P>> for Size {
|
|
|
|
+ #[inline]
|
|
|
|
+ fn from(size: PhysicalSize<P>) -> Size {
|
|
|
|
+ Size::Physical(size.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel> From<LogicalSize<P>> for Size {
|
|
|
|
+ #[inline]
|
|
|
|
+ fn from(size: LogicalSize<P>) -> Size {
|
|
|
|
+ Size::Logical(size.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// A position that's either physical or logical.
|
|
|
|
+#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
+pub enum Position {
|
|
|
|
+ Physical(PhysicalPosition<i32>),
|
|
|
|
+ Logical(LogicalPosition<f64>),
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Position {
|
|
|
|
+ pub fn new<S: Into<Position>>(position: S) -> Position {
|
|
|
|
+ position.into()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalPosition<P> {
|
|
|
|
+ match *self {
|
|
|
|
+ Position::Physical(position) => position.to_logical(scale_factor),
|
|
|
|
+ Position::Logical(position) => position.cast(),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<P> {
|
|
|
|
+ match *self {
|
|
|
|
+ Position::Physical(position) => position.cast(),
|
|
|
|
+ Position::Logical(position) => position.to_physical(scale_factor),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel> From<PhysicalPosition<P>> for Position {
|
|
|
|
+ #[inline]
|
|
|
|
+ fn from(position: PhysicalPosition<P>) -> Position {
|
|
|
|
+ Position::Physical(position.cast())
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<P: Pixel> From<LogicalPosition<P>> for Position {
|
|
|
|
+ #[inline]
|
|
|
|
+ fn from(position: LogicalPosition<P>) -> Position {
|
|
|
|
+ Position::Logical(position.cast())
|
|
|
|
+ }
|
|
|
|
+}
|