2022-07-29 09:46:09 -05:00
|
|
|
//! SVG rendering support.
|
|
|
|
//!
|
|
|
|
//! # Example
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! use qrcode::QrCode;
|
|
|
|
//! use qrcode::render::svg;
|
|
|
|
//!
|
|
|
|
//! let code = QrCode::new(b"Hello").unwrap();
|
|
|
|
//! let svg_xml = code.render::<svg::Color>().build();
|
|
|
|
//! println!("{}", svg_xml);
|
|
|
|
|
2022-08-01 05:50:07 -05:00
|
|
|
#![cfg(feature = "svg")]
|
2022-07-29 09:46:09 -05:00
|
|
|
|
|
|
|
use std::fmt::Write;
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
use crate::render::{Canvas as RenderCanvas, Pixel};
|
|
|
|
use crate::types::Color as ModuleColor;
|
|
|
|
|
|
|
|
/// An SVG color.
|
|
|
|
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
pub struct Color<'a>(pub &'a str);
|
|
|
|
|
|
|
|
impl<'a> Pixel for Color<'a> {
|
|
|
|
type Canvas = Canvas<'a>;
|
|
|
|
type Image = String;
|
|
|
|
|
|
|
|
fn default_color(color: ModuleColor) -> Self {
|
|
|
|
Color(color.select("#000", "#fff"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub struct Canvas<'a> {
|
|
|
|
svg: String,
|
|
|
|
marker: PhantomData<Color<'a>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> RenderCanvas for Canvas<'a> {
|
|
|
|
type Pixel = Color<'a>;
|
|
|
|
type Image = String;
|
|
|
|
|
|
|
|
fn new(width: u32, height: u32, dark_pixel: Color<'a>, light_pixel: Color<'a>) -> Self {
|
|
|
|
Canvas {
|
|
|
|
svg: format!(
|
|
|
|
concat!(
|
|
|
|
r#"<?xml version="1.0" standalone="yes"?>"#,
|
|
|
|
r#"<svg xmlns="http://www.w3.org/2000/svg""#,
|
|
|
|
r#" version="1.1" width="{w}" height="{h}""#,
|
|
|
|
r#" viewBox="0 0 {w} {h}" shape-rendering="crispEdges">"#,
|
|
|
|
r#"<rect x="0" y="0" width="{w}" height="{h}" fill="{bg}"/>"#,
|
|
|
|
r#"<path fill="{fg}" d=""#,
|
|
|
|
),
|
|
|
|
w = width,
|
|
|
|
h = height,
|
|
|
|
fg = dark_pixel.0,
|
|
|
|
bg = light_pixel.0
|
|
|
|
),
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn draw_dark_pixel(&mut self, x: u32, y: u32) {
|
|
|
|
self.draw_dark_rect(x, y, 1, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) {
|
|
|
|
write!(self.svg, "M{l} {t}h{w}v{h}H{l}V{t}", l = left, t = top, w = width, h = height).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_image(mut self) -> String {
|
|
|
|
self.svg.push_str(r#""/></svg>"#);
|
|
|
|
self.svg
|
|
|
|
}
|
|
|
|
}
|