diff --git a/Cargo.toml b/Cargo.toml index 21bf344..fffcbaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,9 @@ travis-ci = { repository = "kennytm/qrcode-rust" } image = { version = "0.13", optional = true } [features] -default = ["image"] +default = ["image", "svg"] bench = [] +svg = [] [[bin]] name = "qrencode" diff --git a/src/lib.rs b/src/lib.rs index de5411a..e2eb75c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -328,3 +328,29 @@ mod image_tests { } } +#[cfg(all(test, feature="svg"))] +mod svg_tests { + use render::svg::Color as SvgColor; + use {QrCode, Version, EcLevel}; + + #[test] + fn test_annex_i_qr_as_svg() { + let code = QrCode::new(b"01234567").unwrap(); + let image = code.render::().build(); + let expected = include_str!("test_annex_i_qr_as_svg.svg"); + assert_eq!(&image, expected); + } + + #[test] + fn test_annex_i_micro_qr_as_svg() { + let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap(); + let image = code.render() + .min_dimensions(200, 200) + .dark_color(SvgColor("#800000")) + .light_color(SvgColor("#ffff80")) + .build(); + let expected = include_str!("test_annex_i_micro_qr_as_svg.svg"); + assert_eq!(&image, expected); + } +} + diff --git a/src/render/mod.rs b/src/render/mod.rs index 03a46ee..c09a38c 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -5,6 +5,7 @@ use types::Color; pub mod image; pub mod string; +pub mod svg; //------------------------------------------------------------------------------ //{{{ Pixel trait diff --git a/src/render/svg.rs b/src/render/svg.rs new file mode 100644 index 0000000..4779d69 --- /dev/null +++ b/src/render/svg.rs @@ -0,0 +1,69 @@ +//! SVG rendering support. +//! +//! # Example +//! +//! ``` +//! extern crate qrcode; +//! +//! use qrcode::QrCode; +//! use qrcode::render::svg; +//! +//! fn main() { +//! let code = QrCode::new(b"Hello").unwrap(); +//! let svg_xml = code.render::().build(); +//! println!("{}", svg_xml); +//! } + +#![cfg(feature="svg")] + +use std::fmt::Write; +use std::marker::PhantomData; + +use render::{Pixel, Canvas as RenderCanvas}; +use 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>, +} + +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!( + r#" String { + self.svg + r#""/>"# + } +} diff --git a/src/test_annex_i_micro_qr_as_svg.svg b/src/test_annex_i_micro_qr_as_svg.svg new file mode 100644 index 0000000..7f67ecc --- /dev/null +++ b/src/test_annex_i_micro_qr_as_svg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/test_annex_i_qr_as_svg.svg b/src/test_annex_i_qr_as_svg.svg new file mode 100644 index 0000000..72b7ff1 --- /dev/null +++ b/src/test_annex_i_qr_as_svg.svg @@ -0,0 +1 @@ + \ No newline at end of file