@@ -54,6 +54,9 @@ public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex
54
54
double pixelsPerModule = Math . Min ( viewBox . Width , viewBox . Height ) / ( double ) drawableModulesCount ;
55
55
double qrSize = drawableModulesCount * pixelsPerModule ;
56
56
string svgSizeAttributes = ( sizingMode == SizingMode . WidthHeightAttribute ) ? $@ "width=""{ viewBox . Width } "" height=""{ viewBox . Height } """ : $@"viewBox = "" 0 0 { viewBox . Width } { viewBox . Height } """;
57
+ ImageAttributes? logoAttr = null;
58
+ if (logo != null)
59
+ logoAttr = GetLogoAttributes(logo, viewBox);
57
60
58
61
// Merge horizontal rectangles
59
62
int[,] matrix = new int[drawableModulesCount, drawableModulesCount];
@@ -66,7 +69,7 @@ public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex
66
69
for (int xi = 0; xi < drawableModulesCount; xi += 1)
67
70
{
68
71
matrix[yi, xi] = 0;
69
- if (bitArray[xi+offset])
72
+ if (bitArray[xi+offset] && !IsBlockedByLogo((xi+offset)*pixelsPerModule, (yi+offset) * pixelsPerModule, logoAttr, pixelsPerModule) )
70
73
{
71
74
if(x0 == -1)
72
75
{
@@ -91,7 +94,7 @@ public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex
91
94
}
92
95
}
93
96
94
- StringBuilder svgFile = new StringBuilder($@"<svg version=""1.1"" baseProfile=""full"" shape-rendering=""crispEdges"" {svgSizeAttributes} xmlns=""http://www.w3.org/2000/svg"">");
97
+ StringBuilder svgFile = new StringBuilder($@"<svg version=""1.1"" baseProfile=""full"" shape-rendering=""crispEdges"" {svgSizeAttributes} xmlns=""http://www.w3.org/2000/svg"" xmlns:xlink=""http://www.w3.org/1999/xlink"" >");
95
98
svgFile.AppendLine($@"<rect x=""0"" y=""0"" width=""{CleanSvgVal(qrSize)}"" height=""{CleanSvgVal(qrSize)}"" fill=""{lightColorHex}"" />");
96
99
for (int yi = 0; yi < drawableModulesCount; yi += 1)
97
100
{
@@ -118,23 +121,55 @@ public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex
118
121
119
122
// Output SVG rectangles
120
123
double x = xi * pixelsPerModule;
121
- svgFile.AppendLine($@"<rect x=""{CleanSvgVal(x)}"" y=""{CleanSvgVal(y)}"" width=""{CleanSvgVal(xL * pixelsPerModule)}"" height=""{CleanSvgVal(yL * pixelsPerModule)}"" fill=""{darkColorHex}"" />");
124
+ if (!IsBlockedByLogo(x, y, logoAttr, pixelsPerModule))
125
+ svgFile.AppendLine($@"<rect x=""{CleanSvgVal(x)}"" y=""{CleanSvgVal(y)}"" width=""{CleanSvgVal(xL * pixelsPerModule)}"" height=""{CleanSvgVal(yL * pixelsPerModule)}"" fill=""{darkColorHex}"" />");
126
+
122
127
}
123
128
}
124
129
}
125
130
126
131
//Render logo, if set
127
132
if (logo != null)
128
- {
133
+ {
129
134
svgFile.AppendLine($@"<svg width=""100%"" height=""100%"" version=""1.1"" xmlns = ""http://www.w3.org/2000/svg"">");
130
- svgFile.AppendLine($@"<image x=""{50 - (logo.GetIconSizePercent() / 2)}% "" y=""{50 - (logo.GetIconSizePercent() / 2)}% "" width=""{logo.GetIconSizePercent()}% "" height=""{logo.GetIconSizePercent()}% "" href=""{logo.GetDataUri()}"" />");
135
+ svgFile.AppendLine($@"<image x=""{CleanSvgVal(logoAttr.Value.X)} "" y=""{CleanSvgVal(logoAttr.Value.Y)} "" width=""{CleanSvgVal(logoAttr.Value.Width)} "" height=""{CleanSvgVal(logoAttr.Value.Height)} "" xlink: href=""{logo.GetDataUri()}"" />");
131
136
svgFile.AppendLine(@"</svg>");
132
137
}
133
138
134
139
svgFile.Append(@"</svg>");
135
140
return svgFile.ToString();
136
141
}
137
142
143
+ private bool IsBlockedByLogo(double x, double y, ImageAttributes? attr, double pixelPerModule)
144
+ {
145
+ if (attr == null)
146
+ return false;
147
+ return x + pixelPerModule >= attr.Value.X && x <= attr.Value.X + attr.Value.Width && y + pixelPerModule >= attr.Value.Y && y <= attr.Value.Y + attr.Value.Height;
148
+ }
149
+
150
+ private ImageAttributes GetLogoAttributes(SvgLogo logo, Size viewBox)
151
+ {
152
+ var imgWidth = logo.GetIconSizePercent() / 100d * viewBox.Width;
153
+ var imgHeight = logo.GetIconSizePercent() / 100d * viewBox.Height;
154
+ var imgPosX = viewBox.Width / 2d - imgWidth / 2d;
155
+ var imgPosY = viewBox.Height / 2d - imgHeight / 2d;
156
+ return new ImageAttributes()
157
+ {
158
+ Width = imgWidth,
159
+ Height = imgHeight,
160
+ X = imgPosX,
161
+ Y = imgPosY
162
+ };
163
+ }
164
+
165
+ private struct ImageAttributes
166
+ {
167
+ public double Width;
168
+ public double Height;
169
+ public double X;
170
+ public double Y;
171
+ }
172
+
138
173
private string CleanSvgVal(double input)
139
174
{
140
175
//Clean double values for international use/formats
@@ -152,13 +187,14 @@ public class SvgLogo
152
187
private string _logoData;
153
188
private string _mediaType;
154
189
private int _iconSizePercent;
190
+ private bool _fillLogoBackground;
155
191
156
192
/// <summary>
157
193
/// Create a logo object to be used in SvgQRCode renderer
158
194
/// </summary>
159
195
/// <param name="iconRasterized">Logo to be rendered as Bitmap/rasterized graphic</param>
160
196
/// <param name="iconSizePercent">Degree of percentage coverage of the QR code by the logo</param>
161
- public SvgLogo(Bitmap iconRasterized, int iconSizePercent = 15)
197
+ public SvgLogo(Bitmap iconRasterized, int iconSizePercent = 15, bool fillLogoBackground = true )
162
198
{
163
199
_iconSizePercent = iconSizePercent;
164
200
using (var ms = new System.IO.MemoryStream())
@@ -170,18 +206,20 @@ public SvgLogo(Bitmap iconRasterized, int iconSizePercent = 15)
170
206
}
171
207
}
172
208
_mediaType = "image/png";
209
+ _fillLogoBackground = fillLogoBackground;
173
210
}
174
211
175
212
/// <summary>
176
213
/// Create a logo object to be used in SvgQRCode renderer
177
214
/// </summary>
178
215
/// <param name="iconVectorized">Logo to be rendered as SVG/vectorized graphic/string</param>
179
216
/// <param name="iconSizePercent">Degree of percentage coverage of the QR code by the logo</param>
180
- public SvgLogo(string iconVectorized, int iconSizePercent = 15)
217
+ public SvgLogo(string iconVectorized, int iconSizePercent = 15, bool fillLogoBackground = true )
181
218
{
182
219
_iconSizePercent = iconSizePercent;
183
220
_logoData = Convert.ToBase64String(Encoding.UTF8.GetBytes(iconVectorized), Base64FormattingOptions.None);
184
221
_mediaType = "image/svg+xml";
222
+ _fillLogoBackground = fillLogoBackground;
185
223
}
186
224
187
225
public string GetDataUri()
@@ -193,6 +231,10 @@ public int GetIconSizePercent()
193
231
{
194
232
return _iconSizePercent;
195
233
}
234
+ public bool FillLogoBackground()
235
+ {
236
+ return _fillLogoBackground;
237
+ }
196
238
}
197
239
}
198
240
0 commit comments