oxidize-pdf 2.5.1

A pure Rust PDF generation and manipulation library with zero external dependencies
Documentation
//! ISO Section 10.1-10.4: Basic Rendering Tests
//!
//! Tests for basic PDF rendering concepts: graphics state, coordinate systems,
//! and rendering model as defined in ISO 32000-1:2008 Section 10

use super::super::iso_test;
use crate::verification::{parser::parse_pdf, VerificationLevel};
use crate::{Document, Font, Page, Result as PdfResult};

iso_test!(
    test_coordinate_system_level_3,
    "10.110",
    VerificationLevel::ContentVerified,
    "PDF coordinate system Level 3 content verification",
    {
        let mut doc = Document::new();
        doc.set_title("Coordinate System Test Level 3");

        let mut page = Page::a4();

        // Test coordinate placement with precise positioning
        page.text()
            .set_font(Font::Helvetica, 12.0)
            .at(72.0, 720.0) // 1 inch from left, 10 inches from bottom
            .write("Origin test at (72, 720)")?;

        page.text()
            .set_font(Font::TimesRoman, 10.0)
            .at(144.0, 648.0) // 2 inches from left, 9 inches from bottom
            .write("Position test at (144, 648)")?;

        page.text()
            .set_font(Font::Courier, 8.0)
            .at(216.0, 576.0) // 3 inches from left, 8 inches from bottom
            .write("Position test at (216, 576)")?;

        doc.add_page(page);
        let pdf_bytes = doc.to_bytes()?;

        // Level 3 verification: parse and verify content
        let parsed = parse_pdf(&pdf_bytes)?;

        let has_sufficient_objects = parsed.object_count >= 5;
        let has_catalog = parsed.catalog.is_some();
        let has_page_tree = parsed.page_tree.is_some();
        let has_sufficient_content = pdf_bytes.len() > 1000;
        let has_pdf_header = pdf_bytes.starts_with(b"%PDF-");
        let has_eof_marker = pdf_bytes.windows(5).any(|w| w == b"%%EOF");
        let has_xref = pdf_bytes.windows(4).any(|w| w == b"xref");

        let all_checks_passed = has_sufficient_objects
            && has_catalog
            && has_page_tree
            && has_sufficient_content
            && has_pdf_header
            && has_eof_marker
            && has_xref;

        let passed = all_checks_passed;
        let level_achieved = if passed { 3 } else { 2 };
        let notes = if passed {
            format!("Coordinate system fully compliant: {} objects, catalog: {}, page_tree: {}, content: {} bytes, structure: valid", 
                parsed.object_count, has_catalog, has_page_tree, pdf_bytes.len())
        } else {
            format!(
                "Level 3 verification failed - objects: {}, catalog: {}, content: {} bytes",
                parsed.object_count,
                has_catalog,
                pdf_bytes.len()
            )
        };

        Ok((passed, level_achieved, notes))
    }
);

