Skip to main content

rust_pdf_box/
facade.rs

1use crate::content::stream::{AppendMode, PDPageContentStream};
2use crate::error::PdfResult;
3use crate::interactive::form::PDAcroForm;
4use crate::manipulation::merger::PDFMerger;
5use crate::manipulation::splitter::PDFSplitter;
6use crate::pd::document::PDDocument;
7use crate::pd::page::PDPage;
8use crate::pd::rectangle::PDRectangle;
9use crate::sign::signer::Signer;
10use crate::stamp::stamper::Stamper;
11use crate::text::stripper::PDFTextStripper;
12use std::fs::File;
13use std::path::Path;
14
15/// Context-oriented facade for intuitive, modern PDF processing.
16pub struct PdfDocument {
17    pub inner: PDDocument,
18}
19
20impl Default for PdfDocument {
21    fn default() -> Self {
22        Self::create()
23    }
24}
25
26impl PdfDocument {
27    /// Creates a new, blank PDF document.
28    pub fn create() -> Self {
29        Self {
30            inner: PDDocument::new(),
31        }
32    }
33
34    /// Opens a PDF document from a file path.
35    pub fn open(path: impl AsRef<Path>) -> PdfResult<Self> {
36        let inner = PDDocument::load_from_file(path)?;
37        Ok(Self { inner })
38    }
39
40    /// Opens a PDF document from in-memory bytes.
41    pub fn open_from_bytes(bytes: &[u8]) -> PdfResult<Self> {
42        let inner = PDDocument::load_from_bytes(bytes)?;
43        Ok(Self { inner })
44    }
45
46    /// Adds a blank page with the specified dimensions (e.g. `PDRectangle::A4`).
47    pub fn add_blank_page(&mut self, size: PDRectangle) -> usize {
48        let page = PDPage::new(size);
49        self.inner.add_page(page);
50        self.inner.page_count() - 1
51    }
52
53    /// Returns the total number of pages.
54    pub fn page_count(&self) -> usize {
55        self.inner.page_count()
56    }
57
58    /// Sets the document title in metadata.
59    pub fn set_title(&mut self, title: impl Into<String>) -> &mut Self {
60        self.inner.info.set_title(title);
61        self
62    }
63
64    /// Sets the document author in metadata.
65    pub fn set_author(&mut self, author: impl Into<String>) -> &mut Self {
66        self.inner.info.set_author(author);
67        self
68    }
69
70    /// Draws onto a page using a closure that receives a `PDPageContentStream`.
71    pub fn draw_on_page<F>(&mut self, page_index: usize, mode: AppendMode, f: F) -> PdfResult<()>
72    where
73        F: FnOnce(&mut PDPageContentStream, &mut PDDocument) -> PdfResult<()>,
74    {
75        let mut stream = PDPageContentStream::new(mode);
76        stream.save_graphics_state();
77        f(&mut stream, &mut self.inner)?;
78        stream.restore_graphics_state();
79        stream.finish(&mut self.inner, page_index)
80    }
81
82    /// Returns a fluent Stamper for watermarking, headers/footers, and rubber stamps.
83    pub fn stamp(&self) -> Stamper {
84        Stamper::new()
85    }
86
87    /// Applies a simple diagonal text watermark across all pages.
88    pub fn watermark(&mut self, text: impl Into<String>) -> PdfResult<()> {
89        self.stamp().simple_watermark(text).apply(&mut self.inner)
90    }
91
92    /// Digitally signs the document using the given Signer and returns signed PDF bytes.
93    pub fn sign(&mut self, signer: Signer) -> PdfResult<Vec<u8>> {
94        signer.sign_document(&mut self.inner)
95    }
96
97    /// Extracts all text from the document.
98    pub fn extract_text(&self) -> PdfResult<String> {
99        PDFTextStripper::extract_text(&self.inner)
100    }
101
102    /// Merges another document into this document.
103    pub fn merge(&mut self, other: &PdfDocument) -> PdfResult<()> {
104        PDFMerger::append_document(&mut self.inner, &other.inner)
105    }
106
107    /// Splits this document into individual 1-page documents.
108    pub fn split_single_pages(&self) -> PdfResult<Vec<PdfDocument>> {
109        let docs = PDFSplitter::split_into_single_pages(&self.inner)?;
110        Ok(docs
111            .into_iter()
112            .map(|inner| PdfDocument { inner })
113            .collect())
114    }
115
116    /// Flattens all interactive form fields into static page contents.
117    pub fn flatten_forms(&mut self) -> PdfResult<()> {
118        if let Some(mut acro_form) = PDAcroForm::from_doc(&self.inner) {
119            acro_form.flatten(&mut self.inner)?;
120        }
121        Ok(())
122    }
123
124    /// Saves the document to a file path.
125    pub fn save(&mut self, path: impl AsRef<Path>) -> PdfResult<()> {
126        let file = File::create(path)?;
127        self.inner.save_to_writer(file)
128    }
129
130    /// Saves the document to an in-memory byte vector.
131    pub fn to_bytes(&mut self) -> PdfResult<Vec<u8>> {
132        let mut buf = Vec::new();
133        self.inner.save_to_writer(&mut buf)?;
134        Ok(buf)
135    }
136}