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.
- 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".
|