use crate::kurbo::{Insets, Line, Point, Rect, Size, Vec2};
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Scale {
x: f64,
y: f64,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct ScaledArea {
size_dp: Size,
size_px: Size,
}
pub trait Scalable {
fn to_px(&self, scale: Scale) -> Self;
fn to_dp(&self, scale: Scale) -> Self;
}
impl Default for Scale {
fn default() -> Scale {
Scale { x: 1.0, y: 1.0 }
}
}
impl Scale {
pub fn new(x: f64, y: f64) -> Scale {
Scale { x, y }
}
#[inline]
pub fn x(self) -> f64 {
self.x
}
#[inline]
pub fn y(self) -> f64 {
self.y
}
#[inline]
pub fn px_to_dp_x<T: Into<f64>>(self, x: T) -> f64 {
x.into() / self.x
}
#[inline]
pub fn px_to_dp_y<T: Into<f64>>(self, y: T) -> f64 {
y.into() / self.y
}
#[inline]
pub fn px_to_dp_xy<T: Into<f64>>(self, x: T, y: T) -> (f64, f64) {
(x.into() / self.x, y.into() / self.y)
}
}
impl Scalable for Vec2 {
#[inline]
fn to_px(&self, scale: Scale) -> Vec2 {
Vec2::new(self.x * scale.x, self.y * scale.y)
}
#[inline]
fn to_dp(&self, scale: Scale) -> Vec2 {
Vec2::new(self.x / scale.x, self.y / scale.y)
}
}
impl Scalable for Point {
#[inline]
fn to_px(&self, scale: Scale) -> Point {
Point::new(self.x * scale.x, self.y * scale.y)
}
#[inline]
fn to_dp(&self, scale: Scale) -> Point {
Point::new(self.x / scale.x, self.y / scale.y)
}
}
impl Scalable for Line {
#[inline]
fn to_px(&self, scale: Scale) -> Line {
Line::new(self.p0.to_px(scale), self.p1.to_px(scale))
}
#[inline]
fn to_dp(&self, scale: Scale) -> Line {
Line::new(self.p0.to_dp(scale), self.p1.to_dp(scale))
}
}
impl Scalable for Size {
#[inline]
fn to_px(&self, scale: Scale) -> Size {
Size::new(self.width * scale.x, self.height * scale.y)
}
#[inline]
fn to_dp(&self, scale: Scale) -> Size {
Size::new(self.width / scale.x, self.height / scale.y)
}
}
impl Scalable for Rect {
#[inline]
fn to_px(&self, scale: Scale) -> Rect {
Rect::new(
self.x0 * scale.x,
self.y0 * scale.y,
self.x1 * scale.x,
self.y1 * scale.y,
)
}
#[inline]
fn to_dp(&self, scale: Scale) -> Rect {
Rect::new(
self.x0 / scale.x,
self.y0 / scale.y,
self.x1 / scale.x,
self.y1 / scale.y,
)
}
}
impl Scalable for Insets {
#[inline]
fn to_px(&self, scale: Scale) -> Insets {
Insets::new(
self.x0 * scale.x,
self.y0 * scale.y,
self.x1 * scale.x,
self.y1 * scale.y,
)
}
#[inline]
fn to_dp(&self, scale: Scale) -> Insets {
Insets::new(
self.x0 / scale.x,
self.y0 / scale.y,
self.x1 / scale.x,
self.y1 / scale.y,
)
}
}
impl Default for ScaledArea {
fn default() -> ScaledArea {
ScaledArea {
size_dp: Size::ZERO,
size_px: Size::ZERO,
}
}
}
impl ScaledArea {
pub fn from_px<T: Into<Size>>(size: T, scale: Scale) -> ScaledArea {
let size_px = size.into();
let size_dp = size_px.to_dp(scale);
ScaledArea { size_dp, size_px }
}
pub fn from_dp<T: Into<Size>>(size: T, scale: Scale) -> ScaledArea {
let size_px = size.into().to_px(scale).expand();
let size_dp = size_px.to_dp(scale);
ScaledArea { size_dp, size_px }
}
#[inline]
pub fn size_dp(&self) -> Size {
self.size_dp
}
#[inline]
pub fn size_px(&self) -> Size {
self.size_px
}
}