Skip to main content

oxidize_pdf/layout/
document_builder.rs

1use crate::error::Result;
2use crate::graphics::Image;
3use crate::layout::{FlowLayout, PageConfig, RichText};
4use crate::text::{Font, Table};
5use crate::Document;
6use std::sync::Arc;
7
8/// High-level builder for creating multi-page PDF documents with automatic layout.
9///
10/// Wraps [`FlowLayout`] with an owned-chaining API so you can build a complete
11/// document in a single expression.
12///
13/// # Example
14///
15/// ```rust,no_run
16/// use oxidize_pdf::layout::DocumentBuilder;
17/// use oxidize_pdf::Font;
18///
19/// let mut doc = DocumentBuilder::a4()
20///     .add_text("Invoice #001", Font::HelveticaBold, 18.0)
21///     .add_spacer(10.0)
22///     .add_text("Date: 2026-04-09", Font::Helvetica, 12.0)
23///     .build()
24///     .unwrap();
25///
26/// doc.save("invoice.pdf").unwrap();
27/// ```
28pub struct DocumentBuilder {
29    layout: FlowLayout,
30}
31
32impl DocumentBuilder {
33    /// Create a builder with A4 page size and default 72pt margins.
34    pub fn a4() -> Self {
35        Self {
36            layout: FlowLayout::new(PageConfig::a4()),
37        }
38    }
39
40    /// Create a builder with custom page configuration.
41    pub fn new(config: PageConfig) -> Self {
42        Self {
43            layout: FlowLayout::new(config),
44        }
45    }
46
47    /// Add a text block with default line height (1.2).
48    pub fn add_text(mut self, text: &str, font: Font, font_size: f64) -> Self {
49        self.layout.add_text(text, font, font_size);
50        self
51    }
52
53    /// Add a text block with custom line height.
54    pub fn add_text_with_line_height(
55        mut self,
56        text: &str,
57        font: Font,
58        font_size: f64,
59        line_height: f64,
60    ) -> Self {
61        self.layout
62            .add_text_with_line_height(text, font, font_size, line_height);
63        self
64    }
65
66    /// Add vertical spacing in points.
67    pub fn add_spacer(mut self, points: f64) -> Self {
68        self.layout.add_spacer(points);
69        self
70    }
71
72    /// Add a table.
73    pub fn add_table(mut self, table: Table) -> Self {
74        self.layout.add_table(table);
75        self
76    }
77
78    /// Add an image scaled to fit within max dimensions, left-aligned.
79    pub fn add_image(
80        mut self,
81        name: &str,
82        image: Arc<Image>,
83        max_width: f64,
84        max_height: f64,
85    ) -> Self {
86        self.layout.add_image(name, image, max_width, max_height);
87        self
88    }
89
90    /// Add an image scaled to fit, centered horizontally.
91    pub fn add_image_centered(
92        mut self,
93        name: &str,
94        image: Arc<Image>,
95        max_width: f64,
96        max_height: f64,
97    ) -> Self {
98        self.layout
99            .add_image_centered(name, image, max_width, max_height);
100        self
101    }
102
103    /// Add a single line of mixed-style text.
104    pub fn add_rich_text(mut self, rich: RichText) -> Self {
105        self.layout.add_rich_text(rich);
106        self
107    }
108
109    /// Build the document, creating pages as needed for all added elements.
110    pub fn build(self) -> Result<Document> {
111        let mut doc = Document::new();
112        self.layout.build_into(&mut doc)?;
113        Ok(doc)
114    }
115}