qrcode-rust/src/render/svg.rs

77 lines
2.0 KiB
Rust

//! 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);
#![cfg(feature = "svg")]
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
}
}