@@ -21,6 +21,7 @@ class QRMarkup extends QROutputAbstract{
2121
2222 /**
2323 * @return string
24+ * @throws \chillerlan\QRCode\Output\QRCodeOutputException
2425 */
2526 public function dump (){
2627
@@ -68,52 +69,60 @@ protected function toHTML(){
6869 * @return string|bool
6970 */
7071 protected function toSVG (){
71- $ length = ($ this ->moduleCount + ($ this ->options ->addQuietzone ? 8 : 0 )) * $ this ->options ->scale ;
72+ $ scale = $ this ->options ->scale ;
73+ $ length = $ this ->moduleCount * $ scale ;
74+ $ matrix = $ this ->matrix ->matrix ();
7275
73- // svg header
74- $ svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=" ' .$ length .'" height=" ' .$ length .'" viewBox="0 0 ' .$ length .' ' .$ length .'"> ' .$ this ->options ->eol .
75- '<defs><style>rect{shape-rendering:crispEdges}</style></defs> ' .$ this ->options ->eol ;
76+ $ svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=" ' .$ length .'px" height=" ' .$ length .'px"> '
77+ .$ this ->options ->eol
78+ .'<defs> ' .$ this ->options ->svgDefs .'</defs> '
79+ .$ this ->options ->eol ;
7680
77- // @todo: optimize -> see https://github.com/alexeyten/qr-image/blob/master/lib/vector.js
78- foreach ($ this ->options ->moduleValues as $ key => $ value ){
81+ foreach ($ this ->options ->moduleValues as $ M_TYPE => $ value ){
7982
8083 // fallback
8184 if (is_bool ($ value )){
8285 $ value = $ value ? '#000 ' : '#fff ' ;
8386 }
8487
85- // svg body
86- foreach ($ this ->matrix ->matrix () as $ y => $ row ){
88+ $ path = '' ;
89+
90+ foreach ($ matrix as $ y => $ row ){
8791 //we'll combine active blocks within a single row as a lightweight compression technique
88- $ from = - 1 ;
92+ $ start = null ;
8993 $ count = 0 ;
9094
91- foreach ($ row as $ x => $ pixel ){
92- if ($ pixel === $ key ){
95+ foreach ($ row as $ x => $ module ){
96+
97+ if ($ module === $ M_TYPE ){
9398 $ count ++;
9499
95- if ($ from < 0 ){
96- $ from = $ x ;
100+ if ($ start === null ){
101+ $ start = $ x * $ scale ;
102+ }
103+
104+ if ($ row [$ x + 1 ] ?? false ){
105+ continue ;
97106 }
98107 }
99- elseif ($ from >= 0 ){
100- $ svg .= '<rect x=" ' .($ from * $ this ->options ->scale ).'" y=" ' .($ y * $ this ->options ->scale )
101- .'" width=" ' .($ this ->options ->scale * $ count ).'" height=" ' .$ this ->options ->scale .'" fill=" ' .$ value .'" '
102- .(trim ($ this ->options ->cssClass ) !== '' ? ' class=" ' .$ this ->options ->cssClass .'" ' :'' ).' /> '
103- .$ this ->options ->eol ;
108+
109+ if ($ count > 0 ){
110+ $ len = $ count * $ scale ;
111+ $ path .= 'M ' .$ start . ' ' .($ y * $ scale ). ' h ' .$ len .' v ' .$ scale .' h- ' .$ len .'Z ' ;
104112
105113 // reset count
106- $ from = -1 ;
107114 $ count = 0 ;
115+ $ start = null ;
108116 }
109- }
110117
111- // close off the row, if applicable
112- if ($ from >= 0 ){
113- $ svg .= '<rect x=" ' .($ from * $ this ->options ->scale ).'" y=" ' .($ y * $ this ->options ->scale )
114- .'" width=" ' .($ this ->options ->scale * $ count ).'" height=" ' .$ this ->options ->scale .'" class=" ' .$ this ->options ->cssClass .'" fill=" ' .$ value .'" /> ' .$ this ->options ->eol ;
115118 }
119+
116120 }
121+
122+ if (!empty ($ path )){
123+ $ svg .= '<path class="qr- ' .$ M_TYPE .' ' .$ this ->options ->cssClass .'" stroke="transparent" fill=" ' .$ value .'" fill-opacity=" ' .$ this ->options ->svgOpacity .'" d=" ' .$ path .'" /> ' ;
124+ }
125+
117126 }
118127
119128 // close svg
0 commit comments