barby 0.6.2 → 0.6.8

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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/CHANGELOG +8 -0
  4. data/Gemfile +5 -0
  5. data/README.md +108 -0
  6. data/Rakefile +15 -0
  7. data/barby.gemspec +31 -0
  8. data/lib/barby/barcode.rb +3 -3
  9. data/lib/barby/barcode/bookland.rb +0 -1
  10. data/lib/barby/barcode/codabar.rb +82 -0
  11. data/lib/barby/barcode/code_128.rb +22 -20
  12. data/lib/barby/barcode/code_25.rb +6 -3
  13. data/lib/barby/barcode/code_25_interleaved.rb +2 -2
  14. data/lib/barby/barcode/code_39.rb +2 -1
  15. data/lib/barby/barcode/data_matrix.rb +1 -1
  16. data/lib/barby/barcode/ean_13.rb +1 -1
  17. data/lib/barby/barcode/gs1_128.rb +5 -1
  18. data/lib/barby/barcode/qr_code.rb +2 -1
  19. data/lib/barby/outputter.rb +1 -1
  20. data/lib/barby/outputter/cairo_outputter.rb +16 -3
  21. data/lib/barby/outputter/png_outputter.rb +43 -7
  22. data/lib/barby/outputter/prawn_outputter.rb +12 -4
  23. data/lib/barby/outputter/rmagick_outputter.rb +43 -11
  24. data/lib/barby/outputter/svg_outputter.rb +11 -13
  25. data/lib/barby/version.rb +2 -2
  26. data/test/barcodes.rb +20 -0
  27. data/test/bookland_test.rb +54 -0
  28. data/test/codabar_test.rb +58 -0
  29. data/test/code_128_test.rb +470 -0
  30. data/test/code_25_iata_test.rb +19 -0
  31. data/test/code_25_interleaved_test.rb +116 -0
  32. data/test/code_25_test.rb +110 -0
  33. data/test/code_39_test.rb +210 -0
  34. data/test/code_93_test.rb +144 -0
  35. data/test/data_matrix_test.rb +30 -0
  36. data/test/ean13_test.rb +169 -0
  37. data/test/ean8_test.rb +100 -0
  38. data/test/outputter/cairo_outputter_test.rb +129 -0
  39. data/test/outputter/html_outputter_test.rb +68 -0
  40. data/test/outputter/pdfwriter_outputter_test.rb +37 -0
  41. data/test/outputter/png_outputter_test.rb +49 -0
  42. data/test/outputter/prawn_outputter_test.rb +79 -0
  43. data/test/outputter/rmagick_outputter_test.rb +83 -0
  44. data/test/outputter/svg_outputter_test.rb +89 -0
  45. data/test/outputter_test.rb +134 -0
  46. data/test/pdf_417_test.rb +45 -0
  47. data/test/qr_code_test.rb +78 -0
  48. data/test/test_helper.rb +24 -0
  49. data/test/upc_supplemental_test.rb +109 -0
  50. metadata +160 -19
  51. data/README +0 -93
  52. data/lib/barby/outputter/point_matrix.rb +0 -211
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+ require 'barby/barcode/code_128'
3
+ #require 'barby/outputter/html_outputter'
4
+
5
+ class HtmlOutputterTest < Barby::TestCase
6
+
7
+ class MockCode
8
+ attr_reader :encoding
9
+ def initialize(e)
10
+ @encoding = e
11
+ end
12
+ def two_dimensional?
13
+ encoding.is_a? Array
14
+ end
15
+ end
16
+
17
+ before do
18
+ load_outputter('html')
19
+ @barcode = Barby::Code128B.new('BARBY')
20
+ @outputter = HtmlOutputter.new(@barcode)
21
+ end
22
+
23
+ it "should register to_html" do
24
+ Barcode.outputters.must_include(:to_html)
25
+ end
26
+
27
+ it 'should have the expected start HTML' do
28
+ assert_equal '<table class="barby-barcode"><tbody>', @outputter.start
29
+ end
30
+
31
+ it 'should be able to set additional class name' do
32
+ @outputter.class_name = 'humbaba'
33
+ assert_equal '<table class="barby-barcode humbaba"><tbody>', @outputter.start
34
+ end
35
+
36
+ it 'should have the expected stop HTML' do
37
+ assert_equal '</tbody></table>', @outputter.stop
38
+ end
39
+
40
+ it 'should build the expected cells' do
41
+ assert_equal ['<td class="barby-cell on"></td>', '<td class="barby-cell off"></td>', '<td class="barby-cell off"></td>', '<td class="barby-cell on"></td>'],
42
+ @outputter.cells_for([true, false, false, true])
43
+ end
44
+
45
+ it 'should build the expected rows' do
46
+ assert_equal(
47
+ [
48
+ "<tr class=\"barby-row\">#{@outputter.cells_for([true, false]).join}</tr>",
49
+ "<tr class=\"barby-row\">#{@outputter.cells_for([false, true]).join}</tr>",
50
+ ],
51
+ @outputter.rows_for([[true, false],[false, true]])
52
+ )
53
+ end
54
+
55
+ it 'should have the expected rows' do
56
+ barcode = MockCode.new('101100')
57
+ outputter = HtmlOutputter.new(barcode)
58
+ assert_equal outputter.rows_for([[true, false, true, true, false, false]]), outputter.rows
59
+ barcode = MockCode.new(['101', '010'])
60
+ outputter = HtmlOutputter.new(barcode)
61
+ assert_equal outputter.rows_for([[true, false, true], [false, true, false]]), outputter.rows
62
+ end
63
+
64
+ it 'should have the expected html' do
65
+ assert_equal @outputter.start + @outputter.rows.join + @outputter.stop, @outputter.to_html
66
+ end
67
+
68
+ end
@@ -0,0 +1,37 @@
1
+ unless RUBY_VERSION >= '1.9'
2
+
3
+ require 'test_helper'
4
+ require 'pdf/writer'
5
+
6
+ class PDFWriterOutputterTest < Barby::TestCase
7
+
8
+ before do
9
+ load_outputter('pdfwriter')
10
+ @barcode = Barcode.new
11
+ def @barcode.encoding; '101100111000'; end
12
+ @outputter = PDFWriterOutputter.new(@barcode)
13
+ @pdf = PDF::Writer.new
14
+ end
15
+
16
+ it "should have registered annotate_pdf" do
17
+ Barcode.outputters.must_include(:annotate_pdf)
18
+ end
19
+
20
+ it "should have defined the annotate_pdf method" do
21
+ @outputter.must_respond_to(:annotate_pdf)
22
+ end
23
+
24
+ it "should return the pdf object it was given in annotate_pdf" do
25
+ @barcode.annotate_pdf(@pdf).object_id.must_equal @pdf.object_id
26
+ end
27
+
28
+ it "should have x, y, height and xdim attributes" do
29
+ @outputter.must_respond_to(:x)
30
+ @outputter.must_respond_to(:y)
31
+ @outputter.must_respond_to(:height)
32
+ @outputter.must_respond_to(:xdim)
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class PngTestBarcode < Barby::Barcode
4
+ def initialize(data)
5
+ @data = data
6
+ end
7
+ def encoding
8
+ @data
9
+ end
10
+ end
11
+
12
+ class PngOutputterTest < Barby::TestCase
13
+
14
+ before do
15
+ load_outputter('png')
16
+ @barcode = PngTestBarcode.new('10110011100011110000')
17
+ @outputter = PngOutputter.new(@barcode)
18
+ end
19
+
20
+ it "should register to_png and to_image" do
21
+ Barcode.outputters.must_include(:to_png)
22
+ Barcode.outputters.must_include(:to_image)
23
+ end
24
+
25
+ it "should return a ChunkyPNG::Datastream on to_datastream" do
26
+ @barcode.to_datastream.must_be_instance_of(ChunkyPNG::Datastream)
27
+ end
28
+
29
+ it "should return a string on to_png" do
30
+ @barcode.to_png.must_be_instance_of(String)
31
+ end
32
+
33
+ it "should return a ChunkyPNG::Image on to_canvas" do
34
+ @barcode.to_image.must_be_instance_of(ChunkyPNG::Image)
35
+ end
36
+
37
+ it "should have a width equal to Xdim * barcode_string.length" do
38
+ @outputter.width.must_equal @outputter.barcode.encoding.length * @outputter.xdim
39
+ end
40
+
41
+ it "should have a full_width which is the sum of width + (margin*2)" do
42
+ @outputter.full_width.must_equal @outputter.width + (@outputter.margin*2)
43
+ end
44
+
45
+ it "should have a full_height which is the sum of height + (margin*2)" do
46
+ @outputter.full_height.must_equal @outputter.height + (@outputter.margin*2)
47
+ end
48
+
49
+ end
@@ -0,0 +1,79 @@
1
+ require 'test_helper'
2
+
3
+ class PrawnOutputterTest < Barby::TestCase
4
+
5
+ before do
6
+ load_outputter('prawn')
7
+ @barcode = Barcode.new
8
+ def @barcode.encoding; '10110011100011110000'; end
9
+ @outputter = PrawnOutputter.new(@barcode)
10
+ end
11
+
12
+ it "should register to_pdf and annotate_pdf" do
13
+ Barcode.outputters.must_include(:to_pdf)
14
+ Barcode.outputters.must_include(:annotate_pdf)
15
+ end
16
+
17
+ it "should have a to_pdf method" do
18
+ @outputter.must_respond_to(:to_pdf)
19
+ end
20
+
21
+ it "should return a PDF document in a string on to_pdf" do
22
+ @barcode.to_pdf.must_be_instance_of(String)
23
+ end
24
+
25
+ it "should return the same Prawn::Document on annotate_pdf" do
26
+ doc = Prawn::Document.new
27
+ @barcode.annotate_pdf(doc).object_id.must_equal doc.object_id
28
+ end
29
+
30
+ it "should default x and y to margin value" do
31
+ @outputter.margin = 123
32
+ @outputter.x.must_equal 123
33
+ @outputter.y.must_equal 123
34
+ end
35
+
36
+ it "should default ydim to xdim value" do
37
+ @outputter.xdim = 321
38
+ @outputter.ydim.must_equal 321
39
+ end
40
+
41
+ it "should be able to calculate width required" do
42
+ @outputter.width.must_equal @barcode.encoding.length
43
+ @outputter.xdim = 2
44
+ @outputter.width.must_equal @barcode.encoding.length * 2
45
+ @outputter.full_width.must_equal @barcode.encoding.length * 2
46
+ @outputter.margin = 5
47
+ @outputter.full_width.must_equal((@barcode.encoding.length * 2) + 10)
48
+
49
+ #2D
50
+ barcode = Barcode2D.new
51
+ def barcode.encoding; ['111', '000', '111'] end
52
+ outputter = PrawnOutputter.new(barcode)
53
+ outputter.width.must_equal 3
54
+ outputter.xdim = 2
55
+ outputter.margin = 5
56
+ outputter.width.must_equal 6
57
+ outputter.full_width.must_equal 16
58
+ end
59
+
60
+ it "should be able to calculate height required" do
61
+ @outputter.full_height.must_equal @outputter.height
62
+ @outputter.margin = 5
63
+ @outputter.full_height.must_equal @outputter.height + 10
64
+
65
+ #2D
66
+ barcode = Barcode2D.new
67
+ def barcode.encoding; ['111', '000', '111'] end
68
+ outputter = PrawnOutputter.new(barcode)
69
+ outputter.height.must_equal 3
70
+ outputter.xdim = 2 #ydim defaults to xdim
71
+ outputter.margin = 5
72
+ outputter.height.must_equal 6
73
+ outputter.full_height.must_equal 16
74
+ outputter.ydim = 3 #ydim overrides xdim when set
75
+ outputter.height.must_equal 9
76
+ outputter.full_height.must_equal 19
77
+ end
78
+
79
+ end
@@ -0,0 +1,83 @@
1
+ require 'test_helper'
2
+
3
+ class RmagickTestBarcode < Barby::Barcode
4
+ def initialize(data)
5
+ @data = data
6
+ end
7
+ def encoding
8
+ @data
9
+ end
10
+ end
11
+
12
+ class RmagickOutputterTest < Barby::TestCase
13
+
14
+ before do
15
+ load_outputter('rmagick')
16
+ @barcode = RmagickTestBarcode.new('10110011100011110000')
17
+ @outputter = RmagickOutputter.new(@barcode)
18
+ end
19
+
20
+ it "should register to_png, to_gif, to_jpg, to_image" do
21
+ Barcode.outputters.must_include(:to_png)
22
+ Barcode.outputters.must_include(:to_gif)
23
+ Barcode.outputters.must_include(:to_jpg)
24
+ Barcode.outputters.must_include(:to_image)
25
+ end
26
+
27
+ it "should have defined to_png, to_gif, to_jpg, to_image" do
28
+ @outputter.must_respond_to(:to_png)
29
+ @outputter.must_respond_to(:to_gif)
30
+ @outputter.must_respond_to(:to_jpg)
31
+ @outputter.must_respond_to(:to_image)
32
+ end
33
+
34
+ it "should return a string on to_png and to_gif" do
35
+ @outputter.to_png.must_be_instance_of(String)
36
+ @outputter.to_gif.must_be_instance_of(String)
37
+ end
38
+
39
+ it "should return a Magick::Image instance on to_image" do
40
+ @outputter.to_image.must_be_instance_of(Magick::Image)
41
+ end
42
+
43
+ it "should have a width equal to the length of the barcode encoding string * x dimension" do
44
+ @outputter.xdim.must_equal 1#Default
45
+ @outputter.width.must_equal @outputter.barcode.encoding.length
46
+ @outputter.xdim = 2
47
+ @outputter.width.must_equal @outputter.barcode.encoding.length * 2
48
+ end
49
+
50
+ it "should have a full_width equal to the width + left and right margins" do
51
+ @outputter.xdim.must_equal 1
52
+ @outputter.margin.must_equal 10
53
+ @outputter.full_width.must_equal (@outputter.width + 10 + 10)
54
+ end
55
+
56
+ it "should have a default height of 100" do
57
+ @outputter.height.must_equal 100
58
+ @outputter.height = 200
59
+ @outputter.height.must_equal 200
60
+ end
61
+
62
+ it "should have a full_height equal to the height + top and bottom margins" do
63
+ @outputter.full_height.must_equal @outputter.height + (@outputter.margin * 2)
64
+ end
65
+
66
+ describe "#to_image" do
67
+
68
+ before do
69
+ @barcode = RmagickTestBarcode.new('10110011100011110000')
70
+ @outputter = RmagickOutputter.new(@barcode)
71
+ @image = @outputter.to_image
72
+ end
73
+
74
+ it "should have a width and height equal to the outputter's full_width and full_height" do
75
+ @image.columns.must_equal @outputter.full_width
76
+ @image.rows.must_equal @outputter.full_height
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+
@@ -0,0 +1,89 @@
1
+ require 'test_helper'
2
+
3
+ class SvgBarcode < Barby::Barcode
4
+ attr_accessor :data, :two_d
5
+ def initialize(data, two_d=false)
6
+ self.data, self.two_d = data, two_d
7
+ end
8
+ def encoding
9
+ data
10
+ end
11
+ def two_dimensional?
12
+ two_d
13
+ end
14
+ def to_s
15
+ data
16
+ end
17
+ end
18
+
19
+ class SvgOutputterTest < Barby::TestCase
20
+
21
+ before do
22
+ load_outputter('svg')
23
+ @barcode = SvgBarcode.new('10110011100011110000')
24
+ @outputter = SvgOutputter.new(@barcode)
25
+ end
26
+
27
+ it 'should register to_svg, bars_to_rects, and bars_to_path' do
28
+ Barcode.outputters.must_include :to_svg
29
+ Barcode.outputters.must_include :bars_to_rects
30
+ Barcode.outputters.must_include :bars_to_path
31
+ end
32
+
33
+ it 'should return a string on to_svg' do
34
+ @barcode.to_svg.must_be_instance_of String
35
+ end
36
+
37
+ it 'should return a string on bars_to_rects' do
38
+ @barcode.bars_to_rects.must_be_instance_of String
39
+ end
40
+
41
+ it 'should return a string on bars_to_path' do
42
+ @barcode.bars_to_path.must_be_instance_of String
43
+ end
44
+
45
+ it 'should produce one rect for each bar' do
46
+ @barcode.bars_to_rects.scan(/<rect/).size.must_equal @outputter.send(:boolean_groups).select{|bg|bg[0]}.size
47
+ end
48
+
49
+ it 'should produce one path stroke for each bar module' do
50
+ @barcode.bars_to_path.scan(/(M\d+\s+\d+)\s*(V\d+)/).size.must_equal @outputter.send(:booleans).select{|bg|bg}.size
51
+ end
52
+
53
+ it 'should return default values for attributes' do
54
+ @outputter.margin.must_be_instance_of Fixnum
55
+ end
56
+
57
+ it 'should use defaults to populate higher level attributes' do
58
+ @outputter.xmargin.must_equal @outputter.margin
59
+ end
60
+
61
+ it 'should return nil for overridden attributes' do
62
+ @outputter.xmargin = 1
63
+ @outputter.margin.must_equal nil
64
+ end
65
+
66
+ it 'should still use defaults for unspecified attributes' do
67
+ @outputter.xmargin = 1
68
+ @outputter.ymargin.must_equal @outputter.send(:_margin)
69
+ end
70
+
71
+ it 'should have a width equal to Xdim * barcode_string.length' do
72
+ @outputter.width.must_equal @outputter.barcode.encoding.length * @outputter.xdim
73
+ end
74
+
75
+ it 'should have a full_width which is by default the sum of width + (margin*2)' do
76
+ @outputter.full_width.must_equal @outputter.width + (@outputter.margin*2)
77
+ end
78
+
79
+ it 'should have a full_width which is the sum of width + xmargin + ymargin' do
80
+ @outputter.full_width.must_equal @outputter.width + @outputter.xmargin + @outputter.ymargin
81
+ end
82
+
83
+ it 'should use Barcode#to_s for title' do
84
+ @outputter.title.must_equal @barcode.data
85
+ def @barcode.to_s; "the eastern star"; end
86
+ @outputter.title.must_equal "the eastern star"
87
+ end
88
+
89
+ end
@@ -0,0 +1,134 @@
1
+ require 'test_helper'
2
+
3
+ class OutputterTest < Barby::TestCase
4
+
5
+ before do
6
+ @outputter = Class.new(Outputter)
7
+ end
8
+
9
+ it "should be able to register an output method for barcodes" do
10
+ @outputter.register :foo
11
+ Barcode.outputters.must_include(:foo)
12
+ @outputter.register :bar, :baz
13
+ Barcode.outputters.must_include(:bar)
14
+ Barcode.outputters.must_include(:baz)
15
+ @outputter.register :quux => :my_quux
16
+ Barcode.outputters.must_include(:quux)
17
+ end
18
+
19
+ describe "Outputter instances" do
20
+
21
+ before do
22
+ @barcode = Barcode.new
23
+ class << @barcode; attr_accessor :encoding; end
24
+ @barcode.encoding = '101100111000'
25
+ @outputter = Outputter.new(@barcode)
26
+ end
27
+
28
+ it "should have a method 'booleans' which converts the barcode encoding to an array of true,false values" do
29
+ @outputter.send(:booleans).length.must_equal @barcode.encoding.length
30
+ t, f = true, false
31
+ @outputter.send(:booleans).must_equal [t,f,t,t,f,f,t,t,t,f,f,f]
32
+ end
33
+
34
+ it "should convert 2D encodings with 'booleans'" do
35
+ barcode = Barcode2D.new
36
+ def barcode.encoding; ['101100','110010']; end
37
+ outputter = Outputter.new(barcode)
38
+ outputter.send(:booleans).length.must_equal barcode.encoding.length
39
+ t, f = true, false
40
+ outputter.send(:booleans).must_equal [[t,f,t,t,f,f], [t,t,f,f,t,f]]
41
+ end
42
+
43
+ it "should have an 'encoding' attribute" do
44
+ @outputter.send(:encoding).must_equal @barcode.encoding
45
+ end
46
+
47
+ it "should cache encoding" do
48
+ @outputter.send(:encoding).must_equal @barcode.encoding
49
+ previous_encoding = @barcode.encoding
50
+ @barcode.encoding = '101010'
51
+ @outputter.send(:encoding).must_equal previous_encoding
52
+ @outputter.send(:encoding, true).must_equal @barcode.encoding
53
+ end
54
+
55
+ it "should have a boolean_groups attribute which collects continuous bars and spaces" do
56
+ t, f = true, false
57
+ # 1 0 11 00 111 000
58
+ @outputter.send(:boolean_groups).must_equal [[t,1],[f,1],[t,2],[f,2],[t,3],[f,3]]
59
+
60
+ barcode = Barcode2D.new
61
+ def barcode.encoding; ['1100', '111000']; end
62
+ outputter = Outputter.new(barcode)
63
+ outputter.send(:boolean_groups).must_equal [[[t,2],[f,2]],[[t,3],[f,3]]]
64
+ end
65
+
66
+ it "should have a with_options method which sets the instance's attributes temporarily while the block gets yielded" do
67
+ class << @outputter; attr_accessor :foo, :bar; end
68
+ @outputter.foo, @outputter.bar = 'humbaba', 'scorpion man'
69
+ @outputter.send(:with_options, :foo => 'horse', :bar => 'donkey') do
70
+ @outputter.foo.must_equal 'horse'
71
+ @outputter.bar.must_equal 'donkey'
72
+ end
73
+ @outputter.foo.must_equal 'humbaba'
74
+ @outputter.bar.must_equal 'scorpion man'
75
+ end
76
+
77
+ it "should return the block value on with_options" do
78
+ @outputter.send(:with_options, {}){ 'donkey' }.must_equal 'donkey'
79
+ end
80
+
81
+ it "should have a two_dimensional? method which returns true if the barcode is 2d" do
82
+ refute Outputter.new(Barcode1D.new).send(:two_dimensional?)
83
+ assert Outputter.new(Barcode2D.new).send(:two_dimensional?)
84
+ end
85
+
86
+ it "should not require the barcode object to respond to two_dimensional?" do
87
+ barcode = Object.new
88
+ def barcode.encoding; "101100111000"; end
89
+ outputter = Outputter.new(barcode)
90
+ assert outputter.send(:booleans)
91
+ assert outputter.send(:boolean_groups)
92
+ end
93
+
94
+ end
95
+
96
+ describe "Barcode instances" do
97
+
98
+ before do
99
+ @outputter = Class.new(Outputter)
100
+ @outputter.register :foo
101
+ @outputter.register :bar => :my_bar
102
+ @outputter.class_eval{ def foo; 'foo'; end; def my_bar; 'bar'; end }
103
+ @barcode = Barcode.new
104
+ end
105
+
106
+ it "should respond to registered output methods" do
107
+ @barcode.foo.must_equal 'foo'
108
+ @barcode.bar.must_equal 'bar'
109
+ end
110
+
111
+ it "should send arguments to registered method on outputter class" do
112
+ @outputter.class_eval{ def foo(*a); a; end; def my_bar(*a); a; end }
113
+ @barcode.foo(1,2,3).must_equal [1,2,3]
114
+ @barcode.bar('humbaba').must_equal ['humbaba']
115
+ end
116
+
117
+ it "should pass block to registered methods" do
118
+ @outputter.class_eval{ def foo(*a, &b); b.call(*a); end }
119
+ @barcode.foo(1,2,3){|*a| a }.must_equal [1,2,3]
120
+ end
121
+
122
+ it "should be able to get an instance of a specific outputter" do
123
+ @barcode.outputter_for(:foo).must_be_instance_of(@outputter)
124
+ end
125
+
126
+ it "should be able to get a specific outputter class" do
127
+ @barcode.outputter_class_for(:foo).must_equal @outputter
128
+ end
129
+
130
+ end
131
+
132
+ end
133
+
134
+