use super::{process_fo_document, validate_pdf_bytes};
#[test]
fn conformance_pdf_renderer_roundtrip() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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="14pt" font-weight="bold">PDF Renderer Test</fo:block>
<fo:block>Content for round-trip conformance test.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"PDF generation should succeed: {:?}",
result.err()
);
let pdf_bytes = result.expect("test: should succeed");
assert!(
pdf_bytes.starts_with(b"%PDF-"),
"Output should be valid PDF"
);
let renderer = fop_pdf_renderer::PdfRenderer::from_bytes(&pdf_bytes);
assert!(
renderer.is_ok(),
"fop-pdf-renderer should parse FOP-generated PDF"
);
let renderer = renderer.expect("test: should succeed");
assert!(renderer.page_count() >= 1, "Should have at least 1 page");
}
#[test]
fn conformance_pdf_renderer_page_count_single() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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>Single page conformance test.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(result.is_ok());
let pdf_bytes = result.expect("test: should succeed");
let renderer = fop_pdf_renderer::PdfRenderer::from_bytes(&pdf_bytes)
.expect("fop-pdf-renderer should parse PDF");
assert_eq!(
renderer.page_count(),
1,
"Single-page document should have 1 page"
);
let page = renderer
.render_page(0, 72.0)
.expect("Page 0 should render successfully");
assert!(page.width > 0, "Rendered page width should be > 0");
assert!(page.height > 0, "Rendered page height should be > 0");
}
#[test]
fn conformance_pdf_renderer_page_dimensions_correct() {
let result = process_fo_document(
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="0mm" margin-bottom="0mm"
margin-left="0mm" margin-right="0mm">
<fo:region-body margin="0mm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4">
<fo:flow flow-name="xsl-region-body">
<fo:block>A4 page dimensions test.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(result.is_ok());
let pdf_bytes = result.expect("test: should succeed");
let renderer = fop_pdf_renderer::PdfRenderer::from_bytes(&pdf_bytes).expect("Should parse");
let page = renderer.render_page(0, 72.0).expect("Should render");
assert!(
(page.width as i32 - 595).abs() <= 5,
"A4 width at 72dpi should be ~595px, got {}",
page.width
);
assert!(
(page.height as i32 - 842).abs() <= 5,
"A4 height at 72dpi should be ~842px, got {}",
page.height
);
}
#[test]
fn conformance_pdf_renderer_render_all_pages() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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>Render all pages conformance test.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(result.is_ok());
let pdf_bytes = result.expect("test: should succeed");
let renderer = fop_pdf_renderer::PdfRenderer::from_bytes(&pdf_bytes).expect("Should parse PDF");
let pages = renderer
.render_all_pages(72.0)
.expect("render_all_pages should succeed");
assert!(!pages.is_empty(), "Should have at least 1 rendered page");
for (i, png) in pages.iter().enumerate() {
assert!(!png.is_empty(), "Page {} PNG should not be empty", i);
let png_sig: &[u8] = &[0x89, b'P', b'N', b'G'];
assert!(png.starts_with(png_sig), "Page {} should be valid PNG", i);
}
}
#[test]
fn conformance_pdf_renderer_colored_blocks() {
let result = process_fo_document(
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 region-name="xsl-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 background-color="navy" color="white" padding="10pt" font-size="18pt">
Dark background block
</fo:block>
<fo:block background-color="yellow" color="black" padding="5pt" font-size="12pt">
Yellow background block
</fo:block>
<fo:block color="red" font-size="14pt">Red colored text</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"Colored blocks PDF generation should succeed"
);
let pdf_bytes = result.expect("test: should succeed");
validate_pdf_bytes(&pdf_bytes);
let renderer =
fop_pdf_renderer::PdfRenderer::from_bytes(&pdf_bytes).expect("Should parse colored PDF");
assert_eq!(renderer.page_count(), 1);
let page = renderer
.render_page(0, 72.0)
.expect("Should render colored page");
assert!(page.width > 0 && page.height > 0);
let _non_white_check = page
.pixels
.chunks(4)
.any(|px| px[0] != 255 || px[1] != 255 || px[2] != 255);
}
#[test]
fn conformance_pdf_renderer_png_output_valid() {
let result = process_fo_document(
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 region-name="xsl-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="12pt">PNG output conformance test.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(result.is_ok());
let pdf_bytes = result.expect("test: should succeed");
let renderer = fop_pdf_renderer::PdfRenderer::from_bytes(&pdf_bytes).expect("Should parse PDF");
let page = renderer
.render_page(0, 96.0)
.expect("Should render at 96 DPI");
let png = page.to_png().expect("to_png should succeed");
let png_sig: &[u8] = &[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
assert!(
png.starts_with(png_sig),
"Output should start with PNG signature"
);
assert!(png.len() > 100, "PNG output should be a reasonable size");
}
#[test]
fn conformance_font_shorthand_all_variants() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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="bold 12pt serif" space-after="4pt">Bold 12pt serif font</fo:block>
<fo:block font="italic 10pt sans-serif" space-after="4pt">Italic 10pt sans-serif</fo:block>
<fo:block font="bold italic 14pt monospace" space-after="4pt">Bold italic 14pt monospace</fo:block>
<fo:block font="normal 11pt/16pt Times New Roman, serif">11pt with 16pt line-height</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"font shorthand should work: {:?}",
result.err()
);
assert!(!result.expect("test: should succeed").is_empty());
}
#[test]
fn conformance_border_shorthand_sides() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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 border="2pt solid black" padding="3mm" space-after="5mm">All 4 borders equal</fo:block>
<fo:block border-top="3pt solid blue" border-bottom="1pt dashed red"
border-left="2pt solid green" border-right="2pt solid green"
padding="3mm" space-after="5mm">Different side borders</fo:block>
<fo:block border-top="3pt double black" border-bottom="3pt double black"
padding="3mm" space-after="5mm">Top and bottom only</fo:block>
<fo:block border-left="5pt solid #003366" padding-left="5mm" space-after="5mm">
Left border accent (decorative)
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"Border shorthand sides should work: {:?}",
result.err()
);
assert!(!result.expect("test: should succeed").is_empty());
}
#[test]
fn conformance_padding_margin_shorthand() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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 border="1pt solid black" padding="5mm" space-after="4mm">
padding: 5mm (all sides equal)
</fo:block>
<fo:block border="1pt solid black" padding="3mm 8mm" space-after="4mm">
padding: 3mm 8mm (top/bottom, left/right)
</fo:block>
<fo:block border="1pt solid black" padding="2mm 6mm 4mm 10mm" space-after="4mm">
padding: top right bottom left
</fo:block>
<fo:block border="1pt solid black" padding-top="8mm" padding-right="2mm"
padding-bottom="8mm" padding-left="2mm" space-after="4mm">
Individual padding sides
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"Padding shorthand should work: {:?}",
result.err()
);
assert!(!result.expect("test: should succeed").is_empty());
}
#[test]
fn conformance_background_shorthand() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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 background-color="#e8f4f8" padding="4mm" space-after="4mm">
Light blue background
</fo:block>
<fo:block background-color="#fff3cd" padding="4mm" border="1pt solid #ffc107" space-after="4mm">
Warning yellow background with border
</fo:block>
<fo:block background-color="#d4edda" padding="4mm" border="1pt solid #28a745" space-after="4mm">
Success green background
</fo:block>
<fo:block background-color="#f8d7da" padding="4mm" border="1pt solid #dc3545">
Error red background
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"Background shorthand should work: {:?}",
result.err()
);
assert!(!result.expect("test: should succeed").is_empty());
}
#[test]
fn conformance_space_shorthand_compound() {
let result = process_fo_document(
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="20mm" margin-right="20mm">
<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="14pt" font-weight="bold"
space-before.minimum="4pt" space-before.optimum="8pt" space-before.maximum="12pt"
space-after.optimum="6pt">
Heading with compound space
</fo:block>
<fo:block space-before="6pt" space-after="6pt">Paragraph 1</fo:block>
<fo:block space-before="6pt" space-after="6pt">Paragraph 2</fo:block>
<fo:block space-before="6pt" space-after="6pt">Paragraph 3</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"##,
);
assert!(
result.is_ok(),
"Space shorthand compound should work: {:?}",
result.err()
);
assert!(!result.expect("test: should succeed").is_empty());
}