qrcode_rs/render/
svg.rs

1//! SVG rendering support.
2//!
3//! # Example
4//!
5//! ```
6//! use qrcode_rs::QrCode;
7//! use qrcode_rs::render::svg;
8//!
9//! let code = QrCode::new(b"Hello").unwrap();
10//! let svg_xml = code.render::<svg::Color>().build();
11//! println!("{}", svg_xml);
12
13#![cfg(feature = "svg")]
14
15use std::fmt::Write;
16use std::marker::PhantomData;
17
18use crate::render::{Canvas as RenderCanvas, Pixel};
19use crate::types::Color as ModuleColor;
20
21/// An SVG color.
22#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct Color<'a>(pub &'a str);
24
25impl<'a> Pixel for Color<'a> {
26    type Image = String;
27    type Canvas = Canvas<'a>;
28
29    fn default_color(color: ModuleColor) -> Self {
30        Color(color.select("#000", "#fff"))
31    }
32}
33
34#[doc(hidden)]
35pub struct Canvas<'a> {
36    svg: String,
37    marker: PhantomData<Color<'a>>,
38}
39
40impl<'a> RenderCanvas for Canvas<'a> {
41    type Pixel = Color<'a>;
42    type Image = String;
43
44    fn new(width: u32, height: u32, dark_pixel: Color<'a>, light_pixel: Color<'a>) -> Self {
45        Canvas {
46            svg: format!(
47                concat!(
48                    r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>"#,
49                    r#"<svg xmlns="http://www.w3.org/2000/svg""#,
50                    r#" version="1.1" width="{w}" height="{h}""#,
51                    r#" viewBox="0 0 {w} {h}" shape-rendering="crispEdges">"#,
52                    r#"<rect x="0" y="0" width="{w}" height="{h}" fill="{bg}"/>"#,
53                    r#"<path fill="{fg}" d=""#,
54                ),
55                w = width,
56                h = height,
57                fg = dark_pixel.0,
58                bg = light_pixel.0
59            ),
60            marker: PhantomData,
61        }
62    }
63
64    fn draw_dark_pixel(&mut self, x: u32, y: u32) {
65        self.draw_dark_rect(x, y, 1, 1);
66    }
67
68    fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) {
69        write!(self.svg, "M{left} {top}h{width}v{height}H{left}V{top}").unwrap();
70    }
71
72    fn into_image(mut self) -> String {
73        self.svg.push_str(r#""/></svg>"#);
74        self.svg
75    }
76}