Skip to content

Commit

Permalink
Drop BarcodeLib dependency (#229)
Browse files Browse the repository at this point in the history
* Drop BarcodeLib dependency

* don't inline regex
  • Loading branch information
primo-ppcg authored Apr 26, 2024
1 parent 9dafc53 commit f949ad6
Show file tree
Hide file tree
Showing 28 changed files with 817 additions and 345 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@ FFFFFFFFFFFFFFFFFFFFFFFFFFFFF00C1B6C00
^FT105,982^BY3^BCN,202,N,N,,A^FV1ZRW01750399905329^FS

^FT273,896^A0N,95,74^FVSAMPLE^FS
^XZ^XZ
^XZ
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,33 @@
^FO10,10
^BY3
^BCN,100,Y
^FD123ABC^FS
^FDABC12345^FS

^FO10,160
^BY4
^BCN,100,Y
^FD123ABC^FS
^FDABC12345^FS

^FO10,320
^BY5
^BCN,100,Y
^FD123ABC^FS
^FDABC12345^FS

^FX Automatic Mode

^FO10,500
^BY3
^BCN,100,Y,,,A
^FD123ABC^FS
^FDABC12345^FS

^FO10,650
^BY4
^BCN,100,Y,,,A
^FD123ABC^FS
^FDABC12345^FS

^FO10,810
^BY5
^BCN,100,Y,,,A
^FD123ABC^FS
^FDABC12345^FS

^XZ
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
^XA

^FO10,10
^BY3
^FO60,10
^BY1
^BEN,50,Y
^FD123456789012^FS

^FO60,90
^BY2
^BEN,100,Y
^FD123456789012^FS

^FO10,160
^FO60,230
^BY3
^BEN,150,Y
^FD123456789012^FS

^FO60,430
^BY4
^BEN,100,Y
^BEN,200,Y
^FD123456789012^FS

^FO10,320
^FO60,700
^BY5
^BEN,100,Y
^BEN,250,Y
^FD123456789012^FS

^XZ
2 changes: 0 additions & 2 deletions src/BinaryKits.Zpl.Viewer/BinaryKits.Zpl.Viewer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BarcodeLib" Version="2.4.0" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.88.8" />
<PackageReference Include="ZXing.Net" Version="0.16.9" />
<PackageReference Include="CoelWu.Zint.Net" Version="1.0.0" />
Expand Down
117 changes: 26 additions & 91 deletions src/BinaryKits.Zpl.Viewer/ElementDrawers/Barcode128ElementDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,138 +1,73 @@
using BarcodeLib;
using BinaryKits.Zpl.Label.Elements;
using BinaryKits.Zpl.Viewer.Helpers;
using BinaryKits.Zpl.Viewer.Symologies;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text.RegularExpressions;

namespace BinaryKits.Zpl.Viewer.ElementDrawers
{
/// <summary>
/// Drawer for Code 128 Barcode elements
/// </summary>
public class Barcode128ElementDrawer : BarcodeDrawerBase
{
/// <summary>
/// Start sequence lookups.
/// <see href="https://supportcommunity.zebra.com/s/article/Creating-GS1-Barcodes-with-Zebra-Printers-for-Data-Matrix-and-Code-128-using-ZPL"/>
/// </summary>
private static readonly Dictionary<string, TYPE> startCodeMap = new Dictionary<string, TYPE>()
{
{ ">6", TYPE.CODE128A },
{ ">9", TYPE.CODE128A },
{ ">:", TYPE.CODE128B },
{ ">;", TYPE.CODE128C },
{ ">5", TYPE.CODE128C },
};

private static readonly Regex startCodeRegex = new Regex(@"(>[569:;])(.+)", RegexOptions.Compiled);
private static readonly Regex invalidInvocationRegex = new Regex(@"(?<!^)>[569:;]", RegexOptions.Compiled);

// As defined in BarcodeLib.Symbologies.Code128
private static readonly string FNC1 = Convert.ToChar(200).ToString();

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

///<inheritdoc/>
public override void Draw(ZplElementBase element)
{
Draw(element, new DrawerOptions());
}

///<inheritdoc/>
public override void Draw(ZplElementBase element, DrawerOptions options)
{
if (element is ZplBarcode128 barcode)
{
var barcodeType = TYPE.CODE128;

//remove the start code form the content we only support the globals N,A,D,U and our barcode library doesn't support these types
string content = startCodeRegex.Replace(barcode.Content, "");
string interpretation = content;

// remove any start sequences not at the start of the content (invalid invocation)
content = invalidInvocationRegex.Replace(content, "");
interpretation = content;

// support hand-rolled GS1
content = content.Replace(">8", FNC1);
interpretation = interpretation.Replace(">8", "");

string content = barcode.Content;
Code128CodeSet codeSet = Code128CodeSet.Code128B;
bool gs1 = false;
if (string.IsNullOrEmpty(barcode.Mode) || barcode.Mode == "N")
{
Match startCodeMatch = startCodeRegex.Match(barcode.Content);
if (startCodeMatch.Success)
{
barcodeType = TYPE.CODE128;
//TODO: Instead of using the auto type, switch type for each part of the content
//>:+B210AC>50270>6/$+2>5023080000582>6L
//[TYPE.CODE128B]+B210AC
//[TYPE.CODE128C]0270
//[TYPE.CODE128A]+/$+2
//[TYPE.CODE128C]023080000582
//[TYPE.CODE128A]L
}

// support hand-rolled GS1
content = content.Replace(">8", FNC1);
interpretation = interpretation.Replace(">8", "");
// TODO: support remaining escapes within a barcode
codeSet = Code128CodeSet.Code128B;
}
else if (barcode.Mode == "A")
{
//A (automatic mode, the ZPL engine automatically determines the subsets that are used to encode the data)
barcodeType = TYPE.CODE128; // dynamic
codeSet = Code128CodeSet.Code128;
}
else if (barcode.Mode == "D")
{
//D (UCC/EAN mode, field data must contain GS1 numbers)
barcodeType = TYPE.CODE128C;

if (!content.StartsWith(FNC1))
{
content = FNC1 + content;
}
codeSet = Code128CodeSet.Code128C;
gs1 = true;
}
else if (barcode.Mode == "U")
{
//U (UCC case mode, field data must contain 19 digits)
barcodeType = TYPE.CODE128C;
codeSet = Code128CodeSet.Code128C;
gs1 = true;
content = content.PadLeft(19, '0').Substring(0, 19);
int checksum = 0;
for (int i = 0; i < 19; i++)
{
checksum += (content[i] - 48) * (i % 2 * 2 + 7);
}
interpretation = string.Format("{0}{1}", interpretation, checksum % 10);
content = string.Format("{0}{1}{2}", FNC1, content, checksum % 10);
content = $">8{content}{checksum % 10}";
}

float x = barcode.PositionX;
float y = barcode.PositionY;

float labelFontSize = Math.Min(barcode.ModuleWidth * 7.2f, 72f);
var labelTypeFace = options.FontLoader("A");
var labelFont = new SKFont(labelTypeFace, labelFontSize).ToSystemDrawingFont();
int labelHeight = barcode.PrintInterpretationLine ? labelFont.Height : 0;
int labelHeightOffset = barcode.PrintInterpretationLineAboveCode ? labelHeight : 0;
var (data, interpretation) = ZplCode128Symbology.Encode(content, codeSet, gs1);
using var resizedImage = this.BoolArrayToSKBitmap(data.ToArray(), barcode.Height, barcode.ModuleWidth);
var png = resizedImage.Encode(SKEncodedImageFormat.Png, 100).ToArray();
this.DrawBarcode(png, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation);

var barcodeElement = new Barcode
if (barcode.PrintInterpretationLine)
{
BarWidth = barcode.ModuleWidth,
BackColor = Color.Transparent,
Height = barcode.Height + labelHeight,
IncludeLabel = barcode.PrintInterpretationLine,
LabelPosition = barcode.PrintInterpretationLineAboveCode ? LabelPositions.TOPCENTER : LabelPositions.BOTTOMCENTER,
LabelFont = labelFont,
AlternateLabel = interpretation
};

using var image = barcodeElement.Encode(barcodeType, content);
this.DrawBarcode(this.GetImageData(image), barcode.Height, image.Width, barcode.FieldOrigin != null, x, y, labelHeightOffset, barcode.FieldOrientation);
// TODO: use font 0, auto scale for Mode D
float labelFontSize = Math.Min(barcode.ModuleWidth * 10f, 100f);
var labelTypeFace = options.FontLoader("A");
var labelFont = new SKFont(labelTypeFace, labelFontSize);
this.DrawInterpretationLine(interpretation, labelFont, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation, barcode.PrintInterpretationLineAboveCode, options);
}
}
}

}
}
48 changes: 20 additions & 28 deletions src/BinaryKits.Zpl.Viewer/ElementDrawers/Barcode39ElementDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using BarcodeLib;
using BinaryKits.Zpl.Label.Elements;
using BinaryKits.Zpl.Viewer.Helpers;
using SkiaSharp;
using System;
using System.Drawing;
using ZXing.OneD;

