1 /// 2 module barcode.ean13; 3 4 import std.experimental.logger; 5 6 import std.algorithm; 7 import std.exception; 8 import std..string; 9 import std.range; 10 import std.array; 11 import std.typecons : tuple; 12 import std.ascii; 13 14 import barcode.types; 15 import barcode.util; 16 17 /// 18 class EAN13 : BarCodeEncoder 19 { 20 protected: 21 22 enum lead_trailer = bitsStr!"#-#"; 23 enum separator = bitsStr!"-#-#-"; 24 25 enum Bits!ushort[10][2] modules_AB = [[ 26 bitsStr!"---##-#", 27 bitsStr!"--##--#", 28 bitsStr!"--#--##", 29 bitsStr!"-####-#", 30 bitsStr!"-#---##", 31 bitsStr!"-##---#", 32 bitsStr!"-#-####", 33 bitsStr!"-###-##", 34 bitsStr!"-##-###", 35 bitsStr!"---#-##" 36 ], 37 [ 38 bitsStr!"-#--###", 39 bitsStr!"-##--##", 40 bitsStr!"--##-##", 41 bitsStr!"-#----#", 42 bitsStr!"--###-#", 43 bitsStr!"-###--#", 44 bitsStr!"----#-#", 45 bitsStr!"--#---#", 46 bitsStr!"---#--#", 47 bitsStr!"--#-###" 48 ]]; 49 50 enum Bits!ushort[10] modules_C = [ 51 bitsStr!"###--#-", 52 bitsStr!"##--##-", 53 bitsStr!"##-##--", 54 bitsStr!"#----#-", 55 bitsStr!"#-###--", 56 bitsStr!"#--###-", 57 bitsStr!"#-#----", 58 bitsStr!"#---#--", 59 bitsStr!"#--#---", 60 bitsStr!"###-#--" 61 ]; 62 63 enum ubyte[6][10] parities = [ 64 [0, 0, 0, 0, 0, 0], 65 [0, 0, 1, 0, 1, 1], 66 [0, 0, 1, 1, 0, 1], 67 [0, 0, 1, 1, 1, 0], 68 [0, 1, 0, 0, 1, 1], 69 [0, 1, 1, 0, 0, 1], 70 [0, 1, 1, 1, 0, 0], 71 [0, 1, 0, 1, 0, 1], 72 [0, 1, 0, 1, 1, 0], 73 [0, 1, 1, 0, 1, 0] 74 ]; 75 76 enum MODULE = 7; 77 enum DIGITS = 12; 78 enum WIDTH = lead_trailer.count * 2 + separator.count + MODULE + DIGITS; 79 80 public: 81 pure: 82 83 /// 84 override BarCode encode(string data) 85 { 86 enforce(data.length == DIGITS, format("length of data must be %s", DIGITS)); 87 enforce(data.all!isDigit, "all symbols must be a numbers"); 88 89 BitArray ret; 90 91 size_t idx(char ch) { return cast(size_t)ch - cast(size_t)'0'; } 92 void append(T)(Bits!T bb) { ret.addBits(bb); } 93 94 append(lead_trailer); 95 96 int checkSum = 0; 97 foreach (i; 0 .. DIGITS) 98 checkSum += (i%2 == 1 ? 1 : 3) * idx(data[i]); 99 100 checkSum %= 10; 101 checkSum = checkSum == 0 ? 0 : 10 - checkSum; 102 103 assert (checkSum >= 0 && checkSum < 10, "checkSum calc wrong"); 104 105 auto pp = parities[checkSum]; 106 107 foreach (i; 0 .. 6) append(modules_AB[pp[i]][idx(data[i])]); 108 109 append(separator); 110 111 foreach (i; 6 .. 12) append(modules_C[idx(data[i])]); 112 113 append(lead_trailer); 114 115 return BarCode(ret.length, ret, "ean13"); 116 } 117 }