1pub mod image;
6pub mod parallel;
7pub mod pdf;
8pub mod ps;
9#[cfg(feature = "raster")]
10pub mod raster;
11pub mod svg;
12pub mod text;
13
14pub use fop_types::{FopError, Result};
15pub use image::{ImageFormat, ImageInfo, ImagePlacement};
16pub use parallel::ParallelRenderer;
17pub use pdf::{
18 EncryptionAlgorithm, EncryptionDict, FontConfig, PdfBuiltinFont, PdfCompliance, PdfDocument,
19 PdfGraphics, PdfPermissions, PdfRenderer, PdfSecurity, PdfValidator, SimpleDocumentBuilder,
20 ValidationResult,
21};
22pub use ps::{PsDocument, PsRenderer};
23#[cfg(feature = "raster")]
24pub use raster::{RasterFormat, RasterRenderer};
25pub use svg::{SvgDocument, SvgGraphics, SvgRenderer};
26pub use text::TextRenderer;
27
28#[cfg(test)]
29mod tests {
30 use fop_core::FoTreeBuilder;
31 use fop_layout::{AreaTree, LayoutEngine};
32 use std::io::Cursor;
33
34 fn minimal_area_tree() -> AreaTree {
36 let fo_xml = r##"<?xml version="1.0"?>
37<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
38 <fo:layout-master-set>
39 <fo:simple-page-master master-name="A4"
40 page-width="210mm" page-height="297mm"
41 margin-top="20mm" margin-bottom="20mm"
42 margin-left="20mm" margin-right="20mm">
43 <fo:region-body/>
44 </fo:simple-page-master>
45 </fo:layout-master-set>
46 <fo:page-sequence master-reference="A4">
47 <fo:flow flow-name="xsl-region-body">
48 <fo:block>Hello, world!</fo:block>
49 </fo:flow>
50 </fo:page-sequence>
51</fo:root>"##;
52 let builder = FoTreeBuilder::new();
53 let fo_tree = builder
54 .parse(Cursor::new(fo_xml))
55 .expect("test: should succeed");
56 let engine = LayoutEngine::new();
57 engine.layout(&fo_tree).expect("test: should succeed")
58 }
59
60 #[test]
63 fn test_pdf_render_produces_bytes() {
64 let area_tree = minimal_area_tree();
65 let renderer = crate::PdfRenderer::new();
66 let doc = renderer.render(&area_tree).expect("test: should succeed");
67 let bytes = doc.to_bytes().expect("test: should succeed");
68 assert!(!bytes.is_empty(), "PDF output must not be empty");
69 assert!(
70 bytes.starts_with(b"%PDF-"),
71 "PDF must start with %PDF- header"
72 );
73 }
74
75 #[test]
76 fn test_pdf_render_has_one_page() {
77 let area_tree = minimal_area_tree();
78 let renderer = crate::PdfRenderer::new();
79 let doc = renderer.render(&area_tree).expect("test: should succeed");
80 assert_eq!(
81 doc.pages.len(),
82 1,
83 "single page-sequence must produce 1 PDF page"
84 );
85 }
86
87 #[test]
88 fn test_pdf_render_has_eof() {
89 let area_tree = minimal_area_tree();
90 let renderer = crate::PdfRenderer::new();
91 let bytes = renderer
92 .render(&area_tree)
93 .expect("test: should succeed")
94 .to_bytes()
95 .expect("test: should succeed");
96 let content = String::from_utf8_lossy(&bytes);
97 assert!(content.contains("%%EOF"), "PDF must end with %%EOF");
98 }
99
100 #[test]
101 fn test_pdf_render_contains_text() {
102 let area_tree = minimal_area_tree();
103 let renderer = crate::PdfRenderer::new();
104 let bytes = renderer
105 .render(&area_tree)
106 .expect("test: should succeed")
107 .to_bytes()
108 .expect("test: should succeed");
109 let content = String::from_utf8_lossy(&bytes);
110 assert!(
111 content.contains("Hello, world!"),
112 "PDF must contain the rendered text"
113 );
114 }
115
116 #[test]
119 fn test_svg_render_produces_string() {
120 let area_tree = minimal_area_tree();
121 let renderer = crate::SvgRenderer::new();
122 let result = renderer
123 .render_to_svg(&area_tree)
124 .expect("test: should succeed");
125 assert!(!result.is_empty(), "SVG output must not be empty");
126 }
127
128 #[test]
129 fn test_svg_render_has_xml_declaration() {
130 let area_tree = minimal_area_tree();
131 let renderer = crate::SvgRenderer::new();
132 let result = renderer
133 .render_to_svg(&area_tree)
134 .expect("test: should succeed");
135 assert!(
136 result.starts_with("<?xml"),
137 "SVG output must start with XML declaration"
138 );
139 }
140
141 #[test]
142 fn test_svg_render_has_svg_element() {
143 let area_tree = minimal_area_tree();
144 let renderer = crate::SvgRenderer::new();
145 let result = renderer
146 .render_to_svg(&area_tree)
147 .expect("test: should succeed");
148 assert!(
149 result.contains("<svg"),
150 "SVG output must contain <svg element"
151 );
152 }
153
154 #[test]
155 fn test_svg_render_contains_text() {
156 let area_tree = minimal_area_tree();
157 let renderer = crate::SvgRenderer::new();
158 let result = renderer
159 .render_to_svg(&area_tree)
160 .expect("test: should succeed");
161 assert!(
162 result.contains("Hello, world!"),
163 "SVG output must contain the rendered text"
164 );
165 }
166
167 #[test]
168 fn test_svg_render_pages_produces_one_page() {
169 let area_tree = minimal_area_tree();
170 let renderer = crate::SvgRenderer::new();
171 let pages = renderer
172 .render_to_svg_pages(&area_tree)
173 .expect("test: should succeed");
174 assert_eq!(
175 pages.len(),
176 1,
177 "single page-sequence must produce 1 SVG page"
178 );
179 }
180
181 #[test]
182 fn test_svg_render_each_page_is_valid_svg() {
183 let area_tree = minimal_area_tree();
184 let renderer = crate::SvgRenderer::new();
185 let pages = renderer
186 .render_to_svg_pages(&area_tree)
187 .expect("test: should succeed");
188 for (i, page) in pages.iter().enumerate() {
189 assert!(
190 page.contains("<svg"),
191 "SVG page {i} must contain <svg element"
192 );
193 assert!(page.contains("</svg>"), "SVG page {i} must close </svg>");
194 }
195 }
196
197 #[test]
200 fn test_ps_render_produces_string() {
201 let area_tree = minimal_area_tree();
202 let renderer = crate::PsRenderer::new();
203 let result = renderer
204 .render_to_ps(&area_tree)
205 .expect("test: should succeed");
206 assert!(!result.is_empty(), "PostScript output must not be empty");
207 }
208
209 #[test]
210 fn test_ps_render_has_ps_header() {
211 let area_tree = minimal_area_tree();
212 let renderer = crate::PsRenderer::new();
213 let result = renderer
214 .render_to_ps(&area_tree)
215 .expect("test: should succeed");
216 assert!(
217 result.starts_with("%!PS-Adobe-3.0"),
218 "PostScript output must start with %!PS-Adobe-3.0"
219 );
220 }
221
222 #[test]
223 fn test_ps_render_has_eof() {
224 let area_tree = minimal_area_tree();
225 let renderer = crate::PsRenderer::new();
226 let result = renderer
227 .render_to_ps(&area_tree)
228 .expect("test: should succeed");
229 assert!(
230 result.contains("%%EOF"),
231 "PostScript output must contain %%EOF"
232 );
233 }
234
235 #[test]
236 fn test_ps_render_has_one_page() {
237 let area_tree = minimal_area_tree();
238 let renderer = crate::PsRenderer::new();
239 let result = renderer
240 .render_to_ps(&area_tree)
241 .expect("test: should succeed");
242 assert!(
243 result.contains("%%Pages: 1"),
244 "single page-sequence must produce 1 PostScript page"
245 );
246 }
247
248 #[test]
251 fn test_text_render_produces_string() {
252 let area_tree = minimal_area_tree();
253 let renderer = crate::TextRenderer::new();
254 let result = renderer
255 .render_to_text(&area_tree)
256 .expect("test: should succeed");
257 assert!(!result.is_empty(), "text output must not be empty");
258 }
259
260 #[test]
261 fn test_text_render_contains_content() {
262 let area_tree = minimal_area_tree();
263 let renderer = crate::TextRenderer::new();
264 let result = renderer
265 .render_to_text(&area_tree)
266 .expect("test: should succeed");
267 assert!(
268 result.contains("Hello, world!"),
269 "text output must contain the rendered text"
270 );
271 }
272
273 #[test]
276 fn test_all_renderers_constructible() {
277 let _pdf = crate::PdfRenderer::new();
278 let _svg = crate::SvgRenderer::new();
279 let _ps = crate::PsRenderer::new();
280 let _text = crate::TextRenderer::new();
281 }
283
284 #[test]
285 fn test_pdf_renderer_with_system_fonts_constructible() {
286 let renderer = crate::PdfRenderer::with_system_fonts();
287 let _ = renderer;
288 }
289}