namespace BinaryKits.Zpl.Viewer.ElementDrawers
{
/// <summary>
/// Drawer for Code 39 Barcode elements
/// </summary>
public class Barcode39ElementDrawer : BarcodeDrawerBase
{
///<inheritdoc/>
Expand All @@ -15,12 +16,6 @@ public override bool CanDraw(ZplElementBase element)
return element is ZplBarcode39;
}

///<inheritdoc/>
public override void Draw(ZplElementBase element)
{
Draw(element, new DrawerOptions());
}

///<inheritdoc/>
public override void Draw(ZplElementBase element, DrawerOptions options)
{
Expand All @@ -29,28 +24,25 @@ public override void Draw(ZplElementBase element, DrawerOptions options)
float x = barcode.PositionX;
float y = barcode.PositionY;

var content = barcode.Content;
var interpretation = string.Format("*{0}*", content.Trim('*'));
var content = barcode.Content.Trim('*');
var interpretation = string.Format("*{0}*", content);

float labelFontSize = Math.Min(barcode.ModuleWidth * 7.2f, 72f);
var labelTypeFace = options.FontLoader("A");
var labelFont = new SKFont(labelTypeFace, labelFontSize).ToSystemDrawingFont();
int labelHeight = barcode.PrintInterpretationLine ? labelFont.Height : 0;
int labelHeightOffset = barcode.PrintInterpretationLineAboveCode ? labelHeight : 0;
var writer = new Code39Writer();
var result = writer.encode(content);
int narrow = barcode.ModuleWidth;
int wide = (int)Math.Floor(barcode.WideBarToNarrowBarWidthRatio * narrow);
result = this.AdjustWidths(result, wide, narrow);
using var resizedImage = this.BoolArrayToSKBitmap(result, barcode.Height);
var png = resizedImage.Encode(SKEncodedImageFormat.Png, 100).ToArray();
this.DrawBarcode(png, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation);

var barcodeElement = new Barcode
if (barcode.PrintInterpretationLine)
{
BarWidth = barcode.ModuleWidth,
BackColor = Color.Transparent,
Height = barcode.Height + labelHeight,
IncludeLabel = barcode.PrintInterpretationLine,
LabelPosition = barcode.PrintInterpretationLineAboveCode ? LabelPositions.TOPCENTER : LabelPositions.BOTTOMCENTER,
LabelFont = labelFont,
AlternateLabel = interpretation
};

using var image = barcodeElement.Encode(TYPE.CODE39Extended, content);
this.DrawBarcode(this.GetImageData(image), barcode.Height, image.Width, barcode.FieldOrigin != null, x, y, labelHeightOffset, barcode.FieldOrientation);
float labelFontSize = Math.Min(barcode.ModuleWidth * 10f, 100f);
var labelTypeFace = options.FontLoader("A");
var labelFont = new SKFont(labelTypeFace, labelFontSize);
this.DrawInterpretationLine(interpretation, labelFont, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation, barcode.PrintInterpretationLineAboveCode, options);
}
}
}
}
Expand Down
33 changes: 13 additions & 20 deletions src/BinaryKits.Zpl.Viewer/ElementDrawers/Barcode93ElementDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using BarcodeLib;
using BinaryKits.Zpl.Label.Elements;
using BinaryKits.Zpl.Viewer.Helpers;
using BinaryKits.Zpl.Label.Elements;
using SkiaSharp;
using System;
using System.Drawing;
using ZXing.OneD;

