zebra_printer 0.1.1

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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +85 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.rdoc +26 -0
  9. data/Rakefile +50 -0
  10. data/VERSION +1 -0
  11. data/features/ascii-text-rotation.feature +48 -0
  12. data/features/ascii-text-simple.feature +31 -0
  13. data/features/ascii-text-size.feature +44 -0
  14. data/features/barcode-code128.feature +59 -0
  15. data/features/barcode-datamatrix.feature +62 -0
  16. data/features/data.feature +17 -0
  17. data/features/position-epl2.feature +59 -0
  18. data/features/position-zpl2.feature +64 -0
  19. data/features/step_definitions/dsl_steps.rb +22 -0
  20. data/features/step_definitions/language_steps.rb +4 -0
  21. data/features/step_definitions/output_steps.rb +9 -0
  22. data/features/support/env.rb +1 -0
  23. data/lib/document_value.rb +4 -0
  24. data/lib/languages/epl2/barcode.rb +50 -0
  25. data/lib/languages/epl2/document.rb +27 -0
  26. data/lib/languages/epl2/font.rb +48 -0
  27. data/lib/languages/epl2/position.rb +11 -0
  28. data/lib/languages/epl2/text.rb +27 -0
  29. data/lib/languages/epl2.rb +78 -0
  30. data/lib/languages/generic/dots.rb +37 -0
  31. data/lib/languages/generic/integer.rb +5 -0
  32. data/lib/languages/generic/millimetres.rb +60 -0
  33. data/lib/languages/generic/position.rb +64 -0
  34. data/lib/languages/generic.rb +7 -0
  35. data/lib/languages/zpl2/barcode.rb +48 -0
  36. data/lib/languages/zpl2/document.rb +27 -0
  37. data/lib/languages/zpl2/font.rb +52 -0
  38. data/lib/languages/zpl2/position.rb +11 -0
  39. data/lib/languages/zpl2/text.rb +15 -0
  40. data/lib/languages/zpl2.rb +76 -0
  41. data/lib/languages.rb +8 -0
  42. data/lib/utils/array.rb +5 -0
  43. data/lib/zebra_printer.rb +4 -0
  44. data/lib/zebra_printer_document.rb +47 -0
  45. data/spec/lib/languages/epl2/barcode_1d_spec.rb +19 -0
  46. data/spec/lib/languages/epl2/barcode_2d_spec.rb +11 -0
  47. data/spec/lib/languages/epl2/barcode_factory_spec.rb +17 -0
  48. data/spec/lib/languages/epl2/document_spec.rb +23 -0
  49. data/spec/lib/languages/epl2/font_spec.rb +49 -0
  50. data/spec/lib/languages/epl2/position_spec.rb +9 -0
  51. data/spec/lib/languages/epl2/text_spec.rb +17 -0
  52. data/spec/lib/languages/generic/dots.rb +18 -0
  53. data/spec/lib/languages/generic/millimetres.rb +36 -0
  54. data/spec/lib/languages/generic/position_spec.rb +24 -0
  55. data/spec/lib/languages/languages.rb +18 -0
  56. data/spec/lib/languages/zpl2/barcode1d_spec.rb +18 -0
  57. data/spec/lib/languages/zpl2/barcode2d_spec.rb +11 -0
  58. data/spec/lib/languages/zpl2/barcode_factory_spec.rb +17 -0
  59. data/spec/lib/languages/zpl2/document_spec.rb +23 -0
  60. data/spec/lib/languages/zpl2/font_spec.rb +49 -0
  61. data/spec/lib/languages/zpl2/position_spec.rb +10 -0
  62. data/spec/lib/languages/zpl2/text_spec.rb +6 -0
  63. data/spec/lib/zebra_printer_document.rb +40 -0
  64. data/spec/spec_helper.rb +16 -0
  65. data/zebra_printer.gemspec +119 -0
  66. metadata +193 -0
