barby 0.6.2 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 25c48f523056303c71f3477a056906f12613bde3
4
- data.tar.gz: 1860f349c37684539345aef410f09a570a50f319
2
+ SHA256:
3
+ metadata.gz: 64d74091ea1f3aa79457c34878fc3b0d6f4c805dbb985d12eb372f29a7837e36
4
+ data.tar.gz: a8a61c1af0a401a1b36bc675653d2063e569443d434a57b5a2d95c7abfc1d193
5
5
  SHA512:
6
- metadata.gz: a793a5c6a5a5fba522ec2300ec703a3340edd5c45d249b9ca5d2056c2460555e6f4944c0cc4d9ccb8863f6a068a1aa2083f5f5181820d0c70b7a79d2c9cf2799
7
- data.tar.gz: f7acba5a08dea02a79c1620a2b4743e1b77a1f53469d83bf4d58229c5f5e618dc3f89959d2e858b8dbf80c0fef7ef33cfe211f5bdf28d750d9e578178d4bda6d
6
+ metadata.gz: 99143c0bf41695fa1416956073bcb6c9d7257c677fa36337638f890681665bacd51c4b04cd3412008592c8f23e4130fec74363eb425c776f8c827bf360d07c5b
7
+ data.tar.gz: d1b1f6aa2a63484b00f79bd184bef605b75850152dd54600b7eb25434f114c45c6994ce725af7535edefb8a536fc93f3e42c7d4bd2547c6f88d8da90d0947f8f
@@ -0,0 +1,2 @@
1
+ *.swp
2
+ Gemfile.lock
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ * 0.6.7
2
+
3
+ * RMagick outputter should use line command for lines [joshuaflanagan]
4
+
5
+ * 0.6.6
6
+
7
+ * Add support for Codabar symbology [labocho]
8
+
1
9
  * 0.6.1
2
10
 
