pdfgen/types/hierarchy/primitives/
rectangle.rs1use std::io::{Error, Write};
2
3use super::unit::Unit;
4
5#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
7pub struct Position {
8 pub x: Unit,
10
11 pub y: Unit,
13}
14
15impl Position {
16 pub const fn new(x: Unit, y: Unit) -> Self {
17 Self { x, y }
18 }
19
20 pub const fn from_mm(x: f32, y: f32) -> Self {
21 Self {
22 x: Unit::from_mm(x),
23 y: Unit::from_mm(y),
24 }
25 }
26
27 pub const fn from_units(x: f32, y: f32) -> Position {
28 Self {
29 x: Unit::from_unit(x),
30 y: Unit::from_unit(y),
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
39pub struct Rectangle {
40 low_left: Position,
42
43 top_right: Position,
45}
46
47macro_rules! gen_page_constants {
48 ($($name:ident, $width:literal, $height:literal),* $(,)?) => {
49 $(
50 pub const $name: Self = Self::new(Position::from_mm(0.0, 0.0), Position::from_mm($width - 1.0, $height - 1.0));
51 )*
52 }
53}
54
55impl Rectangle {
56 gen_page_constants! {
57 A0_4, 1682.0, 2378.0,
58 A0_2, 1189.0, 1682.0,
59 A0, 841.0, 1189.0,
60 A1, 594.0, 841.0,
61 A2, 420.0, 594.0,
62 A3, 297.0, 420.0,
63 A4, 210.0, 297.0,
64 A5, 148.0, 210.0,
65 A6, 105.0, 148.0,
66 A7, 74.0, 105.0,
67 A8, 52.0, 74.0,
68 A9, 37.0, 52.0,
69 A10, 26.0, 37.0,
70 }
71
72 pub const fn new(low_left: Position, top_right: Position) -> Self {
74 Self {
75 low_left,
76 top_right,
77 }
78 }
79
80 pub fn write(&self, writer: &mut dyn Write) -> Result<usize, Error> {
82 let output = format!(
83 "[{} {} {} {}]",
84 self.low_left.x, self.low_left.y, self.top_right.x, self.top_right.y
85 );
86 writer.write(output.as_bytes())
87 }
88
89 pub fn from_units(ll_x: f32, ll_y: f32, tr_x: f32, tr_y: f32) -> Self {
90 Self {
91 low_left: Position::from_units(ll_x, ll_y),
92 top_right: Position::from_units(tr_x, tr_y),
93 }
94 }
95
96 pub fn width(&self) -> Unit {
98 self.top_right.x - self.low_left.x
99 }
100
101 pub fn height(&self) -> Unit {
103 self.top_right.y - self.low_left.y
104 }
105}
106
107impl From<(u32, u32, u32, u32)> for Rectangle {
108 fn from((ll_x, ll_y, tr_x, tr_y): (u32, u32, u32, u32)) -> Self {
109 Self::from((ll_x as f32, ll_y as f32, tr_x as f32, tr_y as f32))
110 }
111}
112
113impl From<(f32, f32, f32, f32)> for Rectangle {
114 fn from((ll_x, ll_y, tr_x, tr_y): (f32, f32, f32, f32)) -> Self {
115 Self {
116 low_left: Position::from_mm(ll_x, ll_y),
117 top_right: Position::from_mm(tr_x, tr_y),
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use crate::types::hierarchy::primitives::unit::Unit;
125
126 use super::Rectangle;
127
128 #[test]
129 fn new_rectangle() {
130 let rect = Rectangle::from((24, 25, 42, 43));
131
132 assert_eq!(rect.low_left.x, Unit::from_mm(24.0));
133 assert_eq!(rect.low_left.y, Unit::from_mm(25.0));
134 assert_eq!(rect.top_right.x, Unit::from_mm(42.0));
135 assert_eq!(rect.top_right.y, Unit::from_mm(43.0));
136 }
137
138 #[test]
139 fn output() {
140 let rect = Rectangle::from_units(24.0, 25.0, 42.0, 43.0);
141
142 let mut output = Vec::new();
143 rect.write(&mut output).unwrap();
144 let output = String::from_utf8(output).unwrap();
145
146 insta::assert_snapshot!(output, @"[24 25 42 43]");
147 }
148}