barcode1dtools 1.0.1.0 → 1.0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,11 +20,26 @@ module Barcode1DTools
20
20
  # Because of this, there are no options for including a check
21
21
  # digit or validating one. It is always included.
22
22
  #
23
- # val = "29382-38"
24
- # bc = Barcode1DTools::Code128.new(val)
25
- # pattern = bc.bars
26
- # rle_pattern = bc.rle
27
- # width = bc.width
23
+ # Be sure to use Latin-1 (ISO-8859-1) in Ruby 1.9+ for any
24
+ # strings that use high characters. They will be encoded and
25
+ # decoded properly.
26
+ #
27
+ # == Example
28
+ # val = "This is a test"
29
+ # bc = Barcode1DTools::Code128.new(val)
30
+ # # Pass an array if you wish to use FNC characters
31
+ # val = [:fnc_1, "42184037211"]
32
+ # bc = Barcode1DTools::Code128.new(val)
33
+ # pattern = bc.bars
34
+ # rle_pattern = bc.rle
35
+ # width = bc.width
36
+ #
37
+ # It is possible to pass a raw value to be encoded by using the
38
+ # option :raw_value => true when creating the object. This
39
+ # must include the start character, string (each character
40
+ # being between 0 and 105 inclusive), the checksum character,
41
+ # and the stop character. No checks are performed on the
42
+ # string.
28
43
  #
29
44
  # The object created is immutable.
30
45
  #
@@ -34,21 +49,22 @@ module Barcode1DTools
34
49
  #
35
50
  # Code128 characters consist of 3 bars and 3 spaces.
36
51
  #
52
+ # == Formats
37
53
  # There are two formats for the returned pattern:
38
54
  #
39
- # bars - 1s and 0s specifying black lines and white spaces. Actual
40
- # characters can be changed from "1" and 0" with options
41
- # :line_character and :space_character.
55
+ # *bars* - 1s and 0s specifying black lines and white spaces. Actual
56
+ # characters can be changed from "1" and 0" with options
57
+ # :line_character and :space_character.
42
58
  #
43
- # rle - Run-length-encoded version of the pattern. The first
44
- # number is always a black line, with subsequent digits
45
- # alternating between spaces and lines. The digits specify
46
- # the width of each line or space.
59
+ # *rle* - Run-length-encoded version of the pattern. The first
60
+ # number is always a black line, with subsequent digits
61
+ # alternating between spaces and lines. The digits specify
62
+ # the width of each line or space.
47
63
  #
48
64
  # The "width" method will tell you the total end-to-end width, in
49
65
  # units, of the entire barcode.
50
66
  #
51
- #== Rendering
67
+ # == Rendering
52
68
  #
53
69
  # The quiet zone on each side should be at least the greater of 10
54
70
  # unit widths or 6.4mm. Typically a textual rendition of the
@@ -79,7 +95,7 @@ module Barcode1DTools
79
95
  '2331112'
80
96
  ]
81
97
 
82
- # Quicker decoding
98
+ # Helps with quicker decoding
83
99
  PATTERN_LOOKUP = (0..106).inject({}) { |a,c| a[PATTERNS[c]] = c; a }
84
100
 
85
101
  # For ease. These can also be looked up in any
@@ -98,11 +114,15 @@ module Barcode1DTools
98
114
  FNC_3 = 96
99
115
  # Note that FNC_4 is 100 in set B and 101 in set A
100
116
 
117
+ # Guard/start patterns
101
118
  GUARD_PATTERN_RIGHT_RLE = PATTERNS[STOP]
102
119
  START_A_RLE = PATTERNS[START_A]
103
120
  START_B_RLE = PATTERNS[START_B]
104
121
  START_C_RLE = PATTERNS[START_C]
105
122
 
123
+ # These are the standard labels for the low-ascii (0-31) characters.
124
+ # They aren't actually used here, but are included as they are
125
+ # useful for debugging.
106
126
  LOW_ASCII_LABELS = [
107
127
  'NUL', 'SOH', 'STX', 'ETX', 'EOT', 'ENQ', 'ACK', 'BEL',
108
128
  'BS', 'HT', 'LF', 'VT', 'FF', 'CR', 'SO', 'SI', 'DLE',
@@ -137,11 +157,17 @@ module Barcode1DTools
137
157
  }