3
11
  * Fix single-pixel error with RMagick [James Brink]
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gemspec
@@ -0,0 +1,108 @@
1
+ # Barby
2
+ Barby is a Ruby library that generates barcodes in a variety of symbologies.
3
+
4
+ Its functionality is split into _barcode_ and "_outputter_" objects:
5
+ * [`Barby::Barcode` objects] [symbologies] turn data into a binary representation for a given symbology.
6
+ * [`Barby::Outputter`] [outputters] then takes this representation and turns it into images, PDF, etc.
7
+
8
+ You can easily add a symbology without having to worry about graphical
9
+ representation. If it can be represented as the usual 1D or 2D matrix of
10
+ lines or squares, outputters will do that for you.
11
+
12
+ Likewise, you can easily add an outputter for a format that doesn't have one
13
+ yet, and it will work with all existing symbologies.
14
+
15
+ For more information, check out [the Barby wiki][wiki].
16
+
17
+
18
+ ### New require policy
19
+
20
+ Barcode symbologies are no longer required automatically, so you'll have to
21
+ require the ones you need.
22
+
23
+ If you need EAN-13, `require 'barby/barcode/ean_13'`. Full list of symbologies and filenames below.
24
+
25
+ ## Example
26
+
27
+ ```ruby
28
+ require 'barby'
29
+ require 'barby/barcode/code_128'
30
+ require 'barby/outputter/ascii_outputter'
31
+
32
+ barcode = Barby::Code128B.new('BARBY')
33
+
34
+ puts barcode.to_ascii #Implicitly uses the AsciiOutputter
35
+
36
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
37
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
38
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
39
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
40
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
41
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
42
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
43
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
44
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
45
+ ## # # # # ## # # ## ## # ### # # ## ### ## # ## ### ### ## ### # ##
46
+ B A R B Y
47
+ ```
48
+
49
+ ## Supported symbologies
50
+
51
+ ```ruby
52
+ require 'barby/barcode/<filename>'
53
+ ```
54
+
55
+ | Name | Filename | Dependencies |
56
+ | ----------------------------------- | --------------------- | ---------------------------------- |
57
+ | Code 25 | `code_25` | ─ |
58
+ | ├─ Interleaved | `code_25_interleaved` | ─ |
59
+ | └─ IATA | `code_25_iata` | ─ |
60
+ | Code 39 | `code_39` | ─ |
61
+ | └─ Extended | `code_39` | ─ |
62
+ | Code 93 | `code_93` | ─ |
63
+ | Code 128 (A, B, and C) | `code_128` | ─ |
64
+ | └─ GS1 128 | `gs1_128` | ─ |
65
+ | EAN-13 | `ean_13` | ─ |
66
+ | ├─ Bookland | `bookland` | ─ |
67
+ | └─ UPC-A | `ean_13` | ─ |
68
+ | EAN-8 | `ean_8` | ─ |
69
+ | UPC/EAN supplemental, 2 & 5 digits | `upc_supplemental` | ─ |
70
+ | QR Code | `qr_code` | `rqrcode` |
71
+ | DataMatrix (Semacode) | `data_matrix` | `semacode` or `semacode-ruby19` |
72
+ | PDF417 | `pdf_417` | JRuby |
73
+
74
+
75
+ ## Outputters
76
+
77
+ ```ruby
78
+ require 'barby/outputter/<filename>_outputter'
79
+ ```
80
+
81
+ | filename | dependencies |
82
+ | ----------- | ------------- |
83
+ | `ascii` | ─ |
84
+ | `cairo` | cairo |
85
+ | `html` | ─ |
86
+ | `pdfwriter` | ─ |
87
+ | `png` | chunky_png |
88
+ | `prawn` | prawn |
89
+ | `rmagick` | rmagick |
90
+ | `svg` | ─ |
91
+
92
+ ### Formats supported by outputters
93
+
94
+ * Text (mostly for testing)
95
+ * PNG, JPEG, GIF
96
+ * PS, EPS
97
+ * SVG
98
+ * PDF
99
+ * HTML
100
+
101
+ ---
102
+
103
+ For more information, check out [the Barby wiki][wiki].
104
+
105
+
106
+ [wiki]: https://github.com/toretore/barby/wiki
107
+ [symbologies]: https://github.com/toretore/barby/wiki/Symbologies
108
+ [outputters]: https://github.com/toretore/barby/wiki/Outputters
@@ -0,0 +1,15 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs = ['lib','test']
7
+ t.test_files = Dir.glob("test/**/*_test.rb").sort
8
+ t.verbose = true
9
+ end
10
+
11
+ RDoc::Task.new do |rdoc|
12
+ rdoc.main = "README"
13
+ rdoc.rdoc_files.include("README", "lib")
14
+ rdoc.rdoc_dir = 'doc'
15
+ end
@@ -0,0 +1,31 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "barby/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "barby"
6
+ s.version = Barby::VERSION::STRING
7
+ s.platform = Gem::Platform::RUBY
8
+ s.summary = "The Ruby barcode generator"
9
+ s.email = "toredarell@gmail.com"
10
+ s.homepage = "http://toretore.github.com/barby"
11
+ s.description = "Barby creates barcodes."
12
+ s.authors = ['Tore Darell']
13
+
14
+ s.rubyforge_project = "barby"
15
+
16
+ s.extra_rdoc_files = ["README.md"]
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.test_files.delete("test/outputter/rmagick_outputter_test.rb")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_development_dependency "minitest", "~> 5.11"
25
+ s.add_development_dependency "bundler", "~> 1.16"
26
+ s.add_development_dependency "rake", "~> 10.0"
27
+ s.add_development_dependency "semacode-ruby19", "~> 0.7"
28
+ s.add_development_dependency "rqrcode", "~> 0.10"
29
+ s.add_development_dependency "prawn", "~> 2.2"
30
+ s.add_development_dependency "cairo", "~> 1.15"
31
+ end
@@ -17,7 +17,7 @@ module Barby
17
17
  # '101100111000111100001'
18
18
  # end
19
19
  # end
20
- #
20
+ #
21
21
  # require 'barby/outputter/ascii_outputter'
22
22
  # puts StaticBarcode.new.to_ascii(:height => 3)
23
23
  #
@@ -33,8 +33,8 @@ module Barby
33
33
  # end
34
34
  # end
35
35
  class Barcode
36
-
37
-
36
+
37
+
38
38
  #Every barcode must have an encoding method. This method returns
39
39
  #a string containing a series of 1 and 0, representing bars and
40
40
  #spaces. One digit is the width of one "module" or X dimension.
@@ -132,7 +132,6 @@ module Barby
132
132
  end
133
133
 
134
134
  def inspect
135
- klass = (self.class.ancestors + [self.class.name]).join(':')
136
135
  "#<#{self.class}:0x#{'%014x' % object_id} #{formatted_isbn}>"
137
136
  end
138
137
 
