Closed
Description
Type of issue
[ x] Bug
[ ] Question (e.g. about handling/usage)
[ ] Request for new feature/improvement
Expected Behavior
Rendering to SVG should work for every (sane) combination of resulting module count and view box.
Current Behavior
Some combinations of input and view box lead to an IndexOutOfRangeException in SvgQRCode.GetGraphic()
.
Possible Solution
It seems the rounding in the back-and-forth calculation of indices and real sizes lead to this error.
I've refactored the GetGraphic method to (in my opinion) clarify the calculations a bit.
If you want, I can create a pull request for this.
public string GetGraphic(Size viewBox, string darkColorHex, string lightColorHex, bool drawQuietZones = true)
{
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 svgFile = new StringBuilder($@"<svg version=""1.1"" baseProfile=""full"" shape-rendering=""crispEdges"" width=""{viewBox.Width}"" height=""{viewBox.Height}"" xmlns=""http://www.w3.org/2000/svg"">");
svgFile.AppendLine($@"<rect x=""0"" y=""0"" width=""{CleanSvgVal(qrSize)}"" height=""{CleanSvgVal(qrSize)}"" fill=""{lightColorHex}"" />");
for (int xi = offset; xi < offset + drawableModulesCount; xi++)
{
for (int yi = offset; yi < offset + drawableModulesCount; yi++)
{
if (this.QrCodeData.ModuleMatrix[xi][yi])
{
var x = (xi - offset) * pixelsPerModule;
var y = (yi - offset) * pixelsPerModule;
svgFile.AppendLine($@"<rect x=""{CleanSvgVal(x)}"" y=""{CleanSvgVal(y)}"" width=""{CleanSvgVal(pixelsPerModule)}"" height=""{CleanSvgVal(pixelsPerModule)}"" fill=""{darkColorHex}"" />");
}
}
}
svgFile.Append(@"</svg>");
return svgFile.ToString();
}
Steps to Reproduce (for bugs)
var generator = new QRCodeGenerator();
var data = generator.CreateQrCode("abc01234567890", QRCodeGenerator.ECCLevel.L, true, true);
var svg = new SvgQRCode(data);
var svgString = svg.GetGraphic(new Size(256,256), "#000000", "#ffffff", true);