138
158
 
139
159
  class << self
140
- # Code128 can encode anything
160
+ # Returns true if Code128 can encode the value.
161
+ # Code128 can encode anything, so this is always true.
141
162
  def can_encode?(value)
142
163
  true
143
164
  end
144
165
 
166
+ # Generates the check digit for the encoded string. Code 128
167
+ # creates the check digit based on the encoded value, so it's of
168
+ # no use outside of this module. Because the same payload may
169
+ # be represented in more than one way, the check digit can't be
170
+ # determined from the original payload value.
145
171
  def generate_check_digit_for(value)
146
172
  md = parse_code128(value)
147
173
  start = md[1].unpack('C')
@@ -149,30 +175,32 @@ module Barcode1DTools
149
175
  [md[2].unpack('C*').inject(start.first) { |a,c| (mult+=1)*c+a } % 103].pack('C')
150
176
  end
151
177
 
178
+ # Validates the check digit given an encoded value.
152
179
  def validate_check_digit_for(value)
153
180
  payload, check_digit = split_payload_and_check_digit(value)
154
181
  self.generate_check_digit_for(payload) == check_digit
155
182
  end
156
183
 
184
+ # Splits the payload (raw) and check digit.
157
185
  def split_payload_and_check_digit(value)
158
186
  md = value.to_s.match(/\A(.*)(.)\z/)
159
187
  [md[1], md[2]]
160
188
  end
161
189
 
162
- # Returns match data - 1: start character 2: payload
163
- # 3: check digit 4: stop character
190
+ # Given a raw encoded value, this returns match data -
191
+ # 1: start character 2: payload 3: check digit 4: stop
192
+ # character.
164
193
  def parse_code128(str)
165
194
  str.match(/\A([\x67-\x69])([\x00-\x66]*?)(?:([\x00-\x66])(\x6a))?\z/)
166
195
  end
167
196
 
168
197
  # Convert a code128 encoded string to an ASCII/Latin-1
169
- # representation. The return value is an array if there
170
- # are any FNC codes included. Use the option
171
- # :no_latin1 => true to simply return FNC 4 instead of
172
- # coding the following characters to the high Latin-1
198
+ # representation. The return value is an array Use the
199
+ # option :no_latin1 => true to simply return FNC 4 instead
200
+ # of coding the following characters to the high Latin-1
173
201
  # range. Use :raw_array => true if you wish to see an
174
- # array of the actual characters in the code. It will
175
- # turn any ASCII/Latin-1 characters to their standard
202
+ # array of the actual characters in the code. It will turn
203
+ # any ASCII/Latin-1 characters to their standard
176
204
  # representation, but it also includes all start, shift,
177
205
  # code change, etc. characters. Useful for debugging.
178
206
  def code128_to_latin1(str, options = {})
@@ -449,6 +477,7 @@ module Barcode1DTools
449
477
 
450
478
  end
451
479
 
480
+ # Create a new Code128 object given a value.
452
481
  # Options are :line_character, :space_character, and
453
482
  # :raw_value.
454
483
  def initialize(value, options = {})
@@ -488,22 +517,22 @@ module Barcode1DTools
488
517
  @check_digit = md[3]
489
518
  end
490
519
 
491
- # variable bar width, no w/n string
520
+ # Code 128 is variable bar width, no w/n string
492
521
  def wn
493
522
  raise NotImplementedError
494
523
  end
495
524
 
496
- # returns a run-length-encoded string representation
525
+ # Returns a run-length-encoded string representation
497
526
  def rle
498
527
  @rle ||= gen_rle(@encoded_string, @options)
499
528
  end
500
529
 
501
- # returns 1s and 0s (for "black" and "white")
530
+ # Returns 1s and 0s (for "black" and "white")
502
531
  def bars
503
532
  @bars ||= self.class.rle_to_bars(self.rle, @options)
504
533
  end
505
534
 
506
- # returns the total unit width of the bar code
535
+ # Returns the total unit width of the bar code
507
536
  def width
