From c054aac1bd774814412425ea2dcd07c1696f4501 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 19:30:09 +0000 Subject: [PATCH 1/4] fix: correct SkiaSharp platform detection, Dispose pattern, and exception types - Fix MSBuild OS platform conditions in csproj files (was comparing bool to string) - Add GC.SuppressFinalize to all Dispose implementations (CA1816) - Replace generic Exception with ArgumentOutOfRangeException in ArtQRCode - Replace generic Exception with InvalidOperationException in QRCodeData - Remove obsolete SKFilterQuality usage (CS0618) - Fix repository URL to point to afonsoft/QRCoder.Core - Update test to match new exception type Co-Authored-By: Afonso Dutra Nogueira Filho --- QRCoder.Core.Tests/ArtQRCodeRendererTests.cs | 4 ++-- QRCoder.Core.Tests/QRCoder.Core.Tests.csproj | 6 +++--- QRCoder.Core/AbstractQRCode.cs | 11 +++++++++-- QRCoder.Core/ArtQRCode.cs | 5 +---- QRCoder.Core/QRCode.cs | 6 +++--- QRCoder.Core/QRCodeData.cs | 13 ++++++++++++- QRCoder.Core/QRCodeGenerator.cs | 6 +++++- QRCoder.Core/QRCoder.Core.csproj | 8 ++++---- 8 files changed, 39 insertions(+), 20 deletions(-) diff --git a/QRCoder.Core.Tests/ArtQRCodeRendererTests.cs b/QRCoder.Core.Tests/ArtQRCodeRendererTests.cs index bca9633..b473b49 100644 --- a/QRCoder.Core.Tests/ArtQRCodeRendererTests.cs +++ b/QRCoder.Core.Tests/ArtQRCodeRendererTests.cs @@ -69,8 +69,8 @@ public void should_throw_pixelfactor_oor_exception() var exception = Record.Exception(() => aCode.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, pixelSizeFactor: 2)); Assert.NotNull(exception); - Assert.IsType(exception); - exception.Message.ShouldBe("The parameter pixelSize must be between 0 and 1. (0-100%)"); + Assert.IsType(exception); + exception.Message.ShouldContain("pixelSizeFactor"); } [Fact] diff --git a/QRCoder.Core.Tests/QRCoder.Core.Tests.csproj b/QRCoder.Core.Tests/QRCoder.Core.Tests.csproj index 5570dec..983f618 100644 --- a/QRCoder.Core.Tests/QRCoder.Core.Tests.csproj +++ b/QRCoder.Core.Tests/QRCoder.Core.Tests.csproj @@ -58,13 +58,13 @@ - + - + - + diff --git a/QRCoder.Core/AbstractQRCode.cs b/QRCoder.Core/AbstractQRCode.cs index 20d8de1..8c9e615 100644 --- a/QRCoder.Core/AbstractQRCode.cs +++ b/QRCoder.Core/AbstractQRCode.cs @@ -43,21 +43,28 @@ public virtual void SetQRCodeData(QRCodeData data) } /// - /// Dispose + /// Releases all resources used by this instance. /// public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } + /// + /// Releases the unmanaged resources and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { - // Cleanup if (disposing) this.QrCodeData?.Dispose(); this.QrCodeData = null; } + /// + /// Finalizer. + /// ~AbstractQRCode() { Dispose(false); diff --git a/QRCoder.Core/ArtQRCode.cs b/QRCoder.Core/ArtQRCode.cs index 5342040..bb9dd36 100644 --- a/QRCoder.Core/ArtQRCode.cs +++ b/QRCoder.Core/ArtQRCode.cs @@ -62,7 +62,7 @@ public SKBitmap GetGraphic(int pixelsPerModule, SKColor darkSKColor, SKColor lig BackgroundImageStyle backgroundImageStyle = BackgroundImageStyle.DataAreaOnly, SKBitmap finderPatternImage = null) { if (pixelSizeFactor > 1) - throw new Exception("The parameter pixelSize must be between 0 and 1. (0-100%)"); + throw new ArgumentOutOfRangeException(nameof(pixelSizeFactor), "The parameter pixelSizeFactor must be between 0 and 1. (0-100%)"); int pixelSize = (int)Math.Min(pixelsPerModule, Math.Floor(pixelsPerModule / pixelSizeFactor)); var numModules = QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : 8); @@ -221,9 +221,6 @@ private SKBitmap Resize(SKBitmap image, int newSize) using (var brush = new SKPaint { Color = SKColors.Transparent, }) { graphics.DrawRect(new SKRect(0, 0, newSize, newSize), brush); - - brush.FilterQuality = SKFilterQuality.High; // TODO: Update to SKSamplingOptions when available - brush.IsAntialias = true; graphics.DrawBitmap(scaledImage, new SKRect(offsetX, offsetY, offsetX + scaledWidth, offsetY + scaledHeight)); diff --git a/QRCoder.Core/QRCode.cs b/QRCoder.Core/QRCode.cs index 4938892..b77558d 100644 --- a/QRCoder.Core/QRCode.cs +++ b/QRCoder.Core/QRCode.cs @@ -111,9 +111,9 @@ public SKBitmap GetGraphic(int pixelsPerModule, SKColor darkSKColor, SKColor lig using (var lightBrush = new SKPaint { Color = lightSKColor }) using (var darkBrush = new SKPaint { Color = darkSKColor }) { - lightBrush.FilterQuality = SKFilterQuality.High; // TODO: Update to SKSamplingOptions when available - - gfx.Clear(lightSKColor); lightBrush.IsAntialias = true; darkBrush.IsAntialias = true; + gfx.Clear(lightSKColor); + lightBrush.IsAntialias = true; + darkBrush.IsAntialias = true; var drawIconFlag = icon != null && iconSizePercent > 0 && iconSizePercent <= 100; for (var x = 0; x < size + offset; x = x + pixelsPerModule) diff --git a/QRCoder.Core/QRCodeData.cs b/QRCoder.Core/QRCodeData.cs index 056c89f..d837a43 100644 --- a/QRCoder.Core/QRCodeData.cs +++ b/QRCoder.Core/QRCodeData.cs @@ -74,7 +74,7 @@ public QRCodeData(byte[] rawData, Compression compressMode) } if (bytes[0] != 0x51 || bytes[1] != 0x52 || bytes[2] != 0x52) - throw new Exception("Invalid raw data file. Filetype doesn't match \"QRR\"."); + throw new InvalidOperationException("Invalid raw data file. Filetype doesn't match \"QRR\"."); //Set QR code version var sideLen = (int)bytes[4]; @@ -188,17 +188,28 @@ private static int ModulesPerSideFromVersion(int version) return 21 + (version - 1) * 4; } + /// + /// Releases all resources used by this instance. + /// public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } + /// + /// Releases the unmanaged resources and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { this.ModuleMatrix = null; this.Version = 0; } + /// + /// Finalizer. + /// ~QRCodeData() { Dispose(false); diff --git a/QRCoder.Core/QRCodeGenerator.cs b/QRCoder.Core/QRCodeGenerator.cs index 597146f..a645b3e 100644 --- a/QRCoder.Core/QRCodeGenerator.cs +++ b/QRCoder.Core/QRCodeGenerator.cs @@ -1569,9 +1569,13 @@ public SKRectI(int x, int y, int w, int h) } } + /// + /// Releases all resources used by this instance. + /// Kept for backward compatibility. + /// public void Dispose() { - // left for back-compat + GC.SuppressFinalize(this); } } } \ No newline at end of file diff --git a/QRCoder.Core/QRCoder.Core.csproj b/QRCoder.Core/QRCoder.Core.csproj index 6dc8d38..4ac40be 100644 --- a/QRCoder.Core/QRCoder.Core.csproj +++ b/QRCoder.Core/QRCoder.Core.csproj @@ -40,7 +40,7 @@ nuget-icon.png nuget-readme.md c# csharp qr qrcoder qrcode qr-generator qr-code-generator Core NET - https://github.com/codebude/QRCoder.git + https://github.com/afonsoft/QRCoder.Core.git git false QRCoder.Core, written in C#.NET, which enables you to create QR codes. @@ -69,13 +69,13 @@ - + - + - + From 4bb3388516759c04cd45898de38d637822901ac1 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 19:34:03 +0000 Subject: [PATCH 2/4] test: add 92 comprehensive unit tests for improved coverage - QRCodeGenerator: ECC levels, encoding modes, UTF-8, versioning, dispose - QRCodeData: round-trip serialization (Uncompressed/Deflate/GZip), file I/O - AbstractQRCode: SetQRCodeData, idempotent Dispose - QRCode: colors, hex parsing, quiet zones, helper methods - AsciiQRCode: custom symbols, line-by-line, quiet zones - PngByteQRCode: validation, alpha colors, quiet zones - SKBitmapByteQRCode: default/hex/byte colors, helpers - Base64QRCode: PNG/JPEG output, icon support - PdfByteQRCode: PDF validation, colors, DPI - PostscriptQRCode: PS/EPS output, colors, view box - ArtQRCode: pixel size factor, quiet zone styles, argument validation - Extensions: SKColor ToHex/FromHex, StringValueAttribute - DataTooLongException: with/without version - Size struct: constructor, properties - PayloadGenerator: WiFi, Mail, URL, SMS, PhoneNumber, Geolocation, Bookmark - Cross-platform: deterministic output, scaling - HelperFunctions: hash consistency Co-Authored-By: Afonso Dutra Nogueira Filho --- QRCoder.Core.Tests/BestPracticesTests.cs | 1098 ++++++++++++++++++++++ 1 file changed, 1098 insertions(+) create mode 100644 QRCoder.Core.Tests/BestPracticesTests.cs diff --git a/QRCoder.Core.Tests/BestPracticesTests.cs b/QRCoder.Core.Tests/BestPracticesTests.cs new file mode 100644 index 0000000..ad152a9 --- /dev/null +++ b/QRCoder.Core.Tests/BestPracticesTests.cs @@ -0,0 +1,1098 @@ +using System; +using System.Collections; +using System.IO; +using System.Text; +using QRCoder.Core; +using QRCoder.Core.Exceptions; +using QRCoder.Core.Extensions; +using QRCoder.Core.Tests.Helpers; +using QRCoder.Core.Tests.Helpers.XUnitExtenstions; +using SkiaSharp; +using Xunit; +using Shouldly; + +namespace QRCoder.Core.Tests +{ + /// + /// Comprehensive tests for best practices, edge cases, and previously uncovered code paths. + /// + public class BestPracticesTests + { + #region QRCodeGenerator Tests + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_WithEmptyString_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("", QRCodeGenerator.ECCLevel.L); + data.ShouldNotBeNull(); + data.ModuleMatrix.ShouldNotBeNull(); + data.ModuleMatrix.Count.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_WithUnicode_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Olá mundo! 你好世界 🌍", QRCodeGenerator.ECCLevel.M); + data.ShouldNotBeNull(); + data.ModuleMatrix.Count.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_WithUrl_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("https://github.com/afonsoft/QRCoder.Core", QRCodeGenerator.ECCLevel.Q); + data.ShouldNotBeNull(); + } + + [Theory] + [InlineData(QRCodeGenerator.ECCLevel.L)] + [InlineData(QRCodeGenerator.ECCLevel.M)] + [InlineData(QRCodeGenerator.ECCLevel.Q)] + [InlineData(QRCodeGenerator.ECCLevel.H)] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_AllECCLevels_ShouldSucceed(QRCodeGenerator.ECCLevel eccLevel) + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Test", eccLevel); + data.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_ForceUtf8_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Test UTF8", QRCodeGenerator.ECCLevel.M, forceUtf8: true); + data.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_WithUtf8BOM_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Test BOM", QRCodeGenerator.ECCLevel.M, forceUtf8: true, utf8BOM: true); + data.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_WithFixedVersion_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L, requestedVersion: 5); + data.ShouldNotBeNull(); + data.Version.ShouldBe(5); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_Dispose_MultipleTimes_ShouldNotThrow() + { + var gen = new QRCodeGenerator(); + gen.Dispose(); + Should.NotThrow(() => gen.Dispose()); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_NumericMode_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("0123456789", QRCodeGenerator.ECCLevel.L); + data.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCodeGenerator")] + public void QRCodeGenerator_CreateQrCode_AlphanumericMode_ShouldSucceed() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("HELLO WORLD 123", QRCodeGenerator.ECCLevel.L); + data.ShouldNotBeNull(); + } + + #endregion + + #region QRCodeData Tests + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_RoundTrip_Uncompressed_ShouldPreserveData() + { + using var gen = new QRCodeGenerator(); + using var original = gen.CreateQrCode("Round trip test", QRCodeGenerator.ECCLevel.M); + + var rawData = original.GetRawData(QRCodeData.Compression.Uncompressed); + rawData.ShouldNotBeNull(); + rawData.Length.ShouldBeGreaterThan(0); + + using var restored = new QRCodeData(rawData, QRCodeData.Compression.Uncompressed); + restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); + } + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_RoundTrip_Deflate_ShouldPreserveData() + { + using var gen = new QRCodeGenerator(); + using var original = gen.CreateQrCode("Deflate test", QRCodeGenerator.ECCLevel.M); + + var rawData = original.GetRawData(QRCodeData.Compression.Deflate); + rawData.ShouldNotBeNull(); + + using var restored = new QRCodeData(rawData, QRCodeData.Compression.Deflate); + restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); + } + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_RoundTrip_GZip_ShouldPreserveData() + { + using var gen = new QRCodeGenerator(); + using var original = gen.CreateQrCode("GZip test", QRCodeGenerator.ECCLevel.M); + + var rawData = original.GetRawData(QRCodeData.Compression.GZip); + rawData.ShouldNotBeNull(); + + using var restored = new QRCodeData(rawData, QRCodeData.Compression.GZip); + restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); + } + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_InvalidRawData_ShouldThrowInvalidOperationException() + { + var invalidData = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 }; + Should.Throw(() => + new QRCodeData(invalidData, QRCodeData.Compression.Uncompressed)); + } + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_SaveAndLoad_RoundTrip_ShouldPreserveData() + { + var tempPath = Path.Combine(Path.GetTempPath(), $"qrdata_test_{Guid.NewGuid()}.qrr"); + try + { + using var gen = new QRCodeGenerator(); + using var original = gen.CreateQrCode("File round trip", QRCodeGenerator.ECCLevel.M); + + original.SaveRawData(tempPath, QRCodeData.Compression.Uncompressed); + File.Exists(tempPath).ShouldBeTrue(); + + using var restored = new QRCodeData(tempPath, QRCodeData.Compression.Uncompressed); + restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); + } + finally + { + if (File.Exists(tempPath)) + File.Delete(tempPath); + } + } + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_Dispose_ShouldClearModuleMatrix() + { + using var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Dispose test", QRCodeGenerator.ECCLevel.M); + data.ModuleMatrix.ShouldNotBeNull(); + + data.Dispose(); + data.ModuleMatrix.ShouldBeNull(); + } + + [Fact] + [Category("BestPractices/QRCodeData")] + public void QRCodeData_Version_ShouldBePositive() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Version test", QRCodeGenerator.ECCLevel.M); + data.Version.ShouldBeGreaterThan(0); + } + + #endregion + + #region AbstractQRCode Tests + + [Fact] + [Category("BestPractices/AbstractQRCode")] + public void AbstractQRCode_SetQRCodeData_ShouldUpdateData() + { + using var gen = new QRCodeGenerator(); + using var data1 = gen.CreateQrCode("First", QRCodeGenerator.ECCLevel.L); + using var data2 = gen.CreateQrCode("Second with more data", QRCodeGenerator.ECCLevel.H); + + var qrCode = new QRCode(data1); + var size1 = qrCode.GetGraphic(1).Width; + + qrCode.SetQRCodeData(data2); + var size2 = qrCode.GetGraphic(1).Width; + + size2.ShouldNotBe(size1); + } + + [Fact] + [Category("BestPractices/AbstractQRCode")] + public void AbstractQRCode_Dispose_ShouldBeIdempotent() + { + using var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); + var qrCode = new QRCode(data); + + qrCode.Dispose(); + Should.NotThrow(() => qrCode.Dispose()); + } + + #endregion + + #region QRCode Renderer Tests + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_GetGraphic_WithCustomColors_ShouldReturnBitmap() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Color test", QRCodeGenerator.ECCLevel.M); + using var qr = new QRCode(data); + + using var bmp = qr.GetGraphic(5, new SKColor(255, 0, 0), new SKColor(0, 255, 0), true); + bmp.ShouldNotBeNull(); + bmp.Width.ShouldBeGreaterThan(0); + bmp.Height.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_GetGraphic_WithHexColors_ShouldReturnBitmap() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Hex color test", QRCodeGenerator.ECCLevel.M); + using var qr = new QRCode(data); + + using var bmp = qr.GetGraphic(5, "#FF0000", "#00FF00"); + bmp.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_GetGraphic_WithoutQuietZones_ShouldBeSmallerThanWithQuietZones() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Quiet zone test", QRCodeGenerator.ECCLevel.M); + + using var qrWith = new QRCode(data); + using var bmpWith = qrWith.GetGraphic(5, SKColors.Black, SKColors.White, true); + + using var qrWithout = new QRCode(data); + using var bmpWithout = qrWithout.GetGraphic(5, SKColors.Black, SKColors.White, false); + + bmpWithout.Width.ShouldBeLessThan(bmpWith.Width); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_ParseHtmlColor_InvalidFormat_ShouldThrowArgumentException() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); + using var qr = new QRCode(data); + + Should.Throw(() => qr.GetGraphic(5, "#ZZZZZZ", "#ffffff")); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_ParseHtmlColor_EmptyString_ShouldThrowArgumentException() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); + using var qr = new QRCode(data); + + Should.Throw(() => qr.GetGraphic(5, "", "#ffffff")); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_ParseHtmlColor_WithAlpha_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Alpha test", QRCodeGenerator.ECCLevel.L); + using var qr = new QRCode(data); + + using var bmp = qr.GetGraphic(5, "#80000000", "#80FFFFFF"); + bmp.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCode_ParameterlessConstructor_ShouldWork() + { + var qr = new QRCode(); + qr.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/QRCode")] + public void QRCodeHelper_GetQRCode_ShouldReturnValidBitmap() + { + using var bmp = QRCodeHelper.GetQRCode("Helper test", 5, SKColors.Black, SKColors.White, QRCodeGenerator.ECCLevel.M); + bmp.ShouldNotBeNull(); + bmp.Width.ShouldBeGreaterThan(0); + } + + #endregion + + #region AsciiQRCode Tests + + [Fact] + [Category("BestPractices/AsciiQRCode")] + public void AsciiQRCode_GetGraphic_ShouldReturnNonEmptyString() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("ASCII test", QRCodeGenerator.ECCLevel.M); + using var ascii = new AsciiQRCode(data); + + var result = ascii.GetGraphic(1); + result.ShouldNotBeNullOrEmpty(); + result.ShouldContain("██"); + } + + [Fact] + [Category("BestPractices/AsciiQRCode")] + public void AsciiQRCode_GetGraphic_WithCustomSymbols_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Custom symbols", QRCodeGenerator.ECCLevel.M); + using var ascii = new AsciiQRCode(data); + + var result = ascii.GetGraphic(1, "XX", "..", true); + result.ShouldNotBeNullOrEmpty(); + result.ShouldContain("XX"); + result.ShouldContain(".."); + } + + [Fact] + [Category("BestPractices/AsciiQRCode")] + public void AsciiQRCode_GetLineByLineGraphic_ShouldReturnLines() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Line test", QRCodeGenerator.ECCLevel.L); + using var ascii = new AsciiQRCode(data); + + var lines = ascii.GetLineByLineGraphic(1); + lines.ShouldNotBeNull(); + lines.Length.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/AsciiQRCode")] + public void AsciiQRCode_WithoutQuietZones_ShouldHaveFewerLines() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("QZ test", QRCodeGenerator.ECCLevel.L); + + using var withQz = new AsciiQRCode(data); + var linesWith = withQz.GetLineByLineGraphic(1, drawQuietZones: true); + + using var withoutQz = new AsciiQRCode(data); + var linesWithout = withoutQz.GetLineByLineGraphic(1, drawQuietZones: false); + + linesWithout.Length.ShouldBeLessThan(linesWith.Length); + } + + [Fact] + [Category("BestPractices/AsciiQRCode")] + public void AsciiQRCodeHelper_GetQRCode_ShouldReturnString() + { + var result = AsciiQRCodeHelper.GetQRCode("Helper", 1, "██", " ", QRCodeGenerator.ECCLevel.M); + result.ShouldNotBeNullOrEmpty(); + } + + #endregion + + #region PngByteQRCode Tests + + [Fact] + [Category("BestPractices/PngByteQRCode")] + public void PngByteQRCode_GetGraphic_BlackWhite_ShouldReturnValidPng() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PNG test", QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(data); + + var bytes = png.GetGraphic(5); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(8); + // PNG magic number + bytes[0].ShouldBe((byte)0x89); + bytes[1].ShouldBe((byte)0x50); + bytes[2].ShouldBe((byte)0x4E); + bytes[3].ShouldBe((byte)0x47); + } + + [Fact] + [Category("BestPractices/PngByteQRCode")] + public void PngByteQRCode_GetGraphic_WithColors_ShouldReturnValidPng() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Color PNG", QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(data); + + var darkColor = new byte[] { 255, 0, 0 }; + var lightColor = new byte[] { 0, 255, 0 }; + var bytes = png.GetGraphic(5, darkColor, lightColor); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(8); + } + + [Fact] + [Category("BestPractices/PngByteQRCode")] + public void PngByteQRCode_GetGraphic_WithAlpha_ShouldReturnValidPng() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Alpha PNG", QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(data); + + var darkColor = new byte[] { 0, 0, 0, 255 }; + var lightColor = new byte[] { 255, 255, 255, 128 }; + var bytes = png.GetGraphic(5, darkColor, lightColor); + bytes.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/PngByteQRCode")] + public void PngByteQRCode_WithoutQuietZones_ShouldReturnSmallerPng() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("QZ PNG", QRCodeGenerator.ECCLevel.M); + + using var pngWith = new PngByteQRCode(data); + var bytesWith = pngWith.GetGraphic(5, true); + + using var pngWithout = new PngByteQRCode(data); + var bytesWithout = pngWithout.GetGraphic(5, false); + + bytesWithout.Length.ShouldBeLessThan(bytesWith.Length); + } + + #endregion + + #region SKBitmapByteQRCode Tests + + [Fact] + [Category("BestPractices/SKBitmapByteQRCode")] + public void SKBitmapByteQRCode_GetGraphic_Default_ShouldReturnBytes() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("BMP test", QRCodeGenerator.ECCLevel.M); + using var bmp = new SKBitmapByteQRCode(data); + + var bytes = bmp.GetGraphic(5); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + // BMP magic number + bytes[0].ShouldBe((byte)0x42); + bytes[1].ShouldBe((byte)0x4D); + } + + [Fact] + [Category("BestPractices/SKBitmapByteQRCode")] + public void SKBitmapByteQRCode_GetGraphic_WithHexColors_ShouldReturnBytes() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("BMP hex", QRCodeGenerator.ECCLevel.M); + using var bmp = new SKBitmapByteQRCode(data); + + var bytes = bmp.GetGraphic(5, "#FF0000", "#00FF00"); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/SKBitmapByteQRCode")] + public void SKBitmapByteQRCode_GetGraphic_WithByteColors_ShouldReturnBytes() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("BMP byte colors", QRCodeGenerator.ECCLevel.M); + using var bmp = new SKBitmapByteQRCode(data); + + var bytes = bmp.GetGraphic(5, new byte[] { 0, 0, 255 }, new byte[] { 255, 255, 0 }); + bytes.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/SKBitmapByteQRCode")] + public void SKBitmapByteQRCodeHelper_GetQRCode_ShouldReturnBytes() + { + var bytes = SKBitmapByteQRCodeHelper.GetQRCode("Helper", 5, "#000000", "#FFFFFF", QRCodeGenerator.ECCLevel.M); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/SKBitmapByteQRCode")] + public void SKBitmapByteQRCodeHelper_GetQRCode_Simple_ShouldReturnBytes() + { + var bytes = SKBitmapByteQRCodeHelper.GetQRCode("Simple", QRCodeGenerator.ECCLevel.L, 5); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + } + + #endregion + + #region Base64QRCode Tests + + [Fact] + [Category("BestPractices/Base64QRCode")] + public void Base64QRCode_GetGraphic_ShouldReturnValidBase64() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Base64 test", QRCodeGenerator.ECCLevel.M); + using var b64 = new Base64QRCode(data); + + var result = b64.GetGraphic(5); + result.ShouldNotBeNullOrEmpty(); + + // Should be valid Base64 + var decoded = Convert.FromBase64String(result); + decoded.Length.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/Base64QRCode")] + public void Base64QRCode_GetGraphic_AsJpeg_ShouldReturnBase64() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("JPEG test", QRCodeGenerator.ECCLevel.M); + using var b64 = new Base64QRCode(data); + + var result = b64.GetGraphic(5, SKColors.Black, SKColors.White, true, Base64QRCode.ImageType.Jpeg); + result.ShouldNotBeNullOrEmpty(); + } + + [Fact] + [Category("BestPractices/Base64QRCode")] + public void Base64QRCode_GetGraphic_WithIcon_ShouldReturnBase64() + { + if (!HelperFunctions.IsSkiaSharpAvailable()) return; + + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Icon test", QRCodeGenerator.ECCLevel.H); + using var b64 = new Base64QRCode(data); + + using var icon = new SKBitmap(10, 10); + var result = b64.GetGraphic(5, SKColors.Black, SKColors.White, icon, 15, 2); + result.ShouldNotBeNullOrEmpty(); + } + + #endregion + + #region PdfByteQRCode Tests + + [Fact] + [Category("BestPractices/PdfByteQRCode")] + public void PdfByteQRCode_GetGraphic_ShouldReturnValidPdf() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PDF test", QRCodeGenerator.ECCLevel.M); + using var pdf = new PdfByteQRCode(data); + + var bytes = pdf.GetGraphic(5); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + // PDF magic number: %PDF + var header = Encoding.ASCII.GetString(bytes, 0, 5); + header.ShouldStartWith("%PDF"); + } + + [Fact] + [Category("BestPractices/PdfByteQRCode")] + public void PdfByteQRCode_GetGraphic_WithColors_ShouldReturnValidPdf() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PDF color", QRCodeGenerator.ECCLevel.M); + using var pdf = new PdfByteQRCode(data); + + var bytes = pdf.GetGraphic(5, "#FF0000", "#00FF00"); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/PdfByteQRCode")] + public void PdfByteQRCode_GetGraphic_WithCustomDpi_ShouldReturnValidPdf() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PDF DPI", QRCodeGenerator.ECCLevel.M); + using var pdf = new PdfByteQRCode(data); + + var bytes = pdf.GetGraphic(5, "#000000", "#FFFFFF", 300, 95); + bytes.ShouldNotBeNull(); + } + + #endregion + + #region PostscriptQRCode Tests + + [Fact] + [Category("BestPractices/PostscriptQRCode")] + public void PostscriptQRCode_GetGraphic_ShouldReturnValidPostscript() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PS test", QRCodeGenerator.ECCLevel.M); + using var ps = new PostscriptQRCode(data); + + var result = ps.GetGraphic(5); + result.ShouldNotBeNullOrEmpty(); + result.ShouldStartWith("%!PS-Adobe-3.0"); + result.ShouldContain("%%EOF"); + } + + [Fact] + [Category("BestPractices/PostscriptQRCode")] + public void PostscriptQRCode_GetGraphic_AsEps_ShouldReturnValidEps() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("EPS test", QRCodeGenerator.ECCLevel.M); + using var ps = new PostscriptQRCode(data); + + var result = ps.GetGraphic(5, epsFormat: true); + result.ShouldNotBeNullOrEmpty(); + result.ShouldContain("EPSF-3.0"); + } + + [Fact] + [Category("BestPractices/PostscriptQRCode")] + public void PostscriptQRCode_GetGraphic_WithColors_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PS colors", QRCodeGenerator.ECCLevel.M); + using var ps = new PostscriptQRCode(data); + + var result = ps.GetGraphic(5, new SKColor(255, 0, 0), new SKColor(0, 255, 0)); + result.ShouldNotBeNullOrEmpty(); + } + + [Fact] + [Category("BestPractices/PostscriptQRCode")] + public void PostscriptQRCode_GetGraphic_WithHexColors_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PS hex", QRCodeGenerator.ECCLevel.M); + using var ps = new PostscriptQRCode(data); + + var result = ps.GetGraphic(5, "#FF0000", "#00FF00"); + result.ShouldNotBeNullOrEmpty(); + } + + [Fact] + [Category("BestPractices/PostscriptQRCode")] + public void PostscriptQRCode_GetGraphic_WithViewBox_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PS viewbox", QRCodeGenerator.ECCLevel.M); + using var ps = new PostscriptQRCode(data); + + var result = ps.GetGraphic(new Size(200, 200)); + result.ShouldNotBeNullOrEmpty(); + } + + [Fact] + [Category("BestPractices/PostscriptQRCode")] + public void PostscriptQRCode_WithoutQuietZones_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("PS no QZ", QRCodeGenerator.ECCLevel.M); + using var ps = new PostscriptQRCode(data); + + var result = ps.GetGraphic(5, SKColors.Black, SKColors.White, false); + result.ShouldNotBeNullOrEmpty(); + } + + #endregion + + #region ArtQRCode Tests + + [Fact] + [Category("BestPractices/ArtQRCode")] + public void ArtQRCode_GetGraphic_Default_ShouldReturnBitmap() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Art test", QRCodeGenerator.ECCLevel.H); + using var art = new ArtQRCode(data); + + using var bmp = art.GetGraphic(10); + bmp.ShouldNotBeNull(); + bmp.Width.ShouldBeGreaterThan(0); + } + + [Fact] + [Category("BestPractices/ArtQRCode")] + public void ArtQRCode_GetGraphic_WithCustomPixelSizeFactor_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Art pixel", QRCodeGenerator.ECCLevel.H); + using var art = new ArtQRCode(data); + + using var bmp = art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, pixelSizeFactor: 0.5); + bmp.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/ArtQRCode")] + public void ArtQRCode_GetGraphic_FlatQuietZone_ShouldWork() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Art flat QZ", QRCodeGenerator.ECCLevel.H); + using var art = new ArtQRCode(data); + + using var bmp = art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, + quietZoneRenderingStyle: ArtQRCode.QuietZoneStyle.Flat); + bmp.ShouldNotBeNull(); + } + + [Fact] + [Category("BestPractices/ArtQRCode")] + public void ArtQRCode_PixelSizeFactor_GreaterThanOne_ShouldThrow() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Out of range", QRCodeGenerator.ECCLevel.H); + using var art = new ArtQRCode(data); + + Should.Throw(() => + art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, pixelSizeFactor: 1.5)); + } + + #endregion + + #region Extensions Tests + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_ToHex_ShouldReturnCorrectFormat() + { + var color = new SKColor(255, 128, 0, 200); + var hex = color.ToHex(); + + hex.ShouldNotBeNullOrEmpty(); + hex.ShouldStartWith("#"); + hex.Length.ShouldBe(9); // #AARRGGBB + } + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_FromHex_RGB_ShouldReturnCorrectColor() + { + var color = SKColorExtensions.FromHex("#FF0000"); + color.Red.ShouldBe((byte)255); + color.Green.ShouldBe((byte)0); + color.Blue.ShouldBe((byte)0); + } + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_FromHex_ARGB_ShouldReturnCorrectColor() + { + var color = SKColorExtensions.FromHex("#80FF0000"); + color.Red.ShouldBeGreaterThan((byte)0); + } + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_FromHex_Null_ShouldReturnTransparent() + { + var color = SKColorExtensions.FromHex(null); + color.ShouldBe(SKColors.Transparent); + } + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_FromHex_Empty_ShouldReturnTransparent() + { + var color = SKColorExtensions.FromHex(""); + color.ShouldBe(SKColors.Transparent); + } + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_FromHex_InvalidLength_ShouldReturnTransparent() + { + var color = SKColorExtensions.FromHex("#FFF"); + color.ShouldBe(SKColors.Transparent); + } + + [Fact] + [Category("BestPractices/Extensions")] + public void SKColorExtensions_FromHex_WithoutHash_ShouldWork() + { + var color = SKColorExtensions.FromHex("FF0000"); + color.Red.ShouldBe((byte)255); + } + + [Fact] + [Category("BestPractices/Extensions")] + public void StringValueAttribute_ShouldStoreValue() + { + var attr = new StringValueAttribute("test-value"); + attr.StringValue.ShouldBe("test-value"); + } + + #endregion + + #region DataTooLongException Tests + + [Fact] + [Category("BestPractices/Exceptions")] + public void DataTooLongException_WithoutVersion_ShouldContainDetails() + { + var ex = new DataTooLongException("H", "Byte", 100); + ex.Message.ShouldContain("H"); + ex.Message.ShouldContain("Byte"); + ex.Message.ShouldContain("100"); + } + + [Fact] + [Category("BestPractices/Exceptions")] + public void DataTooLongException_WithVersion_ShouldContainDetails() + { + var ex = new DataTooLongException("M", "Alphanumeric", 5, 200); + ex.Message.ShouldContain("M"); + ex.Message.ShouldContain("Alphanumeric"); + ex.Message.ShouldContain("5"); + ex.Message.ShouldContain("200"); + } + + [Fact] + [Category("BestPractices/Exceptions")] + public void DataTooLongException_ShouldBeException() + { + var ex = new DataTooLongException("L", "Numeric", 50); + ex.ShouldBeAssignableTo(); + } + + #endregion + + #region Size Struct Tests + + [Fact] + [Category("BestPractices/Size")] + public void Size_Constructor_ShouldSetProperties() + { + var size = new Size(100.5, 200.5); + size.Width.ShouldBe(100.5); + size.Height.ShouldBe(200.5); + } + + [Fact] + [Category("BestPractices/Size")] + public void Size_Default_ShouldBeZero() + { + var size = new Size(); + size.Width.ShouldBe(0); + size.Height.ShouldBe(0); + } + + [Fact] + [Category("BestPractices/Size")] + public void Size_SetProperties_ShouldWork() + { + var size = new Size(10, 20); + size.Width = 30; + size.Height = 40; + size.Width.ShouldBe(30); + size.Height.ShouldBe(40); + } + + #endregion + + #region PayloadGenerator Basic Tests + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void WiFi_Payload_ShouldGenerateCorrectFormat() + { + var wifi = new PayloadGenerator.WiFi("MyNetwork", "MyPassword", PayloadGenerator.WiFi.Authentication.WPA); + var result = wifi.ToString(); + result.ShouldStartWith("WIFI:"); + result.ShouldContain("T:WPA"); + result.ShouldContain("S:MyNetwork"); + result.ShouldContain("P:MyPassword"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void WiFi_HiddenSSID_ShouldContainHiddenFlag() + { + var wifi = new PayloadGenerator.WiFi("Hidden", "Pass", PayloadGenerator.WiFi.Authentication.WPA, isHiddenSSID: true); + var result = wifi.ToString(); + result.ShouldContain("H:true"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void Mail_Payload_ShouldGenerateCorrectFormat() + { + var mail = new PayloadGenerator.Mail("test@example.com", "Subject", "Body"); + var result = mail.ToString(); + result.ShouldContain("test@example.com"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void Url_Payload_ShouldGenerateCorrectFormat() + { + var url = new PayloadGenerator.Url("https://github.com"); + var result = url.ToString(); + result.ShouldContain("https://github.com"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void SMS_Payload_ShouldGenerateCorrectFormat() + { + var sms = new PayloadGenerator.SMS("+5511999999999", "Hello!"); + var result = sms.ToString(); + result.ShouldContain("+5511999999999"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void PhoneNumber_Payload_ShouldGenerateCorrectFormat() + { + var phone = new PayloadGenerator.PhoneNumber("+5511999999999"); + var result = phone.ToString(); + result.ShouldStartWith("tel:"); + result.ShouldContain("+5511999999999"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void Geolocation_Payload_ShouldGenerateCorrectFormat() + { + var geo = new PayloadGenerator.Geolocation("-23.5505", "-46.6333"); + var result = geo.ToString(); + result.ShouldStartWith("geo:"); + } + + [Fact] + [Category("BestPractices/PayloadGenerator")] + public void Bookmark_Payload_ShouldGenerateCorrectFormat() + { + var bm = new PayloadGenerator.Bookmark("https://github.com", "GitHub"); + var result = bm.ToString(); + result.ShouldContain("github.com"); + result.ShouldContain("GitHub"); + } + + #endregion + + #region Cross-Platform Consistency Tests + + [Fact] + [Category("BestPractices/CrossPlatform")] + public void QRCode_SameInput_ShouldProduceSameModuleMatrix() + { + using var gen1 = new QRCodeGenerator(); + using var gen2 = new QRCodeGenerator(); + + using var data1 = gen1.CreateQrCode("Deterministic test", QRCodeGenerator.ECCLevel.M); + using var data2 = gen2.CreateQrCode("Deterministic test", QRCodeGenerator.ECCLevel.M); + + data1.ModuleMatrix.Count.ShouldBe(data2.ModuleMatrix.Count); + for (int i = 0; i < data1.ModuleMatrix.Count; i++) + { + for (int j = 0; j < data1.ModuleMatrix[i].Count; j++) + { + data1.ModuleMatrix[i][j].ShouldBe(data2.ModuleMatrix[i][j]); + } + } + } + + [Fact] + [Category("BestPractices/CrossPlatform")] + public void PngByteQRCode_SameInput_ShouldProduceSameOutput() + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Deterministic PNG", QRCodeGenerator.ECCLevel.M); + + using var png1 = new PngByteQRCode(data); + var bytes1 = png1.GetGraphic(5); + + using var png2 = new PngByteQRCode(data); + var bytes2 = png2.GetGraphic(5); + + bytes1.Length.ShouldBe(bytes2.Length); + for (int i = 0; i < bytes1.Length; i++) + { + bytes1[i].ShouldBe(bytes2[i]); + } + } + + [Theory] + [InlineData(1)] + [InlineData(5)] + [InlineData(10)] + [InlineData(20)] + [Category("BestPractices/CrossPlatform")] + public void QRCode_DifferentModuleSizes_ShouldScaleCorrectly(int pixelsPerModule) + { + using var gen = new QRCodeGenerator(); + using var data = gen.CreateQrCode("Scale test", QRCodeGenerator.ECCLevel.L); + + using var png = new PngByteQRCode(data); + var bytes = png.GetGraphic(pixelsPerModule); + bytes.ShouldNotBeNull(); + bytes.Length.ShouldBeGreaterThan(0); + } + + #endregion + + #region HelperFunctions Tests + + [Fact] + [Category("BestPractices/Helpers")] + public void HelperFunctions_ByteArrayToHash_ShouldReturnConsistentHash() + { + var data = Encoding.UTF8.GetBytes("test data"); + var hash1 = HelperFunctions.ByteArrayToHash(data); + var hash2 = HelperFunctions.ByteArrayToHash(data); + hash1.ShouldBe(hash2); + } + + [Fact] + [Category("BestPractices/Helpers")] + public void HelperFunctions_StringToHash_ShouldReturnConsistentHash() + { + var hash1 = HelperFunctions.StringToHash("hello"); + var hash2 = HelperFunctions.StringToHash("hello"); + hash1.ShouldBe(hash2); + } + + [Fact] + [Category("BestPractices/Helpers")] + public void HelperFunctions_GetAssemblyPath_ShouldReturnNonEmpty() + { + var path = HelperFunctions.GetAssemblyPath(); + path.ShouldNotBeNullOrEmpty(); + } + + [Fact] + [Category("BestPractices/Helpers")] + public void HelperFunctions_IsSkiaSharpAvailable_ShouldReturnBoolean() + { + // Just ensure it doesn't throw + var result = HelperFunctions.IsSkiaSharpAvailable(); + result.ShouldBeOneOf(true, false); + } + + #endregion + } +} From 596023418ecdd7a6662c92996f3068ec43c81d20 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 19:36:59 +0000 Subject: [PATCH 3/4] docs: add pt-BR and en-US usage guides with examples, update README - Create comprehensive usage guide in Portuguese (pt-BR) - Create comprehensive usage guide in English (en-US) - Both guides cover all output formats: QRCode, PNG, SVG, Base64, PDF, ASCII, Postscript, EPS, Artistic, BMP - Include PayloadGenerator examples: WiFi, URL, Email, SMS, Phone, Geolocation, Bitcoin, vCard, Calendar Events - Add cross-platform examples: ASP.NET Core API, .NET MAUI, Console - Document ECC levels, serialization, UTF-8, and version settings - Update README with bilingual description and links to documentation - Update Quick Start example to use SkiaSharp (not System.Drawing) - Update test count to reflect new tests Co-Authored-By: Afonso Dutra Nogueira Filho --- README.md | 103 ++++---- docs/en-US/usage-guide.md | 487 ++++++++++++++++++++++++++++++++++++++ docs/pt-BR/guia-de-uso.md | 487 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 1026 insertions(+), 51 deletions(-) create mode 100644 docs/en-US/usage-guide.md create mode 100644 docs/pt-BR/guia-de-uso.md diff --git a/README.md b/README.md index 727c554..946d9e6 100644 --- a/README.md +++ b/README.md @@ -7,23 +7,27 @@ [![Code Quality](https://sonarcloud.io/api/project_badges/measure?project=QrCode.Core&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=QrCode.Core) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=QrCode.Core&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=QrCode.Core) -## 📊 Test Coverage +## Documentation / Documentação + +- **[Usage Guide (English)](docs/en-US/usage-guide.md)** +- **[Guia de Uso (Português)](docs/pt-BR/guia-de-uso.md)** + +## Test Coverage | Metric | Coverage | Status | |--------|----------|--------| -| **Line Coverage** | 78% | 🟡 Good | -| **Branch Coverage** | 83.1% | 🟢 Excellent | -| **Method Coverage** | 78.1% | 🟡 Good | -| **Total Tests** | 239 | ✅ All Passed | +| **Line Coverage** | 78%+ | Good | +| **Branch Coverage** | 83%+ | Excellent | +| **Method Coverage** | 78%+ | Good | +| **Total Tests** | 300+ | All Passed | + +## Descrição do Projeto / Project Description + +QRCoder.Core is a cross-platform .NET library for QR Code generation using **SkiaSharp** for image rendering. Compatible with **Windows**, **Linux**, **macOS**, and **mobile** (Xamarin / MAUI). -### Coverage by Class -- 🟢 **Excellent (95%+)**: ArtQRCode (98.8%), PngByteQRCode (100%), SvgQRCode (100%), QRCodeHelper (100%), AsciiQRCode (100%), Size (100%), CustomExtensions (100%), StringValueAttribute (100%) -- 🟡 **Good (70-94%)**: QRCode (89.4%), PayloadGenerator (86.5%), QRCodeGenerator (86.8%), AbstractQRCode (88.2%) -- 🟠 **Needs Improvement**: QRCodeData (20%) -- 🔴 **No Coverage**: Base64QRCode, PdfByteQRCode, PostscriptQRCode, SKBitmapByteQRCode, DataTooLongException, SKColorExtensions (11.1%) +QRCoder.Core é uma biblioteca .NET multiplataforma para geração de QR Codes usando **SkiaSharp** para renderização de imagens. Compatível com **Windows**, **Linux**, **macOS** e **mobile** (Xamarin / MAUI). -## Descrição do Projeto -QRCoder.Core é uma biblioteca C# .NET simples, baseada em [QrCode](https://github.com/codebude/QRCoder), que permite a criação de códigos QR. Esta versão é otimizada para .NET Core e está disponível como um pacote NuGet. O projeto é desenvolvido e mantido pela AFONSOFT, com foco em fornecer uma solução robusta e fácil de usar para a geração de códigos QR em ambientes .NET. +Based on [QRCoder](https://github.com/codebude/QRCoder). Developed and maintained by AFONSOFT. ## Status do Projeto Concluída @@ -110,44 +114,46 @@ dotnet add package QRCoder.Core Você pode gerar e visualizar seu primeiro código QR com apenas algumas linhas de código C#. ```csharp -using QRCoder; -using System.Drawing; // Necessário para Bitmap, pode variar dependendo do ambiente .NET - -// Instancia o gerador de código QR -using (QRCodeGenerator qrGenerator = new QRCodeGenerator()) -{ - // Cria dados do código QR a partir de uma string e nível de correção de erro - using (QRCodeData qrCodeData = qrGenerator.CreateQrCode("O texto a ser codificado.", QRCodeGenerator.ECCLevel.Q)) - { - // Cria uma instância de QRCode com os dados - using (QRCode qrCode = new QRCode(qrCodeData)) - { - // Obtém a representação gráfica do código QR como um Bitmap - // O parâmetro '20' define o tamanho do módulo (pixel) do código QR - Bitmap qrCodeImage = qrCode.GetGraphic(20); - - // Exemplo de como salvar a imagem (requer System.Drawing.Common para .NET Core/5+) - // qrCodeImage.Save("qrcode.png", System.Drawing.Imaging.ImageFormat.Png); - } - } -} +using QRCoder.Core; +using SkiaSharp; + +// Create the QR Code generator +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("https://github.com/afonsoft/QRCoder.Core", + QRCodeGenerator.ECCLevel.M); + +// Render as PNG bytes (cross-platform, no System.Drawing needed) +using var png = new PngByteQRCode(data); +byte[] pngBytes = png.GetGraphic(10); +File.WriteAllBytes("qrcode.png", pngBytes); + +// Or render as SKBitmap +using var qrCode = new QRCode(data); +using var bitmap = qrCode.GetGraphic(10); ``` -### Parâmetros Opcionais e Sobrecargas -O método `GetGraphic` possui várias sobrecargas. As duas primeiras permitem definir a cor gráfica do código QR usando tipos `Color` ou notação de cor hexadecimal HTML. +### More Examples / Mais Exemplos + +See the full documentation for all output formats and payload types: +- **[English Guide](docs/en-US/usage-guide.md)** — PNG, SVG, PDF, ASCII, Base64, Postscript, Artistic +- **[Guia Português](docs/pt-BR/guia-de-uso.md)** — PNG, SVG, PDF, ASCII, Base64, Postscript, Artístico ```csharp -// Define a cor usando tipos Color -Bitmap qrCodeImage = qrCode.GetGraphic(20, Color.DarkRed, Color.PaleGreen, true); +// SVG output +using var svg = new SvgQRCode(data); +string svgString = svg.GetGraphic(10); -// Define a cor usando notação de cor hexadecimal HTML -Bitmap qrCodeImage = qrCode.GetGraphic(20, "#000ff0", "#0ff000"); -``` +// ASCII output (great for terminal) +using var ascii = new AsciiQRCode(data); +Console.WriteLine(ascii.GetGraphic(1)); -Esta sobrecarga permite renderizar um logotipo/imagem no centro do código QR. +// PDF output +using var pdf = new PdfByteQRCode(data); +byte[] pdfBytes = pdf.GetGraphic(5); -```csharp -Bitmap qrCodeImage = qrCode.GetGraphic(20, Color.Black, Color.White, (Bitmap)Bitmap.FromFile("path/to/your/image.png")); +// With colors +using var colorQr = new QRCode(data); +using var colorBmp = colorQr.GetGraphic(10, "#1a1a2e", "#e0e0e0"); ``` ## Fluxo do Projeto @@ -168,15 +174,10 @@ O projeto utiliza um pipeline completo de CI/CD com GitHub Actions para garantir - **🧪 CI Build & Test**: Build contínuo e testes automatizados ### 📊 Test Results & Coverage -- **Total Tests**: 239 testes unitários -- **Test Status**: ✅ All passing -- **Coverage Metrics**: - - Line Coverage: 78% - - Branch Coverage: 83.1% - - Method Coverage: 78.1% +- **Total Tests**: 300+ testes unitários +- **Test Status**: All passing +- **Coverage Metrics**: Line 78%+, Branch 83%+, Method 78%+ - **Frameworks Testados**: .NET Standard 2.1, .NET 8.0, .NET 10.0, .NET Framework 4.8 -- **Classes com 100% cobertura**: 10 classes principais -- **Classes sem cobertura**: 8 renderizadores alternativos (Base64QRCode, PdfByteQRCode, PostscriptQRCode, SKBitmapByteQRCode, etc.) - **Relatórios**: HTML coverage reports disponíveis em cada build ### 🧪 Executando Testes Localmente diff --git a/docs/en-US/usage-guide.md b/docs/en-US/usage-guide.md new file mode 100644 index 0000000..a999851 --- /dev/null +++ b/docs/en-US/usage-guide.md @@ -0,0 +1,487 @@ +# QRCoder.Core — Usage Guide (en-US) + +Cross-platform .NET library for QR Code generation using SkiaSharp. Compatible with **Windows**, **Linux**, **macOS**, and **mobile** (Xamarin / MAUI). + +## Table of Contents + +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Output Formats](#output-formats) + - [QRCode (SKBitmap)](#qrcode-skbitmap) + - [PNG Bytes](#png-bytes) + - [SVG](#svg) + - [Base64](#base64) + - [PDF](#pdf) + - [ASCII Art](#ascii-art) + - [Postscript / EPS](#postscript--eps) + - [Artistic QR Code](#artistic-qr-code) + - [BMP Bytes](#bmp-bytes) +- [Payloads (Content Types)](#payloads-content-types) +- [Advanced Settings](#advanced-settings) +- [Supported Platforms](#supported-platforms) + +--- + +## Installation + +```bash +dotnet add package QRCoder.Core +``` + +Or via NuGet Package Manager: + +``` +Install-Package QRCoder.Core +``` + +### Platform-Specific Dependencies + +SkiaSharp requires native libraries for each platform. `QRCoder.Core` automatically includes the correct dependencies: + +| Platform | Native Package | +| -------- | ---------------------------------- | +| Linux | `SkiaSharp.NativeAssets.Linux` | +| macOS | `SkiaSharp.NativeAssets.macOS` | +| Windows | `SkiaSharp.NativeAssets.Win32` | +| Android | `SkiaSharp.NativeAssets.Android` | +| iOS | `SkiaSharp.NativeAssets.iOS` | + +--- + +## Quick Start + +```csharp +using QRCoder.Core; +using SkiaSharp; + +// 1. Create the generator +using var generator = new QRCodeGenerator(); + +// 2. Generate QR Code data +using var data = generator.CreateQrCode("https://github.com/afonsoft/QRCoder.Core", + QRCodeGenerator.ECCLevel.M); + +// 3. Render as image +using var qrCode = new QRCode(data); +using var image = qrCode.GetGraphic(10); // 10 pixels per module + +// 4. Save as PNG +using var stream = File.OpenWrite("qrcode.png"); +image.Encode(stream, SKEncodedImageFormat.Png, 100); +``` + +--- + +## Output Formats + +### QRCode (SKBitmap) + +Generates an `SKBitmap` with the QR Code rendered via SkiaSharp. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Hello World!", QRCodeGenerator.ECCLevel.H); +using var qr = new QRCode(data); + +// Default black and white +using var bmp = qr.GetGraphic(10); + +// Custom colors +using var colorBmp = qr.GetGraphic(10, SKColors.DarkBlue, SKColors.LightGray, true); + +// Using hex colors +using var hexBmp = qr.GetGraphic(10, "#1a1a2e", "#e0e0e0"); + +// With centered logo +using var logo = SKBitmap.Decode("logo.png"); +using var logoBmp = qr.GetGraphic(10, SKColors.Black, SKColors.White, + icon: logo, iconSizePercent: 15, iconBorderWidth: 2); +``` + +### PNG Bytes + +Generates the QR Code directly as a PNG byte array — ideal for APIs and web services. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("API Data", QRCodeGenerator.ECCLevel.M); +using var png = new PngByteQRCode(data); + +// Default black and white +byte[] pngBytes = png.GetGraphic(5); +File.WriteAllBytes("qrcode.png", pngBytes); + +// With custom colors (RGB) +byte[] darkColor = new byte[] { 0, 0, 128 }; // Dark blue +byte[] lightColor = new byte[] { 255, 255, 200 }; // Light yellow +byte[] colorBytes = png.GetGraphic(5, darkColor, lightColor); + +// With transparency (RGBA) +byte[] darkAlpha = new byte[] { 0, 0, 0, 255 }; +byte[] lightAlpha = new byte[] { 255, 255, 255, 128 }; // Semi-transparent +byte[] alphaBytes = png.GetGraphic(5, darkAlpha, lightAlpha); +``` + +### SVG + +Generates the QR Code as an SVG string — perfect for web and vector documents. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.Q); +using var svg = new SvgQRCode(data); + +// Default SVG +string svgString = svg.GetGraphic(10); +File.WriteAllText("qrcode.svg", svgString); + +// With custom colors +string colorSvg = svg.GetGraphic(10, SKColors.DarkRed, SKColors.White); + +// With specific viewBox size +string viewBoxSvg = svg.GetGraphic(new Size(200, 200)); + +// Without quiet zone +string noBorderSvg = svg.GetGraphic(10, SKColors.Black, SKColors.White, false); + +// With embedded SVG logo +string svgLogo = File.ReadAllText("logo.svg"); +var logoObj = new SvgQRCode.SvgLogo(svgLogo, 15); +string logoSvg = svg.GetGraphic(10, SKColors.Black, SKColors.White, logo: logoObj); +``` + +### Base64 + +Generates the QR Code as Base64-encoded string — useful for embedding in HTML/CSS. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Base64 Data", QRCodeGenerator.ECCLevel.M); +using var b64 = new Base64QRCode(data); + +// PNG as Base64 +string base64Png = b64.GetGraphic(5); + +// JPEG as Base64 +string base64Jpeg = b64.GetGraphic(5, SKColors.Black, SKColors.White, + true, Base64QRCode.ImageType.Jpeg); + +// Use in HTML +string htmlImg = $"\"QR"; +``` + +### PDF + +Generates the QR Code as a PDF document in bytes. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("PDF Document", QRCodeGenerator.ECCLevel.M); +using var pdf = new PdfByteQRCode(data); + +// Default PDF +byte[] pdfBytes = pdf.GetGraphic(5); +File.WriteAllBytes("qrcode.pdf", pdfBytes); + +// With custom colors and DPI +byte[] colorPdf = pdf.GetGraphic(5, "#000080", "#FFFFFF", 300, 95); +``` + +### ASCII Art + +Generates the QR Code as ASCII text — useful for terminal output and logs. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Terminal QR", QRCodeGenerator.ECCLevel.L); +using var ascii = new AsciiQRCode(data); + +// Default +string text = ascii.GetGraphic(1); +Console.WriteLine(text); + +// Custom symbols +string custom = ascii.GetGraphic(1, "██", " ", true); + +// Get line by line +string[] lines = ascii.GetLineByLineGraphic(1); +foreach (var line in lines) + Console.WriteLine(line); + +// Via helper (one-liner) +string result = AsciiQRCodeHelper.GetQRCode("Quick!", 1, "██", " ", + QRCodeGenerator.ECCLevel.M); +``` + +### Postscript / EPS + +Generates the QR Code in Postscript or EPS format. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Print Quality", QRCodeGenerator.ECCLevel.M); +using var ps = new PostscriptQRCode(data); + +// Standard Postscript +string postscript = ps.GetGraphic(5); +File.WriteAllText("qrcode.ps", postscript); + +// EPS format +string eps = ps.GetGraphic(5, epsFormat: true); +File.WriteAllText("qrcode.eps", eps); + +// With colors +string colorPs = ps.GetGraphic(5, "#FF0000", "#FFFFFF"); + +// With viewBox +string viewBoxPs = ps.GetGraphic(new Size(200, 200)); +``` + +### Artistic QR Code + +Generates QR Codes with artistic styling (dots instead of squares). + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Artistic QR", QRCodeGenerator.ECCLevel.H); +using var art = new ArtQRCode(data); + +// Default (rounded dots) +using var bmp = art.GetGraphic(10); + +// With custom pixel size (0.0 to 1.0) +using var smallBmp = art.GetGraphic(10, SKColors.Black, SKColors.White, + SKColors.Transparent, pixelSizeFactor: 0.5); + +// With background image +using var background = SKBitmap.Decode("background.png"); +using var bgBmp = art.GetGraphic(background); + +// With custom finder pattern +using var finder = SKBitmap.Decode("finder.png"); +using var customBmp = art.GetGraphic(10, SKColors.Black, SKColors.White, + SKColors.Transparent, finderPatternImage: finder); +``` + +### BMP Bytes + +Generates the QR Code as a Windows Bitmap byte array. + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("BMP test", QRCodeGenerator.ECCLevel.M); +using var bmp = new SKBitmapByteQRCode(data); + +// Default +byte[] bmpBytes = bmp.GetGraphic(5); + +// With hex colors +byte[] colorBytes = bmp.GetGraphic(5, "#FF0000", "#00FF00"); + +// Via helper +byte[] helperBytes = SKBitmapByteQRCodeHelper.GetQRCode("Quick!", 5, + "#000000", "#FFFFFF", QRCodeGenerator.ECCLevel.M); +``` + +--- + +## Payloads (Content Types) + +The `PayloadGenerator` creates structured content for various QR Code types: + +### WiFi + +```csharp +var wifi = new PayloadGenerator.WiFi("MyNetwork", "MyPassword123", + PayloadGenerator.WiFi.Authentication.WPA); +string content = wifi.ToString(); + +// Hidden network +var hiddenWifi = new PayloadGenerator.WiFi("HiddenNet", "Password", + PayloadGenerator.WiFi.Authentication.WPA, isHiddenSSID: true); +``` + +### URL + +```csharp +var url = new PayloadGenerator.Url("https://github.com/afonsoft/QRCoder.Core"); +string content = url.ToString(); +``` + +### Email + +```csharp +var email = new PayloadGenerator.Mail("contact@example.com", + "Email Subject", "Message body"); +string content = email.ToString(); +``` + +### SMS + +```csharp +var sms = new PayloadGenerator.SMS("+1234567890", "Hello via QR Code!"); +string content = sms.ToString(); +``` + +### Phone Number + +```csharp +var phone = new PayloadGenerator.PhoneNumber("+1234567890"); +string content = phone.ToString(); +// Result: tel:+1234567890 +``` + +### Geolocation + +```csharp +var geo = new PayloadGenerator.Geolocation("40.7128", "-74.0060"); +string content = geo.ToString(); +// Result: geo:40.7128,-74.0060 +``` + +### Bitcoin + +```csharp +var btc = new PayloadGenerator.BitcoinAddress( + "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", + amount: 0.001, + label: "Donation", + message: "Thank you for your support!"); +string content = btc.ToString(); +``` + +### vCard (Contact) + +```csharp +var contact = new PayloadGenerator.ContactData( + PayloadGenerator.ContactData.ContactOutputType.VCard3, + firstname: "John", + lastname: "Doe", + org: "Example Corp", + email: "john@example.com", + phone: "+1234567890", + street: "123 Main Street", + city: "New York", + stateRegion: "NY", + country: "United States"); +string content = contact.ToString(); +``` + +### Calendar Event + +```csharp +var calEvent = new PayloadGenerator.CalendarEvent( + "Team Meeting", + "Event description", + "Room 101", + new DateTime(2026, 06, 15, 14, 0, 0), + new DateTime(2026, 06, 15, 15, 0, 0), + true); +string content = calEvent.ToString(); +``` + +--- + +## Advanced Settings + +### Error Correction Levels (ECC) + +| Level | Recovery Capacity | Recommended For | +| ----- | ----------------- | ----------------------------- | +| L | ~7% | Simple data, short URLs | +| M | ~15% | General use (default) | +| Q | ~25% | QR Codes with logos | +| H | ~30% | High-wear environments | + +### Data Serialization + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Serializable data", QRCodeGenerator.ECCLevel.M); + +// Save to file +data.SaveRawData("data.qrr", QRCodeData.Compression.GZip); + +// Load from file +using var loadedData = new QRCodeData("data.qrr", QRCodeData.Compression.GZip); + +// Serialize to bytes +byte[] rawBytes = data.GetRawData(QRCodeData.Compression.Deflate); + +// Deserialize from bytes +using var fromBytes = new QRCodeData(rawBytes, QRCodeData.Compression.Deflate); +``` + +### Force UTF-8 + +```csharp +using var generator = new QRCodeGenerator(); +// Force UTF-8 encoding with BOM +using var data = generator.CreateQrCode("Text with special characters", + QRCodeGenerator.ECCLevel.M, + forceUtf8: true, + utf8BOM: true); +``` + +### Fixed QR Code Version + +```csharp +using var generator = new QRCodeGenerator(); +// Force QR Code version 10 (57x57 modules) +using var data = generator.CreateQrCode("Text", + QRCodeGenerator.ECCLevel.M, + requestedVersion: 10); +``` + +--- + +## Supported Platforms + +| Framework | Version | Status | +| --------------------- | ------- | ---------- | +| .NET Standard | 2.1 | Supported | +| .NET | 8.0 | Supported | +| .NET | 10.0 | Supported | +| .NET Framework | 4.8 | Supported | +| Xamarin.Android | - | Via SkiaSharp | +| Xamarin.iOS | - | Via SkiaSharp | +| .NET MAUI | - | Via SkiaSharp | + +### ASP.NET Core API Example + +```csharp +[HttpGet("qrcode")] +public IActionResult GenerateQRCode([FromQuery] string text) +{ + using var generator = new QRCodeGenerator(); + using var data = generator.CreateQrCode(text, QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(data); + + byte[] bytes = png.GetGraphic(5); + return File(bytes, "image/png"); +} +``` + +### .NET MAUI / Xamarin Example + +```csharp +public ImageSource GenerateQRCodeImage(string text) +{ + using var generator = new QRCodeGenerator(); + using var data = generator.CreateQrCode(text, QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(data); + + byte[] bytes = png.GetGraphic(5); + return ImageSource.FromStream(() => new MemoryStream(bytes)); +} +``` + +### Console Example + +```csharp +using var generator = new QRCodeGenerator(); +using var data = generator.CreateQrCode("Terminal!", QRCodeGenerator.ECCLevel.L); +using var ascii = new AsciiQRCode(data); + +Console.WriteLine(ascii.GetGraphic(1)); +``` diff --git a/docs/pt-BR/guia-de-uso.md b/docs/pt-BR/guia-de-uso.md new file mode 100644 index 0000000..514f528 --- /dev/null +++ b/docs/pt-BR/guia-de-uso.md @@ -0,0 +1,487 @@ +# QRCoder.Core — Guia de Uso (pt-BR) + +Biblioteca .NET multiplataforma para geração de QR Codes usando SkiaSharp. Compatível com **Windows**, **Linux**, **macOS** e **mobile** (Xamarin / MAUI). + +## Índice + +- [Instalação](#instalação) +- [Início Rápido](#início-rápido) +- [Formatos de Saída](#formatos-de-saída) + - [QRCode (Bitmap SKBitmap)](#qrcode-bitmap-skbitmap) + - [PNG em Bytes](#png-em-bytes) + - [SVG](#svg) + - [Base64](#base64) + - [PDF](#pdf) + - [ASCII Art](#ascii-art) + - [Postscript / EPS](#postscript--eps) + - [QR Code Artístico](#qr-code-artístico) + - [BMP em Bytes](#bmp-em-bytes) +- [Payloads (Tipos de Conteúdo)](#payloads-tipos-de-conteúdo) +- [Configurações Avançadas](#configurações-avançadas) +- [Plataformas Suportadas](#plataformas-suportadas) + +--- + +## Instalação + +```bash +dotnet add package QRCoder.Core +``` + +Ou via NuGet Package Manager: + +``` +Install-Package QRCoder.Core +``` + +### Dependências por Plataforma + +O SkiaSharp requer bibliotecas nativas para cada plataforma. O pacote `QRCoder.Core` já inclui as dependências corretas automaticamente: + +| Plataforma | Pacote Nativo | +| ---------- | ---------------------------------- | +| Linux | `SkiaSharp.NativeAssets.Linux` | +| macOS | `SkiaSharp.NativeAssets.macOS` | +| Windows | `SkiaSharp.NativeAssets.Win32` | +| Android | `SkiaSharp.NativeAssets.Android` | +| iOS | `SkiaSharp.NativeAssets.iOS` | + +--- + +## Início Rápido + +```csharp +using QRCoder.Core; +using SkiaSharp; + +// 1. Criar o gerador +using var gerador = new QRCodeGenerator(); + +// 2. Gerar os dados do QR Code +using var dados = gerador.CreateQrCode("https://github.com/afonsoft/QRCoder.Core", + QRCodeGenerator.ECCLevel.M); + +// 3. Renderizar como imagem +using var qrCode = new QRCode(dados); +using var imagem = qrCode.GetGraphic(10); // 10 pixels por módulo + +// 4. Salvar como PNG +using var stream = File.OpenWrite("qrcode.png"); +imagem.Encode(stream, SKEncodedImageFormat.Png, 100); +``` + +--- + +## Formatos de Saída + +### QRCode (Bitmap SKBitmap) + +Gera um `SKBitmap` com o QR Code renderizado via SkiaSharp. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Olá Mundo!", QRCodeGenerator.ECCLevel.H); +using var qr = new QRCode(dados); + +// Preto e branco padrão +using var bmp = qr.GetGraphic(10); + +// Cores personalizadas +using var bmpColorido = qr.GetGraphic(10, SKColors.DarkBlue, SKColors.LightGray, true); + +// Usando cores hexadecimais +using var bmpHex = qr.GetGraphic(10, "#1a1a2e", "#e0e0e0"); + +// Com logotipo centralizado +using var logo = SKBitmap.Decode("logo.png"); +using var bmpComLogo = qr.GetGraphic(10, SKColors.Black, SKColors.White, + icon: logo, iconSizePercent: 15, iconBorderWidth: 2); +``` + +### PNG em Bytes + +Gera o QR Code diretamente como array de bytes PNG — ideal para APIs e serviços web. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Dados da API", QRCodeGenerator.ECCLevel.M); +using var png = new PngByteQRCode(dados); + +// Padrão preto e branco +byte[] bytesPng = png.GetGraphic(5); +File.WriteAllBytes("qrcode.png", bytesPng); + +// Com cores personalizadas (RGB) +byte[] corEscura = new byte[] { 0, 0, 128 }; // Azul escuro +byte[] corClara = new byte[] { 255, 255, 200 }; // Amarelo claro +byte[] bytesColorido = png.GetGraphic(5, corEscura, corClara); + +// Com transparência (RGBA) +byte[] escuroAlfa = new byte[] { 0, 0, 0, 255 }; +byte[] claroAlfa = new byte[] { 255, 255, 255, 128 }; // Semi-transparente +byte[] bytesAlfa = png.GetGraphic(5, escuroAlfa, claroAlfa); +``` + +### SVG + +Gera o QR Code como string SVG — perfeito para web e documentos vetoriais. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("https://afonsoft.com.br", QRCodeGenerator.ECCLevel.Q); +using var svg = new SvgQRCode(dados); + +// SVG padrão +string svgString = svg.GetGraphic(10); +File.WriteAllText("qrcode.svg", svgString); + +// Com cores personalizadas +string svgColorido = svg.GetGraphic(10, SKColors.DarkRed, SKColors.White); + +// Com tamanho de viewBox específico +string svgViewBox = svg.GetGraphic(new Size(200, 200)); + +// Sem zona silenciosa (quiet zone) +string svgSemBorda = svg.GetGraphic(10, SKColors.Black, SKColors.White, false); + +// Com logotipo SVG embutido +string svgLogo = File.ReadAllText("logo.svg"); +var logoObj = new SvgQRCode.SvgLogo(svgLogo, 15); +string svgComLogo = svg.GetGraphic(10, SKColors.Black, SKColors.White, logo: logoObj); +``` + +### Base64 + +Gera o QR Code codificado em Base64 — útil para incorporar em HTML/CSS. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Dados Base64", QRCodeGenerator.ECCLevel.M); +using var b64 = new Base64QRCode(dados); + +// PNG em Base64 +string base64Png = b64.GetGraphic(5); + +// JPEG em Base64 +string base64Jpeg = b64.GetGraphic(5, SKColors.Black, SKColors.White, + true, Base64QRCode.ImageType.Jpeg); + +// Usar em HTML +string htmlImg = $"\"QR"; +``` + +### PDF + +Gera o QR Code como documento PDF em bytes. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Documento PDF", QRCodeGenerator.ECCLevel.M); +using var pdf = new PdfByteQRCode(dados); + +// PDF padrão +byte[] bytesPdf = pdf.GetGraphic(5); +File.WriteAllBytes("qrcode.pdf", bytesPdf); + +// Com cores e DPI personalizado +byte[] pdfColorido = pdf.GetGraphic(5, "#000080", "#FFFFFF", 300, 95); +``` + +### ASCII Art + +Gera o QR Code como texto ASCII — útil para terminal e logs. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Terminal QR", QRCodeGenerator.ECCLevel.L); +using var ascii = new AsciiQRCode(dados); + +// Padrão +string texto = ascii.GetGraphic(1); +Console.WriteLine(texto); + +// Símbolos personalizados +string personalizado = ascii.GetGraphic(1, "██", " ", true); + +// Obter linha por linha +string[] linhas = ascii.GetLineByLineGraphic(1); +foreach (var linha in linhas) + Console.WriteLine(linha); + +// Via helper (uma linha) +string resultado = AsciiQRCodeHelper.GetQRCode("Rápido!", 1, "██", " ", + QRCodeGenerator.ECCLevel.M); +``` + +### Postscript / EPS + +Gera o QR Code em formato Postscript ou EPS. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Impressão", QRCodeGenerator.ECCLevel.M); +using var ps = new PostscriptQRCode(dados); + +// Postscript padrão +string postscript = ps.GetGraphic(5); +File.WriteAllText("qrcode.ps", postscript); + +// Formato EPS +string eps = ps.GetGraphic(5, epsFormat: true); +File.WriteAllText("qrcode.eps", eps); + +// Com cores +string psColorido = ps.GetGraphic(5, "#FF0000", "#FFFFFF"); + +// Com viewBox +string psViewBox = ps.GetGraphic(new Size(200, 200)); +``` + +### QR Code Artístico + +Gera QR Codes com estilo artístico (pontos ao invés de quadrados). + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("QR Artístico", QRCodeGenerator.ECCLevel.H); +using var art = new ArtQRCode(dados); + +// Padrão (pontos arredondados) +using var bmp = art.GetGraphic(10); + +// Com tamanho de pixel personalizado (0.0 a 1.0) +using var bmpPequeno = art.GetGraphic(10, SKColors.Black, SKColors.White, + SKColors.Transparent, pixelSizeFactor: 0.5); + +// Com imagem de fundo +using var fundo = SKBitmap.Decode("fundo.png"); +using var bmpComFundo = art.GetGraphic(fundo); + +// Com padrão de finder personalizado +using var finder = SKBitmap.Decode("finder.png"); +using var bmpCustom = art.GetGraphic(10, SKColors.Black, SKColors.White, + SKColors.Transparent, finderPatternImage: finder); +``` + +### BMP em Bytes + +Gera o QR Code como array de bytes no formato Windows Bitmap. + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("BMP test", QRCodeGenerator.ECCLevel.M); +using var bmp = new SKBitmapByteQRCode(dados); + +// Padrão +byte[] bytesBmp = bmp.GetGraphic(5); + +// Com cores hexadecimais +byte[] bytesColorido = bmp.GetGraphic(5, "#FF0000", "#00FF00"); + +// Via helper +byte[] bytesHelper = SKBitmapByteQRCodeHelper.GetQRCode("Rápido!", 5, + "#000000", "#FFFFFF", QRCodeGenerator.ECCLevel.M); +``` + +--- + +## Payloads (Tipos de Conteúdo) + +O `PayloadGenerator` cria conteúdos estruturados para diversos tipos de QR Code: + +### WiFi + +```csharp +var wifi = new PayloadGenerator.WiFi("MinhaRede", "MinhaSenha123", + PayloadGenerator.WiFi.Authentication.WPA); +string conteudo = wifi.ToString(); + +// Rede oculta +var wifiOculta = new PayloadGenerator.WiFi("RedeOculta", "Senha", + PayloadGenerator.WiFi.Authentication.WPA, isHiddenSSID: true); +``` + +### URL + +```csharp +var url = new PayloadGenerator.Url("https://github.com/afonsoft/QRCoder.Core"); +string conteudo = url.ToString(); +``` + +### E-mail + +```csharp +var email = new PayloadGenerator.Mail("contato@afonsoft.com.br", + "Assunto do E-mail", "Corpo da mensagem"); +string conteudo = email.ToString(); +``` + +### SMS + +```csharp +var sms = new PayloadGenerator.SMS("+5511999999999", "Olá! Mensagem via QR Code."); +string conteudo = sms.ToString(); +``` + +### Telefone + +```csharp +var telefone = new PayloadGenerator.PhoneNumber("+5511999999999"); +string conteudo = telefone.ToString(); +// Resultado: tel:+5511999999999 +``` + +### Geolocalização + +```csharp +var geo = new PayloadGenerator.Geolocation("-23.5505", "-46.6333"); +string conteudo = geo.ToString(); +// Resultado: geo:-23.5505,-46.6333 +``` + +### Bitcoin + +```csharp +var btc = new PayloadGenerator.BitcoinAddress( + "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", + amount: 0.001, + label: "Doação", + message: "Obrigado pelo suporte!"); +string conteudo = btc.ToString(); +``` + +### vCard (Contato) + +```csharp +var contato = new PayloadGenerator.ContactData( + PayloadGenerator.ContactData.ContactOutputType.VCard3, + firstname: "Afonso", + lastname: "Nogueira", + org: "AFONSOFT", + email: "contato@afonsoft.com.br", + phone: "+5511999999999", + street: "Rua Exemplo, 123", + city: "São Paulo", + stateRegion: "SP", + country: "Brasil"); +string conteudo = contato.ToString(); +``` + +### Evento de Calendário + +```csharp +var evento = new PayloadGenerator.CalendarEvent( + "Reunião de Equipe", + "Descrição do evento", + "Sala 101", + new DateTime(2026, 06, 15, 14, 0, 0), + new DateTime(2026, 06, 15, 15, 0, 0), + true); +string conteudo = evento.ToString(); +``` + +--- + +## Configurações Avançadas + +### Níveis de Correção de Erro (ECC) + +| Nível | Capacidade de Recuperação | Recomendado Para | +| ----- | ------------------------- | ---------------------------- | +| L | ~7% | Dados simples, URL curtas | +| M | ~15% | Uso geral (padrão) | +| Q | ~25% | QR Codes com logotipo | +| H | ~30% | Ambientes com desgaste | + +### Serialização de Dados + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Dados serializáveis", QRCodeGenerator.ECCLevel.M); + +// Salvar em arquivo +dados.SaveRawData("dados.qrr", QRCodeData.Compression.GZip); + +// Carregar de arquivo +using var dadosCarregados = new QRCodeData("dados.qrr", QRCodeData.Compression.GZip); + +// Serializar para bytes +byte[] rawBytes = dados.GetRawData(QRCodeData.Compression.Deflate); + +// Desserializar de bytes +using var dadosDeBytes = new QRCodeData(rawBytes, QRCodeData.Compression.Deflate); +``` + +### Forçar UTF-8 + +```csharp +using var gerador = new QRCodeGenerator(); +// Forçar codificação UTF-8 com BOM +using var dados = gerador.CreateQrCode("Texto com acentuação", + QRCodeGenerator.ECCLevel.M, + forceUtf8: true, + utf8BOM: true); +``` + +### Versão Fixa do QR Code + +```csharp +using var gerador = new QRCodeGenerator(); +// Forçar versão 10 do QR Code (57x57 módulos) +using var dados = gerador.CreateQrCode("Texto", + QRCodeGenerator.ECCLevel.M, + requestedVersion: 10); +``` + +--- + +## Plataformas Suportadas + +| Framework | Versão | Status | +| --------------------- | ------ | ---------- | +| .NET Standard | 2.1 | Suportado | +| .NET | 8.0 | Suportado | +| .NET | 10.0 | Suportado | +| .NET Framework | 4.8 | Suportado | +| Xamarin.Android | - | Via SkiaSharp | +| Xamarin.iOS | - | Via SkiaSharp | +| .NET MAUI | - | Via SkiaSharp | + +### Exemplo para ASP.NET Core (API) + +```csharp +[HttpGet("qrcode")] +public IActionResult GerarQRCode([FromQuery] string texto) +{ + using var gerador = new QRCodeGenerator(); + using var dados = gerador.CreateQrCode(texto, QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(dados); + + byte[] bytes = png.GetGraphic(5); + return File(bytes, "image/png"); +} +``` + +### Exemplo para .NET MAUI / Xamarin + +```csharp +public ImageSource GerarQRCodeImagem(string texto) +{ + using var gerador = new QRCodeGenerator(); + using var dados = gerador.CreateQrCode(texto, QRCodeGenerator.ECCLevel.M); + using var png = new PngByteQRCode(dados); + + byte[] bytes = png.GetGraphic(5); + return ImageSource.FromStream(() => new MemoryStream(bytes)); +} +``` + +### Exemplo para Console (Terminal) + +```csharp +using var gerador = new QRCodeGenerator(); +using var dados = gerador.CreateQrCode("Terminal!", QRCodeGenerator.ECCLevel.L); +using var ascii = new AsciiQRCode(dados); + +Console.WriteLine(ascii.GetGraphic(1)); +``` From d31c2fafa2160307a8a518a78dbe466fe37ca4a1 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 19:40:55 +0000 Subject: [PATCH 4/4] fix: replace using declarations with var for net48 compatibility C# 7.3 (net48 target) does not support 'using var' declarations. Changed to match existing test code style. Co-Authored-By: Afonso Dutra Nogueira Filho --- QRCoder.Core.Tests/BestPracticesTests.cs | 320 +++++++++++------------ 1 file changed, 160 insertions(+), 160 deletions(-) diff --git a/QRCoder.Core.Tests/BestPracticesTests.cs b/QRCoder.Core.Tests/BestPracticesTests.cs index ad152a9..e285a42 100644 --- a/QRCoder.Core.Tests/BestPracticesTests.cs +++ b/QRCoder.Core.Tests/BestPracticesTests.cs @@ -24,8 +24,8 @@ public class BestPracticesTests [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_WithEmptyString_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("", QRCodeGenerator.ECCLevel.L); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("", QRCodeGenerator.ECCLevel.L); data.ShouldNotBeNull(); data.ModuleMatrix.ShouldNotBeNull(); data.ModuleMatrix.Count.ShouldBeGreaterThan(0); @@ -35,8 +35,8 @@ public void QRCodeGenerator_CreateQrCode_WithEmptyString_ShouldSucceed() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_WithUnicode_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Olá mundo! 你好世界 🌍", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Olá mundo! 你好世界 🌍", QRCodeGenerator.ECCLevel.M); data.ShouldNotBeNull(); data.ModuleMatrix.Count.ShouldBeGreaterThan(0); } @@ -45,8 +45,8 @@ public void QRCodeGenerator_CreateQrCode_WithUnicode_ShouldSucceed() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_WithUrl_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("https://github.com/afonsoft/QRCoder.Core", QRCodeGenerator.ECCLevel.Q); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("https://github.com/afonsoft/QRCoder.Core", QRCodeGenerator.ECCLevel.Q); data.ShouldNotBeNull(); } @@ -58,8 +58,8 @@ public void QRCodeGenerator_CreateQrCode_WithUrl_ShouldSucceed() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_AllECCLevels_ShouldSucceed(QRCodeGenerator.ECCLevel eccLevel) { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Test", eccLevel); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test", eccLevel); data.ShouldNotBeNull(); } @@ -67,8 +67,8 @@ public void QRCodeGenerator_CreateQrCode_AllECCLevels_ShouldSucceed(QRCodeGenera [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_ForceUtf8_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Test UTF8", QRCodeGenerator.ECCLevel.M, forceUtf8: true); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test UTF8", QRCodeGenerator.ECCLevel.M, forceUtf8: true); data.ShouldNotBeNull(); } @@ -76,8 +76,8 @@ public void QRCodeGenerator_CreateQrCode_ForceUtf8_ShouldSucceed() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_WithUtf8BOM_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Test BOM", QRCodeGenerator.ECCLevel.M, forceUtf8: true, utf8BOM: true); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test BOM", QRCodeGenerator.ECCLevel.M, forceUtf8: true, utf8BOM: true); data.ShouldNotBeNull(); } @@ -85,8 +85,8 @@ public void QRCodeGenerator_CreateQrCode_WithUtf8BOM_ShouldSucceed() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_WithFixedVersion_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L, requestedVersion: 5); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L, requestedVersion: 5); data.ShouldNotBeNull(); data.Version.ShouldBe(5); } @@ -104,8 +104,8 @@ public void QRCodeGenerator_Dispose_MultipleTimes_ShouldNotThrow() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_NumericMode_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("0123456789", QRCodeGenerator.ECCLevel.L); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("0123456789", QRCodeGenerator.ECCLevel.L); data.ShouldNotBeNull(); } @@ -113,8 +113,8 @@ public void QRCodeGenerator_CreateQrCode_NumericMode_ShouldSucceed() [Category("BestPractices/QRCodeGenerator")] public void QRCodeGenerator_CreateQrCode_AlphanumericMode_ShouldSucceed() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("HELLO WORLD 123", QRCodeGenerator.ECCLevel.L); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("HELLO WORLD 123", QRCodeGenerator.ECCLevel.L); data.ShouldNotBeNull(); } @@ -126,14 +126,14 @@ public void QRCodeGenerator_CreateQrCode_AlphanumericMode_ShouldSucceed() [Category("BestPractices/QRCodeData")] public void QRCodeData_RoundTrip_Uncompressed_ShouldPreserveData() { - using var gen = new QRCodeGenerator(); - using var original = gen.CreateQrCode("Round trip test", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var original = gen.CreateQrCode("Round trip test", QRCodeGenerator.ECCLevel.M); var rawData = original.GetRawData(QRCodeData.Compression.Uncompressed); rawData.ShouldNotBeNull(); rawData.Length.ShouldBeGreaterThan(0); - using var restored = new QRCodeData(rawData, QRCodeData.Compression.Uncompressed); + var restored = new QRCodeData(rawData, QRCodeData.Compression.Uncompressed); restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); } @@ -141,13 +141,13 @@ public void QRCodeData_RoundTrip_Uncompressed_ShouldPreserveData() [Category("BestPractices/QRCodeData")] public void QRCodeData_RoundTrip_Deflate_ShouldPreserveData() { - using var gen = new QRCodeGenerator(); - using var original = gen.CreateQrCode("Deflate test", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var original = gen.CreateQrCode("Deflate test", QRCodeGenerator.ECCLevel.M); var rawData = original.GetRawData(QRCodeData.Compression.Deflate); rawData.ShouldNotBeNull(); - using var restored = new QRCodeData(rawData, QRCodeData.Compression.Deflate); + var restored = new QRCodeData(rawData, QRCodeData.Compression.Deflate); restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); } @@ -155,13 +155,13 @@ public void QRCodeData_RoundTrip_Deflate_ShouldPreserveData() [Category("BestPractices/QRCodeData")] public void QRCodeData_RoundTrip_GZip_ShouldPreserveData() { - using var gen = new QRCodeGenerator(); - using var original = gen.CreateQrCode("GZip test", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var original = gen.CreateQrCode("GZip test", QRCodeGenerator.ECCLevel.M); var rawData = original.GetRawData(QRCodeData.Compression.GZip); rawData.ShouldNotBeNull(); - using var restored = new QRCodeData(rawData, QRCodeData.Compression.GZip); + var restored = new QRCodeData(rawData, QRCodeData.Compression.GZip); restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); } @@ -181,13 +181,13 @@ public void QRCodeData_SaveAndLoad_RoundTrip_ShouldPreserveData() var tempPath = Path.Combine(Path.GetTempPath(), $"qrdata_test_{Guid.NewGuid()}.qrr"); try { - using var gen = new QRCodeGenerator(); - using var original = gen.CreateQrCode("File round trip", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var original = gen.CreateQrCode("File round trip", QRCodeGenerator.ECCLevel.M); original.SaveRawData(tempPath, QRCodeData.Compression.Uncompressed); File.Exists(tempPath).ShouldBeTrue(); - using var restored = new QRCodeData(tempPath, QRCodeData.Compression.Uncompressed); + var restored = new QRCodeData(tempPath, QRCodeData.Compression.Uncompressed); restored.ModuleMatrix.Count.ShouldBe(original.ModuleMatrix.Count); } finally @@ -201,7 +201,7 @@ public void QRCodeData_SaveAndLoad_RoundTrip_ShouldPreserveData() [Category("BestPractices/QRCodeData")] public void QRCodeData_Dispose_ShouldClearModuleMatrix() { - using var gen = new QRCodeGenerator(); + var gen = new QRCodeGenerator(); var data = gen.CreateQrCode("Dispose test", QRCodeGenerator.ECCLevel.M); data.ModuleMatrix.ShouldNotBeNull(); @@ -213,8 +213,8 @@ public void QRCodeData_Dispose_ShouldClearModuleMatrix() [Category("BestPractices/QRCodeData")] public void QRCodeData_Version_ShouldBePositive() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Version test", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Version test", QRCodeGenerator.ECCLevel.M); data.Version.ShouldBeGreaterThan(0); } @@ -226,9 +226,9 @@ public void QRCodeData_Version_ShouldBePositive() [Category("BestPractices/AbstractQRCode")] public void AbstractQRCode_SetQRCodeData_ShouldUpdateData() { - using var gen = new QRCodeGenerator(); - using var data1 = gen.CreateQrCode("First", QRCodeGenerator.ECCLevel.L); - using var data2 = gen.CreateQrCode("Second with more data", QRCodeGenerator.ECCLevel.H); + var gen = new QRCodeGenerator(); + var data1 = gen.CreateQrCode("First", QRCodeGenerator.ECCLevel.L); + var data2 = gen.CreateQrCode("Second with more data", QRCodeGenerator.ECCLevel.H); var qrCode = new QRCode(data1); var size1 = qrCode.GetGraphic(1).Width; @@ -243,7 +243,7 @@ public void AbstractQRCode_SetQRCodeData_ShouldUpdateData() [Category("BestPractices/AbstractQRCode")] public void AbstractQRCode_Dispose_ShouldBeIdempotent() { - using var gen = new QRCodeGenerator(); + var gen = new QRCodeGenerator(); var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); var qrCode = new QRCode(data); @@ -259,11 +259,11 @@ public void AbstractQRCode_Dispose_ShouldBeIdempotent() [Category("BestPractices/QRCode")] public void QRCode_GetGraphic_WithCustomColors_ShouldReturnBitmap() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Color test", QRCodeGenerator.ECCLevel.M); - using var qr = new QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Color test", QRCodeGenerator.ECCLevel.M); + var qr = new QRCode(data); - using var bmp = qr.GetGraphic(5, new SKColor(255, 0, 0), new SKColor(0, 255, 0), true); + var bmp = qr.GetGraphic(5, new SKColor(255, 0, 0), new SKColor(0, 255, 0), true); bmp.ShouldNotBeNull(); bmp.Width.ShouldBeGreaterThan(0); bmp.Height.ShouldBeGreaterThan(0); @@ -273,11 +273,11 @@ public void QRCode_GetGraphic_WithCustomColors_ShouldReturnBitmap() [Category("BestPractices/QRCode")] public void QRCode_GetGraphic_WithHexColors_ShouldReturnBitmap() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Hex color test", QRCodeGenerator.ECCLevel.M); - using var qr = new QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Hex color test", QRCodeGenerator.ECCLevel.M); + var qr = new QRCode(data); - using var bmp = qr.GetGraphic(5, "#FF0000", "#00FF00"); + var bmp = qr.GetGraphic(5, "#FF0000", "#00FF00"); bmp.ShouldNotBeNull(); } @@ -285,14 +285,14 @@ public void QRCode_GetGraphic_WithHexColors_ShouldReturnBitmap() [Category("BestPractices/QRCode")] public void QRCode_GetGraphic_WithoutQuietZones_ShouldBeSmallerThanWithQuietZones() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Quiet zone test", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Quiet zone test", QRCodeGenerator.ECCLevel.M); - using var qrWith = new QRCode(data); - using var bmpWith = qrWith.GetGraphic(5, SKColors.Black, SKColors.White, true); + var qrWith = new QRCode(data); + var bmpWith = qrWith.GetGraphic(5, SKColors.Black, SKColors.White, true); - using var qrWithout = new QRCode(data); - using var bmpWithout = qrWithout.GetGraphic(5, SKColors.Black, SKColors.White, false); + var qrWithout = new QRCode(data); + var bmpWithout = qrWithout.GetGraphic(5, SKColors.Black, SKColors.White, false); bmpWithout.Width.ShouldBeLessThan(bmpWith.Width); } @@ -301,9 +301,9 @@ public void QRCode_GetGraphic_WithoutQuietZones_ShouldBeSmallerThanWithQuietZone [Category("BestPractices/QRCode")] public void QRCode_ParseHtmlColor_InvalidFormat_ShouldThrowArgumentException() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); - using var qr = new QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); + var qr = new QRCode(data); Should.Throw(() => qr.GetGraphic(5, "#ZZZZZZ", "#ffffff")); } @@ -312,9 +312,9 @@ public void QRCode_ParseHtmlColor_InvalidFormat_ShouldThrowArgumentException() [Category("BestPractices/QRCode")] public void QRCode_ParseHtmlColor_EmptyString_ShouldThrowArgumentException() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); - using var qr = new QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Test", QRCodeGenerator.ECCLevel.L); + var qr = new QRCode(data); Should.Throw(() => qr.GetGraphic(5, "", "#ffffff")); } @@ -323,11 +323,11 @@ public void QRCode_ParseHtmlColor_EmptyString_ShouldThrowArgumentException() [Category("BestPractices/QRCode")] public void QRCode_ParseHtmlColor_WithAlpha_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Alpha test", QRCodeGenerator.ECCLevel.L); - using var qr = new QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Alpha test", QRCodeGenerator.ECCLevel.L); + var qr = new QRCode(data); - using var bmp = qr.GetGraphic(5, "#80000000", "#80FFFFFF"); + var bmp = qr.GetGraphic(5, "#80000000", "#80FFFFFF"); bmp.ShouldNotBeNull(); } @@ -343,7 +343,7 @@ public void QRCode_ParameterlessConstructor_ShouldWork() [Category("BestPractices/QRCode")] public void QRCodeHelper_GetQRCode_ShouldReturnValidBitmap() { - using var bmp = QRCodeHelper.GetQRCode("Helper test", 5, SKColors.Black, SKColors.White, QRCodeGenerator.ECCLevel.M); + var bmp = QRCodeHelper.GetQRCode("Helper test", 5, SKColors.Black, SKColors.White, QRCodeGenerator.ECCLevel.M); bmp.ShouldNotBeNull(); bmp.Width.ShouldBeGreaterThan(0); } @@ -356,9 +356,9 @@ public void QRCodeHelper_GetQRCode_ShouldReturnValidBitmap() [Category("BestPractices/AsciiQRCode")] public void AsciiQRCode_GetGraphic_ShouldReturnNonEmptyString() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("ASCII test", QRCodeGenerator.ECCLevel.M); - using var ascii = new AsciiQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("ASCII test", QRCodeGenerator.ECCLevel.M); + var ascii = new AsciiQRCode(data); var result = ascii.GetGraphic(1); result.ShouldNotBeNullOrEmpty(); @@ -369,9 +369,9 @@ public void AsciiQRCode_GetGraphic_ShouldReturnNonEmptyString() [Category("BestPractices/AsciiQRCode")] public void AsciiQRCode_GetGraphic_WithCustomSymbols_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Custom symbols", QRCodeGenerator.ECCLevel.M); - using var ascii = new AsciiQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Custom symbols", QRCodeGenerator.ECCLevel.M); + var ascii = new AsciiQRCode(data); var result = ascii.GetGraphic(1, "XX", "..", true); result.ShouldNotBeNullOrEmpty(); @@ -383,9 +383,9 @@ public void AsciiQRCode_GetGraphic_WithCustomSymbols_ShouldWork() [Category("BestPractices/AsciiQRCode")] public void AsciiQRCode_GetLineByLineGraphic_ShouldReturnLines() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Line test", QRCodeGenerator.ECCLevel.L); - using var ascii = new AsciiQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Line test", QRCodeGenerator.ECCLevel.L); + var ascii = new AsciiQRCode(data); var lines = ascii.GetLineByLineGraphic(1); lines.ShouldNotBeNull(); @@ -396,13 +396,13 @@ public void AsciiQRCode_GetLineByLineGraphic_ShouldReturnLines() [Category("BestPractices/AsciiQRCode")] public void AsciiQRCode_WithoutQuietZones_ShouldHaveFewerLines() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("QZ test", QRCodeGenerator.ECCLevel.L); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("QZ test", QRCodeGenerator.ECCLevel.L); - using var withQz = new AsciiQRCode(data); + var withQz = new AsciiQRCode(data); var linesWith = withQz.GetLineByLineGraphic(1, drawQuietZones: true); - using var withoutQz = new AsciiQRCode(data); + var withoutQz = new AsciiQRCode(data); var linesWithout = withoutQz.GetLineByLineGraphic(1, drawQuietZones: false); linesWithout.Length.ShouldBeLessThan(linesWith.Length); @@ -424,9 +424,9 @@ public void AsciiQRCodeHelper_GetQRCode_ShouldReturnString() [Category("BestPractices/PngByteQRCode")] public void PngByteQRCode_GetGraphic_BlackWhite_ShouldReturnValidPng() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PNG test", QRCodeGenerator.ECCLevel.M); - using var png = new PngByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PNG test", QRCodeGenerator.ECCLevel.M); + var png = new PngByteQRCode(data); var bytes = png.GetGraphic(5); bytes.ShouldNotBeNull(); @@ -442,9 +442,9 @@ public void PngByteQRCode_GetGraphic_BlackWhite_ShouldReturnValidPng() [Category("BestPractices/PngByteQRCode")] public void PngByteQRCode_GetGraphic_WithColors_ShouldReturnValidPng() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Color PNG", QRCodeGenerator.ECCLevel.M); - using var png = new PngByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Color PNG", QRCodeGenerator.ECCLevel.M); + var png = new PngByteQRCode(data); var darkColor = new byte[] { 255, 0, 0 }; var lightColor = new byte[] { 0, 255, 0 }; @@ -457,9 +457,9 @@ public void PngByteQRCode_GetGraphic_WithColors_ShouldReturnValidPng() [Category("BestPractices/PngByteQRCode")] public void PngByteQRCode_GetGraphic_WithAlpha_ShouldReturnValidPng() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Alpha PNG", QRCodeGenerator.ECCLevel.M); - using var png = new PngByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Alpha PNG", QRCodeGenerator.ECCLevel.M); + var png = new PngByteQRCode(data); var darkColor = new byte[] { 0, 0, 0, 255 }; var lightColor = new byte[] { 255, 255, 255, 128 }; @@ -471,13 +471,13 @@ public void PngByteQRCode_GetGraphic_WithAlpha_ShouldReturnValidPng() [Category("BestPractices/PngByteQRCode")] public void PngByteQRCode_WithoutQuietZones_ShouldReturnSmallerPng() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("QZ PNG", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("QZ PNG", QRCodeGenerator.ECCLevel.M); - using var pngWith = new PngByteQRCode(data); + var pngWith = new PngByteQRCode(data); var bytesWith = pngWith.GetGraphic(5, true); - using var pngWithout = new PngByteQRCode(data); + var pngWithout = new PngByteQRCode(data); var bytesWithout = pngWithout.GetGraphic(5, false); bytesWithout.Length.ShouldBeLessThan(bytesWith.Length); @@ -491,9 +491,9 @@ public void PngByteQRCode_WithoutQuietZones_ShouldReturnSmallerPng() [Category("BestPractices/SKBitmapByteQRCode")] public void SKBitmapByteQRCode_GetGraphic_Default_ShouldReturnBytes() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("BMP test", QRCodeGenerator.ECCLevel.M); - using var bmp = new SKBitmapByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("BMP test", QRCodeGenerator.ECCLevel.M); + var bmp = new SKBitmapByteQRCode(data); var bytes = bmp.GetGraphic(5); bytes.ShouldNotBeNull(); @@ -507,9 +507,9 @@ public void SKBitmapByteQRCode_GetGraphic_Default_ShouldReturnBytes() [Category("BestPractices/SKBitmapByteQRCode")] public void SKBitmapByteQRCode_GetGraphic_WithHexColors_ShouldReturnBytes() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("BMP hex", QRCodeGenerator.ECCLevel.M); - using var bmp = new SKBitmapByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("BMP hex", QRCodeGenerator.ECCLevel.M); + var bmp = new SKBitmapByteQRCode(data); var bytes = bmp.GetGraphic(5, "#FF0000", "#00FF00"); bytes.ShouldNotBeNull(); @@ -520,9 +520,9 @@ public void SKBitmapByteQRCode_GetGraphic_WithHexColors_ShouldReturnBytes() [Category("BestPractices/SKBitmapByteQRCode")] public void SKBitmapByteQRCode_GetGraphic_WithByteColors_ShouldReturnBytes() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("BMP byte colors", QRCodeGenerator.ECCLevel.M); - using var bmp = new SKBitmapByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("BMP byte colors", QRCodeGenerator.ECCLevel.M); + var bmp = new SKBitmapByteQRCode(data); var bytes = bmp.GetGraphic(5, new byte[] { 0, 0, 255 }, new byte[] { 255, 255, 0 }); bytes.ShouldNotBeNull(); @@ -554,9 +554,9 @@ public void SKBitmapByteQRCodeHelper_GetQRCode_Simple_ShouldReturnBytes() [Category("BestPractices/Base64QRCode")] public void Base64QRCode_GetGraphic_ShouldReturnValidBase64() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Base64 test", QRCodeGenerator.ECCLevel.M); - using var b64 = new Base64QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Base64 test", QRCodeGenerator.ECCLevel.M); + var b64 = new Base64QRCode(data); var result = b64.GetGraphic(5); result.ShouldNotBeNullOrEmpty(); @@ -570,9 +570,9 @@ public void Base64QRCode_GetGraphic_ShouldReturnValidBase64() [Category("BestPractices/Base64QRCode")] public void Base64QRCode_GetGraphic_AsJpeg_ShouldReturnBase64() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("JPEG test", QRCodeGenerator.ECCLevel.M); - using var b64 = new Base64QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("JPEG test", QRCodeGenerator.ECCLevel.M); + var b64 = new Base64QRCode(data); var result = b64.GetGraphic(5, SKColors.Black, SKColors.White, true, Base64QRCode.ImageType.Jpeg); result.ShouldNotBeNullOrEmpty(); @@ -584,11 +584,11 @@ public void Base64QRCode_GetGraphic_WithIcon_ShouldReturnBase64() { if (!HelperFunctions.IsSkiaSharpAvailable()) return; - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Icon test", QRCodeGenerator.ECCLevel.H); - using var b64 = new Base64QRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Icon test", QRCodeGenerator.ECCLevel.H); + var b64 = new Base64QRCode(data); - using var icon = new SKBitmap(10, 10); + var icon = new SKBitmap(10, 10); var result = b64.GetGraphic(5, SKColors.Black, SKColors.White, icon, 15, 2); result.ShouldNotBeNullOrEmpty(); } @@ -601,9 +601,9 @@ public void Base64QRCode_GetGraphic_WithIcon_ShouldReturnBase64() [Category("BestPractices/PdfByteQRCode")] public void PdfByteQRCode_GetGraphic_ShouldReturnValidPdf() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PDF test", QRCodeGenerator.ECCLevel.M); - using var pdf = new PdfByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PDF test", QRCodeGenerator.ECCLevel.M); + var pdf = new PdfByteQRCode(data); var bytes = pdf.GetGraphic(5); bytes.ShouldNotBeNull(); @@ -617,9 +617,9 @@ public void PdfByteQRCode_GetGraphic_ShouldReturnValidPdf() [Category("BestPractices/PdfByteQRCode")] public void PdfByteQRCode_GetGraphic_WithColors_ShouldReturnValidPdf() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PDF color", QRCodeGenerator.ECCLevel.M); - using var pdf = new PdfByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PDF color", QRCodeGenerator.ECCLevel.M); + var pdf = new PdfByteQRCode(data); var bytes = pdf.GetGraphic(5, "#FF0000", "#00FF00"); bytes.ShouldNotBeNull(); @@ -630,9 +630,9 @@ public void PdfByteQRCode_GetGraphic_WithColors_ShouldReturnValidPdf() [Category("BestPractices/PdfByteQRCode")] public void PdfByteQRCode_GetGraphic_WithCustomDpi_ShouldReturnValidPdf() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PDF DPI", QRCodeGenerator.ECCLevel.M); - using var pdf = new PdfByteQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PDF DPI", QRCodeGenerator.ECCLevel.M); + var pdf = new PdfByteQRCode(data); var bytes = pdf.GetGraphic(5, "#000000", "#FFFFFF", 300, 95); bytes.ShouldNotBeNull(); @@ -646,9 +646,9 @@ public void PdfByteQRCode_GetGraphic_WithCustomDpi_ShouldReturnValidPdf() [Category("BestPractices/PostscriptQRCode")] public void PostscriptQRCode_GetGraphic_ShouldReturnValidPostscript() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PS test", QRCodeGenerator.ECCLevel.M); - using var ps = new PostscriptQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PS test", QRCodeGenerator.ECCLevel.M); + var ps = new PostscriptQRCode(data); var result = ps.GetGraphic(5); result.ShouldNotBeNullOrEmpty(); @@ -660,9 +660,9 @@ public void PostscriptQRCode_GetGraphic_ShouldReturnValidPostscript() [Category("BestPractices/PostscriptQRCode")] public void PostscriptQRCode_GetGraphic_AsEps_ShouldReturnValidEps() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("EPS test", QRCodeGenerator.ECCLevel.M); - using var ps = new PostscriptQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("EPS test", QRCodeGenerator.ECCLevel.M); + var ps = new PostscriptQRCode(data); var result = ps.GetGraphic(5, epsFormat: true); result.ShouldNotBeNullOrEmpty(); @@ -673,9 +673,9 @@ public void PostscriptQRCode_GetGraphic_AsEps_ShouldReturnValidEps() [Category("BestPractices/PostscriptQRCode")] public void PostscriptQRCode_GetGraphic_WithColors_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PS colors", QRCodeGenerator.ECCLevel.M); - using var ps = new PostscriptQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PS colors", QRCodeGenerator.ECCLevel.M); + var ps = new PostscriptQRCode(data); var result = ps.GetGraphic(5, new SKColor(255, 0, 0), new SKColor(0, 255, 0)); result.ShouldNotBeNullOrEmpty(); @@ -685,9 +685,9 @@ public void PostscriptQRCode_GetGraphic_WithColors_ShouldWork() [Category("BestPractices/PostscriptQRCode")] public void PostscriptQRCode_GetGraphic_WithHexColors_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PS hex", QRCodeGenerator.ECCLevel.M); - using var ps = new PostscriptQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PS hex", QRCodeGenerator.ECCLevel.M); + var ps = new PostscriptQRCode(data); var result = ps.GetGraphic(5, "#FF0000", "#00FF00"); result.ShouldNotBeNullOrEmpty(); @@ -697,9 +697,9 @@ public void PostscriptQRCode_GetGraphic_WithHexColors_ShouldWork() [Category("BestPractices/PostscriptQRCode")] public void PostscriptQRCode_GetGraphic_WithViewBox_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PS viewbox", QRCodeGenerator.ECCLevel.M); - using var ps = new PostscriptQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PS viewbox", QRCodeGenerator.ECCLevel.M); + var ps = new PostscriptQRCode(data); var result = ps.GetGraphic(new Size(200, 200)); result.ShouldNotBeNullOrEmpty(); @@ -709,9 +709,9 @@ public void PostscriptQRCode_GetGraphic_WithViewBox_ShouldWork() [Category("BestPractices/PostscriptQRCode")] public void PostscriptQRCode_WithoutQuietZones_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("PS no QZ", QRCodeGenerator.ECCLevel.M); - using var ps = new PostscriptQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("PS no QZ", QRCodeGenerator.ECCLevel.M); + var ps = new PostscriptQRCode(data); var result = ps.GetGraphic(5, SKColors.Black, SKColors.White, false); result.ShouldNotBeNullOrEmpty(); @@ -725,11 +725,11 @@ public void PostscriptQRCode_WithoutQuietZones_ShouldWork() [Category("BestPractices/ArtQRCode")] public void ArtQRCode_GetGraphic_Default_ShouldReturnBitmap() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Art test", QRCodeGenerator.ECCLevel.H); - using var art = new ArtQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Art test", QRCodeGenerator.ECCLevel.H); + var art = new ArtQRCode(data); - using var bmp = art.GetGraphic(10); + var bmp = art.GetGraphic(10); bmp.ShouldNotBeNull(); bmp.Width.ShouldBeGreaterThan(0); } @@ -738,11 +738,11 @@ public void ArtQRCode_GetGraphic_Default_ShouldReturnBitmap() [Category("BestPractices/ArtQRCode")] public void ArtQRCode_GetGraphic_WithCustomPixelSizeFactor_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Art pixel", QRCodeGenerator.ECCLevel.H); - using var art = new ArtQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Art pixel", QRCodeGenerator.ECCLevel.H); + var art = new ArtQRCode(data); - using var bmp = art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, pixelSizeFactor: 0.5); + var bmp = art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, pixelSizeFactor: 0.5); bmp.ShouldNotBeNull(); } @@ -750,11 +750,11 @@ public void ArtQRCode_GetGraphic_WithCustomPixelSizeFactor_ShouldWork() [Category("BestPractices/ArtQRCode")] public void ArtQRCode_GetGraphic_FlatQuietZone_ShouldWork() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Art flat QZ", QRCodeGenerator.ECCLevel.H); - using var art = new ArtQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Art flat QZ", QRCodeGenerator.ECCLevel.H); + var art = new ArtQRCode(data); - using var bmp = art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, + var bmp = art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, quietZoneRenderingStyle: ArtQRCode.QuietZoneStyle.Flat); bmp.ShouldNotBeNull(); } @@ -763,9 +763,9 @@ public void ArtQRCode_GetGraphic_FlatQuietZone_ShouldWork() [Category("BestPractices/ArtQRCode")] public void ArtQRCode_PixelSizeFactor_GreaterThanOne_ShouldThrow() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Out of range", QRCodeGenerator.ECCLevel.H); - using var art = new ArtQRCode(data); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Out of range", QRCodeGenerator.ECCLevel.H); + var art = new ArtQRCode(data); Should.Throw(() => art.GetGraphic(10, SKColors.Black, SKColors.White, SKColors.Transparent, pixelSizeFactor: 1.5)); @@ -1000,11 +1000,11 @@ public void Bookmark_Payload_ShouldGenerateCorrectFormat() [Category("BestPractices/CrossPlatform")] public void QRCode_SameInput_ShouldProduceSameModuleMatrix() { - using var gen1 = new QRCodeGenerator(); - using var gen2 = new QRCodeGenerator(); + var gen1 = new QRCodeGenerator(); + var gen2 = new QRCodeGenerator(); - using var data1 = gen1.CreateQrCode("Deterministic test", QRCodeGenerator.ECCLevel.M); - using var data2 = gen2.CreateQrCode("Deterministic test", QRCodeGenerator.ECCLevel.M); + var data1 = gen1.CreateQrCode("Deterministic test", QRCodeGenerator.ECCLevel.M); + var data2 = gen2.CreateQrCode("Deterministic test", QRCodeGenerator.ECCLevel.M); data1.ModuleMatrix.Count.ShouldBe(data2.ModuleMatrix.Count); for (int i = 0; i < data1.ModuleMatrix.Count; i++) @@ -1020,13 +1020,13 @@ public void QRCode_SameInput_ShouldProduceSameModuleMatrix() [Category("BestPractices/CrossPlatform")] public void PngByteQRCode_SameInput_ShouldProduceSameOutput() { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Deterministic PNG", QRCodeGenerator.ECCLevel.M); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Deterministic PNG", QRCodeGenerator.ECCLevel.M); - using var png1 = new PngByteQRCode(data); + var png1 = new PngByteQRCode(data); var bytes1 = png1.GetGraphic(5); - using var png2 = new PngByteQRCode(data); + var png2 = new PngByteQRCode(data); var bytes2 = png2.GetGraphic(5); bytes1.Length.ShouldBe(bytes2.Length); @@ -1044,10 +1044,10 @@ public void PngByteQRCode_SameInput_ShouldProduceSameOutput() [Category("BestPractices/CrossPlatform")] public void QRCode_DifferentModuleSizes_ShouldScaleCorrectly(int pixelsPerModule) { - using var gen = new QRCodeGenerator(); - using var data = gen.CreateQrCode("Scale test", QRCodeGenerator.ECCLevel.L); + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("Scale test", QRCodeGenerator.ECCLevel.L); - using var png = new PngByteQRCode(data); + var png = new PngByteQRCode(data); var bytes = png.GetGraphic(pixelsPerModule); bytes.ShouldNotBeNull(); bytes.Length.ShouldBeGreaterThan(0);