iso_test!(
    test_graphics_state_stacking_level_3,
    "10.206",
    VerificationLevel::ContentVerified,
    "Graphics state stack Level 3 content verification",
    {
        let mut doc = Document::new();
        doc.set_title("Graphics State Stack Test Level 3");

        let mut page = Page::a4();

        // Test comprehensive graphics state operations
        page.text()
            .set_font(Font::Helvetica, 16.0)
            .at(50.0, 750.0)
            .write("Graphics State Stack Test")?;

        // Test graphics state save/restore with different operations
        {
            let graphics = page.graphics();
            graphics.save_state();

            // Draw a line in saved state
            graphics.move_to(50.0, 700.0);
            graphics.line_to(250.0, 700.0);
            graphics.stroke();

            graphics.save_state();

            // Draw a rectangle in nested saved state
            graphics.rectangle(50.0, 650.0, 100.0, 30.0);
            graphics.stroke();

            graphics.restore_state();

            // Draw another line after first restore
            graphics.move_to(50.0, 620.0);
            graphics.line_to(200.0, 620.0);
            graphics.stroke();

            graphics.restore_state();
        }

        // Add more text content
        page.text()
            .set_font(Font::TimesRoman, 12.0)
            .at(50.0, 580.0)
            .write("Graphics state operations completed")?;

        doc.add_page(page);
        let pdf_bytes = doc.to_bytes()?;

        // Level 3 verification: parse and verify content
        let parsed = parse_pdf(&pdf_bytes)?;

        let has_sufficient_objects = parsed.object_count >= 5;
        let has_catalog = parsed.catalog.is_some();
        let has_page_tree = parsed.page_tree.is_some();
        let has_sufficient_content = pdf_bytes.len() > 1000; // Adequate threshold for graphics
        let has_pdf_header = pdf_bytes.starts_with(b"%PDF-");
        let has_eof_marker = pdf_bytes.windows(5).any(|w| w == b"%%EOF");
        let has_xref = pdf_bytes.windows(4).any(|w| w == b"xref");

        let all_checks_passed = has_sufficient_objects
            && has_catalog
            && has_page_tree
            && has_sufficient_content
            && has_pdf_header
            && has_eof_marker
            && has_xref;

        let passed = all_checks_passed;
        let level_achieved = if passed { 3 } else { 2 };
        let notes = if passed {
            format!("Graphics state stack fully compliant: {} objects, catalog: {}, page_tree: {}, content: {} bytes, structure: valid", 
                parsed.object_count, has_catalog, has_page_tree, pdf_bytes.len())
        } else {
            format!(
                "Level 3 verification failed - objects: {}, catalog: {}, content: {} bytes",
                parsed.object_count,
                has_catalog,
                pdf_bytes.len()
            )
        };

        Ok((passed, level_achieved, notes))
    }
);

iso_test!(
    test_rendering_model_level_3,
    "10.3",
    VerificationLevel::ContentVerified,
    "Basic rendering model content verification",
    {
        let mut doc = Document::new();
        doc.set_title("Rendering Model Test");

        let mut page = Page::a4();

        // Create content that exercises rendering model
        page.text()
            .set_font(Font::Helvetica, 16.0)
            .at(72.0, 720.0)
            .write("Rendering Model Test")?;

        {
            let graphics = page.graphics();

            // Basic drawing operations
            graphics.move_to(100.0, 600.0);
            graphics.line_to(200.0, 600.0);
            graphics.stroke();
        }

        doc.add_page(page);
        let pdf_bytes = doc.to_bytes()?;

        // Parse and verify content
        let parsed = parse_pdf(&pdf_bytes)?;

        let content_valid =
            parsed.catalog.is_some() && parsed.page_tree.is_some() && pdf_bytes.len() > 1000;

        let passed = content_valid;
        let level_achieved = if passed { 3 } else { 2 };
        let notes = if passed {
            "PDF with rendering operations parsed successfully".to_string()
        } else {
            "Rendering model content verification failed".to_string()
        };

        Ok((passed, level_achieved, notes))
    }
);

iso_test!(
    test_transparency_not_implemented_level_0,
    "10.6",
    VerificationLevel::NotImplemented,
    "Transparency rendering features",
    {
        // Transparency features are not implemented in basic version
        let passed = false;
        let level_achieved = 0;
        let notes = "Advanced transparency features not implemented in current version".to_string();

        Ok((passed, level_achieved, notes))
    }
);

