zebra_printer 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+