@@ -0,0 +1,82 @@
1
+ require "barby/barcode"
2
+
3
+ module Barby
4
+ # https://en.wikipedia.org/wiki/Codabar
5
+ class Codabar < Barcode1D
6
+ BLACK_NARROW_WIDTH = 1
7
+ WHITE_NARROW_WIDTH = 2
8
+ WIDE_WIDTH_RATE = 3
9
+ SPACING = 5 # must be equal to or wider than white narrow width
10
+ CHARACTERS = "0123456789-$:/.+ABCD".freeze
11
+ # even: black, odd: white
12
+ # 0: narrow, 1: wide
13
+ BINARY_EXPRESSION = [
14
+ "0000011", # 0
15
+ "0000110", # 1
16
+ "0001001", # 2
17
+ "1100000", # 3
18
+ "0010010", # 4
19
+ "1000010", # 5
20
+ "0100001", # 6
21
+ "0100100", # 7
22
+ "0110000", # 8
23
+ "1001000", # 9
24
+ "0001100", # -
25
+ "0011000", # $
26
+ "1000101", # :
27
+ "1010001", # /
28
+ "1010100", # .
29
+ "0010101", # +
30
+ "0011010", # A
31
+ "0101001", # B
32
+ "0001011", # C
33
+ "0001110", # D
34
+ ].each(&:freeze)
35
+ CHARACTER_TO_BINARY = Hash[CHARACTERS.chars.zip(BINARY_EXPRESSION)].freeze
36
+ FORMAT = /\A[ABCD][0123456789\-\$:\/\.\+]+[ABCD]\z/.freeze
37
+ ONE = "1".freeze
38
+ ZERO = "0".freeze
39
+
40
+ attr_accessor :data, :black_narrow_width, :white_narrow_width, :wide_width_rate, :spacing
41
+
42
+ def initialize(data)
43
+ self.data = data
44
+ raise ArgumentError, 'data not valid' unless valid?
45
+
46
+ self.black_narrow_width = BLACK_NARROW_WIDTH
47
+ self.white_narrow_width = WHITE_NARROW_WIDTH
48
+ self.wide_width_rate = WIDE_WIDTH_RATE
49
+ self.spacing = SPACING
50
+ end
51
+
52
+ def encoding
53
+ data.chars.map{|c| binary_to_bars(CHARACTER_TO_BINARY[c]) }.join(ZERO * spacing)
54
+ end
55
+
56
+ def valid?
57
+ data =~ FORMAT
58
+ end
59
+
60
+ private
61
+ def binary_to_bars(bin)
62
+ bin.chars.each_with_index.map{|c, i|
63
+ black = i % 2 == 0
64
+ narrow = c == ZERO
65
+
66
+ if black
67
+ if narrow
68
+ ONE * black_narrow_width
69
+ else
70
+ ONE * (black_narrow_width * wide_width_rate).to_i
71
+ end
72
+ else
73
+ if narrow
74
+ ZERO * white_narrow_width
75
+ else
76
+ ZERO * (white_narrow_width * wide_width_rate).to_i
77
+ end
78
+ end
79
+ }.join
80
+ end
81
+ end
82
+ end
@@ -18,6 +18,14 @@ module Barby
18
18
  #As an example, here's one that starts out as type A and then switches to B and then C:
19
19
  #
20
20
  # Code128A.new("ABC123\306def\3074567")
21
+ #
22
+ #
23
+ #GS1-128/EAN-128/UCC-128
24
+ #
25
+ #To make a GS1-128 code, prefix the data with FNC1 and the Application Identifier:
26
+ #
27
+ # #AI=00, data=12345
28
+ # Code128.new("#{Code128::FNC1}0012345")
21
29
  class Code128 < Barcode1D
22
30
 
23
31
  FNC1 = "\xc1"
@@ -175,7 +183,7 @@ module Barby
175
183
 
176
184
 
177
185
  def type=(type)
178
- type.upcase!
186
+ type = type.upcase
179
187
  raise ArgumentError, 'type must be A, B or C' unless type =~ /^[ABC]$/
180
188
  @type = type
181
189
  end
@@ -230,7 +238,8 @@ module Barby
230
238
  #there are no more extras, the barcode ends with that object.
231
239
  #Most barcodes probably don't change charsets and don't have extras.
232
240
  def extra
233
- @extra
241
+ return @extra if defined?(@extra)
242
+ @extra = nil
234
243
  end
235
244
 
236
245
  #Set the extra for this barcode. The argument is a string starting with the
@@ -396,6 +405,9 @@ module Barby
396
405
  LOWR_RE = /[a-z]/
397
406
  DGTS_RE = /\d{4,}/