508
537
  @width ||= rle.split('').inject(0) { |a,c| a + c.to_i }
509
538
  end
@@ -22,14 +22,15 @@ module Barcode1DTools
22
22
  # dash "-", period ".", dollar sign "$", forward slash "/", plus
23
23
  # sign "+", percent sign "%", as well as a space " ".
24
24
  #
25
- # val = "THIS IS A TEST"
26
- # bc = Barcode1DTools::Code3of9.new(val)
27
- # pattern = bc.bars
28
- # rle_pattern = bc.rle
29
- # wn_pattern = bc.wn
30
- # width = bc.width
31
- # # Note that the check digit is actually one of the characters.
32
- # check_digit = Barcode1DTools::Code3of9.generate_check_digit_for(num)
25
+ # == Example
26
+ # val = "THIS IS A TEST"
27
+ # bc = Barcode1DTools::Code3of9.new(val)
28
+ # pattern = bc.bars
29
+ # rle_pattern = bc.rle
30
+ # wn_pattern = bc.wn
31
+ # width = bc.width
32
+ # # Note that the check digit is actually one of the characters.
33
+ # check_digit = Barcode1DTools::Code3of9.generate_check_digit_for(num)
33
34
  #
34
35
  # The object created is immutable.
35
36
  #
@@ -41,27 +42,28 @@ module Barcode1DTools
41
42
  # "wide" or "narrow", with "wide" lines or spaces being twice the
42
43
  # width of narrow lines or spaces.
43
44
  #
45
+ # == Formats
44
46
  # There are three formats for the returned pattern:
45
47
  #
46
- # bars - 1s and 0s specifying black lines and white spaces. Actual
47
- # characters can be changed from "1" and 0" with options
48
- # :line_character and :space_character.
48
+ # *bars* - 1s and 0s specifying black lines and white spaces. Actual
49
+ # characters can be changed from "1" and 0" with options
50
+ # :line_character and :space_character.
49
51
  #
50
- # rle - Run-length-encoded version of the pattern. The first
51
- # number is always a black line, with subsequent digits
52
- # alternating between spaces and lines. The digits specify
53
- # the width of each line or space.
52
+ # *rle* - Run-length-encoded version of the pattern. The first
53
+ # number is always a black line, with subsequent digits
54
+ # alternating between spaces and lines. The digits specify
55
+ # the width of each line or space.
54
56
  #
55
- # wn - The native format for this barcode type. The string
56
- # consists of a series of "w" and "n" characters. The first
57
- # item is always a black line, with subsequent characters
58
- # alternating between spaces and lines. A "wide" item
59
- # is twice the width of a "narrow" item.
57
+ # *wn* - The native format for this barcode type. The string
58
+ # consists of a series of "w" and "n" characters. The first
59
+ # item is always a black line, with subsequent characters
60
+ # alternating between spaces and lines. A "wide" item
61
+ # is twice the width of a "narrow" item.
60
62
  #
61
63
  # The "width" method will tell you the total end-to-end width, in
62
64
  # units, of the entire barcode.
63
65
  #
64
- #== Miscellaneous Information
66
+ # == Miscellaneous Information
65
67
  #
66
68
  # Code 3 of 9 can encode text and digits. There is also a way to do
67
69
  # "full ascii" mode, but it's not recommended. Full ascii mode uses
@@ -72,14 +74,14 @@ module Barcode1DTools
72
74
  # only for shifting. However, if you need to use a full character
73
75
  # set, Code 128 is probably a better choice.
74
76
  #
75
- # Note:
77
+ # *Note:*
76
78
  # Please note that Code 3 of 9 is not suggested for new applications
77
79
  # due to the fact that the code is sparse and doesn't encode a full
78
80
  # range of characters without using the "full ascii extensions",
79
81
  # which cause it to be even more sparse. For newer 1D applications
80
82
  # use Code 128.
81
83
  #
82
- #== Rendering
84
+ # == Rendering
83
85
  #
84
86
  # Code 3 of 9 may be rendered however the programmer wishes. Since
85
87
  # there is a simple mapping between number of characters and length of
@@ -145,8 +147,13 @@ module Barcode1DTools
145
147
  '%' => { 'position' => 42, 'wn' => 'nnnwnwnwn' }
