Skip to content

Added Unicode block element support #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions QRCoder/Utf8QRCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Text;
using static QRCoder.QRCodeGenerator;

namespace QRCoder
{
public class Utf8QRCode : AbstractQRCode, IDisposable
{
/// <summary>
/// Constructor without params to be used in COM Objects connections
/// </summary>
public Utf8QRCode() { }

public Utf8QRCode(QRCodeData data) : base(data) { }


/// <summary>
/// Returns a string that contains the resulting QR code, represented by the UTF8 chars SPACE, FULL BLOCK, UPPER HALF BLOCK and LOWER HALF BLOCK.
/// </summary>
/// <param name="drawQuietZones">If true, the mandatory space around the QR code is included</param>
/// <param name="endOfLine">End of line separator. (Default: \n)</param>
/// <param name="invert">If true, the returned QR code will be drawn inverted</param>
public string GetGraphic(bool drawQuietZones = true, string endOfLine = "\n", bool invert = false)
{
return string.Join(endOfLine, GetLineByLineGraphic(drawQuietZones, invert));
}

private IEnumerable<string> GetLineByLineGraphic(bool drawQuietZones = true, bool invert = false)
{
var quietZonesModifier = (drawQuietZones ? 0 : 8);
var quietZonesOffset = (int)(quietZonesModifier * 0.5);
var sideLength = QrCodeData.ModuleMatrix.Count - quietZonesModifier;

var lineBuilder = new StringBuilder(sideLength);

for (var y = 0; y < sideLength; y += 2)
{
for (var x = 0; x < sideLength; x++)
{
var module1 = QrCodeData.ModuleMatrix[x + quietZonesOffset][y + quietZonesOffset] ^ invert;
var module2 = (y + quietZonesOffset + 1 < QrCodeData.ModuleMatrix.Count && QrCodeData.ModuleMatrix[x + quietZonesOffset][y + quietZonesOffset + 1]) ^ invert;

if (module1 && module2)
{
lineBuilder.Append('\u2588');
}
else if (module1)
{
lineBuilder.Append('\u2580');
}
else if (module2)
{
lineBuilder.Append('\u2584');
}
else
{
lineBuilder.Append(' ');
}
}
yield return lineBuilder.ToString();
lineBuilder.Clear();
}
}
}

public static class Utf8QRCodeHelper
{
public static string GetQRCode(string plainText, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, string endOfLine = "\n", bool drawQuietZones = true, bool invert = false)
{
using (var qrGenerator = new QRCodeGenerator())
using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion))
using (var qrCode = new Utf8QRCode(qrCodeData))
return qrCode.GetGraphic(drawQuietZones, endOfLine, invert);
}
}
}
74 changes: 74 additions & 0 deletions QRCoderTests/Utf8CodeRendererTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using QRCoder;
using QRCoderTests.Helpers.XUnitExtenstions;
using Shouldly;
using Xunit;


