### Configure Cargo Dependencies Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Example configuration for Cargo.toml including optional features. ```toml pdfpurr = "0.4" pdfpurr = { version = "0.4", features = ["ocr"] } ``` -------------------------------- ### Perform OCR on PDF pages Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Examples of using different OCR engines for image-only PDFs. ```rust // Windows OCR (~95% accuracy, zero dependencies) use pdfpurr::ocr::windows_engine::WindowsOcrEngine; let engine = WindowsOcrEngine::new(); doc.ocr_all_pages(&engine, &OcrConfig::default()).unwrap(); // Tesseract (~85-89%, requires tesseract CLI) use pdfpurr::ocr::tesseract_engine::TesseractEngine; let engine = TesseractEngine::new("eng"); // ocrs (pure Rust, Latin only, requires "ocr" feature) use pdfpurr::ocr::ocrs_engine::OcrsEngine; let engine = OcrsEngine::new("det.rten", "rec.rten").unwrap(); ``` -------------------------------- ### Run Development Commands Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Common CLI commands for testing, benchmarking, and documentation. ```bash cargo test # 1150+ tests cargo bench # Criterion benchmarks cargo clippy # Lint (clean on stable + nightly) cargo doc --no-deps # Docs (zero warnings) ``` -------------------------------- ### Create and Manipulate PDFs Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Demonstrates creating a new document, adding pages, rotating, merging, and saving. ```rust let mut doc = Document::new(); doc.add_page(612.0, 792.0).unwrap(); doc.rotate_page(0, 90).unwrap(); doc.merge(&other_doc).unwrap(); doc.save("output.pdf").unwrap(); ``` -------------------------------- ### Create and validate a PDF document Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Demonstrates creating a new document, adding a page, and verifying the page count. ```rust use pdfpurr::Document; let mut doc = Document::new(); doc.add_page(612.0, 792.0).unwrap(); // US Letter let bytes = doc.to_bytes().unwrap(); let doc = Document::from_bytes(&bytes).unwrap(); assert_eq!(doc.page_count().unwrap(), 1); ``` -------------------------------- ### Page Rendering Source: https://context7.com/pratikp1/pdfpurr/llms.txt Render PDF pages into pixel maps using the tiny-skia engine, supporting custom DPI and PNG export. ```rust use pdfpurr::Document; use pdfpurr::rendering::{Renderer, RenderOptions}; let doc = Document::open("document.pdf").unwrap(); // Configure rendering options let opts = RenderOptions { dpi: 150.0, ..Default::default() }; // Create renderer and render a page let renderer = Renderer::new(&doc, opts); let pixmap = renderer.render_page(0).unwrap(); // Save as PNG pixmap.save_png("page1.png") .map_err(|e| pdfpurr::PdfError::Other(format!("PNG save: {}", e))) .unwrap(); println!("Rendered {}x{} pixels", pixmap.width(), pixmap.height()); // Convenience method for single-page rendering let pixmap = doc.render_page(0, 300.0).unwrap(); // 300 DPI ``` -------------------------------- ### Open and parse PDF documents Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Various methods for loading PDF documents from files, memory, or memory-mapped files. ```rust use pdfpurr::Document; let doc = Document::open("report.pdf").unwrap(); let doc = Document::from_bytes(&data).unwrap(); let doc = Document::from_bytes_with_password(&data, b"secret").unwrap(); let doc = Document::from_bytes_lazy(&data).unwrap(); // parse on demand let doc = Document::open_mmap("large.pdf").unwrap(); // memory-mapped ``` -------------------------------- ### Access Document Structure Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Retrieves outlines, page annotations, form fields, and digital signatures. ```rust let outlines = doc.outlines(); let annots = doc.page_annotations(page); let fields = doc.form_fields(); let sigs = doc.signatures(); ``` -------------------------------- ### Add PDFPurr dependency Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Include the library in your Cargo.toml file. ```toml [dependencies] pdfpurr = "0.4" ``` -------------------------------- ### Create Linearized and Incremental PDF Updates Source: https://context7.com/pratikp1/pdfpurr/llms.txt Generate linearized PDFs for fast web viewing using `to_linearized_bytes()`. To preserve digital signatures or original document integrity, create incremental updates by loading an existing document with `from_bytes` and then using `to_incremental_update`. ```rust use pdfpurr::Document; let mut doc = Document::new(); doc.add_page(612.0, 792.0).unwrap(); doc.add_page(612.0, 792.0).unwrap(); // Linearized output ("Fast Web View") // First page objects appear early for progressive display let linearized = doc.to_linearized_bytes().unwrap(); std::fs::write("linearized.pdf", &linearized).unwrap(); // Incremental update (preserves original bytes + digital signatures) let original = std::fs::read("signed_original.pdf").unwrap(); let mut doc = Document::from_bytes(&original).unwrap(); doc.add_page(612.0, 792.0).unwrap(); // Add content // Original bytes preserved at start, modifications appended let updated = doc.to_incremental_update(&original).unwrap(); std::fs::write("updated.pdf", &updated).unwrap(); ``` -------------------------------- ### Compare content stream text with OCR Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Hybrid approach to verify text reliability by comparing content streams against OCR results. ```rust let result = doc.hybrid_ocr_page(0, &engine, &config).unwrap(); match result.source { TextSource::ContentStream => println!("Text is reliable"), TextSource::Ocr => println!("OCR is better"), TextSource::Both => println!("Disagreement: {}", result.accessible_text), TextSource::Neither => println!("No text found"), } ``` -------------------------------- ### Auto-Tag and Validate Accessibility Source: https://context7.com/pratikp1/pdfpurr/llms.txt Add PDF/UA structure trees to untagged documents and generate accessibility reports. ```rust use pdfpurr::Document; let mut doc = Document::open("untagged.pdf").unwrap(); // Check if document already has structure tree if doc.structure_tree().is_none() { println!("Document is untagged"); // Auto-tag based on detected structure let blocks_tagged = doc.auto_tag("en-US").unwrap(); println!("Tagged {} blocks", blocks_tagged); } // Check accessibility issues let issues = doc.check_accessibility(); for issue in &issues { println!("[{}] {}: {}", issue.severity, issue.description, issue.suggestion ); } // Run PDF/UA validation let report = doc.accessibility_report(); for check in &report.checks { println!("{}: {} - {}", check.name, if check.passed { "PASS" } else { "FAIL" }, check.message ); } ``` -------------------------------- ### Document Creation and Loading Source: https://context7.com/pratikp1/pdfpurr/llms.txt The Document struct handles PDF lifecycle operations including creation, various loading methods, and metadata retrieval. ```rust use pdfpurr::Document; // Create a new empty PDF document let mut doc = Document::new(); // Add pages with dimensions in points (72 points = 1 inch) doc.add_page(612.0, 792.0).unwrap(); // US Letter (8.5" x 11") doc.add_page(595.0, 842.0).unwrap(); // A4 // Serialize to bytes let bytes = doc.to_bytes().unwrap(); // Save to file doc.save("output.pdf").unwrap(); // Open from file let doc = Document::open("input.pdf").unwrap(); // Parse from bytes let doc = Document::from_bytes(&pdf_bytes).unwrap(); // Memory-mapped loading for large files let doc = Document::open_mmap("large.pdf").unwrap(); // Lazy loading (parse objects on demand) let doc = Document::from_bytes_lazy(&pdf_bytes).unwrap(); // Open password-protected PDF let doc = Document::from_bytes_with_password(&pdf_bytes, b"secret").unwrap(); // Get document info println!("Pages: {}", doc.page_count().unwrap()); println!("Title: {:?}", doc.title()); println!("Version: {:?}", doc.version); ``` -------------------------------- ### Access PDF Outlines and Annotations Source: https://context7.com/pratikp1/pdfpurr/llms.txt Retrieve document outlines (bookmarks) and annotations from a specific page. Outlines include titles and destination page numbers, while annotations show their subtype and rectangular coordinates. ```rust use pdfpurr::Document; let doc = Document::open("document.pdf").unwrap(); // Get document outlines (bookmarks) let outlines = doc.outlines(); for outline in &outlines { println!("Bookmark: {} -> page {}", outline.title, outline.destination.unwrap_or(0) ); for child in &outline.children { println!(" - {}", child.title); } } // Get annotations from a page let page = doc.get_page(0).unwrap(); let annotations = doc.page_annotations(page); for annot in &annotations { println!("Annotation: {:?} at {:?}", annot.subtype, annot.rect); } ``` -------------------------------- ### Build PDF Content Streams with Rust Source: https://context7.com/pratikp1/pdfpurr/llms.txt Use `ContentStreamBuilder` to programmatically construct PDF content streams. This includes drawing text with specified fonts and positions, drawing graphics like rectangles with custom colors and line widths, and embedding images. Ensure correct state management using `save_state` and `restore_state`. ```rust use pdfpurr::content::ContentStreamBuilder; let mut builder = ContentStreamBuilder::new(); // Draw text builder .begin_text() .set_font("F1", 24.0) .move_to(72.0, 720.0) .show_text("Hello World!") .set_font("F1", 12.0) .move_to(72.0, 700.0) .show_text("This is body text.") .end_text(); // Draw graphics builder .save_state() .set_fill_color_rgb(1.0, 0.0, 0.0) // Red .rect(72.0, 600.0, 200.0, 50.0) .fill() .restore_state(); // Draw lines builder .save_state() .set_stroke_color_rgb(0.0, 0.0, 1.0) // Blue .set_line_width(2.0) .move_line_to(72.0, 550.0) .line_to(272.0, 550.0) .stroke() .restore_state(); // Insert an image XObject builder .save_state() .set_transform(200.0, 0.0, 0.0, 200.0, 72.0, 300.0) .draw_image("Im1") .restore_state(); // Invisible OCR text (rendering mode 3) builder .begin_text() .set_text_rendering_mode(3) .set_font("F_OCR", 12.0) .move_to(100.0, 400.0) .show_text("Invisible OCR text") .end_text(); let content_bytes = builder.build(); ``` -------------------------------- ### Read Metadata Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Accesses the document's Info dictionary and XMP streams. ```rust let meta = doc.metadata(); if let Some(title) = &meta.title { println!("Title: {title}"); } ``` -------------------------------- ### Check PDF accessibility Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Validates document structure against accessibility standards. ```rust let issues = doc.check_accessibility(); for issue in &issues { println!("[{}] {}: {}", issue.severity, issue.description, issue.suggestion); } ``` -------------------------------- ### Structure Detection Source: https://context7.com/pratikp1/pdfpurr/llms.txt Analyze page layouts to identify semantic blocks like headings, paragraphs, and tables based on font metrics and positioning. ```rust use pdfpurr::Document; use pdfpurr::content::structure_detection::BlockRole; let doc = Document::open("document.pdf").unwrap(); // Analyze page structure let blocks = doc.analyze_page_structure(0).unwrap(); for block in &blocks { match &block.role { BlockRole::Heading(level) => { println!("H{}: {}", level, block.runs[0].text); } BlockRole::Paragraph => { let text: String = block.runs.iter().map(|r| r.text.as_str()).collect(); println!("Paragraph: {} chars", text.len()); } BlockRole::ListItem => { println!("List item: {}", block.runs[0].text); } BlockRole::Code => { println!("Code block detected"); } BlockRole::Table => { println!("Table detected"); } _ => {} } } ``` -------------------------------- ### Render PDF Pages Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Renders a specific page to a pixel buffer using the Renderer. ```rust use pdfpurr::{Renderer, RenderOptions}; let renderer = Renderer::new(&doc, RenderOptions { dpi: 150.0, ..Default::default() }); let pixmap = renderer.render_page(0).unwrap(); ``` -------------------------------- ### Perform OCR on Image-Only PDFs Source: https://context7.com/pratikp1/pdfpurr/llms.txt Apply OCR to scanned documents using Windows, Tesseract, or pure Rust engines to create searchable text layers. ```rust use pdfpurr::Document; use pdfpurr::ocr::{OcrConfig, OcrEngine}; let mut doc = Document::open("scanned.pdf").unwrap(); // Windows OCR engine (~95% accuracy, zero dependencies) #[cfg(target_os = "windows")] { use pdfpurr::ocr::windows_engine::WindowsOcrEngine; let engine = WindowsOcrEngine::new(); let config = OcrConfig::default(); // OCR a single page let applied = doc.ocr_page(0, &engine, &config).unwrap(); println!("OCR applied: {}", applied); // OCR all image-only pages let count = doc.ocr_all_pages(&engine, &config).unwrap(); println!("OCR'd {} pages", count); } // Tesseract engine (~85-89% accuracy, requires tesseract CLI) use pdfpurr::ocr::tesseract_engine::TesseractEngine; let engine = TesseractEngine::new("eng"); let config = OcrConfig { dpi: 300.0, language: "eng".to_string(), skip_text_pages: true, // Skip pages that already have text preprocess: true, // Apply contrast/binarization ..Default::default() }; doc.ocr_all_pages(&engine, &config).unwrap(); // Pure Rust ocrs engine (requires "ocr" feature, Latin only) #[cfg(feature = "ocr")] { use pdfpurr::ocr::ocrs_engine::OcrsEngine; let engine = OcrsEngine::new("det.rten", "rec.rten").unwrap(); doc.ocr_all_pages(&engine, &OcrConfig::default()).unwrap(); } // Extract text after OCR let text = doc.extract_page_text(0).unwrap(); println!("Extracted: {}", text); ``` -------------------------------- ### Embed and Subset TrueType/OpenType Fonts Source: https://context7.com/pratikp1/pdfpurr/llms.txt Load TrueType and OpenType fonts, extract font metrics, measure text, create font subsets containing only necessary glyphs, and generate PDF objects for embedding. ```rust use pdfpurr::fonts::embedding::EmbeddedFont; // Load a TrueType font let font_data = std::fs::read("arial.ttf").unwrap(); let font = EmbeddedFont::from_ttf(&font_data).unwrap(); println!("Font: {}", font.ps_name()); println!("Units per em: {}", font.units_per_em()); println!("Ascent: {}", font.ascent()); // Measure text width let width = font.measure_text("Hello World", 12.0).unwrap(); println!("Text width at 12pt: {:.2} points", width); // Create a subset with only needed glyphs let chars_to_include: Vec = "Hello World".chars().collect(); let subset = font.subset(&chars_to_include).unwrap(); println!("Subset has {} glyphs", subset.glyph_count()); // Encode text using the subset let encoded = subset.encode_text("Hello"); // Generate PDF objects for embedding let font_stream = subset.to_font_stream().unwrap(); let font_descriptor = subset.to_font_descriptor(pdfpurr::Object::Null); let font_dict = subset.to_font_dictionary(pdfpurr::Object::Null); let tounicode = subset.to_unicode_cmap().unwrap(); // Variable fonts with axis settings let bold = EmbeddedFont::from_ttf_with_axes(&font_data, &[("wght", 700.0)]).unwrap(); // OpenType CFF fonts let otf_data = std::fs::read("source-code-pro.otf").unwrap(); let otf_font = EmbeddedFont::from_otf(&otf_data).unwrap(); ``` -------------------------------- ### Perform Hybrid OCR and Text Comparison Source: https://context7.com/pratikp1/pdfpurr/llms.txt Compare existing content stream text with OCR output to resolve encoding issues or verify quality. ```rust use pdfpurr::Document; use pdfpurr::ocr::{OcrConfig, hybrid::TextSource}; use pdfpurr::ocr::tesseract_engine::TesseractEngine; let mut doc = Document::open("suspicious.pdf").unwrap(); let engine = TesseractEngine::new("eng"); let config = OcrConfig::default(); let result = doc.hybrid_ocr_page(0, &engine, &config).unwrap(); match result.source { TextSource::ContentStream => { println!("Native text is reliable"); } TextSource::Ocr => { println!("OCR text is better quality"); } TextSource::Both => { println!("Text sources disagree - both preserved"); println!("Accessible text: {}", result.accessible_text); } TextSource::Neither => { println!("No usable text found"); } } ``` -------------------------------- ### Analyze document structure Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Detects document elements like headings, paragraphs, and code blocks. ```rust use pdfpurr::content::structure_detection::BlockRole; let blocks = doc.analyze_page_structure(0).unwrap(); for block in &blocks { match &block.role { BlockRole::Heading(level) => println!("H{level}: {}", block.runs[0].text), BlockRole::Paragraph => println!("P: {} chars", block.runs.len()), BlockRole::ListItem => println!("LI: {}", block.runs[0].text), BlockRole::Code => println!("Code block"), _ => {} } } ``` -------------------------------- ### Extract Images from PDF Source: https://context7.com/pratikp1/pdfpurr/llms.txt Retrieve XObject and inline images from specific pages or the entire document. ```rust use pdfpurr::Document; let doc = Document::open("document.pdf").unwrap(); // Extract all images from all pages let images = doc.extract_all_images().unwrap(); for (page_idx, name, img) in &images { println!("Page {}: {} ({}x{}, {:?})", page_idx, name, img.width, img.height, img.color_space ); } // Extract images from a specific page let page = doc.get_page(0).unwrap(); let page_images = doc.page_images(page); for (name, img) in &page_images { println!("Image {}: {}x{}", name, img.width, img.height); } ``` -------------------------------- ### Read and Modify PDF Form Fields Source: https://context7.com/pratikp1/pdfpurr/llms.txt Interact with AcroForm form fields by listing existing fields and their values, then setting new values and saving the modified PDF. ```rust use pdfpurr::Document; let mut doc = Document::open("form.pdf").unwrap(); // List all form fields let fields = doc.form_fields(); for field in &fields { println!("Field '{}': {:?} = {:?}", field.name, field.field_type, field.value ); } // Set a form field value doc.set_form_field("email", "user@example.com").unwrap(); doc.set_form_field("name", "John Doe").unwrap(); doc.save("filled_form.pdf").unwrap(); ``` -------------------------------- ### Auto-tag PDF content Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Adds a PDF/UA structure tree to an untagged document. ```rust let blocks_tagged = doc.auto_tag("en-US").unwrap(); println!("Tagged {} blocks", blocks_tagged); ``` -------------------------------- ### Access PDF Metadata Source: https://context7.com/pratikp1/pdfpurr/llms.txt Retrieve document metadata such as title, author, subject, creator, producer, and creation date by merging information from the Info dictionary and XMP streams. ```rust use pdfpurr::Document; let doc = Document::open("document.pdf").unwrap(); // Get metadata (merges Info dict and XMP) let meta = doc.metadata(); if let Some(title) = &meta.title { println!("Title: {}", title); } if let Some(author) = &meta.author { println!("Author: {}", author); } if let Some(subject) = &meta.subject { println!("Subject: {}", subject); } if let Some(creator) = &meta.creator { println!("Creator: {}", creator); } if let Some(producer) = &meta.producer { println!("Producer: {}", producer); } if let Some(created) = &meta.creation_date { println!("Created: {}", created); } ``` -------------------------------- ### Extract Images Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Extracts XObject and inline images from the document. ```rust let images = doc.extract_all_images().unwrap(); for (page, name, img) in &images { println!("Page {page}: {name} ({}x{})", img.width, img.height); } ``` -------------------------------- ### Extract Text Runs Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Retrieves positioned text runs including font details, coordinates, and style flags. ```rust let runs = doc.extract_text_runs(0).unwrap(); for run in &runs { println!("{} at ({:.0}, {:.0}) {}pt {}{}", run.text, run.x, run.y, run.font_size, if run.is_bold { "bold " } else { "" }, if run.is_italic { "italic" } else { "" }, ); } ``` -------------------------------- ### Extract text from PDF Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Extract text from a specific page or the entire document. ```rust let text = doc.extract_page_text(0).unwrap(); let all_text = doc.extract_all_text().unwrap(); ``` -------------------------------- ### Validate Standards Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Performs PDF/A validation and generates accessibility reports. ```rust let report = doc.validate_pdfa(PdfALevel::A2b); let a11y = doc.accessibility_report(); ``` -------------------------------- ### Validate PDF Standards Compliance Source: https://context7.com/pratikp1/pdfpurr/llms.txt Check PDF documents for compliance against PDF/A and PDF/X standards. The validation report details each check and whether it passed or failed. ```rust use pdfpurr::Document; use pdfpurr::standards::{PdfALevel, PdfXLevel}; let doc = Document::open("document.pdf").unwrap(); // Validate against PDF/A-2b let pdfa_report = doc.validate_pdfa(PdfALevel::A2b); println!("PDF/A-2b compliance:"); for check in &pdfa_report.checks { println!(" {}: {}", check.name, if check.passed { "OK" } else { "FAIL" }); } // Validate against PDF/X-1a let pdfx_report = doc.validate_pdfx(PdfXLevel::X1a); println!("PDF/X-1a compliance:"); for check in &pdfx_report.checks { println!(" {}: {}", check.name, if check.passed { "OK" } else { "FAIL" }); } ``` -------------------------------- ### Manipulate PDF Pages Source: https://context7.com/pratikp1/pdfpurr/llms.txt Perform document modifications including adding, removing, rotating, reordering, and merging pages. ```rust use pdfpurr::Document; let mut doc = Document::new(); // Add pages doc.add_page(612.0, 792.0).unwrap(); // Page 0 doc.add_page(595.0, 842.0).unwrap(); // Page 1 doc.add_page(612.0, 792.0).unwrap(); // Page 2 // Rotate a page (must be multiple of 90) doc.rotate_page(0, 90).unwrap(); // Remove a page doc.remove_page(1).unwrap(); // Reorder pages (new order: [page2, page0]) doc.reorder_pages(&[1, 0]).unwrap(); // Merge another document let other_doc = Document::open("other.pdf").unwrap(); doc.merge(&other_doc).unwrap(); println!("Total pages: {}", doc.page_count().unwrap()); doc.save("merged.pdf").unwrap(); ``` -------------------------------- ### Linearized Writing and Updates Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Generates linearized bytes or incremental updates for a document. ```rust let linearized = doc.to_linearized_bytes().unwrap(); let incremental = doc.to_incremental_update(&original_bytes).unwrap(); ``` -------------------------------- ### Access Digital Signature Information Source: https://context7.com/pratikp1/pdfpurr/llms.txt Retrieve details about digital signatures present in a signed PDF document, including signer name, signing time, reason, location, and sub-filter. ```rust use pdfpurr::Document; let doc = Document::open("signed.pdf").unwrap(); // Get all signatures let signatures = doc.signatures(); for sig in &signatures { println!("Signer: {:?}", sig.name); println!("Signing time: {:?}", sig.signing_time); println!("Reason: {:?}", sig.reason); println!("Location: {:?}", sig.location); println!("SubFilter: {:?}", sig.sub_filter); } ``` -------------------------------- ### Embed Fonts Source: https://github.com/pratikp1/pdfpurr/blob/main/README.md Embeds TTF, OTF, or variable fonts with support for subsetting. ```rust let font = EmbeddedFont::from_ttf(&data).unwrap(); let subset = font.subset(&['H', 'e', 'l', 'o']).unwrap(); let otf = EmbeddedFont::from_otf(&otf_data).unwrap(); // CFF outlines let bold = EmbeddedFont::from_ttf_with_axes(&data, &[("wght", 700.0)]).unwrap(); ``` -------------------------------- ### Text Extraction Source: https://context7.com/pratikp1/pdfpurr/llms.txt Extract raw text or detailed text runs including font information and coordinates from PDF pages. ```rust use pdfpurr::Document; let doc = Document::open("report.pdf").unwrap(); // Extract text from a specific page (zero-indexed) let text = doc.extract_page_text(0).unwrap(); println!("Page 1 text: {}", text); // Extract text from all pages (separated by form feed \x0C) let all_text = doc.extract_all_text().unwrap(); // Extract positioned text runs with font info, coordinates, and styles let runs = doc.extract_text_runs(0).unwrap(); for run in &runs { println!("{} at ({:.0}, {:.0}) {}pt {}{}", run.text, run.x, run.y, run.font_size, if run.is_bold { "bold " } else { "" }, if run.is_italic { "italic" } else { "" }, ); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.