Skip to main content

qr_code_styling/rendering/
pdf_renderer.rs

1//! PDF renderer for QR codes using SVG to PDF vector conversion.
2
3use crate::error::{QRError, Result};
4use svg2pdf::usvg;
5
6/// PDF renderer for converting SVG to PDF format (vector).
7pub struct PdfRenderer;
8
9impl PdfRenderer {
10    /// Render SVG string directly to PDF format (preserves vector quality).
11    pub fn render_from_svg(svg: &str, _width: u32, _height: u32) -> Result<Vec<u8>> {
12        // Create font database and load system fonts
13        let mut fontdb = usvg::fontdb::Database::new();
14        fontdb.load_system_fonts();
15        let fontdb = std::sync::Arc::new(fontdb);
16
17        // Create options with the font database
18        let mut options = usvg::Options::default();
19        options.fontdb = fontdb;
20
21        // Parse SVG using usvg with font database (text will be converted to paths)
22        let tree = usvg::Tree::from_str(svg, &options)
23            .map_err(|e| QRError::SvgError(format!("Failed to parse SVG: {}", e)))?;
24
25        // Convert to PDF using svg2pdf
26        let pdf = svg2pdf::to_pdf(
27            &tree,
28            svg2pdf::ConversionOptions::default(),
29            svg2pdf::PageOptions::default(),
30        )
31        .map_err(|e| QRError::ImageEncodeError(format!("PDF conversion error: {:?}", e)))?;
32
33        Ok(pdf)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn test_pdf_render_from_svg() {
43        let svg = r#"<?xml version="1.0" encoding="UTF-8"?>
44<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
45    <rect x="0" y="0" width="100" height="100" fill="white"/>
46    <rect x="25" y="25" width="50" height="50" fill="black"/>
47</svg>"#;
48
49        let result = PdfRenderer::render_from_svg(svg, 100, 100);
50        assert!(result.is_ok());
51
52        let pdf_bytes = result.unwrap();
53        // PDF files start with %PDF
54        assert!(pdf_bytes.starts_with(b"%PDF"));
55    }
56
57    #[test]
58    fn test_pdf_render_circle() {
59        let svg = r#"<?xml version="1.0" encoding="UTF-8"?>
60<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
61    <circle cx="100" cy="100" r="50" fill="blue"/>
62</svg>"#;
63
64        let result = PdfRenderer::render_from_svg(svg, 200, 200);
65        assert!(result.is_ok());
66    }
67}