146
148
  }
147
149
 
150
+ # Guard pattern
148
151
  SIDE_GUARD_PATTERN = 'nwnnwnwnn'
149
152
 
153
+ # This table is useful for implementing "full ascii" mode.
154
+ # It is a 128 element array that will return the character
155
+ # or characters to represent the ascii character at a
156
+ # particular code point.
150
157
  FULL_ASCII_LOOKUP = [
151
158
  '%U', '$A', '$B', '$C', '$D', '$E', '$F', '$G', '$H', '$I',
152
159
  '$J', '$K', '$L', '$M', '$N', '$O', '$P', '$Q', '$R', '$S',
@@ -163,6 +170,9 @@ module Barcode1DTools
163
170
  '%S', '%T'
164
171
  ]
165
172
 
173
+ # This is a reverse lookup. Given a character or character pair
174
+ # from a "full ascii" representation this will give the ascii
175
+ # code point as well as a character name.
166
176
  FULL_ASCII_REVERSE_LOOKUP = {
167
177
  '%U' => { 'position' => 0, 'name' => '<NUL>' },
168
178
  '$A' => { 'position' => 1, 'name' => '<SOH>' },
@@ -297,6 +307,7 @@ module Barcode1DTools
297
307
  '%Z' => { 'position' => 127, 'name' => '<DEL>' }
298
308
  }
299
309
 
310
+ # Default w/n ratio.
300
311
  WN_RATIO = 2
301
312
 
302
313
  DEFAULT_OPTIONS = {
@@ -309,7 +320,9 @@ module Barcode1DTools
309
320
  }
310
321
 
311
322
  class << self
312
- # returns true or false
323
+ # Returns true if the given value can be encoded
324
+ # in the Code 3 of 9 symbology. See CHAR_SEQUENCE
325
+ # for a full list of characters and their positions.
313
326
  def can_encode?(value)
314
327
  value.to_s =~ /\A[0-9A-Z\-\. \$\/\+%]*\z/
315
328
  end
@@ -325,7 +338,7 @@ module Barcode1DTools
325
338
  CHAR_SEQUENCE[sum % 43,1]
326
339
  end
327
340
 
328
- # validates the check digit given a string - assumes check digit
341
+ # Validates the check digit given a string - assumes check digit
329
342
  # is last digit of string.
330
343
  def validate_check_digit_for(value)
331
344
  raise UnencodableCharactersError unless self.can_encode?(value)
@@ -398,6 +411,7 @@ module Barcode1DTools
398
411
  end
399
412
  end
400
413
 
414
+ # Create a new Code3of9 barcode object.
401
415
  # Options are :line_character, :space_character, :w_character,
402
416
  # :n_character, :skip_checksum, and :checksum_included.
403
417
  def initialize(value, options = {})
@@ -432,17 +446,17 @@ module Barcode1DTools
432
446
  @wn ||= wn_str.tr('wn', @options[:w_character].to_s + @options[:n_character].to_s)
433
447
  end
434
448
 
435
- # returns a run-length-encoded string representation
449
+ # Returns a run-length-encoded string representation
436
450
  def rle
437
451
  @rle ||= self.class.wn_to_rle(self.wn, @options)
438
452
  end
439
453
 
440
- # returns 1s and 0s (for "black" and "white")
454
+ # Returns 1s and 0s (for "black" and "white")
441
455
  def bars
442
456
  @bars ||= self.class.rle_to_bars(self.rle, @options)
443
457
  end
444
458
 
445
- # returns the total unit width of the bar code
459
+ # Returns the total unit width of the bar code
446
460
  def width
447
461
  @width ||= rle.split('').inject(0) { |a,c| a + c.to_i }
448
462
  end
@@ -21,40 +21,42 @@ module Barcode1DTools
21
21
  # dash "-", period ".", dollar sign "$", forward slash "/", plus
22
22
  # sign "+", percent sign "%", as well as a space " ".
23
23
  #
