oxidize_pdf/lib.rs
1//! # oxidize-pdf
2//!
3//! A comprehensive, pure Rust PDF library for generation, parsing, and manipulation with zero external PDF dependencies.
4//!
5//! ## Features
6//!
7//! - **PDF Generation**: Create multi-page documents with text, graphics, and images
8//! - **PDF Parsing**: Complete parser supporting rendering and content extraction
9//! - **PDF Operations**: Split, merge, rotate, and extract pages
10//! - **Text Extraction**: Extract text with position and formatting information
11//! - **Resource Access**: Work with fonts, images, and other PDF resources
12//! - **Pure Rust**: No C dependencies or external libraries
13//! - **100% Native**: Complete PDF implementation from scratch
14//!
15//! ## Quick Start
16//!
17//! ### Creating PDFs
18//!
19//! ```rust
20//! use oxidize_pdf_core::{Document, Page, Font, Color, Result};
21//!
22//! # fn main() -> Result<()> {
23//! // Create a new document
24//! let mut doc = Document::new();
25//! doc.set_title("My PDF");
26//!
27//! // Create a page
28//! let mut page = Page::a4();
29//!
30//! // Add text
31//! page.text()
32//! .set_font(Font::Helvetica, 24.0)
33//! .at(50.0, 700.0)
34//! .write("Hello, PDF!")?;
35//!
36//! // Add graphics
37//! page.graphics()
38//! .set_fill_color(Color::rgb(0.0, 0.5, 1.0))
39//! .circle(300.0, 400.0, 50.0)
40//! .fill();
41//!
42//! // Save the document
43//! doc.add_page(page);
44//! doc.save("output.pdf")?;
45//! # Ok(())
46//! # }
47//! ```
48//!
49//! ### Parsing PDFs
50//!
51//! ```rust,no_run
52//! use oxidize_pdf_core::parser::{PdfDocument, PdfReader};
53//!
54//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
55//! // Open and parse a PDF
56//! let reader = PdfReader::open("document.pdf")?;
57//! let document = PdfDocument::new(reader);
58//!
59//! // Get document information
60//! println!("Pages: {}", document.page_count()?);
61//! println!("Version: {}", document.version()?);
62//!
63//! // Process pages
64//! for i in 0..document.page_count()? {
65//! let page = document.get_page(i)?;
66//! println!("Page {} size: {}x{} points", i+1, page.width(), page.height());
67//! }
68//!
69//! // Extract text
70//! let text_pages = document.extract_text()?;
71//! for (i, page_text) in text_pages.iter().enumerate() {
72//! println!("Page {} text: {}", i+1, page_text.text);
73//! }
74//! # Ok(())
75//! # }
76//! ```
77//!
78//! ## Modules
79//!
80//! ### Generation Modules
81//! - [`document`] - PDF document creation and management
82//! - [`page`] - Page creation and layout
83//! - [`graphics`] - Vector graphics and images
84//! - [`text`] - Text rendering and flow
85//! - [`writer`] - Low-level PDF writing
86//!
87//! ### Parsing Modules
88//! - [`parser`] - Complete PDF parsing and reading
89//! - [`parser::PdfDocument`] - High-level document interface
90//! - [`parser::ParsedPage`] - Page representation with resources
91//! - [`parser::ContentParser`] - Content stream parsing
92//! - [`parser::PdfObject`] - Low-level PDF objects
93//!
94//! ### Manipulation Modules
95//! - [`operations`] - PDF manipulation (split, merge, rotate)
96//! - [`text::extraction`] - Text extraction with positioning
97//!
98//! ## Examples
99//!
100//! ### Content Stream Processing
101//!
102//! ```rust,no_run
103//! use oxidize_pdf_core::parser::{PdfDocument, PdfReader};
104//! use oxidize_pdf_core::parser::content::{ContentParser, ContentOperation};
105//!
106//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
107//! let reader = PdfReader::open("document.pdf")?;
108//! let document = PdfDocument::new(reader);
109//! let page = document.get_page(0)?;
110//!
111//! // Get and parse content streams
112//! let streams = page.content_streams_with_document(&document)?;
113//! for stream in streams {
114//! let operations = ContentParser::parse(&stream)?;
115//!
116//! for op in operations {
117//! match op {
118//! ContentOperation::ShowText(text) => {
119//! println!("Text: {:?}", String::from_utf8_lossy(&text));
120//! }
121//! ContentOperation::SetFont(name, size) => {
122//! println!("Font: {} at {} pt", name, size);
123//! }
124//! ContentOperation::MoveTo(x, y) => {
125//! println!("Move to ({}, {})", x, y);
126//! }
127//! _ => {} // Handle other operations
128//! }
129//! }
130//! }
131//! # Ok(())
132//! # }
133//! ```
134//!
135//! ### Resource Access
136//!
137//! ```rust,no_run
138//! use oxidize_pdf_core::parser::{PdfDocument, PdfReader};
139//!
140//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
141//! let reader = PdfReader::open("document.pdf")?;
142//! let document = PdfDocument::new(reader);
143//! let page = document.get_page(0)?;
144//!
145//! // Access page resources
146//! if let Some(resources) = page.get_resources() {
147//! // Check fonts
148//! if let Some(fonts) = resources.get("Font").and_then(|f| f.as_dict()) {
149//! for (name, _) in &fonts.0 {
150//! println!("Font resource: {}", name.as_str());
151//! }
152//! }
153//!
154//! // Check images/XObjects
155//! if let Some(xobjects) = resources.get("XObject").and_then(|x| x.as_dict()) {
156//! for (name, _) in &xobjects.0 {
157//! println!("XObject resource: {}", name.as_str());
158//! }
159//! }
160//! }
161//! # Ok(())
162//! # }
163//! ```
164
165pub mod document;
166pub mod error;
167pub mod graphics;
168pub mod objects;
169pub mod operations;
170pub mod page;
171pub mod parser;
172pub mod text;
173pub mod writer;
174
175#[cfg(feature = "semantic")]
176pub mod semantic;
177
178// Re-export generation types
179pub use document::{Document, DocumentMetadata};
180pub use error::{OxidizePdfError, PdfError, Result};
181pub use graphics::{Color, GraphicsContext, Image, ImageColorSpace, ImageFormat};
182pub use page::{Margins, Page};
183pub use text::{
184 measure_text, split_into_words, Font, FontFamily, TextAlign, TextContext, TextFlowContext,
185};
186
187// Re-export parsing types
188pub use parser::{
189 ContentOperation, ContentParser, DocumentMetadata as ParsedDocumentMetadata,
190 ParsedPage, PdfArray, PdfDictionary, PdfDocument, PdfName, PdfObject,
191 PdfReader, PdfStream, PdfString,
192};
193
194// Re-export operations
195pub use operations::{merge_pdfs, rotate_pdf_pages, split_pdf};
196
197/// Current version of oxidize-pdf
198pub const VERSION: &str = env!("CARGO_PKG_VERSION");
199
200/// Supported PDF versions
201pub mod pdf_version {
202 /// PDF 1.0 - 1.7 are fully supported
203 pub const SUPPORTED_VERSIONS: &[&str] = &["1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7"];
204 /// PDF 2.0 support is planned
205 pub const PLANNED_VERSIONS: &[&str] = &["2.0"];
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[test]
213 fn test_create_empty_document() {
214 let doc = Document::new();
215 assert_eq!(doc.pages.len(), 0);
216 }
217
218 #[test]
219 fn test_create_page() {
220 let page = Page::new(595.0, 842.0);
221 assert_eq!(page.width(), 595.0);
222 assert_eq!(page.height(), 842.0);
223 }
224
225 #[test]
226 fn test_version_info() {
227 assert!(!VERSION.is_empty());
228 assert!(pdf_version::SUPPORTED_VERSIONS.contains(&"1.7"));
229 }
230}