namespace BinaryKits.Zpl.Viewer.ElementDrawers
{
Expand Down Expand Up @@ -31,25 +29,20 @@ public override void Draw(ZplElementBase element, DrawerOptions options)

var content = barcode.Content;

float labelFontSize = Math.Min(barcode.ModuleWidth * 7.2f, 72f);
var labelTypeFace = options.FontLoader("A");
var labelFont = new SKFont(labelTypeFace, labelFontSize).ToSystemDrawingFont();
int labelHeight = barcode.PrintInterpretationLine ? labelFont.Height : 0;
int labelHeightOffset = barcode.PrintInterpretationLineAboveCode ? labelHeight : 0;
var writer = new Code93Writer();
var result = writer.encode(content);
using var resizedImage = this.BoolArrayToSKBitmap(result, barcode.Height, barcode.ModuleWidth);
var png = resizedImage.Encode(SKEncodedImageFormat.Png, 100).ToArray();
this.DrawBarcode(png, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrigin != null, barcode.FieldOrientation);

var barcodeElement = new Barcode
if (barcode.PrintInterpretationLine)
{
BarWidth = barcode.ModuleWidth,
BackColor = Color.Transparent,
Height = barcode.Height + labelHeight,
IncludeLabel = barcode.PrintInterpretationLine,
LabelPosition = barcode.PrintInterpretationLineAboveCode ? LabelPositions.TOPCENTER : LabelPositions.BOTTOMCENTER,
LabelFont = labelFont,
AlternateLabel = content
};
float labelFontSize = Math.Min(barcode.ModuleWidth * 10f, 100f);
var labelTypeFace = options.FontLoader("A");
var labelFont = new SKFont(labelTypeFace, labelFontSize);
this.DrawInterpretationLine(content, labelFont, x, y, resizedImage.Width, resizedImage.Height, barcode.FieldOrientation != null, barcode.FieldOrientation, barcode.PrintInterpretationLineAboveCode, options);

Check warning on line 43 in src/BinaryKits.Zpl.Viewer/ElementDrawers/Barcode93ElementDrawer.cs

View workflow job for this annotation

GitHub Actions / build-windows

The result of the expression is always 'true' since a value of type 'FieldOrientation' is never equal to 'null' of type 'FieldOrientation?'

Check warning on line 43 in src/BinaryKits.Zpl.Viewer/ElementDrawers/Barcode93ElementDrawer.cs

View workflow job for this annotation

GitHub Actions / build-linux

The result of the expression is always 'true' since a value of type 'FieldOrientation' is never equal to 'null' of type 'FieldOrientation?'
}

using var image = barcodeElement.Encode(TYPE.CODE93, content);
this.DrawBarcode(this.GetImageData(image), barcode.Height, image.Width, barcode.FieldOrigin != null, x, y, labelHeightOffset, barcode.FieldOrientation);
}
}
}
Expand Down
Loading

0 comments on commit f949ad6

Please sign in to comment.