24
- # val = "THIS IS A TEST"
25
- # bc = Barcode1DTools::Code93.new(val)
26
- # pattern = bc.bars
27
- # rle_pattern = bc.rle
28
- # width = bc.width
29
- # # Note that the check digits are actually two of the characters.
30
- # check_digit = Barcode1DTools::Code93.generate_check_digit_for(num)
24
+ # == Example
25
+ # val = "THIS IS A TEST"
26
+ # bc = Barcode1DTools::Code93.new(val)
27
+ # pattern = bc.bars
28
+ # rle_pattern = bc.rle
29
+ # width = bc.width
30
+ # # Note that the check digits are actually two of the characters.
31
+ # check_digit = Barcode1DTools::Code93.generate_check_digit_for(num)
31
32
  #
32
33
  # The object created is immutable.
33
34
  #
34
35
  # Barcode1DTools::Code93 creates the patterns that you need to
35
- # display Code 93 barcodes. It can also decode a simple w/n
36
+ # display Code 93 barcodes. It can also decode a simple rle
36
37
  # string.
37
38
  #
38
39
  # Code 93 barcodes consist of lines and spaces that are from
39
40
  # one to four units wide each. A particular character has 3 bars
40
41
  # and 3 spaces.
41
42
  #
43
+ # == Formats
42
44
  # There are two formats for the returned pattern:
43
45
  #
44
- # bars - 1s and 0s specifying black lines and white spaces. Actual
45
- # characters can be changed from "1" and 0" with options
46
- # :line_character and :space_character.
46
+ # *bars* - 1s and 0s specifying black lines and white spaces. Actual
47
+ # characters can be changed from "1" and 0" with options
48
+ # :line_character and :space_character.
47
49
  #
48
- # rle - Run-length-encoded version of the pattern. The first
49
- # number is always a black line, with subsequent digits
50
- # alternating between spaces and lines. The digits specify
51
- # the width of each line or space.
50
+ # *rle* - Run-length-encoded version of the pattern. The first
51
+ # number is always a black line, with subsequent digits
52
+ # alternating between spaces and lines. The digits specify
53
+ # the width of each line or space.
52
54
  #
53
55
  # The "width" method will tell you the total end-to-end width, in
54
56
  # units, of the entire barcode. Note that the w/n format is
55
57
  # unavailable for this symbology.
56
58
  #
57
- #== Miscellaneous Information
59
+ # == Miscellaneous Information
58
60
  #
59
61
  # Code 93 can encode any ascii character from 0 to 127. The design
60
62
  # is identical to Code 3 of 9 in most respects, with the main
@@ -76,7 +78,7 @@ module Barcode1DTools
76
78
  # Internally, the four shift characters are represented as characters
77
79
  # 128 "($)", 129 "(%)", 130 "(/)", and 131 "(+)".
78
80
  #
79
- #== Rendering
81
+ # == Rendering
80
82
  #
81
83
  # Code 93 may be rendered however the programmer wishes. Since
82
84
  # there is a simple mapping between number of characters and length of
@@ -146,12 +148,17 @@ module Barcode1DTools
146
148
  "\x83" => {'position' => 46, 'display' => '(+)', 'rle' => '122211', 'bars' => '100110010'},
147
149
  }
148
150
 
149
- # Note that the right side has another thin line
151
+ # Left guard pattern
150
152
  LEFT_GUARD_PATTERN = '101011110'
153
+ # Left guard pattern as an RLE string
151
154
  LEFT_GUARD_PATTERN_RLE = '111141'
155
+ # Right guard pattern - just the left pattern with another bar
152
156
  RIGHT_GUARD_PATTERN = LEFT_GUARD_PATTERN + '1'
157
+ # Right guard pattern as RLE - just the left pattern with another bar
153
158
  RIGHT_GUARD_PATTERN_RLE = LEFT_GUARD_PATTERN_RLE + '1'
154
159
 
160
+ # This is a lookup table for the full ASCII mode. Index this with an ascii
161
+ # codepoint to get a one or two character representation of any character.
155
162
  FULL_ASCII_LOOKUP = [
156
163
  "\x81U", "\x80A", "\x80B", "\x80C", "\x80D", "\x80E", "\x80F", "\x80G", "\x80H", "\x80I",
157
164
  "\x80J", "\x80K", "\x80L", "\x80M", "\x80N", "\x80O", "\x80P", "\x80Q", "\x80R", "\x80S",
@@ -168,6 +175,8 @@ module Barcode1DTools
168
175
  "\x81S", "\x81T"
169
176
  ]
