BinaryKits / BinaryKits.Zpl

BinaryKits.Zpl a set of .net libraries. The project supports you in the simple creation of zebra labels. It generates the ZPL data, it is a printer description language from Zebra Technologies. ZPL II is now emulated by many label printers from different manufacturers. So with this implementation you can create labels for most printers.
MIT License
307 stars 112 forks source link

Title: ArgumentNullException in SkiaSharp.HarfBuzz on Windows NanoServer .NET 8 #231

Closed KlausBenislavskis closed 4 months ago

KlausBenislavskis commented 5 months ago

Environment

Issue Description

I'm experiencing an issue when trying to convert ZPL to an image in a production environment using Windows NanoServer and .NET 8. Locally, everything runs smoothly, but in the production environment, I initially encountered a System.TypeInitializationException due to SkiaSharp.SKImageInfo failing to initialize because it couldn't load the libSkiaSharp DLL. I resolved this issue by adding the SkiaSharp.NativeAssets.NanoServer package.

However, I am now facing a new issue:

Error Details

System.ArgumentNullException: Value cannot be null. (Parameter 'typeface') at SkiaSharp.HarfBuzz.SKShaper..ctor(SKTypeface typeface) at SkiaSharp.HarfBuzz.CanvasExtensions.DrawShapedText(SKCanvas canvas, String text, Single x, Single y, SKPaint paint) at BinaryKits.Zpl.Viewer.ElementDrawers.TextFieldElementDrawer.Draw(ZplElementBase element, DrawerOptions options) at BinaryKits.Zpl.Viewer.ZplElementDrawer.Draw(ZplElementBase[] elements, Double labelWidth, Double labelHeight, Int32 printDensityDpmm)

This exception occurs during the text rendering process. It appears that the typeface required for text shaping is null.

Steps to Reproduce

  1. Run the ZPL to image conversion process in the Windows NanoServer environment.
  2. Observe the ArgumentNullException during the rendering of text elements.

Any help or suggestions on how to resolve this issue would be greatly appreciated.

primo-ppcg commented 5 months ago

Could you also try to add a package reference for HarfBuzzSharp.NativeAssets.NanoServer?

KlausBenislavskis commented 5 months ago

@primo-ppcg there is no such package image I tried already with HarfBuzzSharp.NativeAssets.Win32 and HarfBuzzSharp.NativeAssets.WebAssembly

primo-ppcg commented 5 months ago

DrawShapedText is not needed in most cases, however right-to-left and segmental scripts (e.g. Arabic, Hebrew, Devanagari) will fail to render properly.

If this isn't an issue, you can fork the BinaryKits.Zpl.Viewer project, and replace the four instances of DrawShapedText with DrawText, which does not require HarfBuzz.

https://github.com/BinaryKits/BinaryKits.Zpl/blob/d6b790375cc6ac3102d4bfccd28d0115059514a4/src/BinaryKits.Zpl.Viewer/ElementDrawers/BarcodeDrawerBase.cs#L82-L89

https://github.com/BinaryKits/BinaryKits.Zpl/blob/d6b790375cc6ac3102d4bfccd28d0115059514a4/src/BinaryKits.Zpl.Viewer/ElementDrawers/FieldBlockElementDrawer.cs#L163

https://github.com/BinaryKits/BinaryKits.Zpl/blob/d6b790375cc6ac3102d4bfccd28d0115059514a4/src/BinaryKits.Zpl.Viewer/ElementDrawers/TextFieldElementDrawer.cs#L121

KlausBenislavskis commented 5 months ago

@primo-ppcg tried this but half of the label is missing and for some bar codes, there is an error. I don't think it is that simple to replace those 4 lines. Would switching to server core image help?

KlausBenislavskis commented 5 months ago

Also switching to server core image doesnt help

@primo-ppcg tried this but half of the label is missing and for some bar codes, there is an error. I don't think it is that simple to replace those 4 lines. Would switching to server core image help?

KlausBenislavskis commented 4 months ago

Fixed for server core by adding on startup

    BinaryKits.Zpl.Viewer.ElementDrawers.DrawerOptions.DefaultFontLoader = fontName =>
{
    var typeface = SkiaSharp.SKTypeface.Default;
    typeface = SkiaSharp.SKTypeface.FromFile("C:\\app\\fonts\\ARIAL.TTF");
    return typeface;
};

For nano servers kinda fixed by adding that and in docker file copying Dwrite.dll

FROM mcr.microsoft.com/dotnet/aspnet:8.0-windowsservercore-ltsc2019 as servercore
FROM mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-1809 AS base
COPY --from=servercore /Windows/System32/DWrite.dll /Windows/System32/DWrite.dll

Still nano server doesn't work because of the System.Drawing dependency. I tried to upgrade to 1.2.0 version for the viewer where the dependency is removed but then I face this error for some labels that is not happening in older versions:

System.Exception: Error on zpl element "42175221774>89011082700058719": Invalid symbol for Code128C: 4>
 ---> System.Exception: Invalid symbol for Code128C: 4>
   at BinaryKits.Zpl.Viewer.Symologies.ZplCode128Symbology.Analyze(String content, Code128CodeSet initialCodeSet)
   at BinaryKits.Zpl.Viewer.Symologies.ZplCode128Symbology.Encode(String content, Code128CodeSet initialCodeSet, Boolean gs1)
   at BinaryKits.Zpl.Viewer.ElementDrawers.Barcode128ElementDrawer.Draw(ZplElementBase element, DrawerOptions options)
   at BinaryKits.Zpl.Viewer.ZplElementDrawer.DrawMulti(ZplElementBase[] elements, Double labelWidth, Double labelHeight, Int32 printDensityDpmm)
   --- End of inner exception stack trace ---
   at BinaryKits.Zpl.Viewer.ZplElementDrawer.DrawMulti(ZplElementBase[] elements, Double labelWidth, Double labelHeight, Int32 printDensityDpmm)
   at BinaryKits.Zpl.Viewer.ZplElementDrawer.Draw(ZplElementBase[] elements, Double labelWidth, Double labelHeight, Int32 printDensityDpmm)
primo-ppcg commented 4 months ago

System.Exception: Error on zpl element "42175221774>89011082700058719": Invalid symbol for Code128C: 4>

GS1-128 should auto-analyze. This is a bug. Minimal example:

^XA
^FO20,20^BY2^BCN,80,Y,,,D
^BCN,120,Y,N,N,D^FD42175221774>89011082700058719^FS
^XZ
KlausBenislavskis commented 4 months ago

Thanks, works on nano server. For someone in future you also need to add this dll from server core COPY --from=servercore /Windows/System32/DWrite.dll /Windows/System32/DWrite.dll and in startup add default fonts to make it work

     BinaryKits.Zpl.Viewer.ElementDrawers.DrawerOptions.DefaultFontLoader = fontName =>
{
    var typeface = SkiaSharp.SKTypeface.Default;
    typeface = SkiaSharp.SKTypeface.FromFile("C:\\app\\fonts\\ARIAL.TTF");
    return typeface;
};