fop 0.1.1

FOP (Formatting Objects Processor) — Apache FOP-compatible XSL-FO processor in pure Rust
//! End-to-end example: Parse XSL-FO → Layout → Generate PDF
//!
//! This demonstrates the complete pipeline from XSL-FO input to PDF output.

use fop_core::FoTreeBuilder;
use fop_layout::LayoutEngine;
use fop_render::PdfRenderer;
use std::io::Cursor;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Simple XSL-FO document with text
    let fo_xml = r##"<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <fo:layout-master-set>
    <fo:simple-page-master master-name="A4"
                          page-width="210mm"
                          page-height="297mm"
                          margin-top="20mm"
                          margin-bottom="20mm"
                          margin-left="25mm"
                          margin-right="25mm">
      <fo:region-body/>
    </fo:simple-page-master>
  </fo:layout-master-set>

  <fo:page-sequence master-reference="A4">
    <fo:flow flow-name="xsl-region-body">
      <fo:block font-size="24pt" color="#000000" space-after="12pt">
        Hello, World!
      </fo:block>
      <fo:block font-size="12pt" color="#666666">
        This is a PDF document generated by the Rust FOP implementation.
      </fo:block>
      <fo:block font-size="12pt" color="#666666" space-before="6pt">
        It demonstrates the complete pipeline: XML parsing, layout engine, and PDF rendering.
      </fo:block>
    </fo:flow>
  </fo:page-sequence>
</fo:root>"##;

    println!("=== Apache FOP Rust Implementation ===");
    println!("Phase 2 Demo: Complete FO → Layout → PDF Pipeline\n");

    // Step 1: Parse XSL-FO into FO tree
    println!("Step 1: Parsing XSL-FO document...");
    let builder = FoTreeBuilder::new();
    let cursor = Cursor::new(fo_xml.as_bytes());
    let arena = builder.parse(cursor)?;
    println!("  ✓ Parsed FO tree");
    println!("  ✓ Total nodes: {}", arena.len());

    // Step 2: Run layout engine to generate area tree
    println!("\nStep 2: Running layout engine...");
    let engine = LayoutEngine::new();
    let area_tree = engine.layout(&arena)?;
    println!("  ✓ Generated area tree");
    println!("  ✓ Total areas: {}", area_tree.len());

    // Step 3: Render to PDF
    println!("\nStep 3: Rendering to PDF...");
    let renderer = PdfRenderer::new();
    let pdf_doc = renderer.render(&area_tree)?;
    println!("  ✓ Generated PDF document");
    println!("  ✓ Pages: {}", pdf_doc.pages.len());
    println!("  ✓ Version: PDF-{}", pdf_doc.version);

    // Step 4: Generate PDF bytes
    println!("\nStep 4: Serializing PDF...");
    let pdf_bytes = pdf_doc.to_bytes()?;
    println!("  ✓ PDF size: {} bytes", pdf_bytes.len());

    // Write to file
    let output_path = "/tmp/hello_fop.pdf";
    std::fs::write(output_path, pdf_bytes)?;
    println!("\n=== SUCCESS ===");
    println!("PDF written to: {}", output_path);
    println!("\nNote: This is a minimal PDF with basic structure.");
    println!("Full PDF rendering (fonts, graphics) will be added in Phase 3.");

    Ok(())
}