170
177
 
178
+ # This is the reverse lookup. Given a character or character pair you
179
+ # can find the ascii value.
171
180
  FULL_ASCII_REVERSE_LOOKUP = {
172
181
  "\x81U" => { 'position' => 0, 'name' => '<NUL>' },
173
182
  "\x80A" => { 'position' => 1, 'name' => '<SOH>' },
@@ -308,7 +317,10 @@ module Barcode1DTools
308
317
  :force_full_ascii => false
309
318
  }
310
319
 
320
+ # Set to true if the string is using the "full ascii" representation.
311
321
  attr_accessor :full_ascii
322
+ # If full_ascii is true, this is the encoded string including the
323
+ # shift characters. Otherwise, it is the same as "value".
312
324
  attr_accessor :full_ascii_value
313
325
 
314
326
  class << self
@@ -317,6 +329,8 @@ module Barcode1DTools
317
329
  value.to_s =~ /\A[\x00-\x7f]*\z/
318
330
  end
319
331
 
332
+ # Returns true if the given value has characters that
333
+ # fall outside the native range.
320
334
  def requires_full_ascii?(value)
321
335
  value.to_s !~ /\A[0-9A-Z\-\. \$\/\+%]*\z/
322
336
  end
@@ -336,7 +350,7 @@ module Barcode1DTools
336
350
  "#{check_c}#{check_k}"
337
351
  end
338
352
 
339
- # validates the check digit given a string - assumes check digit
353
+ # Validates the check digit given a string - assumes check digit
340
354
  # is last digit of string.
341
355
  def validate_check_digit_for(value)
342
356
  md = value.to_s.match(/^(.*)(..)$/)
@@ -400,7 +414,7 @@ module Barcode1DTools
400
414
  str.bytes.collect { |c| FULL_ASCII_LOOKUP[c] }.join
401
415
  end
402
416
 
403
- # Decodes a "full ascii" string from Code 3 of 9 into standard
417
+ # Decodes a "full ascii" string from Code 93 into standard
404
418
  # ascii. Note that this will silently fail if a string is
405
419
  # malformed.
406
420
  def decode_full_ascii(str)
@@ -412,6 +426,7 @@ module Barcode1DTools
412
426
  end
413
427
  end
414
428
 
429
+ # Create a new Code93 barcode object.
415
430
  # Options are :line_character, :space_character, :force_full_ascii,
416
431
  # and :checksum_included.
417
432
  def initialize(value, options = {})
@@ -444,30 +459,30 @@ module Barcode1DTools
444
459
  end
445
460
  end
446
461
 
447
- # Returns a string of "w" or "n" ("wide" and "narrow")
462
+ # Returns a string of "w" or "n" ("wide" and "narrow"). For Code93 this
463
+ # simply raises a NotImplementedError.
448
464
  def wn
449
465
  raise NotImplementedError
450
466
  end
451
467
 
452
- # returns a run-length-encoded string representation
468
+ # Returns a run-length-encoded string representation
453
469
  def rle
454
470
  @rle ||= gen_rle(@encoded_string)
455
471
  end
456
472
 
457
- # returns 1s and 0s (for "black" and "white")
473
+ # Returns 1s and 0s (for "black" and "white")
458
474
  def bars
459
475
  @bars ||= self.class.rle_to_bars(self.rle, @options)
460
476
  end
461
477
 
462
- # returns the total unit width of the bar code
478
+ # Returns the total unit width of the bar code
463
479
  def width
464
480
  @width ||= rle.split('').inject(0) { |a,c| a + c.to_i }
465
481
  end
466
482
 
467
483
  private
468
484
 
469
- # Creates the actual w/n pattern. Note that there is a narrow space
470
- # between each character.
485
+ # Creates the actual rle pattern.
471
486
  def gen_rle(str)
472
487
  @rle_str ||=
473
488
  ([LEFT_GUARD_PATTERN_RLE] +