1use crate::error::{GraphitePdfKitError, Result};
2use std::fmt;
3
4#[derive(Clone, Copy, Debug, PartialEq)]
6pub struct PageSize {
7 pub width: f64,
8 pub height: f64,
9}
10
11impl PageSize {
12 pub const A0: Self = Self::new(2383.937, 3370.394);
14 pub const A1: Self = Self::new(1683.780, 2383.937);
16 pub const A2: Self = Self::new(1190.551, 1683.780);
18 pub const A3: Self = Self::new(841.890, 1190.551);
20 pub const A4: Self = Self::new(595.276, 841.890);
22 pub const A5: Self = Self::new(420.472, 595.276);
24 pub const A6: Self = Self::new(297.638, 420.472);
26 pub const LETTER: Self = Self::new(612.0, 792.0);
28 pub const LEGAL: Self = Self::new(612.0, 1008.0);
30 pub const TABLOID: Self = Self::new(792.0, 1224.0);
32
33 pub const fn new(width: f64, height: f64) -> Self {
35 Self { width, height }
36 }
37
38 pub fn landscape(&self) -> Self {
40 Self::new(self.height, self.width)
41 }
42
43 pub fn from_inches(width_in: f64, height_in: f64) -> Result<Self> {
45 if width_in <= 0.0 || height_in <= 0.0 {
46 return Err(GraphitePdfKitError::InvalidPageSize(
47 "Page dimensions must be positive".to_string(),
48 ));
49 }
50 Ok(Self::new(width_in * 72.0, height_in * 72.0))
51 }
52
53 pub fn from_mm(width_mm: f64, height_mm: f64) -> Result<Self> {
55 if width_mm <= 0.0 || height_mm <= 0.0 {
56 return Err(GraphitePdfKitError::InvalidPageSize(
57 "Page dimensions must be positive".to_string(),
58 ));
59 }
60 const MM_PER_POINT: f64 = 25.4 / 72.0;
61 Ok(Self::new(width_mm / MM_PER_POINT, height_mm / MM_PER_POINT))
62 }
63
64 pub fn from_cm(width_cm: f64, height_cm: f64) -> Result<Self> {
66 Self::from_mm(width_cm * 10.0, height_cm * 10.0)
67 }
68}
69
70impl TryFrom<(f64, f64)> for PageSize {
71 type Error = GraphitePdfKitError;
72
73 fn try_from(value: (f64, f64)) -> Result<Self> {
74 if value.0 <= 0.0 || value.1 <= 0.0 {
75 return Err(GraphitePdfKitError::InvalidPageSize(
76 "Page width and height must be positive".to_string(),
77 ));
78 }
79 Ok(Self::new(value.0, value.1))
80 }
81}
82
83impl Default for PageSize {
84 fn default() -> Self {
85 Self::A4
86 }
87}
88
89impl fmt::Display for PageSize {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 write!(f, "{} × {} pt", self.width, self.height)
92 }
93}
94
95#[derive(Clone, Copy, Debug, PartialEq)]
97pub struct PageMargins {
98 pub left: f64,
99 pub right: f64,
100 pub top: f64,
101 pub bottom: f64,
102}
103
104impl PageMargins {
105 pub const fn new(left: f64, right: f64, top: f64, bottom: f64) -> Self {
107 Self {
108 left,
109 right,
110 top,
111 bottom,
112 }
113 }
114
115 pub const fn all(value: f64) -> Self {
117 Self::new(value, value, value, value)
118 }
119
120 pub const ZERO: Self = Self::all(0.0);
122
123 pub const ONE_INCH: Self = Self::all(72.0);
125}
126
127impl Default for PageMargins {
128 fn default() -> Self {
129 Self::ONE_INCH
130 }
131}
132
133impl fmt::Display for PageMargins {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(
136 f,
137 "left: {} pt, right: {} pt, top: {} pt, bottom: {} pt",
138 self.left, self.right, self.top, self.bottom
139 )
140 }
141}
142
143impl From<f64> for PageMargins {
144 fn from(value: f64) -> Self {
145 Self::all(value)
146 }
147}
148
149#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
151pub enum PageOrientation {
152 #[default]
154 Portrait,
155 Landscape,
157}