1use crate::enums::{TextAlignment, VerticalAlignment};
4use crate::style::{PdfColor, PdfFont};
5
6#[derive(Debug, Clone)]
10pub struct PdfText {
11 pub content: String,
13 pub alignment: TextAlignment,
15 pub font: PdfFont,
17 pub color: PdfColor,
19}
20
21impl PdfText {
22 #[must_use]
24 pub fn new(content: impl Into<String>) -> Self {
25 Self {
26 content: content.into(),
27 alignment: TextAlignment::default(),
28 font: PdfFont::default(),
29 color: PdfColor::default(),
30 }
31 }
32
33 #[must_use]
35 pub fn font(mut self, font: PdfFont) -> Self {
36 self.font = font;
37 self
38 }
39
40 #[must_use]
42 pub const fn alignment(mut self, alignment: TextAlignment) -> Self {
43 self.alignment = alignment;
44 self
45 }
46
47 #[must_use]
49 pub const fn color(mut self, color: PdfColor) -> Self {
50 self.color = color;
51 self
52 }
53}
54
55#[derive(Debug, Clone)]
59pub struct PdfTable {
60 pub headers: Vec<String>,
62 pub rows: Vec<Vec<String>>,
64 pub column_widths: Vec<f64>,
66 pub width: f64,
68}
69
70impl PdfTable {
71 #[must_use]
73 pub fn new(headers: Vec<String>) -> Self {
74 Self {
75 headers,
76 rows: Vec::new(),
77 column_widths: Vec::new(),
78 width: 0.0,
79 }
80 }
81
82 #[must_use]
84 pub fn row(mut self, row: Vec<String>) -> Self {
85 self.rows.push(row);
86 self
87 }
88
89 #[must_use]
91 pub fn rows(mut self, rows: Vec<Vec<String>>) -> Self {
92 self.rows.extend(rows);
93 self
94 }
95
96 #[must_use]
98 pub const fn width(mut self, width: f64) -> Self {
99 self.width = width;
100 self
101 }
102}
103
104#[derive(Debug, Clone, Default)]
108pub struct PdfTableCell {
109 pub content: String,
111 pub h_alignment: TextAlignment,
113 pub v_alignment: VerticalAlignment,
115 pub font: PdfFont,
117 pub color: PdfColor,
119}
120
121#[derive(Debug, Clone)]
125pub struct PdfImage {
126 pub data: Vec<u8>,
128 pub width: f64,
130 pub height: f64,
132}
133
134impl PdfImage {
135 #[must_use]
137 pub fn from_bytes(data: Vec<u8>) -> Self {
138 Self {
139 data,
140 width: 0.0,
141 height: 0.0,
142 }
143 }
144
145 pub fn from_path(path: impl AsRef<std::path::Path>) -> crate::error::Result<Self> {
151 let data = std::fs::read(path)?;
152 Ok(Self::from_bytes(data))
153 }
154}
155
156#[derive(Debug, Clone, Copy)]
160pub struct PdfLine {
161 pub x1: f64,
163 pub y1: f64,
165 pub x2: f64,
167 pub y2: f64,
169 pub width: f64,
171 pub color: PdfColor,
173}
174
175#[derive(Debug, Clone, Copy)]
177pub struct PdfRect {
178 pub x: f64,
180 pub y: f64,
182 pub w: f64,
184 pub h: f64,
186 pub border_width: f64,
188 pub border_color: PdfColor,
190 pub fill_color: Option<PdfColor>,
192}
193
194#[cfg(test)]
195#[allow(clippy::uninlined_format_args, clippy::float_cmp)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn pdf_text_new() {
201 let t = PdfText::new("hello");
202 assert_eq!(t.content, "hello");
203 }
204
205 #[test]
206 fn pdf_text_font() {
207 let t = PdfText::new("x").font(PdfFont::default());
208 let _ = format!("{:?}", t.font);
209 }
210
211 #[test]
212 fn pdf_text_alignment() {
213 let t = PdfText::new("x").alignment(TextAlignment::Center);
214 assert_eq!(t.alignment, TextAlignment::Center);
215 }
216
217 #[test]
218 fn pdf_text_color() {
219 let t = PdfText::new("x").color(PdfColor::default());
220 assert_eq!(t.color, PdfColor::default());
221 }
222
223 #[test]
224 fn pdf_text_debug_clone() {
225 let t = PdfText::new("test");
226 let cloned = t.clone();
227 assert_eq!(t.content, cloned.content);
228 let _ = format!("{:?}", t);
229 }
230
231 #[test]
232 fn pdf_table_new() {
233 let t = PdfTable::new(vec!["A".into(), "B".into()]);
234 assert_eq!(t.headers.len(), 2);
235 assert!(t.rows.is_empty());
236 }
237
238 #[test]
239 fn pdf_table_row() {
240 let t = PdfTable::new(vec!["A".into()]).row(vec!["1".into()]);
241 assert_eq!(t.rows.len(), 1);
242 }
243
244 #[test]
245 fn pdf_table_rows() {
246 let t = PdfTable::new(vec!["A".into()]).rows(vec![vec!["1".into()], vec!["2".into()]]);
247 assert_eq!(t.rows.len(), 2);
248 }
249
250 #[test]
251 fn pdf_table_width() {
252 let t = PdfTable::new(vec!["A".into()]).width(200.0);
253 assert_eq!(t.width, 200.0);
254 }
255
256 #[test]
257 fn pdf_table_debug_clone() {
258 let t = PdfTable::new(vec!["A".into()]);
259 let cloned = t.clone();
260 assert_eq!(t.headers, cloned.headers);
261 let _ = format!("{:?}", t);
262 }
263
264 #[test]
265 fn pdf_image_from_bytes() {
266 let img = PdfImage::from_bytes(vec![1, 2, 3]);
267 assert_eq!(img.data, vec![1, 2, 3]);
268 assert_eq!(img.width, 0.0);
269 assert_eq!(img.height, 0.0);
270 }
271
272 #[test]
273 fn pdf_image_debug_clone() {
274 let img = PdfImage::from_bytes(vec![1]);
275 let cloned = img.clone();
276 assert_eq!(img.data, cloned.data);
277 let _ = format!("{:?}", img);
278 }
279
280 #[test]
281 fn pdf_table_cell_default() {
282 let cell = PdfTableCell::default();
283 assert!(cell.content.is_empty());
284 }
285
286 #[test]
287 fn pdf_table_cell_debug_clone() {
288 let cell = PdfTableCell {
289 content: "x".into(),
290 ..Default::default()
291 };
292 let cloned = cell.clone();
293 assert_eq!(cell.content, cloned.content);
294 let _ = format!("{:?}", cell);
295 }
296
297 #[test]
298 fn pdf_line_debug_copy() {
299 let line = PdfLine {
300 x1: 0.0,
301 y1: 0.0,
302 x2: 100.0,
303 y2: 100.0,
304 width: 1.0,
305 color: PdfColor::default(),
306 };
307 let copied = line;
308 assert_eq!(line.x2, copied.x2);
309 let _ = format!("{:?}", line);
310 }
311
312 #[test]
313 fn pdf_rect_debug_copy() {
314 let rect = PdfRect {
315 x: 0.0,
316 y: 0.0,
317 w: 100.0,
318 h: 50.0,
319 border_width: 1.0,
320 border_color: PdfColor::default(),
321 fill_color: None,
322 };
323 let copied = rect;
324 assert_eq!(rect.w, copied.w);
325 let _ = format!("{:?}", rect);
326 }
327}