barby-chunky_png 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +29 -0
- data/bin/barby +41 -0
- data/lib/barby/barcode/bookland.rb +37 -0
- data/lib/barby/barcode/code_128.rb +410 -0
- data/lib/barby/barcode/code_25.rb +193 -0
- data/lib/barby/barcode/code_25_iata.rb +23 -0
- data/lib/barby/barcode/code_25_interleaved.rb +73 -0
- data/lib/barby/barcode/code_39.rb +233 -0
- data/lib/barby/barcode/code_93.rb +230 -0
- data/lib/barby/barcode/data_matrix.rb +46 -0
- data/lib/barby/barcode/ean_13.rb +178 -0
- data/lib/barby/barcode/ean_8.rb +32 -0
- data/lib/barby/barcode/gs1_128.rb +42 -0
- data/lib/barby/barcode/pdf_417.rb +76 -0
- data/lib/barby/barcode/qr_code.rb +101 -0
- data/lib/barby/barcode.rb +116 -0
- data/lib/barby/outputter/ascii_outputter.rb +41 -0
- data/lib/barby/outputter/cairo_outputter.rb +185 -0
- data/lib/barby/outputter/pdfwriter_outputter.rb +83 -0
- data/lib/barby/outputter/png_outputter.rb +97 -0
- data/lib/barby/outputter/prawn_outputter.rb +99 -0
- data/lib/barby/outputter/rmagick_outputter.rb +126 -0
- data/lib/barby/outputter/svg_outputter.rb +225 -0
- data/lib/barby/outputter.rb +132 -0
- data/lib/barby/vendor.rb +3 -0
- data/lib/barby/version.rb +9 -0
- data/lib/barby.rb +17 -0
- data/vendor/Pdf417lib-java-0.91/lib/Pdf417lib.jar +0 -0
- data/vendor/Pdf417lib-java-0.91/lib/Pdf417lib.java +1471 -0
- data/vendor/rqrcode/CHANGELOG +29 -0
- data/vendor/rqrcode/COPYING +19 -0
- data/vendor/rqrcode/README +98 -0
- data/vendor/rqrcode/Rakefile +65 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/array/behavior.rb +9 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/array.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/integer/bitwise.rb +11 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/integer.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_8bit_byte.rb +37 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_bit_buffer.rb +56 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_code.rb +421 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_math.rb +63 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_polynomial.rb +78 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_rs_block.rb +313 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_util.rb +254 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode.rb +4 -0
- data/vendor/rqrcode/lib/rqrcode.rb +13 -0
- data/vendor/rqrcode/test/runtest.rb +78 -0
- data/vendor/rqrcode/test/test_data.rb +21 -0
- metadata +129 -0
data/README
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Barby is a Ruby barcode generator. It does not depend on other libraries
|
2
|
+
(for the core functionality) and is easily extentable.
|
3
|
+
|
4
|
+
The barcode objects are separated from the process of generating graphical
|
5
|
+
(or other) representations. A barcode's only responsibility is to provide
|
6
|
+
a string representation consisting of 1s and 0s representing bars and spaces.
|
7
|
+
This string can then be used to generate (for example) an image with the
|
8
|
+
RMagickOutputter, or an ASCII string such as the one below.
|
9
|
+
|
10
|
+
See Barby::Barcode and Barby::Outputter for more information.
|
11
|
+
|
12
|
+
require 'barby'
|
13
|
+
require 'barby/outputter/ascii_outputter'
|
14
|
+
|
15
|
+
barcode = Barby::Code128B.new('BARBY')
|
16
|
+
|
17
|
+
puts barcode.to_ascii
|
18
|
+
|
19
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
20
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
21
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
22
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
23
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
24
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
25
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
26
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
27
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
28
|
+
## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
|
29
|
+
B A R B Y
|
data/bin/barby
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
#$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
6
|
+
require 'barby'
|
7
|
+
|
8
|
+
options = {
|
9
|
+
:outputter => 'Png',
|
10
|
+
:outputter_method => 'to_png',
|
11
|
+
:barcode => 'Code128B'
|
12
|
+
}
|
13
|
+
|
14
|
+
ARGV.options do |o|
|
15
|
+
o.banner = " Usage: #{File.basename(__FILE__)} [OPTIONS] data"
|
16
|
+
o.define_head ' Generates barcodes and prints the generated output to STDOUT'
|
17
|
+
|
18
|
+
o.separator ''
|
19
|
+
o.separator ' EXPERIMENTAL'
|
20
|
+
o.separator ''
|
21
|
+
|
22
|
+
o.on('-b', '--barcode=ClassName', String, 'Barcode type (Code128B)'){|v| options[:barcode] = v }
|
23
|
+
o.on('-o', '--outputter=ClassName', String, 'Outputter (Png)'){|v| options[:outputter] = v }
|
24
|
+
o.on('-m', '--method=method_name', String, 'Outputter method (to_png)'){|v| options[:outputter_method] = v }
|
25
|
+
|
26
|
+
o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
|
27
|
+
|
28
|
+
o.parse!
|
29
|
+
end
|
30
|
+
|
31
|
+
#p STDIN.read
|
32
|
+
#exit
|
33
|
+
|
34
|
+
require "barby/outputter/#{options[:outputter].gsub(/[A-Z]/){|c| '_'+c.downcase }[1..-1]}_outputter"
|
35
|
+
|
36
|
+
barcode_class = Barby.const_get(options[:barcode])
|
37
|
+
barcode = barcode_class.new($*.empty? ? STDIN.read.chomp : $*)
|
38
|
+
outputter_class = Barby.const_get("#{options[:outputter]}Outputter")
|
39
|
+
outputter = outputter_class.new(barcode)
|
40
|
+
|
41
|
+
print eval("outputter.#{options[:outputter_method]}(#{ENV['OPTIONS']})")
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'barby/barcode/ean_13'
|
2
|
+
|
3
|
+
module Barby
|
4
|
+
|
5
|
+
#Bookland barcodes are EAN-13 barcodes with number system
|
6
|
+
#978 (hence "Bookland"). The data they encode is an ISBN
|
7
|
+
#with its check digit removed. This is a convenience class
|
8
|
+
#that takes an ISBN no instead of "pure" EAN-13 data.
|
9
|
+
class Bookland < EAN13
|
10
|
+
|
11
|
+
BOOKLAND_NUMBER_SYSTEM = '978'
|
12
|
+
|
13
|
+
attr_accessor :isbn
|
14
|
+
|
15
|
+
def initialize(isbn)
|
16
|
+
self.isbn = isbn
|
17
|
+
raise ArgumentError, 'data not valid' unless valid?
|
18
|
+
end
|
19
|
+
|
20
|
+
def data
|
21
|
+
BOOKLAND_NUMBER_SYSTEM+isbn_only
|
22
|
+
end
|
23
|
+
|
24
|
+
#Removes any non-digit characters, number system and check digit
|
25
|
+
#from ISBN, so "978-82-92526-14-9" would result in "829252614"
|
26
|
+
def isbn_only
|
27
|
+
s = isbn.gsub(/[^0-9]/, '')
|
28
|
+
if s.size > 10#Includes number system
|
29
|
+
s[3,9]
|
30
|
+
else#No number system, may include check digit
|
31
|
+
s[0,9]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,410 @@
|
|
1
|
+
require 'barby/barcode'
|
2
|
+
|
3
|
+
module Barby
|
4
|
+
|
5
|
+
|
6
|
+
#Code 128 barcodes
|
7
|
+
#
|
8
|
+
#Note that you must provide a type for each object, either by passing a string
|
9
|
+
#as a second parameter to Code128.new or by instantiating one of the child classes.
|
10
|
+
#
|
11
|
+
#You can switch type by using the CODEA, CODEB and CODEC characters:
|
12
|
+
#
|
13
|
+
# "\305" => A
|
14
|
+
# "\306" => B
|
15
|
+
# "\307" => C
|
16
|
+
#
|
17
|
+
#As an example, here's one that starts out as type A and then switches to B and then C:
|
18
|
+
#
|
19
|
+
# Code128A.new("ABC123\306def\3074567")
|
20
|
+
class Code128 < Barcode1D
|
21
|
+
|
22
|
+
ENCODINGS = {
|
23
|
+
0 => "11011001100", 1 => "11001101100", 2 => "11001100110",
|
24
|
+
3 => "10010011000", 4 => "10010001100", 5 => "10001001100",
|
25
|
+
6 => "10011001000", 7 => "10011000100", 8 => "10001100100",
|
26
|
+
9 => "11001001000", 10 => "11001000100", 11 => "11000100100",
|
27
|
+
12 => "10110011100", 13 => "10011011100", 14 => "10011001110",
|
28
|
+
15 => "10111001100", 16 => "10011101100", 17 => "10011100110",
|
29
|
+
18 => "11001110010", 19 => "11001011100", 20 => "11001001110",
|
30
|
+
21 => "11011100100", 22 => "11001110100", 23 => "11101101110",
|
31
|
+
24 => "11101001100", 25 => "11100101100", 26 => "11100100110",
|
32
|
+
27 => "11101100100", 28 => "11100110100", 29 => "11100110010",
|
33
|
+
30 => "11011011000", 31 => "11011000110", 32 => "11000110110",
|
34
|
+
33 => "10100011000", 34 => "10001011000", 35 => "10001000110",
|
35
|
+
36 => "10110001000", 37 => "10001101000", 38 => "10001100010",
|
36
|
+
39 => "11010001000", 40 => "11000101000", 41 => "11000100010",
|
37
|
+
42 => "10110111000", 43 => "10110001110", 44 => "10001101110",
|
38
|
+
45 => "10111011000", 46 => "10111000110", 47 => "10001110110",
|
39
|
+
48 => "11101110110", 49 => "11010001110", 50 => "11000101110",
|
40
|
+
51 => "11011101000", 52 => "11011100010", 53 => "11011101110",
|
41
|
+
54 => "11101011000", 55 => "11101000110", 56 => "11100010110",
|
42
|
+
57 => "11101101000", 58 => "11101100010", 59 => "11100011010",
|
43
|
+
60 => "11101111010", 61 => "11001000010", 62 => "11110001010",
|
44
|
+
63 => "10100110000", 64 => "10100001100", 65 => "10010110000",
|
45
|
+
66 => "10010000110", 67 => "10000101100", 68 => "10000100110",
|
46
|
+
69 => "10110010000", 70 => "10110000100", 71 => "10011010000",
|
47
|
+
72 => "10011000010", 73 => "10000110100", 74 => "10000110010",
|
48
|
+
75 => "11000010010", 76 => "11001010000", 77 => "11110111010",
|
49
|
+
78 => "11000010100", 79 => "10001111010", 80 => "10100111100",
|
50
|
+
81 => "10010111100", 82 => "10010011110", 83 => "10111100100",
|
51
|
+
84 => "10011110100", 85 => "10011110010", 86 => "11110100100",
|
52
|
+
87 => "11110010100", 88 => "11110010010", 89 => "11011011110",
|
53
|
+
90 => "11011110110", 91 => "11110110110", 92 => "10101111000",
|
54
|
+
93 => "10100011110", 94 => "10001011110", 95 => "10111101000",
|
55
|
+
96 => "10111100010", 97 => "11110101000", 98 => "11110100010",
|
56
|
+
99 => "10111011110", 100 => "10111101110", 101 => "11101011110",
|
57
|
+
102 => "11110101110", 103 => "11010000100", 104 => "11010010000",
|
58
|
+
105 => "11010011100"
|
59
|
+
}
|
60
|
+
|
61
|
+
VALUES = {
|
62
|
+
'A' => {
|
63
|
+
0 => " ", 1 => "!", 2 => "\"",
|
64
|
+
3 => "#", 4 => "$", 5 => "%",
|
65
|
+
6 => "&", 7 => "'", 8 => "(",
|
66
|
+
9 => ")", 10 => "*", 11 => "+",
|
67
|
+
12 => ",", 13 => "-", 14 => ".",
|
68
|
+
15 => "/", 16 => "0", 17 => "1",
|
69
|
+
18 => "2", 19 => "3", 20 => "4",
|
70
|
+
21 => "5", 22 => "6", 23 => "7",
|
71
|
+
24 => "8", 25 => "9", 26 => ":",
|
72
|
+
27 => ";", 28 => "<", 29 => "=",
|
73
|
+
30 => ">", 31 => "?", 32 => "@",
|
74
|
+
33 => "A", 34 => "B", 35 => "C",
|
75
|
+
36 => "D", 37 => "E", 38 => "F",
|
76
|
+
39 => "G", 40 => "H", 41 => "I",
|
77
|
+
42 => "J", 43 => "K", 44 => "L",
|
78
|
+
45 => "M", 46 => "N", 47 => "O",
|
79
|
+
48 => "P", 49 => "Q", 50 => "R",
|
80
|
+
51 => "S", 52 => "T", 53 => "U",
|
81
|
+
54 => "V", 55 => "W", 56 => "X",
|
82
|
+
57 => "Y", 58 => "Z", 59 => "[",
|
83
|
+
60 => "\\", 61 => "]", 62 => "^",
|
84
|
+
63 => "_", 64 => "\000", 65 => "\001",
|
85
|
+
66 => "\002", 67 => "\003", 68 => "\004",
|
86
|
+
69 => "\005", 70 => "\006", 71 => "\a",
|
87
|
+
72 => "\b", 73 => "\t", 74 => "\n",
|
88
|
+
75 => "\v", 76 => "\f", 77 => "\r",
|
89
|
+
78 => "\016", 79 => "\017", 80 => "\020",
|
90
|
+
81 => "\021", 82 => "\022", 83 => "\023",
|
91
|
+
84 => "\024", 85 => "\025", 86 => "\026",
|
92
|
+
87 => "\027", 88 => "\030", 89 => "\031",
|
93
|
+
90 => "\032", 91 => "\e", 92 => "\034",
|
94
|
+
93 => "\035", 94 => "\036", 95 => "\037",
|
95
|
+
96 => "\303", 97 => "\302", 98 => "SHIFT",
|
96
|
+
99 => "\307", 100 => "\306", 101 => "\304",
|
97
|
+
102 => "\301", 103 => "STARTA", 104 => "STARTB",
|
98
|
+
105 => "STARTC"
|
99
|
+
}.invert,
|
100
|
+
|
101
|
+
'B' => {
|
102
|
+
0 => " ", 1 => "!", 2 => "\"", 3 => "#", 4 => "$", 5 => "%",
|
103
|
+
6 => "&", 7 => "'", 8 => "(", 9 => ")", 10 => "*", 11 => "+",
|
104
|
+
12 => ",", 13 => "-", 14 => ".", 15 => "/", 16 => "0", 17 => "1",
|
105
|
+
18 => "2", 19 => "3", 20 => "4", 21 => "5", 22 => "6", 23 => "7",
|
106
|
+
24 => "8", 25 => "9", 26 => ":", 27 => ";", 28 => "<", 29 => "=",
|
107
|
+
30 => ">", 31 => "?", 32 => "@", 33 => "A", 34 => "B", 35 => "C",
|
108
|
+
36 => "D", 37 => "E", 38 => "F", 39 => "G", 40 => "H", 41 => "I",
|
109
|
+
42 => "J", 43 => "K", 44 => "L", 45 => "M", 46 => "N", 47 => "O",
|
110
|
+
48 => "P", 49 => "Q", 50 => "R", 51 => "S", 52 => "T", 53 => "U",
|
111
|
+
54 => "V", 55 => "W", 56 => "X", 57 => "Y", 58 => "Z", 59 => "[",
|
112
|
+
60 => "\\", 61 => "]", 62 => "^", 63 => "_", 64 => "`", 65 => "a",
|
113
|
+
66 => "b", 67 => "c", 68 => "d", 69 => "e", 70 => "f", 71 => "g",
|
114
|
+
72 => "h", 73 => "i", 74 => "j", 75 => "k", 76 => "l", 77 => "m",
|
115
|
+
78 => "n", 79 => "o", 80 => "p", 81 => "q", 82 => "r", 83 => "s",
|
116
|
+
84 => "t", 85 => "u", 86 => "v", 87 => "w", 88 => "x", 89 => "y",
|
117
|
+
90 => "z", 91 => "{", 92 => "|", 93 => "}", 94 => "~", 95 => "\177",
|
118
|
+
96 => "\303", 97 => "\302", 98 => "SHIFT", 99 => "\307", 100 => "\304",
|
119
|
+
101 => "\305", 102 => "\301", 103 => "STARTA", 104 => "STARTB",
|
120
|
+
105 => "STARTC",
|
121
|
+
}.invert,
|
122
|
+
|
123
|
+
'C' => {
|
124
|
+
0 => "00", 1 => "01", 2 => "02", 3 => "03", 4 => "04", 5 => "05",
|
125
|
+
6 => "06", 7 => "07", 8 => "08", 9 => "09", 10 => "10", 11 => "11",
|
126
|
+
12 => "12", 13 => "13", 14 => "14", 15 => "15", 16 => "16", 17 => "17",
|
127
|
+
18 => "18", 19 => "19", 20 => "20", 21 => "21", 22 => "22", 23 => "23",
|
128
|
+
24 => "24", 25 => "25", 26 => "26", 27 => "27", 28 => "28", 29 => "29",
|
129
|
+
30 => "30", 31 => "31", 32 => "32", 33 => "33", 34 => "34", 35 => "35",
|
130
|
+
36 => "36", 37 => "37", 38 => "38", 39 => "39", 40 => "40", 41 => "41",
|
131
|
+
42 => "42", 43 => "43", 44 => "44", 45 => "45", 46 => "46", 47 => "47",
|
132
|
+
48 => "48", 49 => "49", 50 => "50", 51 => "51", 52 => "52", 53 => "53",
|
133
|
+
54 => "54", 55 => "55", 56 => "56", 57 => "57", 58 => "58", 59 => "59",
|
134
|
+
60 => "60", 61 => "61", 62 => "62", 63 => "63", 64 => "64", 65 => "65",
|
135
|
+
66 => "66", 67 => "67", 68 => "68", 69 => "69", 70 => "70", 71 => "71",
|
136
|
+
72 => "72", 73 => "73", 74 => "74", 75 => "75", 76 => "76", 77 => "77",
|
137
|
+
78 => "78", 79 => "79", 80 => "80", 81 => "81", 82 => "82", 83 => "83",
|
138
|
+
84 => "84", 85 => "85", 86 => "86", 87 => "87", 88 => "88", 89 => "89",
|
139
|
+
90 => "90", 91 => "91", 92 => "92", 93 => "93", 94 => "94", 95 => "95",
|
140
|
+
96 => "96", 97 => "97", 98 => "98", 99 => "99", 100 => "\306", 101 => "\305",
|
141
|
+
102 => "\301", 103 => "STARTA", 104 => "STARTB", 105 => "STARTC"
|
142
|
+
}.invert
|
143
|
+
}
|
144
|
+
|
145
|
+
FNC1 = "\xc1"
|
146
|
+
FNC2 = "\xc2"
|
147
|
+
FNC3 = "\xc3"
|
148
|
+
FNC4 = "\xc4"
|
149
|
+
CODEA = "\xc5"
|
150
|
+
CODEB = "\xc6"
|
151
|
+
CODEC = "\xc7"
|
152
|
+
|
153
|
+
STOP = '11000111010'
|
154
|
+
TERMINATE = '11'
|
155
|
+
|
156
|
+
attr_reader :type
|
157
|
+
|
158
|
+
|
159
|
+
def initialize(data, type)
|
160
|
+
self.type = type
|
161
|
+
self.data = "#{data}"
|
162
|
+
raise ArgumentError, 'Data not valid' unless valid?
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
def type=(type)
|
167
|
+
type.upcase!
|
168
|
+
raise ArgumentError, 'type must be A, B or C' unless type =~ /^[ABC]$/
|
169
|
+
@type = type
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
def to_s
|
174
|
+
full_data
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def data
|
179
|
+
@data
|
180
|
+
end
|
181
|
+
|
182
|
+
#Returns the data for this barcode plus that for the entire extra chain,
|
183
|
+
#excluding all change codes
|
184
|
+
def full_data
|
185
|
+
data + full_extra_data
|
186
|
+
end
|
187
|
+
|
188
|
+
#Returns the data for this barcode plus that for the entire extra chain,
|
189
|
+
#including all change codes prefixing each extra
|
190
|
+
def full_data_with_change_codes
|
191
|
+
data + full_extra_data_with_change_code
|
192
|
+
end
|
193
|
+
|
194
|
+
#Returns the full_data for the extra or an empty string if there is no extra
|
195
|
+
def full_extra_data
|
196
|
+
return '' unless extra
|
197
|
+
extra.full_data
|
198
|
+
end
|
199
|
+
|
200
|
+
#Returns the full_data for the extra with the change code for the extra
|
201
|
+
#prepended. If there is no extra, an empty string is returned
|
202
|
+
def full_extra_data_with_change_code
|
203
|
+
return '' unless extra
|
204
|
+
change_code_for(extra) + extra.full_data_with_change_codes
|
205
|
+
end
|
206
|
+
|
207
|
+
#Set the data for this barcode. If the barcode changes
|
208
|
+
#character set, an extra will be created.
|
209
|
+
def data=(data)
|
210
|
+
data, *extra = data.split(/([#{CODEA+CODEB+CODEC}])/n)
|
211
|
+
@data = data || ''
|
212
|
+
self.extra = extra.join unless extra.empty?
|
213
|
+
end
|
214
|
+
|
215
|
+
#An "extra" is present if the barcode changes character set. If
|
216
|
+
#a 128A barcode changes to C, the extra will be an instance of
|
217
|
+
#Code128C. Extras can themselves have an extra if the barcode
|
218
|
+
#changes character set again. It's like a linked list, and when
|
219
|
+
#there are no more extras, the barcode ends with that object.
|
220
|
+
#Most barcodes probably don't change charsets and don't have extras.
|
221
|
+
def extra
|
222
|
+
@extra
|
223
|
+
end
|
224
|
+
|
225
|
+
#Set the extra for this barcode. The argument is a string starting with the
|
226
|
+
#"change character set" symbol. The string may contain several character
|
227
|
+
#sets, in which case the extra will itself have an extra.
|
228
|
+
def extra=(extra)
|
229
|
+
raise ArgumentError, "Extra must begin with \\305, \\306 or \\307" unless extra =~ /^[#{CODEA+CODEB+CODEC}]/n
|
230
|
+
type, data = extra[0,1], extra[1..-1]
|
231
|
+
@extra = class_for(type).new(data)
|
232
|
+
end
|
233
|
+
|
234
|
+
#Get an array of the individual characters for this barcode. Special
|
235
|
+
#characters like FNC1 will be present. Characters from extras are not
|
236
|
+
#present.
|
237
|
+
def characters
|
238
|
+
chars = data.split(//n)
|
239
|
+
|
240
|
+
if type == 'C'
|
241
|
+
result = []
|
242
|
+
count = 0
|
243
|
+
while count < chars.size
|
244
|
+
if chars[count] =~ /^\d$/
|
245
|
+
result << "#{chars[count]}#{chars[count+1]}"
|
246
|
+
count += 2
|
247
|
+
else
|
248
|
+
result << chars[count]
|
249
|
+
count += 1
|
250
|
+
end
|
251
|
+
end
|
252
|
+
result
|
253
|
+
else
|
254
|
+
chars
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
#Return the encoding of this barcode as a string of 1 and 0
|
259
|
+
def encoding
|
260
|
+
start_encoding+data_encoding+extra_encoding+checksum_encoding+stop_encoding
|
261
|
+
end
|
262
|
+
|
263
|
+
#Returns the encoding for the data part of this barcode, without any extras
|
264
|
+
def data_encoding
|
265
|
+
characters.map do |char|
|
266
|
+
encoding_for char
|
267
|
+
end.join
|
268
|
+
end
|
269
|
+
|
270
|
+
#Returns the data encoding of this barcode and extras.
|
271
|
+
def data_encoding_with_extra_encoding
|
272
|
+
data_encoding+extra_encoding
|
273
|
+
end
|
274
|
+
|
275
|
+
#Returns the data encoding of this barcode's extra and its
|
276
|
+
#extra until the barcode ends.
|
277
|
+
def extra_encoding
|
278
|
+
return '' unless extra
|
279
|
+
change_code_encoding_for(extra) + extra.data_encoding + extra.extra_encoding
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
#Calculate the checksum for the data in this barcode. The data includes
|
284
|
+
#data from extras.
|
285
|
+
def checksum
|
286
|
+
pos = 0
|
287
|
+
(numbers+extra_numbers).inject(start_num) do |sum,number|
|
288
|
+
pos += 1
|
289
|
+
sum + (number * pos)
|
290
|
+
end % 103
|
291
|
+
end
|
292
|
+
|
293
|
+
#Get the encoding for the checksum
|
294
|
+
def checksum_encoding
|
295
|
+
encodings[checksum]
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
#protected
|
300
|
+
|
301
|
+
#Returns the numeric values for the characters in the barcode in an array
|
302
|
+
def numbers
|
303
|
+
characters.map do |char|
|
304
|
+
values[char]
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
#Returns the numeric values for extras
|
309
|
+
def extra_numbers
|
310
|
+
return [] unless extra
|
311
|
+
[change_code_number_for(extra)] + extra.numbers + extra.extra_numbers
|
312
|
+
end
|
313
|
+
|
314
|
+
def encodings
|
315
|
+
ENCODINGS
|
316
|
+
end
|
317
|
+
|
318
|
+
#The start encoding starts the barcode
|
319
|
+
def stop_encoding
|
320
|
+
STOP+TERMINATE
|
321
|
+
end
|
322
|
+
|
323
|
+
#Find the encoding for the specified character for this barcode
|
324
|
+
def encoding_for(char)
|
325
|
+
encodings[values[char]]
|
326
|
+
end
|
327
|
+
|
328
|
+
def change_code_for_class(klass)
|
329
|
+
{Code128A => CODEA, Code128B => CODEB, Code128C => CODEC}[klass]
|
330
|
+
end
|
331
|
+
|
332
|
+
#Find the character that changes the character set to the one
|
333
|
+
#represented in +barcode+
|
334
|
+
def change_code_for(barcode)
|
335
|
+
change_code_for_class(barcode.class)
|
336
|
+
end
|
337
|
+
|
338
|
+
#Find the numeric value for the character that changes the character
|
339
|
+
#set to the one represented in +barcode+
|
340
|
+
def change_code_number_for(barcode)
|
341
|
+
values[change_code_for(barcode)]
|
342
|
+
end
|
343
|
+
|
344
|
+
#Find the encoding to change to the character set in +barcode+
|
345
|
+
def change_code_encoding_for(barcode)
|
346
|
+
encodings[change_code_number_for(barcode)]
|
347
|
+
end
|
348
|
+
|
349
|
+
def class_for(character)
|
350
|
+
case character
|
351
|
+
when 'A' then Code128A
|
352
|
+
when 'B' then Code128B
|
353
|
+
when 'C' then Code128C
|
354
|
+
when CODEA then Code128A
|
355
|
+
when CODEB then Code128B
|
356
|
+
when CODEC then Code128C
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
#Is the data in this barcode valid? Does a lookup of every character
|
361
|
+
#and checks if it exists in the character set. An empty data string
|
362
|
+
#will also be reported as invalid.
|
363
|
+
def valid?
|
364
|
+
characters.any? && characters.all?{|c| values.include?(c) }
|
365
|
+
end
|
366
|
+
|
367
|
+
def values
|
368
|
+
VALUES[type]
|
369
|
+
end
|
370
|
+
|
371
|
+
def start_num
|
372
|
+
values["START#{type}"]
|
373
|
+
end
|
374
|
+
|
375
|
+
def start_encoding
|
376
|
+
encodings[start_num]
|
377
|
+
end
|
378
|
+
|
379
|
+
|
380
|
+
end
|
381
|
+
|
382
|
+
|
383
|
+
class Code128A < Code128
|
384
|
+
|
385
|
+
def initialize(data)
|
386
|
+
super(data, 'A')
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
class Code128B < Code128
|
393
|
+
|
394
|
+
def initialize(data)
|
395
|
+
super(data, 'B')
|
396
|
+
end
|
397
|
+
|
398
|
+
end
|
399
|
+
|
400
|
+
|
401
|
+
class Code128C < Code128
|
402
|
+
|
403
|
+
def initialize(data)
|
404
|
+
super(data, 'C')
|
405
|
+
end
|
406
|
+
|
407
|
+
end
|
408
|
+
|
409
|
+
|
410
|
+
end
|