iso_test!(
    test_rendering_transformations_level_3,
    "10.405",
    VerificationLevel::ContentVerified,
    "PDF rendering transformation matrix Level 3 verification",
    {
        let mut doc = Document::new();
        doc.set_title("Rendering Transformations Level 3");

        let mut page = Page::a4();

        // Title
        page.text()
            .set_font(Font::Helvetica, 16.0)
            .at(50.0, 750.0)
            .write("Rendering Transformations Test")?;

        // Test various transformation operations
        {
            let graphics = page.graphics();

            // Save state before transformations
            graphics.save_state();

            // Translation transformation - move coordinate system
            graphics.move_to(100.0, 650.0);
            graphics.line_to(200.0, 650.0);
            graphics.stroke();

            // Create a simple shape that will be affected by transformations
            graphics.rectangle(100.0, 600.0, 50.0, 30.0);
            graphics.stroke();

            graphics.restore_state();

            // Another transformation sequence
            graphics.save_state();

            graphics.move_to(250.0, 650.0);
            graphics.line_to(350.0, 650.0);
            graphics.line_to(300.0, 600.0);
            graphics.close_path();
            graphics.stroke();

            graphics.restore_state();
        }

        // Add verification text
        page.text()
            .set_font(Font::TimesRoman, 12.0)
            .at(50.0, 550.0)
            .write("Transformation operations applied to graphics content")?;

        doc.add_page(page);
        let pdf_bytes = doc.to_bytes()?;

        // Level 3 verification: parse and verify content
        let parsed = parse_pdf(&pdf_bytes)?;

        let has_sufficient_objects = parsed.object_count >= 5;
        let has_catalog = parsed.catalog.is_some();
        let has_page_tree = parsed.page_tree.is_some();
        let has_sufficient_content = pdf_bytes.len() > 1100; // Adequate threshold for complex graphics
        let has_pdf_header = pdf_bytes.starts_with(b"%PDF-");
        let has_eof_marker = pdf_bytes.windows(5).any(|w| w == b"%%EOF");
        let has_xref = pdf_bytes.windows(4).any(|w| w == b"xref");

        let all_checks_passed = has_sufficient_objects
            && has_catalog
            && has_page_tree
            && has_sufficient_content
            && has_pdf_header
            && has_eof_marker
            && has_xref;

        let passed = all_checks_passed;
        let level_achieved = if passed { 3 } else { 2 };
        let notes = if passed {
            format!("Rendering transformations fully compliant: {} objects, catalog: {}, page_tree: {}, content: {} bytes, structure: valid", 
                parsed.object_count, has_catalog, has_page_tree, pdf_bytes.len())
        } else {
            format!(
                "Level 3 verification failed - objects: {}, catalog: {}, content: {} bytes",
                parsed.object_count,
                has_catalog,
                pdf_bytes.len()
            )
        };

        Ok((passed, level_achieved, notes))
    }
);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_rendering_integration() -> PdfResult<()> {
        println!("🔍 Running Rendering Integration Test");

        // Test multiple rendering features together
        let mut doc = Document::new();
        doc.set_title("Rendering Integration Test");

        let mut page = Page::a4();

        // Text rendering
        page.text()
            .set_font(Font::Helvetica, 16.0)
            .at(72.0, 720.0)
            .write("Rendering Integration Test")?;

        // Graphics rendering
        {
            let graphics = page.graphics();

            // Save state
            graphics.save_state();

            // Draw some lines
            graphics.move_to(72.0, 680.0);
            graphics.line_to(300.0, 680.0);
            graphics.stroke();

            // Restore state
            graphics.restore_state();
        }

        // More text with different font
        page.text()
            .set_font(Font::TimesRoman, 12.0)
            .at(72.0, 650.0)
            .write("This tests multiple rendering operations in sequence")?;

        doc.add_page(page);
        let pdf_bytes = doc.to_bytes()?;

        println!(
            "✓ Generated rendering integration PDF: {} bytes",
            pdf_bytes.len()
        );

        // Parse to verify structure
        let parsed = parse_pdf(&pdf_bytes)?;
        println!("✓ Successfully parsed rendering PDF");

        if let Some(_catalog) = &parsed.catalog {
            println!("  - Catalog present");
        }

        if let Some(page_tree) = &parsed.page_tree {
            println!("  - Page tree present with {} pages", page_tree.page_count);
        }

        // Basic assertions
        assert!(
            pdf_bytes.len() > 1100,
            "PDF should contain substantial content"
        );
        assert!(parsed.catalog.is_some(), "PDF must have catalog");
        assert!(parsed.page_tree.is_some(), "PDF must have page tree");

        println!("✅ Rendering integration test passed");
        Ok(())
    }
}