diff --git a/QRCoder/SvgQRCode.cs b/QRCoder/SvgQRCode.cs index f3e6d99e..a5153d4a 100644 --- a/QRCoder/SvgQRCode.cs +++ b/QRCoder/SvgQRCode.cs @@ -1,5 +1,6 @@ -#if NETFRAMEWORK || NETSTANDARD2_0 +#if NETFRAMEWORK || NETSTANDARD2_0 using System; +using System.Collections; using System.Drawing; using System.Text; using static QRCoder.QRCodeGenerator; @@ -44,22 +45,76 @@ public string GetGraphic(Size viewBox, Color darkColor, Color lightColor, bool d public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex, bool drawQuietZones = true, SizingMode sizingMode = SizingMode.WidthHeightAttribute) { - var offset = drawQuietZones ? 0 : 4; - var drawableModulesCount = this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : offset * 2); - var pixelsPerModule = (double)Math.Min(viewBox.Width, viewBox.Height) / (double)drawableModulesCount; - var qrSize = drawableModulesCount * pixelsPerModule; - var svgSizeAttributes = (sizingMode == SizingMode.WidthHeightAttribute) ? $@"width=""{viewBox.Width}"" height=""{viewBox.Height}""" : $@"viewBox=""0 0 {viewBox.Width} {viewBox.Height}"""; - var svgFile = new StringBuilder($@""); + int offset = drawQuietZones ? 0 : 4; + int drawableModulesCount = this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : offset * 2); + double pixelsPerModule = Math.Min(viewBox.Width, viewBox.Height) / (double)drawableModulesCount; + double qrSize = drawableModulesCount * pixelsPerModule; + string svgSizeAttributes = (sizingMode == SizingMode.WidthHeightAttribute) ? $@"width=""{viewBox.Width}"" height=""{viewBox.Height}""" : $@"viewBox=""0 0 {viewBox.Width} {viewBox.Height}"""; + + // Merge horizontal rectangles + int[,] matrix = new int[drawableModulesCount, drawableModulesCount]; + for (int yi = 0; yi < drawableModulesCount; yi += 1) + { + BitArray bitArray = this.QrCodeData.ModuleMatrix[yi]; + + int x0 = -1; + int xL = 0; + for (int xi = 0; xi < drawableModulesCount; xi += 1) + { + matrix[yi, xi] = 0; + if (bitArray[xi]) + { + if(x0 == -1) + { + x0 = xi; + } + xL += 1; + } + else + { + if(xL > 0) + { + matrix[yi, x0] = xL; + x0 = -1; + xL = 0; + } + } + } + + if (xL > 0) + { + matrix[yi, x0] = xL; + } + } + + StringBuilder svgFile = new StringBuilder($@""); svgFile.AppendLine($@""); - for (int xi = offset; xi < offset + drawableModulesCount; xi++) + for (int yi = 0; yi < drawableModulesCount; yi += 1) { - for (int yi = offset; yi < offset + drawableModulesCount; yi++) + double y = yi * pixelsPerModule; + for (int xi = 0; xi < drawableModulesCount; xi += 1) { - if (this.QrCodeData.ModuleMatrix[yi][xi]) + int xL = matrix[yi, xi]; + if(xL > 0) { - var x = (xi - offset) * pixelsPerModule; - var y = (yi - offset) * pixelsPerModule; - svgFile.AppendLine($@""); + // Merge vertical rectangles + int yL = 1; + for (int y2 = yi + 1; y2 < drawableModulesCount; y2 += 1) + { + if(matrix[y2, xi] == xL) + { + matrix[y2, xi] = 0; + yL += 1; + } + else + { + break; + } + } + + // Output SVG rectangles + double x = xi * pixelsPerModule; + svgFile.AppendLine($@""); } } } @@ -92,4 +147,4 @@ public static string GetQRCode(string plainText, int pixelsPerModule, string dar } } -#endif \ No newline at end of file +#endif