use std::{
fmt::Debug,
marker::PhantomData,
ops::{Div, Mul},
};
use glamour::{Box2, Point2, Scalar, Size2, Transform2, TransformMap, Unit, Vector2};
pub struct Grid<T> {
phantom: PhantomData<T>,
}
impl<T: Scalar> Unit for Grid<T> {
type Scalar = T;
}
pub struct Pixel<T> {
phantom: PhantomData<T>,
}
impl<T: Scalar> Unit for Pixel<T> {
type Scalar = T;
}
pub type GridVec<T> = Vector2<Grid<T>>;
pub type PixelVec<T> = Vector2<Pixel<T>>;
pub type GridSize<T> = Size2<Grid<T>>;
pub type PixelSize<T> = Size2<Pixel<T>>;
pub type GridPos<T> = Point2<Grid<T>>;
pub type PixelPos<T> = Point2<Pixel<T>>;
pub type GridRect<T> = Box2<Grid<T>>;
pub type PixelRect<T> = Box2<Pixel<T>>;
pub fn to_skia_point(pos: PixelPos<f32>) -> skia_safe::Point {
skia_safe::Point::new(pos.x, pos.y)
}
pub fn to_skia_rect(rect: &PixelRect<f32>) -> skia_safe::Rect {
skia_safe::Rect { left: rect.min.x, top: rect.min.y, right: rect.max.x, bottom: rect.max.y }
}
#[derive(Copy, Clone, Debug)]
pub struct GridScale {
transform: Transform2<Grid<f32>, Pixel<f32>>,
}
impl GridScale {
pub fn new(scale: PixelSize<f32>) -> Self {
Self { transform: Transform2::from_scale(scale.as_vector().cast()) }
}
pub fn height(&self) -> f32 {
self.transform.matrix.y_axis.y
}
pub fn width(&self) -> f32 {
self.transform.matrix.x_axis.x
}
}
impl From<PixelSize<f32>> for GridScale {
fn from(value: PixelSize<f32>) -> Self {
Self::new(value)
}
}
impl<T: Scalar> Mul<GridScale> for GridVec<T> {
type Output = PixelVec<f32>;
#[inline]
fn mul(self, scale: GridScale) -> Self::Output {
let grid_vec: GridVec<f32> = self.try_cast().unwrap();
scale.transform.map(grid_vec)
}
}
impl<T: Scalar> Mul<GridScale> for GridSize<T> {
type Output = PixelSize<f32>;
#[inline]
fn mul(self, scale: GridScale) -> Self::Output {
(*self.as_vector() * scale).to_size()
}
}
impl<T: Scalar> Mul<GridScale> for GridPos<T> {
type Output = PixelPos<f32>;
#[inline]
fn mul(self, scale: GridScale) -> Self::Output {
(*self.as_vector() * scale).to_point()
}
}
impl<T: Scalar> Mul<GridScale> for GridRect<T> {
type Output = PixelRect<f32>;
#[inline]
fn mul(self, scale: GridScale) -> Self::Output {
PixelRect::new(
(*self.min.as_vector() * scale).into(),
(*self.max.as_vector() * scale).into(),
)
}
}
impl<T: Scalar> Div<GridScale> for PixelVec<T> {
type Output = GridVec<f32>;
#[inline]
fn div(self, scale: GridScale) -> Self::Output {
let pixel_vec: PixelVec<f32> = self.try_cast().unwrap();
scale.transform.inverse().map(pixel_vec)
}
}
impl<T: Scalar> Div<GridScale> for PixelSize<T> {
type Output = GridSize<f32>;
#[inline]
fn div(self, scale: GridScale) -> Self::Output {
(*self.as_vector() / scale).to_size()
}
}
impl<T: Scalar> Div<GridScale> for PixelPos<T> {
type Output = GridPos<f32>;
#[inline]
fn div(self, scale: GridScale) -> Self::Output {
(*self.as_vector() / scale).to_point()
}
}
impl<T: Scalar> Div<GridScale> for PixelRect<T> {
type Output = GridRect<f32>;
#[inline]
fn div(self, scale: GridScale) -> Self::Output {
GridRect::new(
(*self.min.as_vector() / scale).into(),
(*self.max.as_vector() / scale).into(),
)
}
}