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.

457 lines
23 KiB

using System;
using System.Collections.Generic;
using System.Linq;
namespace Barcoded
{
/// <summary>
/// Code 39 barcode encoder.
/// </summary>
internal class Code39Encoder : LinearEncoder
{
private Dictionary<int, List<int>> _symbolDictionary;
private Dictionary<int, LinearPattern> _patternDictionary;
private Dictionary<int, int> _checkDigitDictionary;
private readonly bool _useCheckDigit;
public Code39Encoder(Symbology symbology) : base(symbology)
{
switch (Symbology)
{
case Symbology.Code39:
// Code39
_useCheckDigit = false;
Description = "Code 39";
break;
case Symbology.Code39C:
// Code39 with check digit
_useCheckDigit = true;
Description = "Code 39 With Check Digit";
break;
case Symbology.Code39Full:
// Code39 full ASCII
_useCheckDigit = false;
Description = "Code 39 - Full ASCII";
break;
case Symbology.Code39FullC:
// Code39 full ASCII with check digit
_useCheckDigit = true;
Description = "Code 39 - Full ASCII With Check Digit";
break;
default:
// Code39
_useCheckDigit = false;
Description = "Code 39";
break;
}
}
internal override ILinearValidator BarcodeValidator { get; } = new Code39Validator();
protected override void Encode(string barcodeValue)
{
switch(Symbology)
{
case Symbology.Code39Full:
LoadCode39FullAsciiDictionary();
break;
case Symbology.Code39FullC:
LoadCode39FullAsciiDictionary();
break;
default:
LoadCode39SymbolDictionary();
break;
}
ZplEncode = "";
LoadSymbologyPattern();
LoadCheckDigitDictionary();
int checkDigitRunning = 0;
for (int position = 0; position <= barcodeValue.Length - 1; position++)
{
// Check if first or last character in barcode and insert start/stop symbol
if (position == 0)
{
LinearEncoding.Add("*", 1, _patternDictionary[0]);
LinearEncoding.Add(" ", 1, _patternDictionary[1]);
}
int asciiCode = barcodeValue[position];
List<int> fullAsciiCharacter = _symbolDictionary[asciiCode];
for (int character = 0; character <= fullAsciiCharacter.Count - 1; character++)
{
int fullAsciiCode = fullAsciiCharacter[character];
char asciiChar = (char)fullAsciiCode;
LinearEncoding.Add(asciiChar.ToString(), 0, _patternDictionary[fullAsciiCode]);
LinearEncoding.Add(" ", 1, _patternDictionary[1]);
ZplEncode += asciiChar.ToString();
checkDigitRunning += _checkDigitDictionary[fullAsciiCode];
}
// Check if last encoding character.
if (position == barcodeValue.Length - 1)
{
if (_useCheckDigit)
{
int checkDigit = checkDigitRunning % 43;
asciiCode = _checkDigitDictionary.FirstOrDefault(x => x.Value == checkDigit).Key;
char character = (char)asciiCode;
LinearEncoding.Add(character.ToString(), 1, _patternDictionary[asciiCode]);
LinearEncoding.Add(" ", 1, _patternDictionary[1]);
}
// Add stop symbol.
LinearEncoding.Add("*", 1, _patternDictionary[0]);
}
}
SetMinXDimension();
SetMinBarcodeHeight();
}
/// <summary>
/// Increases the barcode Xdimension to minimum required by symbology, if currently set lower
/// </summary>
internal override void SetMinXDimension()
{
int xdimensionOriginal = XDimension;
int minXdimension = (int)Math.Ceiling(Dpi * 0.0075);
XDimension = Math.Max(XDimension, minXdimension);
// Set flag to show xdimension was adjusted
if (xdimensionOriginal != XDimension)
{
XDimensionChanged = true;
}
}
/// <summary>
/// Increases the barcode height to minimum required by symbology, if currently set lower
/// </summary>
internal override void SetMinBarcodeHeight()
{
int barcodeHeightOriginal = BarcodeHeight;
int minBarcodeHeight = (int)Math.Ceiling(Math.Max(LinearEncoding.MinimumWidth * XDimension * 0.15, Dpi * 0.25));
BarcodeHeight = Math.Max(BarcodeHeight, minBarcodeHeight);
// Set flag to show barcode height was adjusted
if (barcodeHeightOriginal != BarcodeHeight)
{
BarcodeHeightChanged = true;
}
}
/// <summary>
/// Load the Full ASCII
/// </summary>
private void LoadCode39FullAsciiDictionary()
{
if (_symbolDictionary != null)
{
return;
}
_symbolDictionary = new Dictionary<int, List<int>>
{
{0, new List<int>() {37, 85}}, // NUL => %U
{1, new List<int>() {36, 65}}, // SOH => $A
{2, new List<int>() {36, 66}}, // STX => $B
{3, new List<int>() {36, 67}}, // ETX => $C
{4, new List<int>() {36, 68}}, // EOT => $D
{5, new List<int>() {36, 69}}, // ENQ => $E
{6, new List<int>() {36, 70}}, // ACK => $F
{7, new List<int>() {36, 71}}, // BEL => $G
{8, new List<int>() {36, 72}}, // BS => $H
{9, new List<int>() {36, 73}}, // HT => $I
{10, new List<int>() {36, 74}}, // LF => $J
{11, new List<int>() {36, 75}}, // VT => $K
{12, new List<int>() {36, 76}}, // FF => $L
{13, new List<int>() {36, 77}}, // CR => $M
{14, new List<int>() {36, 78}}, // SO => $N
{15, new List<int>() {36, 79}}, // SI => $O
{16, new List<int>() {36, 80}}, // DLE => $P
{17, new List<int>() {36, 81}}, // DC1 => $Q
{18, new List<int>() {36, 82}}, // DC2 => $R
{19, new List<int>() {36, 83}}, // DC3 => $S
{20, new List<int>() {36, 84}}, // DC4 => $T
{21, new List<int>() {36, 85}}, // NAK => $U
{22, new List<int>() {36, 86}}, // SYN => $V
{23, new List<int>() {36, 87}}, // ETB => $W
{24, new List<int>() {36, 88}}, // CAN => $X
{25, new List<int>() {36, 89}}, // EM => $Y
{26, new List<int>() {36, 90}}, // SUB => $Z
{27, new List<int>() {37, 65}}, // ESC => %A
{28, new List<int>() {37, 66}}, // FS => %B
{29, new List<int>() {37, 67}}, // GS => %C
{30, new List<int>() {37, 68}}, // RS => %D
{31, new List<int>() {37, 69}}, // US => %E
{32, new List<int>() {32}}, // SPACE => SPACE
{33, new List<int>() {47, 65}}, // ! => /A
{34, new List<int>() {47, 66}}, // " => /B
{35, new List<int>() {47, 67}}, // # => /C
{36, new List<int>() {47, 68}}, // $ => /D
{37, new List<int>() {47, 69}}, // % => /E
{38, new List<int>() {47, 70}}, // & => /F
{39, new List<int>() {47, 71}}, // ' => /G
{40, new List<int>() {47, 72}}, // ( => /H
{41, new List<int>() {47, 73}}, // ) => /I
{42, new List<int>() {47, 74}}, // * => /J
{43, new List<int>() {47, 75}}, // + => /K
{44, new List<int>() {47, 76}}, // , => /L
{45, new List<int>() {45}}, // - => -
{46, new List<int>() {46}}, // . => .
{47, new List<int>() {47, 79}}, // / => /O
{48, new List<int>() {48}}, // 0 => 0
{49, new List<int>() {49}}, // 1 => 1
{50, new List<int>() {50}}, // 2 => 2
{51, new List<int>() {51}}, // 3 => 3
{52, new List<int>() {52}}, // 4 => 4
{53, new List<int>() {53}}, // 5 => 5
{54, new List<int>() {54}}, // 6 => 6
{55, new List<int>() {55}}, // 7 => 7
{56, new List<int>() {56}}, // 8 => 8
{57, new List<int>() {57}}, // 9 => 9
{58, new List<int>() {47, 90}}, // : => /Z
{59, new List<int>() {37, 70}}, // ; => %F
{60, new List<int>() {37, 71}}, // < => %G
{61, new List<int>() {37, 72}}, // = => %H
{62, new List<int>() {37, 73}}, // > => %I
{63, new List<int>() {37, 74}}, // ? => %J
{64, new List<int>() {37, 86}}, // @ => %V
{65, new List<int>() {65}}, // A => A
{66, new List<int>() {66}}, // B => B
{67, new List<int>() {67}}, // C => C
{68, new List<int>() {68}}, // D => D
{69, new List<int>() {69}}, // E => E
{70, new List<int>() {70}}, // F => F
{71, new List<int>() {71}}, // G => G
{72, new List<int>() {72}}, // H => H
{73, new List<int>() {73}}, // I => I
{74, new List<int>() {74}}, // J => J
{75, new List<int>() {75}}, // K => K
{76, new List<int>() {76}}, // L => L
{77, new List<int>() {77}}, // M => M
{78, new List<int>() {78}}, // N => N
{79, new List<int>() {79}}, // O => O
{80, new List<int>() {80}}, // P => P
{81, new List<int>() {81}}, // Q => Q
{82, new List<int>() {82}}, // R => R
{83, new List<int>() {83}}, // S => S
{84, new List<int>() {84}}, // T => T
{85, new List<int>() {85}}, // U => U
{86, new List<int>() {86}}, // V => V
{87, new List<int>() {87}}, // W => W
{88, new List<int>() {88}}, // X => X
{89, new List<int>() {89}}, // Y => Y
{90, new List<int>() {90}}, // Z => Z
{91, new List<int>() {37, 75}}, // [ => %K
{92, new List<int>() {37, 76}}, // \ => %L
{93, new List<int>() {37, 77}}, // ] => %M
{94, new List<int>() {37, 78}}, // ^ => %N
{95, new List<int>() {37, 79}}, // _ => %O
{96, new List<int>() {37, 87}}, // ` => %W
{97, new List<int>() {43, 65}}, // a => +A
{98, new List<int>() {43, 66}}, // b => +B
{99, new List<int>() {43, 67}}, // c => +C
{100, new List<int>() {43, 68}}, // d => +D
{101, new List<int>() {43, 69}}, // e => +E
{102, new List<int>() {43, 70}}, // f => +F
{103, new List<int>() {43, 71}}, // g => +G
{104, new List<int>() {43, 72}}, // h => +H
{105, new List<int>() {43, 73}}, // i => +I
{106, new List<int>() {43, 74}}, // j => +J
{107, new List<int>() {43, 75}}, // k => +K
{108, new List<int>() {43, 76}}, // l => +L
{109, new List<int>() {43, 77}}, // m => +M
{110, new List<int>() {43, 78}}, // n => +N
{111, new List<int>() {43, 79}}, // o => +O
{112, new List<int>() {43, 80}}, // p => +P
{113, new List<int>() {43, 81}}, // q => +Q
{114, new List<int>() {43, 82}}, // r => +R
{115, new List<int>() {43, 83}}, // s => +S
{116, new List<int>() {43, 84}}, // t => +T
{117, new List<int>() {43, 85}}, // u => +U
{118, new List<int>() {43, 86}}, // v => +V
{119, new List<int>() {43, 87}}, // w => +W
{120, new List<int>() {43, 88}}, // x => +X
{121, new List<int>() {43, 89}}, // y => +Y
{122, new List<int>() {43, 90}}, // z => +Z
{123, new List<int>() {37, 80}}, // { => %P
{124, new List<int>() {37, 81}}, // | => %Q
{125, new List<int>() {37, 82}}, // } => %R
{126, new List<int>() {37, 83}}, // ~ => %S
{127, new List<int>() {37, 84}} // DEL => %T
};
}
private void LoadCode39SymbolDictionary()
{
if (_symbolDictionary != null)
{
return;
}
_symbolDictionary = new Dictionary<int, List<int>>
{
{32, new List<int>() {32}}, // SPACE
{36, new List<int>() {36}}, // $
{37, new List<int>() {37}}, // %
{43, new List<int>() {43}}, // +
{45, new List<int>() {45}}, // -
{46, new List<int>() {46}}, // .
{47, new List<int>() {47}}, // /
{48, new List<int>() {48}}, // 0
{49, new List<int>() {49}}, // 1
{50, new List<int>() {50}}, // 2
{51, new List<int>() {51}}, // 3
{52, new List<int>() {52}}, // 4
{53, new List<int>() {53}}, // 5
{54, new List<int>() {54}}, // 6
{55, new List<int>() {55}}, // 7
{56, new List<int>() {56}}, // 8
{57, new List<int>() {57}}, // 9
{65, new List<int>() {65}}, // A
{66, new List<int>() {66}}, // B
{67, new List<int>() {67}}, // C
{68, new List<int>() {68}}, // D
{69, new List<int>() {69}}, // E
{70, new List<int>() {70}}, // F
{71, new List<int>() {71}}, // G
{72, new List<int>() {72}}, // H
{73, new List<int>() {73}}, // I
{74, new List<int>() {74}}, // J
{75, new List<int>() {75}}, // K
{76, new List<int>() {76}}, // L
{77, new List<int>() {77}}, // M
{78, new List<int>() {78}}, // N
{79, new List<int>() {79}}, // O
{80, new List<int>() {80}}, // P
{81, new List<int>() {81}}, // Q
{82, new List<int>() {82}}, // R
{83, new List<int>() {83}}, // S
{84, new List<int>() {84}}, // T
{85, new List<int>() {85}}, // U
{86, new List<int>() {86}}, // V
{87, new List<int>() {87}}, // W
{88, new List<int>() {88}}, // X
{89, new List<int>() {89}}, // Y
{90, new List<int>() {90}} // Z
};
}
private void LoadSymbologyPattern()
{
if (_patternDictionary != null)
{
return;
}
_patternDictionary = new Dictionary<int, LinearPattern>
{
{0, new LinearPattern("NWNNWNWNN", ModuleType.Bar, WideBarRatio)}, // START/STOP
{1, new LinearPattern("N", ModuleType.Space, WideBarRatio)}, // SPACER
{32, new LinearPattern("NWWNNNWNN", ModuleType.Bar, WideBarRatio)}, // SPACE
{36, new LinearPattern("NWNWNWNNN", ModuleType.Bar, WideBarRatio)}, // $
{37, new LinearPattern("NNNWNWNWN", ModuleType.Bar, WideBarRatio)}, // %
{43, new LinearPattern("NWNNNWNWN", ModuleType.Bar, WideBarRatio)}, // +
{45, new LinearPattern("NWNNNNWNW", ModuleType.Bar, WideBarRatio)}, // -
{46, new LinearPattern("WWNNNNWNN", ModuleType.Bar, WideBarRatio)}, // .
{47, new LinearPattern("NWNWNNNWN", ModuleType.Bar, WideBarRatio)}, // /
{48, new LinearPattern("NNNWWNWNN", ModuleType.Bar, WideBarRatio)}, // 0
{49, new LinearPattern("WNNWNNNNW", ModuleType.Bar, WideBarRatio)}, // 1
{50, new LinearPattern("NNWWNNNNW", ModuleType.Bar, WideBarRatio)}, // 2
{51, new LinearPattern("WNWWNNNNN", ModuleType.Bar, WideBarRatio)}, // 3
{52, new LinearPattern("NNNWWNNNW", ModuleType.Bar, WideBarRatio)}, // 4
{53, new LinearPattern("WNNWWNNNN", ModuleType.Bar, WideBarRatio)}, // 5
{54, new LinearPattern("NNWWWNNNN", ModuleType.Bar, WideBarRatio)}, // 6
{55, new LinearPattern("NNNWNNWNW", ModuleType.Bar, WideBarRatio)}, // 7
{56, new LinearPattern("WNNWNNWNN", ModuleType.Bar, WideBarRatio)}, // 8
{57, new LinearPattern("NNWWNNWNN", ModuleType.Bar, WideBarRatio)}, // 9
{65, new LinearPattern("WNNNNWNNW", ModuleType.Bar, WideBarRatio)}, // A
{66, new LinearPattern("NNWNNWNNW", ModuleType.Bar, WideBarRatio)}, // B
{67, new LinearPattern("WNWNNWNNN", ModuleType.Bar, WideBarRatio)}, // C
{68, new LinearPattern("NNNNWWNNW", ModuleType.Bar, WideBarRatio)}, // D
{69, new LinearPattern("WNNNWWNNN", ModuleType.Bar, WideBarRatio)}, // E
{70, new LinearPattern("NNWNWWNNN", ModuleType.Bar, WideBarRatio)}, // F
{71, new LinearPattern("NNNNNWWNW", ModuleType.Bar, WideBarRatio)}, // G
{72, new LinearPattern("WNNNNWWNN", ModuleType.Bar, WideBarRatio)}, // H
{73, new LinearPattern("NNWNNWWNN", ModuleType.Bar, WideBarRatio)}, // I
{74, new LinearPattern("NNNNWWWNN", ModuleType.Bar, WideBarRatio)}, // J
{75, new LinearPattern("WNNNNNNWW", ModuleType.Bar, WideBarRatio)}, // K
{76, new LinearPattern("NNWNNNNWW", ModuleType.Bar, WideBarRatio)}, // L
{77, new LinearPattern("WNWNNNNWN", ModuleType.Bar, WideBarRatio)}, // M
{78, new LinearPattern("NNNNWNNWW", ModuleType.Bar, WideBarRatio)}, // N
{79, new LinearPattern("WNNNWNNWN", ModuleType.Bar, WideBarRatio)}, // O
{80, new LinearPattern("NNWNWNNWN", ModuleType.Bar, WideBarRatio)}, // P
{81, new LinearPattern("NNNNNNWWW", ModuleType.Bar, WideBarRatio)}, // Q
{82, new LinearPattern("WNNNNNWWN", ModuleType.Bar, WideBarRatio)}, // R
{83, new LinearPattern("NNWNNNWWN", ModuleType.Bar, WideBarRatio)}, // S
{84, new LinearPattern("NNNNWNWWN", ModuleType.Bar, WideBarRatio)}, // T
{85, new LinearPattern("WWNNNNNNW", ModuleType.Bar, WideBarRatio)}, // U
{86, new LinearPattern("NWWNNNNNW", ModuleType.Bar, WideBarRatio)}, // V
{87, new LinearPattern("WWWNNNNNN", ModuleType.Bar, WideBarRatio)}, // W
{88, new LinearPattern("NWNNWNNNW", ModuleType.Bar, WideBarRatio)}, // X
{89, new LinearPattern("WWNNWNNNN", ModuleType.Bar, WideBarRatio)}, // Y
{90, new LinearPattern("NWWNWNNNN", ModuleType.Bar, WideBarRatio)} // Z
};
}
private void LoadCheckDigitDictionary()
{
if (_checkDigitDictionary != null)
{
return;
}
_checkDigitDictionary = new Dictionary<int, int>
{
{32, 38}, // SPACE
{36, 39}, // $
{37, 42}, // %
{43, 41}, // +
{45, 36}, // -
{46, 37}, // .
{47, 40}, // /
{48, 0}, // 0
{49, 1}, // 1
{50, 2}, // 2
{51, 3}, // 3
{52, 4}, // 4
{53, 5}, // 5
{54, 6}, // 6
{55, 7}, // 7
{56, 8}, // 8
{57, 9}, // 9
{65, 10}, // A
{66, 11}, // B
{67, 12}, // C
{68, 13}, // D
{69, 14}, // E
{70, 15}, // F
{71, 16}, // G
{72, 17}, // H
{73, 18}, // I
{74, 19}, // J
{75, 20}, // K
{76, 21}, // L
{77, 22}, // M
{78, 23}, // N
{79, 24}, // O
{80, 25}, // P
{81, 26}, // Q
{82, 27}, // R
{83, 28}, // S
{84, 29}, // T
{85, 30}, // U
{86, 31}, // V
{87, 32}, // W
{88, 33}, // X
{89, 34}, // Y
{90, 35} // Z
};
}
}
}