barby 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/barby +40 -0
- data/lib/barby.rb +3 -0
- data/lib/barby/barcode.rb +6 -0
- data/lib/barby/barcode/code_128.rb +16 -3
- data/lib/barby/barcode/code_25.rb +161 -0
- data/lib/barby/barcode/code_25_interleaved.rb +73 -0
- data/lib/barby/barcode/code_93.rb +225 -0
- data/lib/barby/barcode/qr_code.rb +93 -0
- data/lib/barby/outputter.rb +56 -2
- data/lib/barby/outputter/ascii_outputter.rb +20 -1
- data/lib/barby/outputter/cairo_outputter.rb +38 -7
- data/lib/barby/outputter/pdfwriter_outputter.rb +44 -35
- data/lib/barby/outputter/png_outputter.rb +48 -16
- data/lib/barby/outputter/prawn_outputter.rb +100 -0
- data/lib/barby/outputter/rmagick_outputter.rb +48 -20
- data/lib/barby/vendor.rb +3 -0
- data/vendor/rqrcode/CHANGELOG +21 -0
- data/vendor/rqrcode/COPYING +19 -0
- data/vendor/rqrcode/README +98 -0
- data/vendor/rqrcode/Rakefile +65 -0
- data/vendor/rqrcode/lib/rqrcode.rb +13 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/array.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/array/behavior.rb +9 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/integer.rb +5 -0
- data/vendor/rqrcode/lib/rqrcode/core_ext/integer/bitwise.rb +11 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode.rb +4 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_8bit_byte.rb +35 -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 +134 -0
- data/vendor/rqrcode/lib/rqrcode/qrcode/qr_util.rb +254 -0
- data/vendor/rqrcode/test/runtest.rb +78 -0
- data/vendor/rqrcode/test/test_data.rb +21 -0
- metadata +86 -44
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'rqrcode'
|
2
|
+
require 'barby/barcode'
|
3
|
+
|
4
|
+
module Barby
|
5
|
+
|
6
|
+
|
7
|
+
#QrCode is a thin wrapper around the RQRCode library
|
8
|
+
class QrCode < Barcode2D
|
9
|
+
|
10
|
+
#Maximum sizes for each correction level for binary data
|
11
|
+
#It's an array
|
12
|
+
SIZES = {
|
13
|
+
#L M Q H
|
14
|
+
1 => [17, 14, 11, 7], 2 => [32, 26, 20, 14],
|
15
|
+
3 => [53, 42, 32, 24], 4 => [78, 62, 46, 34],
|
16
|
+
5 => [106, 84, 60, 44], 6 => [134, 106, 74, 58],
|
17
|
+
7 => [154, 122, 86, 64], 8 => [192, 152, 108, 84],
|
18
|
+
9 => [230, 180, 130, 98], 10 => [271, 213, 151, 119]#,
|
19
|
+
|
20
|
+
#I think RQRCode only supports sizes up to 10
|
21
|
+
# 11 => [321, 251, 177, 137], 12 => [367, 287, 203, 155],
|
22
|
+
# 13 => [425, 331, 241, 177], 14 => [458, 362, 258, 194],
|
23
|
+
# 15 => [520, 412, 292, 220], 16 => [586, 450, 322, 250],
|
24
|
+
# 17 => [644, 504, 364, 280], 18 => [718, 560, 394, 310],
|
25
|
+
# 19 => [792, 624, 442, 338], 20 => [858, 666, 482, 382],
|
26
|
+
# 21 => [929, 711, 509, 403], 22 => [1003, 779, 565, 439],
|
27
|
+
# 23 => [1091, 857, 611, 461], 24 => [1171, 911, 661, 511],
|
28
|
+
# 25 => [1273, 997, 715, 535], 26 => [1367, 1059, 751, 593],
|
29
|
+
# 27 => [1465, 1125, 805, 625], 28 => [1528, 1190, 868, 658],
|
30
|
+
# 29 => [1628, 1264, 908, 698], 30 => [1732, 1370, 982, 742],
|
31
|
+
# 31 => [1840, 1452, 1030, 790], 32 => [1952, 1538, 1112, 842],
|
32
|
+
# 33 => [2068, 1628, 1168, 898], 34 => [2188, 1722, 1228, 958],
|
33
|
+
# 35 => [2303, 1809, 1283, 983], 36 => [2431, 1911, 1351, 1051],
|
34
|
+
# 37 => [2563, 1989, 1423, 1093], 38 => [2699, 2099, 1499, 1139],
|
35
|
+
# 39 => [2809, 2213, 1579, 1219], 40 => [2953, 2331, 1663, 1273]
|
36
|
+
}.sort
|
37
|
+
|
38
|
+
LEVELS = { :l => 0, :m => 1, :q => 2, :h => 3 }
|
39
|
+
|
40
|
+
attr_reader :data
|
41
|
+
attr_writer :level
|
42
|
+
|
43
|
+
|
44
|
+
def initialize(data, options={})
|
45
|
+
self.data = data
|
46
|
+
options.each{|k,v| send("#{k}=", v) }
|
47
|
+
raise(ArgumentError, "data too large") unless size
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def data=(data)
|
52
|
+
@data = data
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def encoding
|
57
|
+
rqrcode.modules.map{|r| r.inject(''){|s,m| s << (m ? '1' : '0') } }
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
#Error correction level
|
62
|
+
#Can be one of [:l, :m, :q, :h] (7%, 15%, 25%, 30%)
|
63
|
+
def level
|
64
|
+
@level || :l
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def size
|
69
|
+
level_index = LEVELS[level]
|
70
|
+
length = data.length
|
71
|
+
found_size = nil
|
72
|
+
SIZES.each do |size,max_values|
|
73
|
+
if max_values[level_index] >= length
|
74
|
+
found_size = size
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
found_size
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
#Generate an RQRCode object with the available values
|
85
|
+
def rqrcode
|
86
|
+
RQRCode::QRCode.new(data, :level => level, :size => size)
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
data/lib/barby/outputter.rb
CHANGED
@@ -62,8 +62,62 @@ module Barby
|
|
62
62
|
|
63
63
|
#Converts the barcode's encoding (a string containing 1s and 0s)
|
64
64
|
#to true and false values (1 == true == "black bar")
|
65
|
-
|
66
|
-
|
65
|
+
#
|
66
|
+
#If the barcode is 2D, each line will be converted to an array
|
67
|
+
#in the same way
|
68
|
+
def booleans(reload=false)#:doc:
|
69
|
+
if barcode.two_dimensional?
|
70
|
+
encoding(reload).map{|l| l.split(//).map{|c| c == '1' } }
|
71
|
+
else
|
72
|
+
encoding(reload).split(//).map{|c| c == '1' }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
#Returns the barcode's encoding. The encoding
|
78
|
+
#is cached and can be reloaded by passing true
|
79
|
+
def encoding(reload=false)#:doc:
|
80
|
+
@encoding = barcode.encoding if reload
|
81
|
+
@encoding ||= barcode.encoding
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
#Collects continuous groups of bars and spaces (1 and 0)
|
86
|
+
#into arrays where the first item is true or false (1 or 0)
|
87
|
+
#and the second is the size of the group
|
88
|
+
#
|
89
|
+
#For example, "1100111000" becomes [[true,2],[false,2],[true,3],[false,3]]
|
90
|
+
def boolean_groups(reload=false)
|
91
|
+
if barcode.two_dimensional?
|
92
|
+
encoding(reload).map do |line|
|
93
|
+
line.scan(/1+|0+/).map do |group|
|
94
|
+
[group[0,1] == '1', group.size]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
else
|
98
|
+
encoding(reload).scan(/1+|0+/).map do |group|
|
99
|
+
[group[0,1] == '1', group.size]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def with_options(options={})
|
106
|
+
original_options = options.inject({}) do |origs,pair|
|
107
|
+
if respond_to?(pair.first) && respond_to?("#{pair.first}=")
|
108
|
+
origs[pair.first] = send(pair.first)
|
109
|
+
send("#{pair.first}=", pair.last)
|
110
|
+
end
|
111
|
+
origs
|
112
|
+
end
|
113
|
+
|
114
|
+
rv = yield
|
115
|
+
|
116
|
+
original_options.each do |attribute,value|
|
117
|
+
send("#{attribute}=", value)
|
118
|
+
end
|
119
|
+
|
120
|
+
rv
|
67
121
|
end
|
68
122
|
|
69
123
|
|
@@ -4,19 +4,38 @@ module Barby
|
|
4
4
|
|
5
5
|
#Outputs an ASCII representation of the barcode. This is mostly useful for printing
|
6
6
|
#the barcode directly to the terminal for testing.
|
7
|
+
#
|
8
|
+
#Registers to_ascii
|
7
9
|
class ASCIIOutputter < Outputter
|
8
10
|
|
9
11
|
register :to_ascii
|
10
12
|
|
11
13
|
|
12
14
|
def to_ascii(opts={})
|
13
|
-
|
15
|
+
default_opts = {:height => 10, :xdim => 1, :bar => '#', :space => ' '}
|
16
|
+
default_opts.update(:height => 1, :bar => ' X ', :space => ' ') if barcode.two_dimensional?
|
17
|
+
opts = default_opts.merge(opts)
|
18
|
+
|
19
|
+
if barcode.two_dimensional?
|
20
|
+
booleans.map do |bools|
|
21
|
+
line_to_ascii(bools, opts)
|
22
|
+
end.join("\n")
|
23
|
+
else
|
24
|
+
line_to_ascii(booleans, opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def line_to_ascii(booleans, opts)
|
14
32
|
Array.new(
|
15
33
|
opts[:height],
|
16
34
|
booleans.map{|b| (b ? opts[:bar] : opts[:space]) * opts[:xdim] }.join
|
17
35
|
).join("\n")
|
18
36
|
end
|
19
37
|
|
38
|
+
|
20
39
|
end
|
21
40
|
|
22
41
|
end
|
@@ -1,7 +1,12 @@
|
|
1
|
+
require 'barby/outputter'
|
1
2
|
require 'cairo'
|
2
3
|
require 'stringio'
|
3
4
|
|
4
5
|
module Barby
|
6
|
+
|
7
|
+
#Uses Cairo to render a barcode to a number of formats: PNG, PS, EPS, PDF and SVG
|
8
|
+
#
|
9
|
+
#Registers methods render_to_cairo_context, to_png, to_ps, to_eps, to_pdf and to_svg
|
5
10
|
class CairoOutputter < Outputter
|
6
11
|
|
7
12
|
register :render_to_cairo_context
|
@@ -18,6 +23,7 @@ module Barby
|
|
18
23
|
attr_writer :x, :y, :xdim, :height, :margin
|
19
24
|
|
20
25
|
|
26
|
+
#Render the barcode onto a Cairo context
|
21
27
|
def render_to_cairo_context(context, options={})
|
22
28
|
if context.respond_to?(:have_current_point?) and
|
23
29
|
context.have_current_point?
|
@@ -29,15 +35,30 @@ module Barby
|
|
29
35
|
|
30
36
|
_xdim = xdim(options)
|
31
37
|
_height = height(options)
|
38
|
+
original_current_x = current_x
|
32
39
|
context.save do
|
33
40
|
context.set_source_color(:black)
|
34
41
|
context.fill do
|
35
|
-
barcode.
|
36
|
-
|
37
|
-
|
38
|
-
|
42
|
+
if barcode.two_dimensional?
|
43
|
+
boolean_groups.each do |groups|
|
44
|
+
groups.each do |bar,amount|
|
45
|
+
current_width = _xdim * amount
|
46
|
+
if bar
|
47
|
+
context.rectangle(current_x, current_y, current_width, _xdim)
|
48
|
+
end
|
49
|
+
current_x += current_width
|
50
|
+
end
|
51
|
+
current_x = original_current_x
|
52
|
+
current_y += _xdim
|
53
|
+
end
|
54
|
+
else
|
55
|
+
boolean_groups.each do |bar,amount|
|
56
|
+
current_width = _xdim * amount
|
57
|
+
if bar
|
58
|
+
context.rectangle(current_x, current_y, current_width, _height)
|
59
|
+
end
|
60
|
+
current_x += current_width
|
39
61
|
end
|
40
|
-
current_x += current_width
|
41
62
|
end
|
42
63
|
end
|
43
64
|
end
|
@@ -46,6 +67,7 @@ module Barby
|
|
46
67
|
end
|
47
68
|
|
48
69
|
|
70
|
+
#Render the barcode to a PNG image
|
49
71
|
def to_png(options={})
|
50
72
|
output_to_string_io do |io|
|
51
73
|
Cairo::ImageSurface.new(options[:format],
|
@@ -58,6 +80,7 @@ module Barby
|
|
58
80
|
end
|
59
81
|
|
60
82
|
|
83
|
+
#Render the barcode to a PS document
|
61
84
|
def to_ps(options={})
|
62
85
|
output_to_string_io do |io|
|
63
86
|
Cairo::PSSurface.new(io,
|
@@ -70,11 +93,13 @@ module Barby
|
|
70
93
|
end
|
71
94
|
|
72
95
|
|
96
|
+
#Render the barcode to an EPS document
|
73
97
|
def to_eps(options={})
|
74
98
|
to_ps(options.merge(:eps => true))
|
75
99
|
end
|
76
100
|
|
77
101
|
|
102
|
+
#Render the barcode to a PDF document
|
78
103
|
def to_pdf(options={})
|
79
104
|
output_to_string_io do |io|
|
80
105
|
Cairo::PDFSurface.new(io,
|
@@ -86,6 +111,7 @@ module Barby
|
|
86
111
|
end
|
87
112
|
|
88
113
|
|
114
|
+
#Render the barcode to an SVG document
|
89
115
|
def to_svg(options={})
|
90
116
|
output_to_string_io do |io|
|
91
117
|
Cairo::SVGSurface.new(io,
|
@@ -106,11 +132,15 @@ module Barby
|
|
106
132
|
end
|
107
133
|
|
108
134
|
def width(options={})
|
109
|
-
barcode.encoding.length * xdim(options)
|
135
|
+
(barcode.two_dimensional? ? encoding.first.length : encoding.length) * xdim(options)
|
110
136
|
end
|
111
137
|
|
112
138
|
def height(options={})
|
113
|
-
|
139
|
+
if barcode.two_dimensional?
|
140
|
+
encoding.size * xdim(options)
|
141
|
+
else
|
142
|
+
@height || options[:height] || 50
|
143
|
+
end
|
114
144
|
end
|
115
145
|
|
116
146
|
def full_width(options={})
|
@@ -151,4 +181,5 @@ module Barby
|
|
151
181
|
|
152
182
|
|
153
183
|
end
|
184
|
+
|
154
185
|
end
|
@@ -2,6 +2,9 @@ require 'barby/outputter'
|
|
2
2
|
|
3
3
|
module Barby
|
4
4
|
|
5
|
+
#Annotates a PDFWriter document with the barcode
|
6
|
+
#
|
7
|
+
#Registers the annotate_pdf method
|
5
8
|
class PDFWriterOutputter < Outputter
|
6
9
|
|
7
10
|
register :annotate_pdf
|
@@ -9,25 +12,50 @@ module Barby
|
|
9
12
|
attr_accessor :x, :y, :height, :xdim
|
10
13
|
|
11
14
|
|
15
|
+
#Annotate a PDFWriter document with the barcode
|
16
|
+
#
|
17
|
+
#Valid options are:
|
18
|
+
#
|
19
|
+
#x, y - The point in the document to start rendering from
|
20
|
+
#height - The height of the bars in PDF units
|
21
|
+
#xdim - The X dimension in PDF units
|
12
22
|
def annotate_pdf(pdf, options={})
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
with_options options do
|
24
|
+
|
25
|
+
xpos, ypos = x, y
|
26
|
+
orig_xpos = xpos
|
27
|
+
|
28
|
+
if barcode.two_dimensional?
|
29
|
+
boolean_groups.reverse_each do |groups|
|
30
|
+
groups.each do |bar,amount|
|
31
|
+
if bar
|
32
|
+
pdf.move_to(xpos, ypos).
|
33
|
+
line_to(xpos, ypos+xdim).
|
34
|
+
line_to(xpos+(xdim*amount), ypos+xdim).
|
35
|
+
line_to(xpos+(xdim*amount), ypos).
|
36
|
+
line_to(xpos, ypos).
|
37
|
+
fill
|
38
|
+
end
|
39
|
+
xpos += (xdim*amount)
|
40
|
+
end
|
41
|
+
xpos = orig_xpos
|
42
|
+
ypos += xdim
|
43
|
+
end
|
44
|
+
else
|
45
|
+
boolean_groups.each do |bar,amount|
|
46
|
+
if bar
|
47
|
+
pdf.move_to(xpos, ypos).
|
48
|
+
line_to(xpos, ypos+height).
|
49
|
+
line_to(xpos+(xdim*amount), ypos+height).
|
50
|
+
line_to(xpos+(xdim*amount), ypos).
|
51
|
+
line_to(xpos, ypos).
|
52
|
+
fill
|
53
|
+
end
|
54
|
+
xpos += (xdim*amount)
|
55
|
+
end
|
26
56
|
end
|
27
|
-
xpos += (xdim*array.size)
|
28
|
-
end
|
29
57
|
|
30
|
-
|
58
|
+
end
|
31
59
|
|
32
60
|
pdf
|
33
61
|
end
|
@@ -49,25 +77,6 @@ module Barby
|
|
49
77
|
@xdim || 1
|
50
78
|
end
|
51
79
|
|
52
|
-
def widths
|
53
|
-
widths = []
|
54
|
-
count = nil
|
55
|
-
|
56
|
-
booleans.inject nil do |previous,current|
|
57
|
-
if current != previous
|
58
|
-
widths << count if count
|
59
|
-
count = [current]
|
60
|
-
else
|
61
|
-
count << current
|
62
|
-
end
|
63
|
-
current
|
64
|
-
end
|
65
|
-
|
66
|
-
widths << count
|
67
|
-
|
68
|
-
widths
|
69
|
-
end
|
70
|
-
|
71
80
|
|
72
81
|
end
|
73
82
|
|
@@ -1,46 +1,70 @@
|
|
1
|
+
require 'barby/outputter'
|
1
2
|
require 'png'
|
2
3
|
|
3
4
|
module Barby
|
4
5
|
|
6
|
+
#Renders the barcode to a PNG image using the "png" gem (gem install png)
|
7
|
+
#
|
8
|
+
#Registers the to_png and to_canvas methods
|
5
9
|
class PngOutputter < Outputter
|
6
10
|
|
7
11
|
register :to_png, :to_canvas
|
8
12
|
|
9
|
-
attr_accessor :xdim, :width, :height, :margin
|
13
|
+
attr_accessor :xdim, :ydim, :width, :height, :margin
|
10
14
|
|
11
15
|
|
16
|
+
#Creates a PNG::Canvas object and renders the barcode on it
|
12
17
|
def to_canvas(opts={})
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
with_options opts do
|
19
|
+
canvas = PNG::Canvas.new(full_width, full_height, PNG::Color::White)
|
20
|
+
|
21
|
+
if barcode.two_dimensional?
|
22
|
+
x, y = margin, margin
|
23
|
+
booleans.reverse_each do |line|
|
24
|
+
line.each do |bar|
|
25
|
+
if bar
|
26
|
+
x.upto(x+(xdim-1)) do |xx|
|
27
|
+
y.upto y+(ydim-1) do |yy|
|
28
|
+
canvas[xx,yy] = PNG::Color::Black
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
x += xdim
|
22
33
|
end
|
34
|
+
y += ydim
|
35
|
+
x = margin
|
36
|
+
end
|
37
|
+
else
|
38
|
+
x, y = margin, margin
|
39
|
+
booleans.each do |bar|
|
40
|
+
if bar
|
41
|
+
x.upto(x+(xdim-1)) do |xx|
|
42
|
+
y.upto y+(height-1) do |yy|
|
43
|
+
canvas[xx,yy] = PNG::Color::Black
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
x += xdim
|
23
48
|
end
|
24
49
|
end
|
25
|
-
x += xdim
|
26
|
-
end
|
27
50
|
|
28
|
-
|
29
|
-
|
51
|
+
canvas
|
52
|
+
end
|
30
53
|
end
|
31
54
|
|
32
55
|
|
56
|
+
#Renders the barcode to a PNG image
|
33
57
|
def to_png(*a)
|
34
58
|
PNG.new(to_canvas(*a)).to_blob
|
35
59
|
end
|
36
60
|
|
37
61
|
|
38
62
|
def width
|
39
|
-
|
63
|
+
length * xdim
|
40
64
|
end
|
41
65
|
|
42
66
|
def height
|
43
|
-
@height || 100
|
67
|
+
barcode.two_dimensional? ? (ydim * encoding.length) : (@height || 100)
|
44
68
|
end
|
45
69
|
|
46
70
|
def full_width
|
@@ -55,10 +79,18 @@ module Barby
|
|
55
79
|
@xdim || 1
|
56
80
|
end
|
57
81
|
|
82
|
+
def ydim
|
83
|
+
@ydim || xdim
|
84
|
+
end
|
85
|
+
|
58
86
|
def margin
|
59
87
|
@margin || 10
|
60
88
|
end
|
61
89
|
|
90
|
+
def length
|
91
|
+
barcode.two_dimensional? ? encoding.first.length : encoding.length
|
92
|
+
end
|
93
|
+
|
62
94
|
|
63
95
|
end
|
64
96
|
|