use std::hash::{Hash, Hasher};
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Default, Debug)]
pub struct Point {
pub x: f32,
pub y: f32,
}
impl Point {
pub fn from_xy(x: f32, y: f32) -> Self {
Self { x, y }
}
pub(crate) fn to_tsp(self) -> tiny_skia_path::Point {
tiny_skia_path::Point::from_xy(self.x, self.y)
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Size(tiny_skia_path::Size);
impl Size {
pub fn from_wh(width: f32, height: f32) -> Option<Self> {
Some(Self(tiny_skia_path::Size::from_wh(width, height)?))
}
pub fn width(&self) -> f32 {
self.0.width()
}
pub fn height(&self) -> f32 {
self.0.height()
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Rect(tiny_skia_path::Rect);
impl Eq for Rect {}
impl Hash for Rect {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.left().to_bits().hash(state);
self.0.top().to_bits().hash(state);
self.0.right().to_bits().hash(state);
self.0.bottom().to_bits().hash(state);
}
}
impl Rect {
pub fn from_ltrb(left: f32, top: f32, right: f32, bottom: f32) -> Option<Self> {
Some(Self(tiny_skia_path::Rect::from_ltrb(
left, top, right, bottom,
)?))
}
pub fn transform(self, transform: Transform) -> Option<Self> {
Some(Self(self.0.transform(transform.to_tsp())?))
}
pub fn from_xywh(x: f32, y: f32, w: f32, h: f32) -> Option<Self> {
Some(Self(tiny_skia_path::Rect::from_xywh(x, y, w, h)?))
}
pub fn left(&self) -> f32 {
self.0.left()
}
pub fn top(&self) -> f32 {
self.0.top()
}
pub fn right(&self) -> f32 {
self.0.right()
}
pub fn bottom(&self) -> f32 {
self.0.bottom()
}
pub fn width(&self) -> f32 {
self.0.width()
}
pub fn height(&self) -> f32 {
self.0.height()
}
pub(crate) fn to_tsp(self) -> tiny_skia_path::Rect {
self.0
}
pub(crate) fn from_tsp(rect: tiny_skia_path::Rect) -> Self {
Self(rect)
}
pub(crate) fn expand(&mut self, other: &Rect) {
let left = self.left().min(other.left());
let top = self.top().min(other.top());
let right = self.right().max(other.right());
let bottom = self.bottom().max(other.bottom());
*self = Rect::from_ltrb(left, top, right, bottom).unwrap();
}
pub(crate) fn to_pdf_rect(self) -> pdf_writer::Rect {
pdf_writer::Rect::new(
self.left(),
self.top(),
self.left() + self.width(),
self.top() + self.height(),
)
}
}
#[derive(Clone, Copy, PartialEq)]
pub struct Quadrilateral(pub [Point; 4]);
impl From<Rect> for Quadrilateral {
fn from(r: Rect) -> Self {
Self([
Point::from_xy(r.left(), r.bottom()),
Point::from_xy(r.right(), r.bottom()),
Point::from_xy(r.right(), r.top()),
Point::from_xy(r.left(), r.top()),
])
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug, Default)]
pub struct Transform(tiny_skia_path::Transform);
impl Transform {
pub fn identity() -> Self {
Self(tiny_skia_path::Transform::default())
}
pub fn from_row(sx: f32, ky: f32, kx: f32, sy: f32, tx: f32, ty: f32) -> Self {
Self(tiny_skia_path::Transform::from_row(sx, ky, kx, sy, tx, ty))
}
pub fn from_translate(tx: f32, ty: f32) -> Self {
Self(tiny_skia_path::Transform::from_translate(tx, ty))
}
pub fn from_scale(sx: f32, sy: f32) -> Self {
Self(tiny_skia_path::Transform::from_scale(sx, sy))
}
pub fn from_skew(kx: f32, ky: f32) -> Self {
Self(tiny_skia_path::Transform::from_skew(kx, ky))
}
pub fn from_rotate(angle: f32) -> Self {
Self(tiny_skia_path::Transform::from_rotate(angle))
}
pub fn from_rotate_at(angle: f32, tx: f32, ty: f32) -> Self {
Self(tiny_skia_path::Transform::from_rotate_at(angle, tx, ty))
}
pub fn sx(&self) -> f32 {
self.0.sx
}
pub fn sy(&self) -> f32 {
self.0.sy
}
pub fn kx(&self) -> f32 {
self.0.kx
}
pub fn ky(&self) -> f32 {
self.0.ky
}
pub fn tx(&self) -> f32 {
self.0.tx
}
pub fn ty(&self) -> f32 {
self.0.ty
}
pub fn invert(&self) -> Option<Self> {
Some(Self(self.0.invert()?))
}
pub(crate) fn pre_concat(&self, other: Self) -> Self {
Self(self.0.pre_concat(other.0))
}
pub(crate) fn post_concat(&self, other: Self) -> Self {
Self(self.0.post_concat(other.0))
}
pub(crate) fn to_tsp(self) -> tiny_skia_path::Transform {
self.0
}
pub(crate) fn from_tsp(ts: tiny_skia_path::Transform) -> Self {
Self(ts)
}
pub(crate) fn to_pdf_transform(self) -> [f32; 6] {
[
self.0.sx, self.0.ky, self.0.kx, self.0.sy, self.0.tx, self.0.ty,
]
}
}
impl Hash for Transform {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.tx.to_bits().hash(state);
self.0.ty.to_bits().hash(state);
self.0.sx.to_bits().hash(state);
self.0.sy.to_bits().hash(state);
self.0.kx.to_bits().hash(state);
self.0.ky.to_bits().hash(state);
}
}
pub struct Path(pub(crate) tiny_skia_path::Path);
impl Path {
pub fn transform(self, transform: Transform) -> Option<Self> {
Some(Self(self.0.transform(transform.to_tsp())?))
}
}
#[derive(Default)]
pub struct PathBuilder(tiny_skia_path::PathBuilder);
impl PathBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn move_to(&mut self, x: f32, y: f32) {
self.0.move_to(x, y)
}
pub fn line_to(&mut self, x: f32, y: f32) {
self.0.line_to(x, y)
}
pub fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
self.0.quad_to(x1, y1, x, y)
}
pub fn cubic_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
self.0.cubic_to(x1, y1, x2, y2, x, y)
}
pub fn close(&mut self) {
self.0.close()
}
pub fn push_rect(&mut self, rect: Rect) {
self.0.push_rect(rect.to_tsp())
}
pub fn finish(self) -> Option<Path> {
Some(Path(self.0.finish()?))
}
}