1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
#encoding: ASCII
require 'barby/barcode'
module Barby
class Code39 < Barcode1D
WIDE = W = true
NARROW = N = false
ENCODINGS = {
' ' => [N,W,W,N,N,N,W,N,N], '$' => [N,W,N,W,N,W,N,N,N],
'%' => [N,N,N,W,N,W,N,W,N], '+' => [N,W,N,N,N,W,N,W,N],
'-' => [N,W,N,N,N,N,W,N,W], '.' => [W,W,N,N,N,N,W,N,N],
'/' => [N,W,N,W,N,N,N,W,N], '0' => [N,N,N,W,W,N,W,N,N],
'1' => [W,N,N,W,N,N,N,N,W], '2' => [N,N,W,W,N,N,N,N,W],
'3' => [W,N,W,W,N,N,N,N,N], '4' => [N,N,N,W,W,N,N,N,W],
'5' => [W,N,N,W,W,N,N,N,N], '6' => [N,N,W,W,W,N,N,N,N],
'7' => [N,N,N,W,N,N,W,N,W], '8' => [W,N,N,W,N,N,W,N,N],
'9' => [N,N,W,W,N,N,W,N,N], 'A' => [W,N,N,N,N,W,N,N,W],
'B' => [N,N,W,N,N,W,N,N,W], 'C' => [W,N,W,N,N,W,N,N,N],
'D' => [N,N,N,N,W,W,N,N,W], 'E' => [W,N,N,N,W,W,N,N,N],
'F' => [N,N,W,N,W,W,N,N,N], 'G' => [N,N,N,N,N,W,W,N,W],
'H' => [W,N,N,N,N,W,W,N,N], 'I' => [N,N,W,N,N,W,W,N,N],
'J' => [N,N,N,N,W,W,W,N,N], 'K' => [W,N,N,N,N,N,N,W,W],
'L' => [N,N,W,N,N,N,N,W,W], 'M' => [W,N,W,N,N,N,N,W,N],
'N' => [N,N,N,N,W,N,N,W,W], 'O' => [W,N,N,N,W,N,N,W,N],
'P' => [N,N,W,N,W,N,N,W,N], 'Q' => [N,N,N,N,N,N,W,W,W],
'R' => [W,N,N,N,N,N,W,W,N], 'S' => [N,N,W,N,N,N,W,W,N],
'T' => [N,N,N,N,W,N,W,W,N], 'U' => [W,W,N,N,N,N,N,N,W],
'V' => [N,W,W,N,N,N,N,N,W], 'W' => [W,W,W,N,N,N,N,N,N],
'X' => [N,W,N,N,W,N,N,N,W], 'Y' => [W,W,N,N,W,N,N,N,N],
'Z' => [N,W,W,N,W,N,N,N,N]
}
#In extended mode, each character is replaced with two characters from the "normal" encoding
EXTENDED_ENCODINGS = {
"\000" => '%U', " " => " ", "@" => "%V", "`" => "%W",
"\001" => '$A', "!" => "/A", "A" => "A", "a" => "+A",
"\002" => '$B', '"' => "/B", "B" => "B", "b" => "+B",
"\003" => '$C', "#" => "/C", "C" => "C", "c" => "+C",
"\004" => '$D', "$" => "/D", "D" => "D", "d" => "+D",
"\005" => '$E', "%" => "/E", "E" => "E", "e" => "+E",
"\006" => '$F', "&" => "/F", "F" => "F", "f" => "+F",
"\007" => '$G', "'" => "/G", "G" => "G", "g" => "+G",
"\010" => '$H', "(" => "/H", "H" => "H", "h" => "+H",
"\011" => '$I', ")" => "/I", "I" => "I", "i" => "+I",
"\012" => '$J', "*" => "/J", "J" => "J", "j" => "+J",
"\013" => '$K', "+" => "/K", "K" => "K", "k" => "+K",
"\014" => '$L', "," => "/L", "L" => "L", "l" => "+L",
"\015" => '$M', "-" => "-", "M" => "M", "m" => "+M",
"\016" => '$N', "." => ".", "N" => "N", "n" => "+N",
"\017" => '$O', "/" => "/O", "O" => "O", "o" => "+O",
"\020" => '$P', "0" => "0", "P" => "P", "p" => "+P",
"\021" => '$Q', "1" => "1", "Q" => "Q", "q" => "+Q",
"\022" => '$R', "2" => "2", "R" => "R", "r" => "+R",
"\023" => '$S', "3" => "3", "S" => "S", "s" => "+S",
"\024" => '$T', "4" => "4", "T" => "T", "t" => "+T",
"\025" => '$U', "5" => "5", "U" => "U", "u" => "+U",
"\026" => '$V', "6" => "6", "V" => "V", "v" => "+V",
"\027" => '$W', "7" => "7", "W" => "W", "w" => "+W",
"\030" => '$X', "8" => "8", "X" => "X", "x" => "+X",
"\031" => '$Y', "9" => "9", "Y" => "Y", "y" => "+Y",
"\032" => '$Z', ":" => "/Z", "Z" => "Z", "z" => "+Z",
"\033" => '%A', ";" => "%F", "[" => "%K", "{" => "%P",
"\034" => '%B', "<" => "%G", "\\" => "%L", "|" => "%Q",
"\035" => '%C', "=" => "%H", "]" => "%M", "}" => "%R",
"\036" => '%D', ">" => "%I", "^" => "%N", "~" => "%S",
"\037" => '%E', "?" => "%J", "_" => "%O", "\177" => "%T"
}
CHECKSUM_VALUES = {
'0' => 0, '1' => 1, '2' => 2, '3' => 3,
'4' => 4, '5' => 5, '6' => 6, '7' => 7,
'8' => 8, '9' => 9, 'A' => 10, 'B' => 11,
'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15,
'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19,
'K' => 20, 'L' => 21, 'N' => 23, 'M' => 22,
'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27,
'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31,
'W' => 32, 'X' => 33, 'Y' => 34, 'Z' => 35,
'-' => 36, '.' => 37, ' ' => 38, '$' => 39,
'/' => 40, '+' => 41, '%' => 42
}
START_ENCODING = [N,W,N,N,W,N,W,N,N] # *
STOP_ENCODING = [N,W,N,N,W,N,W,N,N] # *
attr_accessor :data, :spacing, :narrow_width, :wide_width, :extended, :include_checksum
# Do not surround "data" with the mandatory "*" as is this is done automically for you.
# So instead of passing "*123456*" as "data", just pass "123456".
def initialize(data, extended=false)
self.data = data
self.extended = extended
raise(ArgumentError, "data is not valid (extended=#{extended?})") unless valid?
yield self if block_given?
end
#Returns the characters that were passed in, no matter it they're part of
#the extended charset or if they're already encodable, "normal" characters
def raw_characters
data.split(//)
end
#Returns the encodable characters. If extended mode is enabled, each character will
#first be replaced by two characters from the encodable charset
def characters
chars = raw_characters
extended ? chars.map{|c| EXTENDED_ENCODINGS[c].split(//) }.flatten : chars
end
def characters_with_checksum
characters + [checksum_character]
end
def encoded_characters
characters.map{|c| encoding_for(c) }
end
def encoded_characters_with_checksum
encoded_characters + [checksum_encoding]
end
#The data part of the encoding (no start+stop characters)
def data_encoding
encoded_characters.join(spacing_encoding)
end
def data_encoding_with_checksum
encoded_characters_with_checksum.join(spacing_encoding)
end
def encoding
return encoding_with_checksum if include_checksum?
start_encoding+spacing_encoding+data_encoding+spacing_encoding+stop_encoding
end
def encoding_with_checksum
start_encoding+spacing_encoding+data_encoding_with_checksum+spacing_encoding+stop_encoding
end
#Checksum is optional
def checksum
characters.inject(0) do |sum,char|
sum + CHECKSUM_VALUES[char]
end % 43
end
def checksum_character
CHECKSUM_VALUES.invert[checksum]
end
def checksum_encoding
encoding_for(checksum_character)
end
#Set include_checksum to true to make +encoding+ include the checksum
def include_checksum?
include_checksum
end
#Takes an array of WIDE/NARROW values and returns the string representation for
#those bars and spaces, using wide_width and narrow_width
def encoding_for_bars(*bars_and_spaces)
bar = false
bars_and_spaces.flatten.map do |width|
bar = !bar
(bar ? '1' : '0') * (width == WIDE ? wide_width : narrow_width)
end.join
end
#Returns the string representation for a single character
def encoding_for(character)
encoding_for_bars(ENCODINGS[character])
end
#Spacing between the characters in xdims. Spacing will be inserted
#between each character in the encoding
def spacing
@spacing ||= 1
end
def spacing_encoding
'0' * spacing
end
def narrow_width
@narrow_width ||= 1
end
def wide_width
@wide_width ||= 2
end
def extended?
extended
end
def start_encoding
encoding_for_bars(START_ENCODING)
end
def stop_encoding
encoding_for_bars(STOP_ENCODING)
end
def valid?
if extended?
raw_characters.all?{|c| EXTENDED_ENCODINGS.include?(c) }
else
raw_characters.all?{|c| ENCODINGS.include?(c) }
end
end
def to_s
data
end
end
end
|