use std::fmt;
#[derive(Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Emu(
pub i64,
);
impl Emu {
pub const ZERO: Emu = Emu(0);
#[inline]
pub const fn new(v: i64) -> Self {
Emu(v)
}
#[inline]
pub const fn value(self) -> i64 {
self.0
}
#[inline]
pub const fn inches(self) -> f64 {
self.0 as f64 / 914_400.0
}
#[inline]
pub const fn pt(self) -> f64 {
self.0 as f64 / 12_700.0
}
#[inline]
pub const fn cm(self) -> f64 {
self.0 as f64 / 360_000.0
}
}
impl fmt::Debug for Emu {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Emu({} = {} in)", self.0, self.inches())
}
}
impl fmt::Display for Emu {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} EMU", self.0)
}
}
impl std::ops::Add for Emu {
type Output = Emu;
#[inline]
fn add(self, rhs: Emu) -> Emu {
Emu(self.0 + rhs.0)
}
}
impl std::ops::Sub for Emu {
type Output = Emu;
#[inline]
fn sub(self, rhs: Emu) -> Emu {
Emu(self.0 - rhs.0)
}
}
impl std::ops::Neg for Emu {
type Output = Emu;
#[inline]
fn neg(self) -> Emu {
Emu(-self.0)
}
}
impl std::ops::Mul<i64> for Emu {
type Output = Emu;
#[inline]
fn mul(self, rhs: i64) -> Emu {
Emu(self.0 * rhs)
}
}
pub trait EmuExt: Copy {
fn emu(self) -> Emu;
}
impl EmuExt for Emu {
#[inline]
fn emu(self) -> Emu {
self
}
}
impl EmuExt for i64 {
#[inline]
fn emu(self) -> Emu {
Emu(self)
}
}
impl EmuExt for i32 {
#[inline]
fn emu(self) -> Emu {
Emu(self as i64)
}
}
impl EmuExt for u32 {
#[inline]
fn emu(self) -> Emu {
Emu(self as i64)
}
}
impl EmuExt for f64 {
#[inline]
fn emu(self) -> Emu {
Emu((self * 914_400.0) as i64)
}
}
impl EmuExt for f32 {
#[inline]
fn emu(self) -> Emu {
Emu((self as f64 * 914_400.0) as i64)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Pt(
pub f64,
);
impl Pt {
#[inline]
pub const fn new(v: f64) -> Self {
Pt(v)
}
#[inline]
pub const fn value(self) -> f64 {
self.0
}
}
impl EmuExt for Pt {
#[inline]
fn emu(self) -> Emu {
Emu((self.0 * 12_700.0) as i64)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Inches(
pub f64,
);
impl Inches {
#[inline]
pub const fn new(v: f64) -> Self {
Inches(v)
}
#[inline]
pub const fn value(self) -> f64 {
self.0
}
}
impl EmuExt for Inches {
#[inline]
fn emu(self) -> Emu {
Emu((self.0 * 914_400.0) as i64)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Cm(
pub f64,
);
impl Cm {
#[inline]
pub const fn new(v: f64) -> Self {
Cm(v)
}
#[inline]
pub const fn value(self) -> f64 {
self.0
}
}
impl EmuExt for Cm {
#[inline]
fn emu(self) -> Emu {
Emu((self.0 * 360_000.0) as i64)
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
pub struct EmuPoint(
pub i64,
pub i64,
);
impl EmuPoint {
#[inline]
pub const fn new(x: i64, y: i64) -> Self {
EmuPoint(x, y)
}
#[inline]
pub const fn x(self) -> i64 {
self.0
}
#[inline]
pub const fn y(self) -> i64 {
self.1
}
#[inline]
pub const fn as_tuple(self) -> (i64, i64) {
(self.0, self.1)
}
}
impl From<(i64, i64)> for EmuPoint {
#[inline]
fn from((x, y): (i64, i64)) -> Self {
EmuPoint(x, y)
}
}
impl From<EmuPoint> for (i64, i64) {
#[inline]
fn from(p: EmuPoint) -> Self {
(p.0, p.1)
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
pub struct RGBColor(
pub u8,
pub u8,
pub u8,
);
impl RGBColor {
pub const BLACK: RGBColor = RGBColor(0, 0, 0);
pub const WHITE: RGBColor = RGBColor(255, 255, 255);
pub const RED: RGBColor = RGBColor(255, 0, 0);
pub const GREEN: RGBColor = RGBColor(0, 255, 0);
pub const BLUE: RGBColor = RGBColor(0, 0, 255);
}
impl From<(u8, u8, u8)> for RGBColor {
#[inline]
fn from((r, g, b): (u8, u8, u8)) -> Self {
RGBColor(r, g, b)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unit_conversion() {
assert_eq!(Pt(72.0).emu().value(), 72 * 12_700);
assert_eq!(Inches(1.0).emu().value(), 914_400);
assert_eq!(Cm(1.0).emu().value(), 360_000);
assert!((Emu(914_400).inches() - 1.0).abs() < 1e-9);
assert!((Emu(12_700).pt() - 1.0).abs() < 1e-9);
}
#[test]
fn rgb() {
let c: RGBColor = (10, 20, 30).into();
assert_eq!(c, RGBColor(10, 20, 30));
}
}