use crate::Twips;
use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub trait Coordinate:
Copy
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Mul<i32, Output = Self>
+ MulAssign<i32>
+ Div<i32, Output = Self>
+ DivAssign<i32>
+ Neg<Output = Self>
+ fmt::Display
{
const ZERO: Self;
}
impl Coordinate for i32 {
const ZERO: Self = 0;
}
impl Coordinate for Twips {
const ZERO: Self = Self::ZERO;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Point<T: Coordinate> {
pub x: T,
pub y: T,
}
impl<T: Coordinate> Point<T> {
pub const ZERO: Self = Self {
x: T::ZERO,
y: T::ZERO,
};
pub const fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl Point<Twips> {
#[inline]
pub fn from_pixels(x: f64, y: f64) -> Self {
Self {
x: Twips::from_pixels(x),
y: Twips::from_pixels(y),
}
}
}
impl<T: Coordinate> Add<PointDelta<T>> for Point<T> {
type Output = Self;
#[inline]
fn add(self, other: PointDelta<T>) -> Self {
Self {
x: self.x + other.dx,
y: self.y + other.dy,
}
}
}
impl<T: Coordinate> AddAssign<PointDelta<T>> for Point<T> {
#[inline]
fn add_assign(&mut self, other: PointDelta<T>) {
self.x += other.dx;
self.y += other.dy;
}
}
impl<T: Coordinate> Sub<PointDelta<T>> for Point<T> {
type Output = Self;
#[inline]
fn sub(self, other: PointDelta<T>) -> Self {
Self {
x: self.x - other.dx,
y: self.y - other.dy,
}
}
}
impl<T: Coordinate> SubAssign<PointDelta<T>> for Point<T> {
#[inline]
fn sub_assign(&mut self, other: PointDelta<T>) {
self.x -= other.dx;
self.y -= other.dy;
}
}
impl<T: Coordinate> Sub for Point<T> {
type Output = PointDelta<T>;
#[inline]
fn sub(self, other: Self) -> PointDelta<T> {
PointDelta {
dx: self.x - other.x,
dy: self.y - other.y,
}
}
}
impl<T: Coordinate> fmt::Display for Point<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct PointDelta<T: Coordinate> {
pub dx: T,
pub dy: T,
}
impl<T: Coordinate> PointDelta<T> {
pub const ZERO: Self = Self {
dx: T::ZERO,
dy: T::ZERO,
};
pub const fn new(dx: T, dy: T) -> Self {
Self { dx, dy }
}
}
impl PointDelta<Twips> {
#[inline]
pub fn from_pixels(dx: f64, dy: f64) -> Self {
Self {
dx: Twips::from_pixels(dx),
dy: Twips::from_pixels(dy),
}
}
}
impl<T: Coordinate> Mul<i32> for PointDelta<T> {
type Output = Self;
#[inline]
fn mul(self, other: i32) -> Self {
Self {
dx: self.dx * other,
dy: self.dy * other,
}
}
}
impl<T: Coordinate> MulAssign<i32> for PointDelta<T> {
#[inline]
fn mul_assign(&mut self, other: i32) {
self.dx *= other;
self.dy *= other;
}
}
impl<T: Coordinate> Div<i32> for PointDelta<T> {
type Output = Self;
#[inline]
fn div(self, other: i32) -> Self {
Self {
dx: self.dx / other,
dy: self.dy / other,
}
}
}
impl<T: Coordinate> DivAssign<i32> for PointDelta<T> {
#[inline]
fn div_assign(&mut self, other: i32) {
self.dx /= other;
self.dy /= other;
}
}
impl<T: Coordinate> Neg for PointDelta<T> {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self {
dx: -self.dx,
dy: -self.dy,
}
}
}