1#[allow(non_camel_case_types)]
8#[derive(Debug, Clone, PartialEq)]
9pub struct CT_PageArea {
10 pub physical_box: Option<String>,
12 pub application_box: Option<String>,
14 pub content_box: Option<String>,
16 pub bleed_box: Option<String>,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq)]
22pub struct Box {
23 pub x: f64,
25 pub y: f64,
27 pub width: f64,
29 pub height: f64,
31}
32
33impl Box {
34 #[must_use]
36 pub fn new(x: f64, y: f64, width: f64, height: f64) -> Self {
37 Self {
38 x,
39 y,
40 width,
41 height,
42 }
43 }
44
45 #[must_use]
47 pub fn to_st_box(&self) -> String {
48 format!("{} {} {} {}", self.x, self.y, self.width, self.height)
49 }
50}
51
52impl CT_PageArea {
53 #[must_use]
55 pub fn new() -> Self {
56 Self {
57 physical_box: None,
58 application_box: None,
59 content_box: None,
60 bleed_box: None,
61 }
62 }
63
64 #[must_use]
66 pub fn with_physical(x: f64, y: f64, width: f64, height: f64) -> Self {
67 Self {
68 physical_box: Some(Box::new(x, y, width, height).to_st_box()),
69 application_box: None,
70 content_box: None,
71 bleed_box: None,
72 }
73 }
74
75 #[must_use]
77 pub fn physical_box(mut self, x: f64, y: f64, width: f64, height: f64) -> Self {
78 self.physical_box = Some(Box::new(x, y, width, height).to_st_box());
79 self
80 }
81
82 #[must_use]
84 pub fn application_box(mut self, x: f64, y: f64, width: f64, height: f64) -> Self {
85 self.application_box = Some(Box::new(x, y, width, height).to_st_box());
86 self
87 }
88
89 #[must_use]
91 pub fn content_box(mut self, x: f64, y: f64, width: f64, height: f64) -> Self {
92 self.content_box = Some(Box::new(x, y, width, height).to_st_box());
93 self
94 }
95
96 #[must_use]
98 pub fn bleed_box(mut self, x: f64, y: f64, width: f64, height: f64) -> Self {
99 self.bleed_box = Some(Box::new(x, y, width, height).to_st_box());
100 self
101 }
102
103 #[must_use]
105 pub fn get_box(&self) -> String {
106 self.physical_box
107 .clone()
108 .unwrap_or_else(|| "0 0 210 297".to_string())
109 }
110
111 #[must_use]
113 pub fn to_xml_string(&self) -> String {
114 use std::fmt::Write;
115 let mut xml = String::from("<ofd:PageArea");
116 if let Some(ref pb) = self.physical_box {
117 let _ = write!(xml, " PhysicalBox=\"{pb}\"");
118 }
119 if let Some(ref ab) = self.application_box {
120 let _ = write!(xml, " ApplicationBox=\"{ab}\"");
121 }
122 if let Some(ref cb) = self.content_box {
123 let _ = write!(xml, " ContentBox=\"{cb}\"");
124 }
125 if let Some(ref bb) = self.bleed_box {
126 let _ = write!(xml, " BleedBox=\"{bb}\"");
127 }
128 xml.push_str(" />");
129 xml
130 }
131}
132
133impl Default for CT_PageArea {
134 fn default() -> Self {
135 Self::new()
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_ct_page_area_new() {
145 let area = CT_PageArea::new();
146 assert!(area.physical_box.is_none());
147 assert!(area.application_box.is_none());
148 assert!(area.content_box.is_none());
149 assert!(area.bleed_box.is_none());
150 }
151
152 #[test]
153 fn test_ct_page_area_with_physical() {
154 let area = CT_PageArea::with_physical(0.0, 0.0, 210.0, 297.0);
155 assert_eq!(area.physical_box.as_deref(), Some("0 0 210 297"));
156 assert!(area.application_box.is_none());
157 }
158
159 #[test]
160 fn test_ct_page_area_builder_chaining() {
161 let area = CT_PageArea::new()
162 .physical_box(0.0, 0.0, 210.0, 297.0)
163 .application_box(10.0, 10.0, 190.0, 277.0)
164 .content_box(20.0, 20.0, 170.0, 257.0)
165 .bleed_box(-5.0, -5.0, 220.0, 307.0);
166 assert!(area.physical_box.is_some());
167 assert!(area.application_box.is_some());
168 assert!(area.content_box.is_some());
169 assert!(area.bleed_box.is_some());
170 }
171
172 #[test]
173 fn test_ct_page_area_get_box_default() {
174 let area = CT_PageArea::new();
175 assert_eq!(area.get_box(), "0 0 210 297");
176 }
177
178 #[test]
179 fn test_ct_page_area_get_box_set() {
180 let area = CT_PageArea::with_physical(10.0, 20.0, 100.0, 200.0);
181 assert_eq!(area.get_box(), "10 20 100 200");
182 }
183
184 #[test]
185 fn test_ct_page_area_to_xml_basic() {
186 let area = CT_PageArea::with_physical(0.0, 0.0, 210.0, 297.0);
187 let xml = area.to_xml_string();
188 assert!(xml.contains("<ofd:PageArea"));
189 assert!(xml.contains("PhysicalBox=\"0 0 210 297\""));
190 assert!(xml.ends_with(" />"));
191 }
192
193 #[test]
194 fn test_ct_page_area_to_xml_full() {
195 let area = CT_PageArea::new()
196 .physical_box(0.0, 0.0, 210.0, 297.0)
197 .bleed_box(-5.0, -5.0, 220.0, 307.0);
198 let xml = area.to_xml_string();
199 assert!(xml.contains("PhysicalBox"));
200 assert!(xml.contains("BleedBox"));
201 }
202
203 #[test]
204 fn test_ct_page_area_clone_debug() {
205 let area = CT_PageArea::with_physical(0.0, 0.0, 1.0, 1.0);
206 let area2 = area.clone();
207 assert!(area2.physical_box.is_some());
208 assert!(format!("{area:?}").contains("CT_PageArea"));
209 }
210
211 #[test]
212 fn test_box_new_and_to_st_box() {
213 let b = Box::new(1.0, 2.0, 3.0, 4.0);
214 assert_eq!(b.to_st_box(), "1 2 3 4");
215 }
216}