mod advanced_tests;
mod basic_tests;
mod cli_tests;
mod conformance_advanced;
mod conformance_basic;
mod conformance_cli_docs;
mod conformance_complex_scenarios;
mod conformance_direction;
mod conformance_edge_cases;
mod conformance_layout;
mod conformance_output_formats;
mod conformance_pdf_renderer;
mod conformance_pdfa;
mod conformance_properties;
mod conformance_realworld;
mod conformance_table_extended;
mod error_tests;
mod i18n_tests;
mod real_world_tests;
mod regression_tests;
mod table_tests;
mod text_flow_tests;
mod verify_tests;
use fop_core::FoTreeBuilder;
use fop_layout::LayoutEngine;
use fop_render::{PdfRenderer, PdfValidator};
use std::fs;
use std::io::Cursor;
pub fn process_fo_document(fo_content: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let builder = FoTreeBuilder::new();
let cursor = Cursor::new(fo_content.as_bytes());
let arena = builder.parse(cursor)?;
let engine = LayoutEngine::new();
let area_tree = engine.layout(&arena)?;
let renderer = PdfRenderer::new();
let pdf_doc = renderer.render_with_fo(&area_tree, &arena)?;
let bytes = pdf_doc.to_bytes()?;
Ok(bytes)
}
pub fn load_fixture(filename: &str) -> String {
let path = format!("tests/integration/fixtures/{}", filename);
fs::read_to_string(&path).unwrap_or_else(|e| panic!("Failed to load fixture {}: {}", path, e))
}
pub fn validate_pdf_bytes(bytes: &[u8]) {
assert!(bytes.len() > 100, "PDF too small: {} bytes", bytes.len());
assert!(
bytes.starts_with(b"%PDF-"),
"Invalid PDF header: {:?}",
&bytes[..20]
);
let validator = PdfValidator::new();
let validation_result = validator.validate_pdf(bytes);
if validation_result.has_errors() {
eprintln!("PDF validation errors: {:?}", validation_result.issues());
}
}
pub fn verify_pdf_rendering(pdf: &[u8], expected_pages: usize) {
let renderer = fop_pdf_renderer::PdfRenderer::from_bytes(pdf).expect("PDF parse failed");
assert_eq!(
renderer.page_count(),
expected_pages,
"Expected {} pages, got {}",
expected_pages,
renderer.page_count()
);
for i in 0..renderer.page_count() {
let page = renderer
.render_page(i, 72.0)
.unwrap_or_else(|e| panic!("Failed to render page {}: {}", i, e));
assert!(page.width > 0, "Page {} has zero width", i);
assert!(page.height > 0, "Page {} has zero height", i);
}
}
pub fn process_fo_document_format(
fo_content: &str,
format: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let builder = FoTreeBuilder::new();
let cursor = Cursor::new(fo_content.as_bytes());
let arena = builder.parse(cursor)?;
let engine = LayoutEngine::new();
let area_tree = engine.layout(&arena)?;
match format {
"ps" => {
use fop_render::PsRenderer;
let renderer = PsRenderer::new();
let ps_string = renderer.render_to_ps(&area_tree)?;
Ok(ps_string.into_bytes())
}
"text" => {
use fop_render::TextRenderer;
let renderer = TextRenderer::new();
let text_string = renderer.render_to_text(&area_tree)?;
Ok(text_string.into_bytes())
}
"svg" => {
use fop_render::SvgRenderer;
let renderer = SvgRenderer::new();
let svg_string = renderer.render_to_svg(&area_tree)?;
Ok(svg_string.into_bytes())
}
_ => {
let renderer = fop_render::PdfRenderer::new();
let pdf_doc = renderer.render_with_fo(&area_tree, &arena)?;
let bytes = pdf_doc.to_bytes()?;
Ok(bytes)
}
}
}