1 module qrcode.renderer.image.svg;
2 
3 import qrcode.renderer.image.abstractrender;
4 import qrcode.renderer.color.colorinterface;
5 
6 
7 import std.xml,std.conv, std.format;
8 /**
9 * SVG backend.
10 */
11 class Svg : AbstractRenderer
12 {
13 	/**
14 	* SVG resource.
15 	*
16 	* @var Document
17 	*/
18     protected Document svg;
19 
20 	protected Element defs;
21     /**
22 	* Colors used for drawing.
23 	*
24 	* @var array
25 	*/
26     protected ColorInterface[string]colors;
27     /**
28 	* Prototype IDs.
29 	*
30 	* @var array
31 	*/
32     protected string[string] prototypeIds;
33 
34 	/**
35 	* init(): defined by RendererInterface.
36 	*
37 	* @see    ImageRendererInterface::init()
38 	* @return void
39 	*/
40     public override void initRender()
41     {
42 		auto tag = new Tag("svg");
43 		tag.attr["xmlns"] = "http://www.w3.org/2000/svg";
44 		tag.attr["xmlns:xlink"] = "http://www.w3.org/1999/xlink";
45 		tag.attr["version"] = "1.1";
46 		tag.attr["width"] = to!string(this.finalWidth) ~ "px";
47 		tag.attr["height"] = to!string(this.finalHeight) ~ "px";
48 		tag.attr["viewBox"] = "0 0 " ~ to!string(this.finalWidth) ~ " " ~ to!string(this.finalHeight);
49 		this.svg = new Document(tag);
50 		this.defs = new Element("defs");
51 		//this.svg ~= element;
52     }
53 
54 
55 	/**
56 	* addColor(): defined by RendererInterface.
57 	*
58 	* @see    ImageRendererInterface::addColor()
59 	* @param  string         id
60 	* @param  ColorInterface color
61 	* @return void
62 	* @throws Exception\InvalidArgumentException
63 	*/
64     public override void addColor(string id, ColorInterface color)
65     {
66         this.colors[id] = color.toRgb();
67     }
68     /**
69 	* drawBackground(): defined by RendererInterface.
70 	*
71 	* @see    ImageRendererInterface::drawBackground()
72 	* @param  string colorId
73 	* @return void
74 	*/
75     public override void drawBackground(string colorId)
76     {
77 		auto rect = new Element("rect");
78 		rect.tag.attr["x"] = "0";
79 		rect.tag.attr["y"] = "0";
80 		rect.tag.attr["width"] = to!string(this.finalWidth);
81 		rect.tag.attr["height"] = to!string(this.finalHeight);
82 		rect.tag.attr["fill"] = "#" ~ this.colors[colorId].toString();
83 		this.svg ~= rect;
84     }
85     /**
86 	* drawBlock(): defined by RendererInterface.
87 	*
88 	* @see    ImageRendererInterface::drawBlock()
89 	* @param  integer x
90 	* @param  integer y
91 	* @param  string  colorId
92 	* @return void
93 	*/
94     public override void drawBlock(int x, int y, string colorId)
95     {
96 
97 		auto use = new Element("use");
98 		use.tag.attr["x"] = to!string(x);
99 		use.tag.attr["y"] = to!string(y);
100 		use.tag.attr["xlink:href"] = this.getRectPrototypeId(colorId);
101 		use.tag.attr["xmlns:xmi"] = "http://www.w3.org/1999/xlink";
102 
103       
104 		this.svg ~= use;
105     }
106     /**
107 	* getByteStream(): defined by RendererInterface.
108 	*
109 	* @see    ImageRendererInterface::getByteStream()
110 	* @return string
111 	*/
112     public override string getByteStream()
113     {
114 		import std..string;
115 		this.svg ~= this.defs;
116 		this.prototypeIds = string[string].init;
117         return this.svg.toString();
118     }
119     /**
120 	* Get the prototype ID for a color.
121 	*
122 	* @param  integer colorId
123 	* @return string
124 	*/
125     protected string getRectPrototypeId(string colorId)
126     {
127 		auto p = colorId in this.prototypeIds;
128 		if(p)
129 		{
130 			return *p;
131 		}
132         auto id = "r" ~ format("%X", this.prototypeIds.length);
133         //srect = this.svg.defs.addChild('rect');
134 		auto rect = new Element("rect");
135 		rect.tag.attr["id"] = id;
136 		rect.tag.attr["width"] = to!string(this.blockSize);
137 		rect.tag.attr["height"] = to!string(this.blockSize);
138 		rect.tag.attr["fill"] =  "#" ~ this.colors[colorId].toString();
139 		this.defs ~= rect;
140         /*rect.addAttribute('id', id);
141         rect.addAttribute('width', this.blockSize);
142         rect.addAttribute('height', this.blockSize);
143         rect.addAttribute('fill', '#' . this.colors[colorId]);
144 		*/
145         this.prototypeIds[colorId] = "#" ~ id;
146         return this.prototypeIds[colorId];
147     }
148 }