398
407
 
408
+ # pairs of digits and FNC1 characters
409
+ CODEC_CHARS_RE = /(?:\d{2}|#{FNC1}){2,}/
410
+
399
411
  class << self
400
412
 
401
413
 
@@ -415,7 +427,7 @@ module Barby
415
427
  #shortest encoding possible
416
428
  def apply_shortest_encoding_for_data(data)
417
429
  extract_codec(data).map do |block|
418
- if possible_codec_segment?(block)
430
+ if codec_segment?(block)
419
431
  "#{CODEC}#{block}"
420
432
  else
421
433
  if control_before_lowercase?(block)
@@ -445,25 +457,15 @@ module Barby
445
457
  # # C A or B C A or B
446
458
  # extract_codec("12345abc678910DEF11") => ["1234", "5abc", "678910", "DEF11"]
447
459
  def extract_codec(data)
448
- segments = data.split(/(\d{4,})/).reject(&:empty?)
449
- segments.each_with_index do |s,i|
450
- if possible_codec_segment?(s) && s.size.odd?
451
- if i == 0
452
- if segments[1]
453
- segments[1].insert(0, s.slice!(-1))
454
- else
455
- segments[1] = s.slice!(-1)
456
- end
457
- else
458
- segments[i-1].insert(-1, s.slice!(0)) if segments[i-1]
459
- end
460
- end
461
- end
462
- segments
460
+ data.split(/
461
+ (^(?:#{CODEC_CHARS_RE})) # matches digits that appear at the beginning of the barcode
462
+ |
463
+ ((?:#{CODEC_CHARS_RE})(?!\d)) # matches digits that appear later in the barcode
464
+ /x).reject(&:empty?)
463
465
  end
464
466
 
465
- def possible_codec_segment?(data)
466
- data =~ /\A\d{4,}\Z/
467
+ def codec_segment?(data)
468
+ data =~ /\A#{CODEC_CHARS_RE}\Z/
467
469
  end
468
470
 
469
471
  def control_character?(char)
@@ -28,11 +28,14 @@ module Barby
28
28
  9 => [N,W,N,W,N]
29
29
  }
30
30
 
31
- attr_accessor :data, :narrow_width, :wide_width, :space_width, :include_checksum
31
+ attr_accessor :include_checksum
32
+ attr_writer :narrow_width, :wide_width, :space_width
33
+ attr_reader :data
34
+
32
35
 
33
-
34
36
  def initialize(data)
35
37
  self.data = data
38
+ @narrow_width, @wide_width, @space_width = nil
36
39
  end
37
40
 
38
41
 
@@ -105,7 +108,7 @@ module Barby
105
108
  #Mod10
106
109
  def checksum
107
110
  evens, odds = even_and_odd_digits
108
- sum = odds.inject(0){|sum,d| sum + d } + evens.inject(0){|sum,d| sum + (d*3) }
111
+ sum = odds.inject(0){|s,d| s + d } + evens.inject(0){|s,d| s + (d*3) }
109
112
  sum %= 10
110
113
  sum.zero? ? 0 : 10-sum
111
114
  end
@@ -14,9 +14,9 @@ module Barby
14
14
 
15
15
 
16
16
  def digit_pairs(d=nil)
17
- (d || digits).inject [] do |ary,d|
17
+ (d || digits).inject [] do |ary,i|
18
18
  ary << [] if !ary.last || ary.last.size == 2
19
- ary.last << d
19
+ ary.last << i
20
20
  ary
21
21
  end
22
22
  end
@@ -87,7 +87,8 @@ module Barby
87
87
  START_ENCODING = [N,W,N,N,W,N,W,N,N] # *
88
88
  STOP_ENCODING = [N,W,N,N,W,N,W,N,N] # *
89
89
 
90
- attr_accessor :data, :spacing, :narrow_width, :wide_width, :extended, :include_checksum
90
+ attr_accessor :data, :extended, :include_checksum
91
+ attr_writer :spacing, :narrow_width, :wide_width
91
92
 
92
93
  # Do not surround "data" with the mandatory "*" as is this is done automically for you.
93
94
  # So instead of passing "*123456*" as "data", just pass "123456".
@@ -7,7 +7,7 @@ module Barby
7
7
  #Uses the semacode library (gem install semacode) to encode DataMatrix barcodes
8
8
  class DataMatrix < Barcode2D
9
9
 
10
- attr_accessor :data
10
+ attr_reader :data
11
11
 
12
12
 
13
13
  def initialize(data)