Skip to content

Commit 4a039ce

Browse files
authored
Implement Aztec Barcode (#249)
Initial implementation of ^BO Aztec Bar Code, fixes #246 Several of the parameters are not respected (menu symbol indicator, number of symbols for structured append, optional ID field for structured append).
1 parent 7961201 commit 4a039ce

File tree

8 files changed

+245
-5
lines changed

8 files changed

+245
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System.Collections.Generic;
2+
3+
namespace BinaryKits.Zpl.Label.Elements
4+
{
5+
public class ZplAztecBarcode : ZplPositionedElementBase, IFormatElement
6+
{
7+
public int MagnificationFactor { get; protected set; }
8+
public bool ExtendedChannel { get; protected set; }
9+
public int ErrorControl { get; protected set; }
10+
public bool MenuSymbol { get; protected set; }
11+
public int SymbolCount { get; protected set; }
12+
public string IdField { get; protected set; }
13+
public string Content { get; protected set; }
14+
public bool UseHexadecimalIndicator { get; protected set; }
15+
public FieldOrientation FieldOrientation { get; protected set; }
16+
17+
/// <summary>
18+
/// Aztec Bar Code
19+
/// </summary>
20+
/// <param name="content"></param>
21+
/// <param name="positionX"></param>
22+
/// <param name="positionY"></param>
23+
/// <param name="magnificationFactor"></param>
24+
/// <param name="extendedChannel">extended channel interpretation code indicator</param>
25+
/// <param name="errorControl">error control and symbol size/type indicator</param>
26+
/// <param name="menuSymbol">menu symbol indicator</param>
27+
/// <param name="symbolCount">number of symbols for structured append</param>
28+
/// <param name="idField">optional ID field for structured append</param>
29+
/// <param name="useHexadecimalIndicator"></param>
30+
/// <param name="fieldOrientation"></param>
31+
/// <param name="bottomToTop"></param>
32+
public ZplAztecBarcode(
33+
string content,
34+
int positionX,
35+
int positionY,
36+
int magnificationFactor = 2,
37+
bool extendedChannel = false,
38+
int errorControl = 0,
39+
bool menuSymbol = false,
40+
int symbolCount = 1,
41+
string idField = null,
42+
bool useHexadecimalIndicator = true,
43+
FieldOrientation fieldOrientation = FieldOrientation.Normal,
44+
bool bottomToTop = false
45+
)
46+
: base(positionX, positionY, bottomToTop)
47+
{
48+
this.Content = content;
49+
this.MagnificationFactor = magnificationFactor;
50+
this.ExtendedChannel = extendedChannel;
51+
this.ErrorControl = errorControl;
52+
this.SymbolCount = symbolCount;
53+
this.IdField = idField;
54+
this.UseHexadecimalIndicator = useHexadecimalIndicator;
55+
this.FieldOrientation = fieldOrientation;
56+
}
57+
58+
///<inheritdoc/>
59+
public override IEnumerable<string> Render(ZplRenderOptions context)
60+
{
61+
var result = new List<string>();
62+
result.AddRange(RenderPosition(context));
63+
result.Add($"^BO{RenderFieldOrientation(this.FieldOrientation)},{this.MagnificationFactor},{RenderBoolean(this.ExtendedChannel)}," +
64+
$"{this.ErrorControl},{RenderBoolean(this.MenuSymbol)},{this.SymbolCount},{this.IdField}");
65+
result.Add($"^FD{this.Content}^FS");
66+
67+
return result;
68+
}
69+
70+
/// <inheritdoc />
71+
public void SetTemplateContent(string content)
72+
{
73+
this.Content = content;
74+
}
75+
}
76+
}

src/BinaryKits.Zpl.Label/Elements/ZplElementBase.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33

44
namespace BinaryKits.Zpl.Label.Elements
@@ -8,7 +8,7 @@ public abstract class ZplElementBase
88
public List<string> Comments { get; protected set; }
99

1010
/// <summary>
11-
/// Indicate the rendering process whether this elemenet can be skipped
11+
/// Indicate the rendering process whether this element can be skipped
1212
/// </summary>
1313
public bool IsEnabled { get; set; }
1414

@@ -108,6 +108,16 @@ public string RenderErrorCorrectionLevel(ErrorCorrectionLevel errorCorrectionLev
108108
throw new NotImplementedException("Unknown Error Correction Level");
109109
}
110110

111+
/// <summary>
112+
/// Render Zpl char for boolean
113+
/// </summary>
114+
/// <param name="value"></param>
115+
/// <returns></returns>
116+
public string RenderBoolean(bool value)
117+
{
118+
return value ? "Y" : "N";
119+
}
120+
111121
public string ToZplString()
112122
{
113123
return ToZplString(new ZplRenderOptions());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using BinaryKits.Zpl.Label.Elements;
2+
using BinaryKits.Zpl.Viewer.Models;
3+
4+
namespace BinaryKits.Zpl.Viewer.CommandAnalyzers
5+
{
6+
public class AztecBarcodeZplCommandAnalyzer : ZplCommandAnalyzerBase
7+
{
8+
public AztecBarcodeZplCommandAnalyzer(VirtualPrinter virtualPrinter) : base("^BO", virtualPrinter) { }
9+
10+
///<inheritdoc/>
11+
public override ZplElementBase Analyze(string zplCommand)
12+
{
13+
var zplDataParts = this.SplitCommand(zplCommand);
14+
15+
int tmpint;
16+
var fieldOrientation = this.ConvertFieldOrientation(zplDataParts[0]);
17+
int magnificationFactor = 2;
18+
bool extendedChannel = false;
19+
int errorControl = 0;
20+
bool menuSymbol = false;
21+
int symbolCount = 1;
22+
string idField = null;
23+
24+
if (zplDataParts.Length > 1 && int.TryParse(zplDataParts[1], out tmpint))
25+
{
26+
magnificationFactor = tmpint;
27+
}
28+
29+
if (zplDataParts.Length > 2)
30+
{
31+
extendedChannel = ConvertBoolean(zplDataParts[2]);
32+
}
33+
34+
if (zplDataParts.Length > 3 && int.TryParse(zplDataParts[3], out tmpint))
35+
{
36+
errorControl = tmpint;
37+
}
38+
39+
if (zplDataParts.Length > 4)
40+
{
41+
menuSymbol = ConvertBoolean(zplDataParts[4]);
42+
}
43+
44+
if (zplDataParts.Length > 5 && int.TryParse(zplDataParts[5], out tmpint))
45+
{
46+
symbolCount = tmpint;
47+
}
48+
49+
if (zplDataParts.Length > 6)
50+
{
51+
idField = zplDataParts[6];
52+
}
53+
54+
this.VirtualPrinter.SetNextElementFieldData(new AztecBarcodeFieldData
55+
{
56+
FieldOrientation = fieldOrientation,
57+
MagnificationFactor = magnificationFactor,
58+
ExtendedChannel = extendedChannel,
59+
ErrorControl = errorControl,
60+
MenuSymbol = menuSymbol,
61+
SymbolCount = symbolCount,
62+
IdField = idField
63+
});
64+
65+
return null;
66+
}
67+
68+
}
69+
}

src/BinaryKits.Zpl.Viewer/CommandAnalyzers/FieldDataZplCommandAnalyzer.cs

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ public override ZplElementBase Analyze(string zplCommand)
9494
{
9595
return new ZplPDF417(text, x, y, pdf147.Height, moduleWidth, pdf147.Columns, pdf147.Rows, pdf147.Compact, pdf147.SecurityLevel, pdf147.FieldOrientation, bottomToTop);
9696
}
97+
if (this.VirtualPrinter.NextElementFieldData is AztecBarcodeFieldData aztec)
98+
{
99+
return new ZplAztecBarcode(text, x, y, aztec.MagnificationFactor, aztec.ExtendedChannel, aztec.ErrorControl, aztec.MenuSymbol, aztec.SymbolCount, aztec.IdField, useHexadecimalIndicator, aztec.FieldOrientation, bottomToTop);
100+
}
97101
}
98102

99103
var font = this.GetFontFromVirtualPrinter();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using BinaryKits.Zpl.Label.Elements;
2+
using BinaryKits.Zpl.Viewer.Helpers;
3+
4+
using SkiaSharp;
5+
6+
using ZXing.Aztec;
7+
8+
namespace BinaryKits.Zpl.Viewer.ElementDrawers
9+
{
10+
public class AztecBarcodeElementDrawer : BarcodeDrawerBase
11+
{
12+
///<inheritdoc/>
13+
public override bool CanDraw(ZplElementBase element)
14+
{
15+
return element is ZplAztecBarcode;
16+
}
17+
18+
///<inheritdoc/>
19+
public override void Draw(ZplElementBase element)
20+
{
21+
if (element is ZplAztecBarcode aztecBarcode)
22+
{
23+
float x = aztecBarcode.PositionX;
24+
float y = aztecBarcode.PositionY;
25+
26+
var content = aztecBarcode.Content;
27+
28+
if (aztecBarcode.UseHexadecimalIndicator)
29+
{
30+
content = content.ReplaceHexEscapes();
31+
}
32+
33+
var writer = new AztecWriter();
34+
var options = new AztecEncodingOptions();
35+
if (aztecBarcode.ErrorControl >= 1 && aztecBarcode.ErrorControl <= 99)
36+
{
37+
options.ErrorCorrection = aztecBarcode.ErrorControl;
38+
}
39+
else if (aztecBarcode.ErrorControl >= 101 && aztecBarcode.ErrorControl <= 104)
40+
{
41+
options.Layers = 100 - aztecBarcode.ErrorControl;
42+
}
43+
else if (aztecBarcode.ErrorControl >= 201 && aztecBarcode.ErrorControl <= 232)
44+
{
45+
options.Layers = aztecBarcode.ErrorControl - 200;
46+
}
47+
else if (aztecBarcode.ErrorControl == 300)
48+
{
49+
options.PureBarcode = true;
50+
}
51+
else
52+
{
53+
// default options
54+
}
55+
56+
var result = writer.encode(content, ZXing.BarcodeFormat.AZTEC, 0, 0, options.Hints);
57+
58+
using var resizedImage = this.BitMatrixToSKBitmap(result, aztecBarcode.MagnificationFactor);
59+
var png = resizedImage.Encode(SKEncodedImageFormat.Png, 100).ToArray();
60+
this.DrawBarcode(png, x, y, resizedImage.Width, resizedImage.Height, aztecBarcode.FieldOrigin != null, aztecBarcode.FieldOrientation);
61+
}
62+
}
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using BinaryKits.Zpl.Label;
2+
3+
namespace BinaryKits.Zpl.Viewer.Models
4+
{
5+
public class AztecBarcodeFieldData : FieldDataBase
6+
{
7+
public FieldOrientation FieldOrientation { get; set; }
8+
public int MagnificationFactor { get; set; }
9+
public bool ExtendedChannel { get; set; }
10+
public int ErrorControl { get; set; }
11+
public bool MenuSymbol { get; set; }
12+
public int SymbolCount { get; set; }
13+
public string IdField { get; set; }
14+
15+
}
16+
}

src/BinaryKits.Zpl.Viewer/ZplAnalyzer.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public AnalyzeInfo Analyze(string zplData)
3737
var elementAnalyzers = new List<IZplCommandAnalyzer>
3838
{
3939
fieldDataAnalyzer,
40+
new AztecBarcodeZplCommandAnalyzer(this._virtualPrinter),
4041
new BarCodeFieldDefaultZplCommandAnalyzer(this._virtualPrinter),
4142
new ChangeAlphanumericDefaultFontZplCommandAnalyzer(this._virtualPrinter),
4243
new Code39BarcodeZplCommandAnalyzer(this._virtualPrinter),
@@ -70,7 +71,6 @@ public AnalyzeInfo Analyze(string zplData)
7071
new RecallFormatCommandAnalyzer(this._virtualPrinter),
7172
new RecallGraphicZplCommandAnalyzer(this._virtualPrinter),
7273
new ScalableBitmappedFontZplCommandAnalyzer(this._virtualPrinter),
73-
7474
};
7575

7676
var labelInfos = new List<LabelInfo>();

src/BinaryKits.Zpl.Viewer/ZplElementDrawer.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public ZplElementDrawer(IPrinterStorage printerStorage, DrawerOptions drawerOpti
2424
this._printerStorage = printerStorage;
2525
this._elementDrawers = new IElementDrawer[]
2626
{
27+
new AztecBarcodeElementDrawer(),
2728
new Barcode128ElementDrawer(),
2829
new Barcode39ElementDrawer(),
2930
new Barcode93ElementDrawer(),
@@ -33,11 +34,11 @@ public ZplElementDrawer(IPrinterStorage printerStorage, DrawerOptions drawerOpti
3334
new GraphicBoxElementDrawer(),
3435
new GraphicCircleElementDrawer(),
3536
new GraphicFieldElementDrawer(),
36-
new Interleaved2of5BarcodeDrawer(),
3737
new ImageMoveElementDrawer(),
38+
new Interleaved2of5BarcodeDrawer(),
3839
new MaxiCodeElementDrawer(),
39-
new QrCodeElementDrawer(),
4040
new Pdf417ElementDrawer(),
41+
new QrCodeElementDrawer(),
4142
new RecallGraphicElementDrawer(),
4243
new TextFieldElementDrawer()
4344
};

0 commit comments

Comments
 (0)