Skip to content
Open
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
16 changes: 16 additions & 0 deletions src/BinaryKits.Zpl.Label.UnitTest/BarcodeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,22 @@ public void BarcodeEan13()
Assert.AreEqual("^XA\n^LH0,0\n\n^FO100,300\n^BY2,3\n^BEN,100,Y,N\n^FD123456^FS\n^XZ", output);
}

[TestMethod]
public void BarcodeEan8()
{
var elements = new List<ZplElementBase>
{
new ZplBarcodeEan8("1234567", 100, 300)
};

var renderEngine = new ZplEngine(elements);
var output = renderEngine.ToZplString(new ZplRenderOptions { AddEmptyLineBeforeElementStart = true });

Debug.WriteLine(output);
Assert.IsNotNull(output);
Assert.AreEqual("^XA\n^LH0,0\n\n^FO100,300\n^BY2,3\n^B8N,100,Y,N\n^FD1234567^FS\n^XZ", output);
}

[TestMethod]
public void DataMatrixDefault()
{
Expand Down
65 changes: 65 additions & 0 deletions src/BinaryKits.Zpl.Label/Elements/ZplBarcodeEan8.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Generic;

namespace BinaryKits.Zpl.Label.Elements
{
/// <summary>
/// EAN-8 Barcode
/// </summary>
public class ZplBarcodeEan8 : ZplBarcode
{
/// <summary>
/// EAN-8 Barcode
/// </summary>
/// <param name="content"></param>
/// <param name="positionX"></param>
/// <param name="positionY"></param>
/// <param name="height"></param>
/// <param name="moduleWidth"></param>
/// <param name="wideBarToNarrowBarWidthRatio"></param>
/// <param name="fieldOrientation"></param>
/// <param name="hexadecimalIndicator"></param>
/// <param name="printInterpretationLine"></param>
/// <param name="printInterpretationLineAboveCode"></param>
/// <param name="bottomToTop"></param>
/// <param name="useDefaultPosition"></param>
public ZplBarcodeEan8(
string content,
int positionX,
int positionY,
int height = 100,
int moduleWidth = 2,
double wideBarToNarrowBarWidthRatio = 3,
FieldOrientation fieldOrientation = FieldOrientation.Normal,
char? hexadecimalIndicator = null,
bool printInterpretationLine = true,
bool printInterpretationLineAboveCode = false,
bool bottomToTop = false,
bool useDefaultPosition = false)
: base(content,
positionX,
positionY,
height,
moduleWidth,
wideBarToNarrowBarWidthRatio,
fieldOrientation,
hexadecimalIndicator,
printInterpretationLine,
printInterpretationLineAboveCode,
bottomToTop,
useDefaultPosition)
{
}

///<inheritdoc/>
public override IEnumerable<string> Render(ZplRenderOptions context)
{
var result = new List<string>();
result.AddRange(RenderPosition(context));
result.Add(RenderModuleWidth());
result.Add($"^B8{RenderFieldOrientation()},{context.Scale(Height)},{RenderPrintInterpretationLine()},{RenderPrintInterpretationLineAboveCode()}");
result.Add(RenderFieldDataSection());

return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<None Update="Labels\Test\BarcodeEAN13-102x152.zpl2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Labels\Test\BarcodeEAN8-102x152.zpl2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Labels\Example\Example1-54x86.zpl2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
^XA

^FO60,10
^BY1
^B8N,50,Y
^FD1234567^FS

^FO60,90
^BY2
^B8N,100,Y
^FD1234567^FS

^FO60,230
^BY3
^B8N,150,Y
^FD1234567^FS

^FO60,430
^BY4
^B8N,200,Y
^FD1234567^FS

^FO60,700
^BY5
^B8N,250,Y
^FH^FD_31_32_33_34_35_36_37^FS

^XZ
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using BinaryKits.Zpl.Label;
using BinaryKits.Zpl.Label.Elements;
using BinaryKits.Zpl.Viewer.Models;

namespace BinaryKits.Zpl.Viewer.CommandAnalyzers
{
public class CodeEAN8BarcodeZplCommandAnalyzer : ZplCommandAnalyzerBase
{
public CodeEAN8BarcodeZplCommandAnalyzer() : base("^B8") { }

///<inheritdoc/>
public override ZplElementBase Analyze(string zplCommand, VirtualPrinter virtualPrinter, IPrinterStorage printerStorage)
{
string[] zplDataParts = this.SplitCommand(zplCommand);

FieldOrientation fieldOrientation = this.ConvertFieldOrientation(zplDataParts[0], virtualPrinter);

int tmpint;
int height = virtualPrinter.BarcodeInfo.Height;
bool printInterpretationLine = true;
bool printInterpretationLineAboveCode = false;

if (zplDataParts.Length > 1 && int.TryParse(zplDataParts[1], out tmpint))
{
height = tmpint;
}

if (zplDataParts.Length > 2)
{
printInterpretationLine = this.ConvertBoolean(zplDataParts[2], "Y");
}

if (zplDataParts.Length > 3)
{
printInterpretationLineAboveCode = this.ConvertBoolean(zplDataParts[3]);
}

//The field data are processing in the FieldDataZplCommandAnalyzer
virtualPrinter.SetNextElementFieldData(new CodeEAN8BarcodeFieldData
{
FieldOrientation = fieldOrientation,
Height = height,
PrintInterpretationLine = printInterpretationLine,
PrintInterpretationLineAboveCode = printInterpretationLineAboveCode
});

return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ public override ZplElementBase Analyze(string zplCommand, VirtualPrinter virtual
{
return new ZplBarcode128(text, x, y, code128.Height, moduleWidth, wideBarToNarrowBarWidthRatio, code128.FieldOrientation, hexadecimalIndicator, code128.PrintInterpretationLine, code128.PrintInterpretationLineAboveCode, bottomToTop, useDefaultPosition, code128.Mode);
}
else if (virtualPrinter.NextElementFieldData is CodeEAN8BarcodeFieldData codeEAN8)
{
return new ZplBarcodeEan8(text, x, y, codeEAN8.Height, moduleWidth, wideBarToNarrowBarWidthRatio, codeEAN8.FieldOrientation, hexadecimalIndicator, codeEAN8.PrintInterpretationLine, codeEAN8.PrintInterpretationLineAboveCode, bottomToTop, useDefaultPosition);
}
else if (virtualPrinter.NextElementFieldData is CodeEAN13BarcodeFieldData codeEAN13)
{
return new ZplBarcodeEan13(text, x, y, codeEAN13.Height, moduleWidth, wideBarToNarrowBarWidthRatio, codeEAN13.FieldOrientation, hexadecimalIndicator, codeEAN13.PrintInterpretationLine, codeEAN13.PrintInterpretationLineAboveCode, bottomToTop, useDefaultPosition);
Expand Down
161 changes: 161 additions & 0 deletions src/BinaryKits.Zpl.Viewer/ElementDrawers/BarcodeEAN8ElementDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
using BinaryKits.Zpl.Label;
using BinaryKits.Zpl.Label.Elements;
using BinaryKits.Zpl.Viewer.Helpers;

using SkiaSharp;

using System;

using ZXing.OneD;

namespace BinaryKits.Zpl.Viewer.ElementDrawers
{
/// <summary>
/// Drawer for EAN-8 Barcode elements
/// </summary>
public class BarcodeEAN8ElementDrawer : BarcodeDrawerBase
{
// EAN-8 module layout (67 modules total):
// 3 (start guard) + 4*7 (left digits) + 5 (middle guard) + 4*7 (right digits) + 3 (end guard)
// Guard bars (long bars below the barcode) at: start 0,2 | middle 32,34 | end 64,66
private static readonly bool[] guards = new bool[67];

static BarcodeEAN8ElementDrawer()
{
foreach (int idx in new int[] { 0, 2, 32, 34, 64, 66 })
{
guards[idx] = true;
}
}

///<inheritdoc/>
public override bool CanDraw(ZplElementBase element)
{
return element is ZplBarcodeEan8;
}

///<inheritdoc/>
public override SKPoint Draw(ZplElementBase element, DrawerOptions options, SKPoint currentPosition, InternationalFont internationalFont, int printDensityDpmm)
{
if (element is ZplBarcodeEan8 barcode)
{
float x = barcode.PositionX;
float y = barcode.PositionY;

if (barcode.UseDefaultPosition)
{
x = currentPosition.X;
y = currentPosition.Y;
}

string content = barcode.Content;
if (barcode.HexadecimalIndicator is char hexIndicator)
{
content = content.ReplaceHexEscapes(hexIndicator, internationalFont);
}

content = content.PadLeft(7, '0').Substring(0, 7);
string interpretation = content;

// EAN-8 check digit: 3*odd-position digits + even-position digits, then (10 - sum%10) % 10.
int checksum = 0;
for (int i = 0; i < 7; i++)
{
checksum += (content[i] - 48) * (i % 2 == 0 ? 3 : 1);
}
int checkDigit = (10 - checksum % 10) % 10;
interpretation = string.Format("{0}{1}", interpretation, checkDigit);

EAN8Writer writer = new();
bool[] result = writer.encode(content);
using SKBitmap resizedImage = BoolArrayToSKBitmap(result, barcode.Height, barcode.ModuleWidth);
byte[] png = resizedImage.Encode(SKEncodedImageFormat.Png, 100).ToArray();
this.DrawBarcode(png, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation);

if (barcode.PrintInterpretationLine)
{
float labelFontSize = FontScale.GetBitmappedFontSize("A", Math.Min(barcode.ModuleWidth, 10), printDensityDpmm).Value;
SKTypeface labelTypeFace = options.FontManager.FontLoader("A");
SKFont labelFont = new(labelTypeFace, labelFontSize);
if (barcode.PrintInterpretationLineAboveCode)
{
this.DrawInterpretationLine(interpretation, labelFont, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation, true, options);
}
else
{
this.DrawEAN8InterpretationLine(interpretation, labelFont, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation, barcode.ModuleWidth, options);
}
}

return this.CalculateNextDefaultPosition(x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation, currentPosition);
}

return currentPosition;
}

private void DrawEAN8InterpretationLine(
string interpretation,
SKFont skFont,
float x,
float y,
int barcodeWidth,
int barcodeHeight,
bool useFieldOrigin,
FieldOrientation fieldOrientation,
int moduleWidth,
DrawerOptions options)
{
using (new SKAutoCanvasRestore(this.skCanvas))
{
using SKPaint skPaint = new()
{
IsAntialias = options.Antialias
};

SKMatrix matrix = GetRotationMatrix(x, y, barcodeWidth, barcodeHeight, useFieldOrigin, fieldOrientation);

if (matrix != SKMatrix.Empty)
{
SKMatrix currentMatrix = this.skCanvas.TotalMatrix;
SKMatrix concatMatrix = SKMatrix.Concat(currentMatrix, matrix);
this.skCanvas.SetMatrix(concatMatrix);
}

skFont.MeasureText(interpretation, out SKRect textBounds);

if (!useFieldOrigin)
{
y -= barcodeHeight;
if (y < 0)
{
y = 0;
}
}

float margin = Math.Max((skFont.Spacing - textBounds.Height) / 2, MIN_LABEL_MARGIN);
int spacing = moduleWidth * 7;

using SKBitmap guardImage = BoolArrayToSKBitmap(guards, (int)(margin + textBounds.Height / 2), moduleWidth);
byte[] guardPng = guardImage.Encode(SKEncodedImageFormat.Png, 100).ToArray();
this.skCanvas.DrawBitmap(SKBitmap.Decode(guardPng), x, y + barcodeHeight);

// Position cursor at the center of the first left-half digit:
// start guard (3 modules) + half of first digit (3.5 modules) = 6.5 modules from barcode origin.
x += moduleWidth * 6.5f;
for (int i = 0; i < interpretation.Length; i++)
{
string digit = interpretation[i].ToString();
skFont.MeasureText(digit, out SKRect digitBounds);
this.skCanvas.DrawText(digit, x - digitBounds.Width / 2, y + barcodeHeight + textBounds.Height + margin, skFont, skPaint);
x += spacing;
if (i == 3)
{
// After the 4 left-half digits, skip the 5-module middle guard.
x += moduleWidth * 5;
}
}
}
}

}
}
13 changes: 13 additions & 0 deletions src/BinaryKits.Zpl.Viewer/Models/CodeEAN8BarcodeFieldData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using BinaryKits.Zpl.Label;

namespace BinaryKits.Zpl.Viewer.Models
{
public class CodeEAN8BarcodeFieldData : FieldDataBase
{
public FieldOrientation FieldOrientation { get; set; }
public int Height { get; set; }
public bool PrintInterpretationLine { get; set; }
public bool PrintInterpretationLineAboveCode { get; set; }

}
}
1 change: 1 addition & 0 deletions src/BinaryKits.Zpl.Viewer/ZplAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ZplAnalyzer : IZplAnalyzer
new Code39BarcodeZplCommandAnalyzer(),
new Code93BarcodeZplCommandAnalyzer(),
new Code128BarcodeZplCommandAnalyzer(),
new CodeEAN8BarcodeZplCommandAnalyzer(),
new CodeEAN13BarcodeZplCommandAnalyzer(),
new CommentZplCommandAnalyzer(),
new DataMatrixZplCommandAnalyzer(),
Expand Down
1 change: 1 addition & 0 deletions src/BinaryKits.Zpl.Viewer/ZplElementDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class ZplElementDrawer
new Barcode128ElementDrawer(),
new Barcode39ElementDrawer(),
new Barcode93ElementDrawer(),
new BarcodeEAN8ElementDrawer(),
new BarcodeEAN13ElementDrawer(),
new BarcodeUpcAElementDrawer(),
new BarcodeUpcEElementDrawer(),
Expand Down