You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
11 KiB

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace Barcoded
{
public abstract class LinearEncoder
{
protected LinearEncoder(Symbology symbology)
{
Symbology = symbology;
}
/// <summary>
/// Encode the value using the barcode symbology selected.
/// </summary>
/// <param name="barcodeValue"></param>
protected abstract void Encode(string barcodeValue);
internal void Generate(string barcodeValue)
{
EncodedValue = BarcodeValidator.Parse(barcodeValue, Symbology);
Encode(EncodedValue);
}
/// <summary>
/// Set the minimum barcode height for the barcode symbology used.
/// </summary>
internal abstract void SetMinBarcodeHeight();
/// <summary>
/// Set the minimum XDimension for the barcode symbology used.
/// </summary>
internal abstract void SetMinXDimension();
/// <summary>
/// Get the generated barcode as a bitmap image.
/// </summary>
/// <param name="barcodeValue"></param>
/// <returns>Barcode image</returns>
internal MemoryStream GetImage(string barcodeValue)
{
LinearEncoding.Clear();
Generate(barcodeValue);
return LinearRenderer.DrawImageMemoryStream(this);
}
/// <summary>
/// Reset the Property Changed flag to false.
/// </summary>
internal void ResetPropertyChanged()
{
PropertyChanged = false;
}
/// <summary>
/// Internal Barcode Value that can be reached by the renderer.
/// </summary>
public string EncodedValue { get; internal set; }
/// <summary>
/// Barcode symbology.
/// </summary>
public Symbology Symbology { get; set; }
/// <summary>
/// Encoder description.
/// </summary>
public string Description { get; internal set; }
internal LinearEncoding LinearEncoding { get; } = new LinearEncoding();
/// <summary>
/// ZPL encoded string.
/// </summary>
internal string ZplEncode { get; set; }
/// <summary>
/// Used to detect if any properties have changed.
/// </summary>
public bool PropertyChanged { get; internal set; }
/// <summary>
/// Symbology specific validator.
/// </summary>
internal abstract ILinearValidator BarcodeValidator { get; }
private string _humanReadableValue = "";
/// <summary>
/// The human readable value.
/// </summary>
public string HumanReadableValue
{
get => _humanReadableValue;
set
{
_humanReadableValue = value;
PropertyChanged = true;
}
}
private bool _humanReadableSymbolAligned;
/// <summary>
/// Sets the human readable label to align with associated barcode symbol
/// </summary>
public bool HumanReadableSymbolAligned
{
get => _humanReadableSymbolAligned;
set
{
_humanReadableSymbolAligned = value;
PropertyChanged = true;
}
}
/// <summary>
/// Sets the visibility and position of the human readable value.
/// Hidden, Above, Below, Embedded
/// </summary>
public HumanReadablePosition HumanReadablePosition { get; private set; }
public void SetHumanReadablePosition(string position)
{
switch(position.ToUpper())
{
case "ABOVE":
HumanReadablePosition = HumanReadablePosition.Above;
break;
case "TOP":
HumanReadablePosition = HumanReadablePosition.Above;
break;
case "BELOW":
HumanReadablePosition = HumanReadablePosition.Below;
break;
case "BOTTOM":
HumanReadablePosition = HumanReadablePosition.Below;
break;
case "HIDDEN":
HumanReadablePosition = HumanReadablePosition.Hidden;
break;
case "EMBEDDED":
HumanReadablePosition = HumanReadablePosition.Embedded;
break;
default:
HumanReadablePosition = HumanReadablePosition.Hidden;
break;
}
PropertyChanged = true;
}
/// <summary>
/// The font to be used for the human readable value, if shown.
/// Will default to the system default font if not set.
/// </summary>
public Font HumanReadableFont { get; internal set; } = SystemFonts.DefaultFont;
/// <summary>
/// Set the font to be used for the human readable label.
/// </summary>
/// <param name="fontFamily"></param>
/// <param name="pointSize"></param>
public void SetHumanReadableFont(string fontFamily, int pointSize)
{
if(pointSize < 1)
{
pointSize = (int)SystemFonts.DefaultFont.Size;
}
try
{
HumanReadableFont = new Font(new FontFamily(fontFamily), pointSize);
}
catch (Exception)
{
HumanReadableFont = SystemFonts.DefaultFont;
}
PropertyChanged = true;
}
private const int BarcodeHeightMin = 1;
private const int BarcodeHeightMax = 2400;
private int _barcodeHeight = 1;
/// <summary>
/// Sets the desired height in pixels for the barcode element of the image.
/// </summary>
public int BarcodeHeight
{
get => _barcodeHeight;
set
{
int barcodeHeightOriginal = value;
_barcodeHeight = (value < BarcodeHeightMin) ? BarcodeHeightMin : (value > BarcodeHeightMax) ? BarcodeHeightMax : value;
if(barcodeHeightOriginal != _barcodeHeight)
{
BarcodeHeightChanged = true;
}
PropertyChanged = true;
}
}
private int _xDimension = 1;
/// <summary>
/// X-dimension is the width of the narrowest bar element in the barcode.
/// All other bar and spaces widths in the barcode are a multiple of this value.
/// </summary>
public int XDimension
{
get => _xDimension;
set
{
_xDimension = value;
PropertyChanged = true;
}
}
private int _wideBarRatio = 3;
/// <summary>
/// X-dimension is the width of the narrowest bar element in the barcode.
/// All other bar and spaces widths in the barcode are a multiple of this value.
/// </summary>
public int WideBarRatio
{
get => _wideBarRatio;
set
{
_wideBarRatio = value > 2? 3 : 2;
PropertyChanged = true;
}
}
private const int DpiMin = 1;
private const int DpiMax = 600;
private int _dpi = 300;
/// <summary>
/// Sets the desired image dpi.
/// </summary>
public int Dpi
{
get => _dpi;
set
{
int dpiOriginal = value;
_dpi = (value < DpiMin) ? DpiMin : (value > DpiMax) ? DpiMax : value;
if(dpiOriginal != _dpi)
{
DpiChanged = true;
}
PropertyChanged = true;
}
}
private int _targetWidth;
/// <summary>
/// Target pixel width for the barcode.
/// If set, the encoder will attempt to get as close to this value without exceeding, when generating the barcode
/// </summary>
public int TargetWidth
{
get => _targetWidth;
set
{
_targetWidth = value;
PropertyChanged = true;
}
}
private bool _showEncoding;
/// <summary>
/// When true, will include a human readable label of the barcode encoding values
/// for the corresponding part of the barcode. The position of this label will adjust
/// top or bottom, dependent on the use of a human readable value and its position. Default is top.
/// </summary>
public bool ShowEncoding
{
get => _showEncoding;
set
{
_showEncoding = value;
PropertyChanged = true;
}
}
/// <summary>
/// The font to be used for the encoding label if shown.
/// Will default to the system default font, if not set.
/// </summary>
public FontFamily EncodingFontFamily { get; private set; } = SystemFonts.DefaultFont.FontFamily;
public void SetEncodingFontFamily(string fontFamily)
{
try
{
EncodingFontFamily = new FontFamily(fontFamily);
}
catch (Exception)
{
EncodingFontFamily = SystemFonts.DefaultFont.FontFamily;
}
PropertyChanged = true;
}
private bool _quietzone;
/// <summary>
/// Sets the starting subset to "A" or "B", where an explicit subset is not required.
/// Will default to "A" if not set.
/// </summary>
public bool Quietzone
{
get => _quietzone;
set
{
_quietzone = value;
PropertyChanged = true;
}
}
public ImageCodecInfo ImageCodec { get; private set; } = ImageHelpers.FindCodecInfo("PNG");
public string CodecName
{
get => ImageCodec.FormatDescription;
set
{
ImageCodec = ImageHelpers.FindCodecInfo(value);
PropertyChanged = true;
}
}
/// <summary>
/// Width of the generated barcode.
/// </summary>
public int BarcodeWidth { get; internal set; }
/// <summary>
/// Indicates if the X-dimension was altered to accomodate symbology constraints.
/// </summary>
public bool XDimensionChanged { get; internal set; }
/// <summary>
/// Indicates if the barcode height was altered to accomodate symbology constraints.
/// </summary>
public bool BarcodeHeightChanged { get; internal set; }
/// <summary>
/// Indicates if DPI was adjusted to fit system set constraints.
/// </summary>
public bool DpiChanged { get; internal set; }
/// <summary>
/// Indicates if the human readable font size was changed to prevent text exceeding barcode width.
/// </summary>
public bool HumanReadableFontSizeChanged { get; internal set; }
}
}