Skip to main content

graphitepdf_kit/
page.rs

1use crate::error::{GraphitePdfKitError, Result};
2use std::fmt;
3
4/// Page size in points (1 point = 1/72 inch).
5#[derive(Clone, Copy, Debug, PartialEq)]
6pub struct PageSize {
7    pub width: f64,
8    pub height: f64,
9}
10
11impl PageSize {
12    /// Standard A0 size (2384 × 3370 points).
13    pub const A0: Self = Self::new(2383.937, 3370.394);
14    /// Standard A1 size (1684 × 2384 points).
15    pub const A1: Self = Self::new(1683.780, 2383.937);
16    /// Standard A2 size (1191 × 1684 points).
17    pub const A2: Self = Self::new(1190.551, 1683.780);
18    /// Standard A3 size (842 × 1191 points).
19    pub const A3: Self = Self::new(841.890, 1190.551);
20    /// Standard A4 size (595 × 842 points) (default).
21    pub const A4: Self = Self::new(595.276, 841.890);
22    /// Standard A5 size (420 × 595 points).
23    pub const A5: Self = Self::new(420.472, 595.276);
24    /// Standard A6 size (298 × 420 points).
25    pub const A6: Self = Self::new(297.638, 420.472);
26    /// Standard Letter size (612 × 792 points).
27    pub const LETTER: Self = Self::new(612.0, 792.0);
28    /// Standard Legal size (612 × 1008 points).
29    pub const LEGAL: Self = Self::new(612.0, 1008.0);
30    /// Standard Tabloid size (792 × 1224 points).
31    pub const TABLOID: Self = Self::new(792.0, 1224.0);
32
33    /// Creates a new page size with given width and height.
34    pub const fn new(width: f64, height: f64) -> Self {
35        Self { width, height }
36    }
37
38    /// Returns a landscape version of the page size (swaps width and height).
39    pub fn landscape(&self) -> Self {
40        Self::new(self.height, self.width)
41    }
42
43    /// Converts inches to points.
44    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    /// Converts millimeters to points.
54    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    /// Converts centimeters to points.
65    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/// Page margins in points.
96#[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    /// Creates new margins.
106    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    /// Creates margins with the same value for all four sides.
116    pub const fn all(value: f64) -> Self {
117        Self::new(value, value, value, value)
118    }
119
120    /// No margins.
121    pub const ZERO: Self = Self::all(0.0);
122
123    /// Default 1 inch margins.
124    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/// Page orientation.
150#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
151pub enum PageOrientation {
152    /// Portrait orientation (default).
153    #[default]
154    Portrait,
155    /// Landscape orientation.
156    Landscape,
157}