namespace QRCoderTests
{

public class Utf8CodeRendererTests
{
[Fact]
[Category("QRRenderer/Utf8QRCode")]
public void can_render_utf8_qrcode()
{
var targetCode = " \n \n █▀▀▀▀▀█ ▄▀ █▄ █▀▀▀▀▀█ \n █ ███ █ ▀ █ ▀ █ ███ █ \n █ ▀▀▀ █ ▀▄▄▄▄ █ ▀▀▀ █ \n ▀▀▀▀▀▀▀ █ █▄▀ ▀▀▀▀▀▀▀ \n ██▀▀█ ▀█ ▄█▀▀▀▄█▄█▀▄ \n ▄ ▀ █ ▀██▀█▄▀▄█ ▀ ▀▀ \n ▀▀▀▀ ▀▀▀ ▄▄██ ▀ ▀ \n █▀▀▀▀▀█ ▀▀ ▀▀▄█▄█▀ ▀▀ \n █ ███ █ █▄█ ▀▄ █ ▀ ▀ \n █ ▀▀▀ █ █▄▀▄█ ▀ ▀█ █▀ \n ▀▀▀▀▀▀▀ ▀▀▀ ▀ ▀▀▀ \n \n ";

//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q);
var utf8Code = new Utf8QRCode(data).GetGraphic();

utf8Code.ShouldBe(targetCode);
}

[Fact]
[Category("QRRenderer/Utf8QRCode")]
public void can_render_utf8_qrcode_without_quietzones()
{
var targetCode = "█▀▀▀▀▀█ ▄▀ █▄ █▀▀▀▀▀█\n█ ███ █ ▀ █ ▀ █ ███ █\n█ ▀▀▀ █ ▀▄▄▄▄ █ ▀▀▀ █\n▀▀▀▀▀▀▀ █ █▄▀ ▀▀▀▀▀▀▀\n██▀▀█ ▀█ ▄█▀▀▀▄█▄█▀▄\n▄ ▀ █ ▀██▀█▄▀▄█ ▀ ▀▀ \n ▀▀▀▀ ▀▀▀ ▄▄██ ▀ ▀\n█▀▀▀▀▀█ ▀▀ ▀▀▄█▄█▀ ▀▀\n█ ███ █ █▄█ ▀▄ █ ▀ ▀\n█ ▀▀▀ █ █▄▀▄█ ▀ ▀█ █▀\n▀▀▀▀▀▀▀ ▀▀▀ ▀ ▀▀▀";

//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q);
var utf8Code = new Utf8QRCode(data).GetGraphic(drawQuietZones: false);

utf8Code.ShouldBe(targetCode);
}

[Fact]
[Category("QRRenderer/Utf8QRCode")]
public void can_render_utf8_qrcode_inverted()
{
var targetCode = "█████████████████████████████\n█████████████████████████████\n████ ▄▄▄▄▄ █▀▀▀▄ █ ▄▄▄▄▄ ████\n████ █ █ ██ ▄▄█ █ █ ████\n████ █▄▄▄█ █▄▀█▄██ █▄▄▄█ ████\n████▄▄▄▄▄▄▄█▄▀ ▀ █▄▄▄▄▄▄▄████\n████▀█ ▀ ▄▄▀ ▄ ▀▀ ██ ▀▀▄▀████\n█████▀████▄▀▄█▄█▀▄▀█ ▀ ██████\n█████▄█▄▄▄▄█ ▄█ ▀▀ ▄▄▄█▀ ████\n████ ▄▄▄▄▄ █▀▀ ▄▄▄█▀ ▀ ▄▄████\n████ █ █ █▄▀ ▄███▀ ▀ ▄█████\n████ █▄▄▄█ █▄▀▄▄▄▄██ ▀▄▄ ████\n████▄▄▄▄▄▄▄██▄██▄▄▄█▄▄█▄▄████\n█████████████████████████████\n█████████████████████████████";

//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("A", QRCodeGenerator.ECCLevel.Q);
var utf8Code = new Utf8QRCode(data).GetGraphic(invert: true);

utf8Code.ShouldBe(targetCode);
}

[Fact]
[Category("QRRenderer/Utf8QRCode")]
public void can_instantate_parameterless()
{
var utf8Code = new Utf8QRCode();
utf8Code.ShouldNotBeNull();
utf8Code.ShouldBeOfType<Utf8QRCode>();
}

[Fact]
[Category("QRRenderer/Utf8QRCode")]
public void can_render_utf8_qrcode_from_helper()
{
var targetCode = " \n \n █▀▀▀▀▀█ ▄▄▄▀█ █▀▀▀▀▀█ \n █ ███ █ ██▀▀ █ ███ █ \n █ ▀▀▀ █ ▀▄ ▀ █ ▀▀▀ █ \n ▀▀▀▀▀▀▀ ▀▄█▄█ ▀▀▀▀▀▀▀ \n ▄ █▄█▀▀▄█▀█▄▄█ █▄▄▀▄ \n ▄ ▀▄▀ ▀ ▄▀▄ █▄█ \n ▀ ▀▀▀▀ █▀ █▄▄█▀▀▀ ▄█ \n █▀▀▀▀▀█ ▄▄█▀▀▀ ▄█▄█▀▀ \n █ ███ █ ▀▄█▀ ▄█▄█▀ \n █ ▀▀▀ █ ▀▄▀▀▀▀ █▄▀▀█ \n ▀▀▀▀▀▀▀ ▀ ▀▀▀ ▀▀ ▀▀ \n \n ";

//Create QR code
var utf8Code = Utf8QRCodeHelper.GetQRCode("A", QRCodeGenerator.ECCLevel.Q);
utf8Code.ShouldBe(targetCode);
}
}
}