@@ -0,0 +1,50 @@
1
+ module Languages
2
+ class Epl2
3
+ class BarcodeFactory
4
+ def self.create_barcode(code_type, opts = {})
5
+ if Barcode1D::BarcodeClasses.keys.include? code_type
6
+ Barcode1D.new code_type, opts
7
+ elsif Barcode2D::BarcodeClasses.keys.include? code_type
8
+ Barcode2D.new code_type, opts
9
+ else
10
+ raise ArgumentException.new("Unknown barcode: #{code_type}")
11
+ end
12
+ end
13
+ end
14
+ class Barcode1D
15
+ BarcodeClasses = {
16
+ code_128: ["1",2,2,50,"B"],
17
+ ean13: ["E30",2,2,50,"B"]
18
+ }
19
+ def initialize(code_type, opts = {})
20
+ @font = opts[:font] || Font.new
21
+ #defaults
22
+ @type,@nb_width,@wb_width,@height,@human_readable = BarcodeClasses[code_type]
23
+ opts[:at] = [0,0] unless opts.has_key? :at
24
+ @x, @y = opts[:at].pop(2)
25
+ @text = opts[:text] || ""
26
+ end
27
+
28
+ def render
29
+ "B#{@x},#{@y},#{@font.rotation},#{@type},#{@nb_width},#{@wb_width},#{@height},#{@human_readable},\"#{@text}\""
30
+ end
31
+ end
32
+
33
+ class Barcode2D
34
+ BarcodeClasses = {
35
+ data_matrix: ["D",16,16]
36
+ }
37
+ def initialize(code_type, opts = {})
38
+ @font = opts[:font] || Font.new
39
+ @type,@columns_encode,@rows_encode = BarcodeClasses[code_type]
40
+ @x = (opts[:at] || [0,0])[0]
41
+ @y = (opts[:at] || [0,0])[1]
42
+ @text = opts[:text] || ""
43
+ end
44
+
45
+ def render
46
+ "b#{@x},#{@y},#{@type},c#{@columns_encode},r#{@rows_encode},\"#{@text}\""
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,27 @@
1
+ module Languages
2
+ class Epl2
3
+ class Document
4
+ def initialize
5
+ @document = document_start.concat "\n"
6
+ end
7
+
8
+ def <<(obj)
9
+ string = obj.is_a?(String) ? obj : obj.render
10
+ string.concat "\n" unless string.end_with? "\n"
11
+ @document.concat string
12
+ end
13
+
14
+ def render
15
+ @document.concat(document_end).concat("\n")
16
+ end
17
+
18
+ def document_start
19
+ "N\n"
20
+ end
21
+
22
+ def document_end
23
+ "P1\n"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,48 @@
1
+ module Languages
2
+ class Epl2
3
+ class Font
4
+ attr_reader :name, :rotation, :height, :width
5
+
6
+ def initialize(opts = {})
7
+ # defaults
8
+ @name = opts[:name] || "2"
9
+ @rotation = opts.include?(:rotation) ? font_rotation(opts[:rotation]) : font_rotation(:by_0)
10
+ @height = opts[:height] || 1
11
+ @width = opts[:width] || 1
12
+ @name, @height, @width = font_size(opts[:size]) if opts.include?(:size)
13
+ end
14
+
15
+ def font_size(val)
16
+ case val
17
+ when :normal
18
+ [2,1,1]
19
+ when :small
20
+ [1,1,1]
21
+ when :large
22
+ [3,1,1]
23
+ when :x_large
24
+ [4,1,1]
25
+ else
26
+ [2,1,1]
27
+ end
28
+ end
29
+
30
+ def font_rotation(amount)
31
+ @rotation = case(amount)
32
+ when :by_90
33
+ 1
34
+ when :by_180
35
+ 2
36
+ when :by_270
37
+ 3
38
+ else
39
+ 0
40
+ end
41
+ end
42
+ def render
43
+ ""
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ module Languages
2
+ class Epl2
3
+ class Position
4
+ include Languages::Generic::Position
5
+
6
+ def render
7
+ ""
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ module Languages
2
+ class Epl2
3
+ class Text
4
+ attr_accessor :font, :text, :position
5
+
6
+ def initialize(opts = {})
7
+ # FIXME
8
+ @position = Languages::Epl2::Position[0,0]
9
+ @font = opts[:font] || Epl2::Font.new
10
+ @position = Languages::Epl2::Position.from_array(opts[:at]) if opts.has_key?(:at)
11
+ @text = ""
12
+ end
13
+
14
+ def render
15
+ "A#{@position},#{@font.rotation},#{@font.name},#{@font.height},#{@font.width},N,\"#{@text}\""
16
+ end
17
+
18
+ def x=(x)
19
+ @position.x = x
20
+ end
21
+
22
+ def y=(y)
23
+ @position.y = y
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,78 @@
1
+ require_relative 'epl2/font'
2
+ require_relative 'epl2/document'
3
+ require_relative 'epl2/text'
4
+ require_relative 'epl2/position'
5
+ require_relative 'epl2/barcode'
6
+ require_relative 'epl2/position'
7
+ require_relative '../utils/array'
8
+
9
+ module Languages
10
+ class Epl2
11
+ def initialize
12
+ @document = Epl2::Document.new
13
+ #defaults
14
+ @font = Epl2::Font.new
15
+ @position = Epl2::Position[0,0]
16
+ end
17
+
18
+ def document
19
+ @document.render
20
+ end
21
+
22
+ def text(value,opts={})
23
+ if opts.include? :at
24
+ opts[:at] = (@position + Epl2::Position.from_array(opts[:at])).to_a
25
+ else
26
+ opts[:at] = @position.to_a
27
+ end
28
+ @document << Epl2::Text.new(:font => @font, :at => opts[:at], :text => value)
29
+ end
30
+
31
+ def rotate(amount,&block)
32
+ if block_given?
33
+ save = @font
34
+ @font.font_rotation amount
35
+ self.instance_eval(&block)
36
+ @font = save
37
+ else
38
+ @font.font_rotation amount
39
+ end
40
+ end
41
+
42
+ def font(opts={},&block)
43
+ if opts.include? :size
44
+ @font = Epl2::Font.new(opts)
45
+ end
46
+ if block_given?
47
+ save = @font
48
+ @font = Epl2::Font.new(opts)
49
+ self.instance_eval(&block)
50
+ @font = save
51
+ end
52
+ end
53
+
54
+ def barcode(*args)
55
+ opts = args.extract_options!
56
+ code,text = args.pop 2
57
+
58
+ opts = opts.merge({:font => font,:text =>text})
59
+ if opts.include? :at
60
+ opts[:at] = (@position + Epl2::Position.from_array(opts[:at])).to_a
61
+ end
62
+
63
+ b = Epl2::BarcodeFactory.create_barcode code,opts
64
+ @document << b.render
65
+ end
66
+
67
+ def position(x,y,&block)
68
+ if block_given?
69
+ save = @position
70
+ @position = Epl2::Position[x,y]
71
+ self.instance_eval(&block)
72
+ @position = save
73
+ else
74
+ @position = Epl2::Position[x,y]
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ module Languages
2
+ module Generic
3
+ class Dots
4
+ def initialize(int)
5
+ @int = int
6
+ end
7
+
8
+ def to_i
9
+ @int
10
+ end
11
+
12
+ def +(other)
13
+ self.class.new(@int + value_of(other))
14
+ end
15
+
16
+ def -(other)
17
+ self.class.new(@int - value_of(other))
18
+ end
19
+
20
+ def ==(other)
21
+ @int == value_of(other)
22
+ end
23
+
24
+ def to_dots
25
+ self
26
+ end
27
+
28
+ def to_s
29
+ @int.to_s
30
+ end
31
+ private
32
+ def value_of(other)
33
+ v = other.respond_to?(:to_dots) ? other.to_dots.to_i : other.to_i
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ class Integer
2
+ def mm
3
+ Languages::Generic::Millimetres.new self
4
+ end
5
+ end
@@ -0,0 +1,60 @@
1
+ module Languages
2
+ module Generic
3
+ class Millimetres
4
+ def initialize(int)
5
+ @int = int
6
+ end
7
+
8
+ def to_i
9
+ @int
10
+ end
11
+
12
+ def +(other)
13
+ if other.is_a? Millimetres
14
+ self.class.new(@int + other.to_i)
15
+ elsif other.is_a? Integer
16
+ self.class.new(@int + other)
17
+ else
18
+ if other.respond_to? :coerce
19
+ a,b = other.coerce(self)
20
+ a + b
21
+ else
22
+ raise TypeError, "#{other.class} can't be coerced into #{self.class.name}"
23
+ end
24
+ end
25
+ end
26
+
27
+ def -(other)
28
+ if other.is_a? Millimetres
29
+ self.class.new(@int - other.to_i)
30
+ elsif other.is_a? Integer
31
+ self.class.new(@int - other)
32
+ else
33
+ if other.respond_to? :coerce
34
+ a,b = other.coerce(self)
35
+ a - b
36
+ else
37
+ raise TypeError, "#{other.class} can't be coerced into #{self.class.name}"
38
+ end
39
+ end
40
+ end
41
+
42
+ def ==(other)
43
+ @int == other.to_i
44
+ end
45
+
46
+ def coerce(other)
47
+ [Millimetres.new(other),self]
48
+ end
49
+
50
+ def to_dots(ratio = :dpi203)
51
+ dpm = if ratio == :dpi203
52
+ (203/25.4)
53
+ else
54
+ (300/25.4)
55
+ end
56
+ Languages::Generic::Dots.new((@int * dpm).round)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,64 @@
1
+ module Languages
2
+ module Generic
3
+ module Position
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def [](x,y)
10
+ o = new
11
+ o.x,o.y = x,y
12
+ o
13
+ end
14
+
15
+ def from_array(ary)
16
+ x, y = ary.pop(2)
17
+ x = Languages::Generic::Dots.new(x) if x.is_a? Integer
18
+ y = Languages::Generic::Dots.new(y) if y.is_a? Integer
19
+ o = new
20
+ o.x,o.y = x,y
21
+ o
22
+ end
23
+ end
24
+
25
+ attr_accessor :x, :y
26
+
27
+
28
+ def +(v)
29
+ case v
30
+ when Position
31
+ self.class[x+v.x,y+v.y]
32
+ end
33
+ end
34
+
35
+ def ==(v)
36
+ (x==v.x) && (y==v.y)
37
+ end
38
+
39
+ def x=(x)
40
+ if x.is_a? Integer
41
+ @x = Languages::Generic::Dots.new(x) if x.is_a? Integer
42
+ else
43
+ @x = x
44
+ end
45
+ end
46
+
47
+ def y=(y)
48
+ if y.is_a? Integer
49
+ @y = Languages::Generic::Dots.new(y) if y.is_a? Integer
50
+ else
51
+ @y = y
52
+ end
53
+ end
54
+
55
+ def to_a
56
+ [x,y]
57
+ end
58
+
59
+ def to_s
60
+ "#{x.to_dots},#{y.to_dots}"
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ module Languages::Generic
2
+ end
3
+
4
+ require_relative 'generic/position'
5
+ require_relative 'generic/dots'
6
+ require_relative 'generic/millimetres'
7
+ require_relative 'generic/integer'
@@ -0,0 +1,48 @@
1
+ module Languages
2
+ class Zpl2
3
+ class BarcodeFactory
4
+ def self.create_barcode(code_type, opts = {})
5
+ if Barcode1D::BarcodeClasses.keys.include? code_type
6
+ Barcode1D.new code_type,opts
7
+ elsif Barcode2D::BarcodeClasses.keys.include? code_type
8
+ Barcode2D.new code_type,opts
9
+ else
10
+ raise ArgumentException.new("Unknown barcode: #{code_type}")
11
+ end
12
+ end
13
+ end
14
+
15
+ class Barcode1D
16
+ BarcodeClasses = {
17
+ code_128: "BC",
18
+ ean13: "BE"
19
+ }
20
+ def initialize(code_type, opts = {})
21
+ @code = BarcodeClasses[code_type]
22
+ @font = opts[:font] || Font.new
23
+ @human_readable = opts[:human_readable] || "Y"
24
+ @text = opts[:text] || ""
25
+ end
26
+
27
+ def render
28
+ "^#{@code}#{@font.rotation},#{@font.height*2},#{@human_readable},N,N^FD#{@text}^FS"
29
+ end
30
+ end
31
+
32
+ class Barcode2D
33
+ BarcodeClasses = {
34
+ data_matrix: ["X",4,16,16]
35
+ }
36
+
37
+ def initialize(code_type, opts = {})
38
+ @font = opts[:font] || Font.new
39
+ @code, @symbol_height, @columns_encode, @rows_encode = BarcodeClasses[code_type]
40
+ @text = opts[:text] || ""
41
+ end
42
+
43
+ def render
44
+ "^B#{@code}#{@font.rotation},#{@symbol_height},200,#{@columns_encode},#{@rows_encode}^FD#{@text}^FS"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,27 @@
1
+ module Languages
2
+ class Zpl2
3
+ class Document
4
+ def initialize
5
+ @document = document_start.concat "\n"
6
+ end
7
+
8
+ def <<(obj)
9
+ string = obj.is_a?(String) ? obj : obj.render
10
+ string.concat "\n" unless string.end_with? "\n"
11
+ @document.concat string
12
+ end
13
+
14
+ def render
15
+ @document.concat(document_end).concat("\n")
16
+ end
17
+
18
+ def document_start
19
+ "^XA"
20
+ end
21
+
22
+ def document_end
23
+ "^XZ"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ module Languages
2
+ class Zpl2
3
+ class Font
4
+ attr_reader :name, :rotation, :height, :width
5
+
6
+ def initialize(opts = {})
7
+ # defaults
8
+ @name = opts[:name] || "B"
9
+ @rotation = opts.include?(:rotation) ? font_rotation(opts[:rotation]) : font_rotation(:by_0)
10
+ @height = opts[:height] || 15
11
+ @width = opts[:width] || 12
12
+ @name, @height, @width = font_size(opts[:size]) if opts.include?(:size)
13
+ @code = "^CF"
14
+ end
15
+
16
+ def font_args(opts={})
17
+ @name = font_size(opts[:size]) if opts.include? :size
18
+ end
19
+
20
+ def font_size(val)
21
+ case val
22
+ when :normal
23
+ ["0",25,25]
24
+ when :small
25
+ ["0",20,20]
26
+ when :large
27
+ ["0",40,40]
28
+ when :x_large
29
+ ["0",60,60]
30
+ else
31
+ ["0",25,25]
32
+ end
33
+ end
34
+
35
+ def font_rotation(amount)
36
+ @rotation = case(amount)
37
+ when :by_90
38
+ "R"
39
+ when :by_180
40
+ "I"
41
+ when :by_270
42
+ "B"
43
+ else
44
+ "N"
45
+ end
46
+ end
47
+ def render
48
+ "^CF#{@name}#{@rotation},#{@height},#{@width}\n"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ module Languages
2
+ class Zpl2
3
+ class Position
4
+ include Languages::Generic::Position
5
+
6
+ def render
7
+ "^FO#{x.to_dots},#{y.to_dots}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Languages
2
+ class Zpl2
3
+ class Text
4
+ # TODO Escape seqs
5
+
6
+ def initialize(string)
7
+ @string = string
8
+ end
9
+
10
+ def render
11
+ "^FD#{@string}^FS"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ require_relative 'zpl2/font'
2
+ require_relative 'zpl2/document'
3
+ require_relative 'zpl2/text'
4
+ require_relative 'zpl2/position'
5
+ require_relative 'zpl2/barcode'
6
+
7
+ module Languages
8
+ class Zpl2
9
+ def initialize
10
+ @document = Zpl2::Document.new
11
+ @font = Zpl2::Font.new
12
+ @position = Zpl2::Position[0,0]
13
+ @document << @position
14
+ end
15
+
16
+ def text(text,opts={})
17
+ if opts.include? :at
18
+ @document << (@position + Zpl2::Position.from_array(opts[:at]))
19
+ end
20
+ @document << Zpl2::Text.new(text)
21
+ @document << @position if opts.include?(:at)
22
+ end
23
+
24
+ def rotate(amount, &block)
25
+ if block_given?
26
+ @document << Zpl2::Font.new(:rotation => amount)
27
+ self.instance_eval &block
28
+ @document << @font
29
+ else
30
+ @font.font_rotation amount
31
+ @document << @font
32
+ end
33
+ end
34
+
35
+ def font(opts={},&block)
36
+ if block_given?
37
+ @document << Zpl2::Font.new(opts)
38
+ self.instance_eval &block
39
+ @document << @font
40
+ else
41
+ @font = Zpl2::Font.new(opts)
42
+ @document << @font
43
+ end
44
+ end
45
+
46
+ def barcode(*args)
47
+ opts = args.extract_options!
48
+ code,text = args.pop 2
49
+
50
+ opts = opts.merge({:font => @font,:text => text})
51
+
52
+ if opts.include? :at
53
+ @document << (@position + Zpl2::Position.from_array(opts[:at]))
54
+ end
55
+
56
+ @document << Zpl2::BarcodeFactory.create_barcode(code, opts)
57
+ end
58
+
59
+ def position(x,y,&block)
60
+ if block_given?
61
+ save = @position
62
+ @position = Zpl2::Position[x,y]
63
+ @document << @position
64
+ self.instance_eval(&block)
65
+ @position = save
66
+ else
67
+ @position = Zpl2::Position[x,y]
68
+ end
69
+ @document << @position
70
+ end
71
+
72
+ def document
73
+ @document.render
74
+ end
75
+ end
76
+ end
data/lib/languages.rb ADDED
@@ -0,0 +1,8 @@
1
+ module Languages
2
+
3
+ end
4
+
5
+ require_relative 'languages/generic'
6
+ require_relative 'languages/epl2'
7
+ require_relative 'languages/zpl2'
8
+
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def extract_options!
3
+ last.is_a?(::Hash) ? pop : {}
4
+ end unless defined? Array.new.extract_options!
5
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'languages'
2
+ require_relative 'zebra_printer_document'
3
+ require_relative 'document_value'
4
+