barby 0.6.2 → 0.6.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/CHANGELOG +8 -0
- data/Gemfile +5 -0
- data/README.md +108 -0
- data/Rakefile +15 -0
- data/barby.gemspec +31 -0
- data/lib/barby/barcode.rb +3 -3
- data/lib/barby/barcode/bookland.rb +0 -1
- data/lib/barby/barcode/codabar.rb +82 -0
- data/lib/barby/barcode/code_128.rb +22 -20
- data/lib/barby/barcode/code_25.rb +6 -3
- data/lib/barby/barcode/code_25_interleaved.rb +2 -2
- data/lib/barby/barcode/code_39.rb +2 -1
- data/lib/barby/barcode/data_matrix.rb +1 -1
- data/lib/barby/barcode/ean_13.rb +1 -1
- data/lib/barby/barcode/gs1_128.rb +5 -1
- data/lib/barby/barcode/qr_code.rb +2 -1
- data/lib/barby/outputter.rb +1 -1
- data/lib/barby/outputter/cairo_outputter.rb +16 -3
- data/lib/barby/outputter/png_outputter.rb +43 -7
- data/lib/barby/outputter/prawn_outputter.rb +12 -4
- data/lib/barby/outputter/rmagick_outputter.rb +43 -11
- data/lib/barby/outputter/svg_outputter.rb +11 -13
- data/lib/barby/version.rb +2 -2
- data/test/barcodes.rb +20 -0
- data/test/bookland_test.rb +54 -0
- data/test/codabar_test.rb +58 -0
- data/test/code_128_test.rb +470 -0
- data/test/code_25_iata_test.rb +19 -0
- data/test/code_25_interleaved_test.rb +116 -0
- data/test/code_25_test.rb +110 -0
- data/test/code_39_test.rb +210 -0
- data/test/code_93_test.rb +144 -0
- data/test/data_matrix_test.rb +30 -0
- data/test/ean13_test.rb +169 -0
- data/test/ean8_test.rb +100 -0
- data/test/outputter/cairo_outputter_test.rb +129 -0
- data/test/outputter/html_outputter_test.rb +68 -0
- data/test/outputter/pdfwriter_outputter_test.rb +37 -0
- data/test/outputter/png_outputter_test.rb +49 -0
- data/test/outputter/prawn_outputter_test.rb +79 -0
- data/test/outputter/rmagick_outputter_test.rb +83 -0
- data/test/outputter/svg_outputter_test.rb +89 -0
- data/test/outputter_test.rb +134 -0
- data/test/pdf_417_test.rb +45 -0
- data/test/qr_code_test.rb +78 -0
- data/test/test_helper.rb +24 -0
- data/test/upc_supplemental_test.rb +109 -0
- metadata +160 -19
- data/README +0 -93
- data/lib/barby/outputter/point_matrix.rb +0 -211
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 64d74091ea1f3aa79457c34878fc3b0d6f4c805dbb985d12eb372f29a7837e36
|
4
|
+
data.tar.gz: a8a61c1af0a401a1b36bc675653d2063e569443d434a57b5a2d95c7abfc1d193
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99143c0bf41695fa1416956073bcb6c9d7257c677fa36337638f890681665bacd51c4b04cd3412008592c8f23e4130fec74363eb425c776f8c827bf360d07c5b
|
7
|
+
data.tar.gz: d1b1f6aa2a63484b00f79bd184bef605b75850152dd54600b7eb25434f114c45c6994ce725af7535edefb8a536fc93f3e42c7d4bd2547c6f88d8da90d0947f8f
|
data/.gitignore
ADDED
data/CHANGELOG
CHANGED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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
|
data/barby.gemspec
ADDED
@@ -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
|
data/lib/barby/barcode.rb
CHANGED
@@ -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.
|
@@ -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
|
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
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
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
|
466
|
-
data =~ /\A
|
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 :
|
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){|
|
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
|
@@ -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, :
|
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".
|