labels 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'tempfile'
8
+ require 'base64'
9
+ require 'uuid'
10
+
11
+ require 'labels/layer'
12
+
13
+ module Labels
14
+
15
+ # This class represents date layers.
16
+ class Image < Layer
17
+
18
+ # Whether or not to fit image to layer width and height
19
+ attr_accessor :fit
20
+
21
+ # Whether or not to stretch image to layer width and height
22
+ attr_accessor :stretch
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'prawn'
8
+
9
+ require 'labels/layer'
10
+
11
+ module Labels
12
+
13
+ # This class represents the base class for all layer types.
14
+ class Layer < Element
15
+
16
+ # Title of layer
17
+ attr_accessor :title
18
+
19
+ # Type of layer
20
+ attr_accessor :type
21
+
22
+ # Column from data set to use as replacement content
23
+ attr_accessor :column
24
+
25
+ # Whether or not layer is locked
26
+ attr_accessor :locked
27
+
28
+ # Whether or not layer is visible
29
+ attr_accessor :visible
30
+
31
+ # Whether or not layer is resizable
32
+ attr_accessor :resizable
33
+
34
+ # X position of layer in pixels
35
+ attr_accessor :x
36
+
37
+ # Y position of layer in pixels
38
+ attr_accessor :y
39
+
40
+ # Z position of layer in pixels
41
+ attr_accessor :z
42
+
43
+ # Width of layer in pixels
44
+ attr_accessor :width
45
+
46
+ # Height of layer in pixels
47
+ attr_accessor :height
48
+
49
+ # Alpha (transparency) of layer
50
+ attr_accessor :alpha
51
+
52
+ # Rotation of layer in degrees
53
+ attr_accessor :rotation
54
+
55
+ # Data content of layer
56
+ attr_accessor :content
57
+ end
58
+ end
@@ -0,0 +1,29 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'labels/element'
8
+
9
+ module Labels
10
+
11
+ # This class represents paper types and dimensions.
12
+ class Paper < Element
13
+ LETTER = {:title => 'Letter', :width => 612, :height => 792}
14
+ LEGAL = {:title => 'Legal', :width => 612, :height => 1008}
15
+ LEDGER = {:title => 'Ledger', :width => 792, :height => 1224}
16
+ A5 = {:title => 'A5', :width => 420, :height => 595}
17
+ A4 = {:title => 'A4', :width => 595, :height => 842}
18
+ A3 = {:title => 'A3', :width => 842, :height => 1191}
19
+
20
+ # Title of paper type
21
+ attr_accessor :title
22
+
23
+ # Width of paper in pixels
24
+ attr_accessor :width
25
+
26
+ # Height of paper in pixels
27
+ attr_accessor :height
28
+ end
29
+ end
@@ -0,0 +1,332 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'labels/document'
8
+ require 'labels/paper'
9
+ require 'labels/template'
10
+ require 'labels/shape'
11
+ require 'labels/text'
12
+ require 'labels/image'
13
+ require 'labels/barcode'
14
+ require 'labels/date'
15
+
16
+ require 'prawn'
17
+
18
+ module Labels
19
+ module PDF
20
+
21
+ # This class builds a PDF document from the given Labels::Document
22
+ class Builder
23
+
24
+ # The document instance
25
+ attr_accessor :document
26
+
27
+ # Creates a new Labels::PDF::Builder instance
28
+ def initialize(document=nil)
29
+ @document = document
30
+ end
31
+
32
+ # Renders the PDF and optionally saves to given filename
33
+ def render(filename=nil)
34
+ unless filename.nil?
35
+ self.pdf.render_file filename
36
+ else
37
+ self.pdf.render
38
+ end
39
+ end
40
+
41
+ # Returns the rendered PDF document
42
+ def pdf
43
+ unless @document.nil?
44
+ paper = @document.paper
45
+ template = @document.template
46
+ data = @document.data
47
+
48
+ if paper && template
49
+ document_options = {
50
+ :page_size => [paper.width, paper.height],
51
+ :left_margin => template.left_margin,
52
+ :right_margin => template.right_margin,
53
+ :top_margin => template.top_margin,
54
+ :bottom_margin => template.bottom_margin
55
+ }
56
+
57
+ page_cell_count = template.columns * template.rows
58
+ page_number_count = (data.length / page_cell_count).ceil
59
+ cell = 0
60
+
61
+ if page_number_count == 0
62
+ page_number_count += 1
63
+ end
64
+
65
+ Prawn::Document.new document_options do |pdf|
66
+ page_number_count.times do |page|
67
+ if page > 0
68
+ pdf.start_new_page
69
+ end
70
+
71
+ pdf.define_grid({
72
+ :columns => template.columns,
73
+ :rows => template.rows,
74
+ :column_gutter => template.vertical_gutter,
75
+ :row_gutter => template.horizontal_gutter
76
+ })
77
+
78
+ # Draw template
79
+ pdf.grid.rows.times do |i|
80
+ pdf.grid.columns.times do |j|
81
+ box = pdf.grid(i,j)
82
+ pdf.bounding_box box.top_left, :width => box.width, :height => box.height do
83
+ self._draw_template(pdf, template)
84
+ end
85
+ end
86
+ end
87
+
88
+ # Draw layers
89
+ pdf.grid.rows.times do |i|
90
+ pdf.grid.columns.times do |j|
91
+ box = pdf.grid(i,j)
92
+ pdf.bounding_box box.top_left, :width => box.width, :height => box.height do
93
+ layers = @document.layers.sort {|x,y| x.z <=> y.z}
94
+ layers.each do |layer|
95
+
96
+ draw = false
97
+ content = nil
98
+ if data.length > 0
99
+ if cell < data.length
100
+ if data[cell].has_key?(layer.column)
101
+ content = data[cell][layer.column]
102
+ end
103
+ draw = true
104
+ end
105
+ else
106
+ draw = true
107
+ end
108
+
109
+ if draw
110
+ case layer
111
+ when Labels::Barcode
112
+ self._draw_barcode(pdf, layer, content)
113
+ when Labels::Date
114
+ self._draw_date(pdf, layer, content)
115
+ when Labels::Image
116
+ self._draw_image(pdf, layer, content)
117
+ when Labels::Shape
118
+ self._draw_shape(pdf, layer, content)
119
+ when Labels::Text
120
+ self._draw_text(pdf, layer, content)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ cell += 1
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ # Draws the given barcode layer with optional content
137
+ def _draw_barcode(pdf, layer, content=nil)
138
+ if pdf.kind_of?(Prawn::Document) && layer.visible
139
+ pdf.save_graphics_state
140
+
141
+ origin = {:x => layer.x, :y => pdf.bounds.top - layer.y}
142
+ center = {:x => origin[:x] + (layer.width * 0.5), :y => origin[:y] - (layer.height * 0.5)}
143
+
144
+ pdf.rotate(layer.rotation, :origin => [center[:x], center[:y]]) do
145
+ pdf.transparent layer.alpha do
146
+ begin
147
+ options = {
148
+ :bar_width => layer.bar_width,
149
+ :bar_height => layer.bar_height,
150
+ :color => layer.color,
151
+ :caption_height => layer.caption_height,
152
+ :caption_size => layer.caption_size,
153
+ :captioned => layer.captioned
154
+ }
155
+
156
+ unless content.nil?
157
+ options[:data] = content
158
+ else
159
+ options[:data] = layer.content
160
+ end
161
+
162
+ barcode = Barcodes.create(layer.symbology, options)
163
+ renderer = Barcodes::Renderer::Pdf.new(barcode)
164
+
165
+ barcode_width = ((barcode.width * 0.001) * 72.0)
166
+ barcode_height = ((barcode.height * 0.001) * 72.0)
167
+
168
+ pdf.bounding_box [origin[:x], origin[:y]], :width => layer.width, :height => layer.height do
169
+ renderer.draw(pdf)
170
+ end
171
+ rescue
172
+ # Barcode error... render nothin
173
+ end
174
+ end
175
+ end
176
+
177
+ pdf.restore_graphics_state
178
+ end
179
+ end
180
+
181
+ # Draws the given date layer with optional content
182
+ def _draw_date(pdf, layer, content=nil)
183
+ if content.nil?
184
+ content = layer.content
185
+ end
186
+
187
+ begin
188
+ content = Time.parse(content).strftime(layer.format)
189
+ rescue
190
+ content = Time.now.strftime(layer.format)
191
+ end
192
+
193
+ self._draw_text(pdf, layer, content)
194
+ end
195
+
196
+ # Draws the given image layer with optional content
197
+ def _draw_image(pdf, layer, content=nil)
198
+ if pdf.kind_of?(Prawn::Document) && layer.visible
199
+ pdf.save_graphics_state
200
+
201
+ origin = {:x => layer.x, :y => pdf.bounds.top - layer.y}
202
+ center = {:x => origin[:x] + (layer.width * 0.5), :y => origin[:y] - (layer.height * 0.5)}
203
+
204
+ pdf.rotate(layer.rotation, :origin => [center[:x], center[:y]]) do
205
+ pdf.transparent layer.alpha do
206
+ begin
207
+ unless content.nil?
208
+ content = Base64.decode64(content)
209
+ else
210
+ content = Base64.decode64(layer.content)
211
+ end
212
+
213
+ temp = Tempfile.new(UUID.generate)
214
+ temp.write(content)
215
+ temp.rewind
216
+
217
+ options = {
218
+ :at => [origin[:x], origin[:y]]
219
+ }
220
+ if layer.fit
221
+ options[:fit] = [layer.width, layer.height]
222
+ end
223
+ if layer.stretch
224
+ options[:width] = layer.width
225
+ options[:height] = layer.height
226
+ end
227
+ pdf.image temp, options
228
+
229
+ temp.close
230
+ temp.unlink
231
+ rescue
232
+ # Image error... render nothin
233
+ end
234
+ end
235
+ end
236
+
237
+ pdf.restore_graphics_state
238
+ end
239
+ end
240
+
241
+ # Draws the given shape layer with optional content
242
+ def _draw_shape(pdf, layer, content=nil)
243
+ if pdf.kind_of?(Prawn::Document) && layer.visible
244
+ pdf.save_graphics_state
245
+
246
+ pdf.fill_color layer.fill_color
247
+ pdf.stroke_color layer.stroke_color
248
+ pdf.line_width layer.stroke_weight
249
+
250
+ origin = {:x => layer.x, :y => pdf.bounds.top - layer.y}
251
+ center = {:x => origin[:x] + (layer.width * 0.5), :y => origin[:y] - (layer.height * 0.5)}
252
+
253
+ pdf.rotate(layer.rotation, :origin => [center[:x], center[:y]]) do
254
+ pdf.transparent layer.alpha do
255
+ unless layer.elliptical
256
+ pdf.rounded_rectangle([origin[:x], origin[:y]], layer.width, layer.height, layer.corner_radius)
257
+ else
258
+ pdf.ellipse([center[:x], center[:y]], layer.width * 0.5, layer.height * 0.5)
259
+ end
260
+
261
+ pdf.fill_and_stroke if layer.fill && layer.stroke
262
+ pdf.stroke if layer.stroke
263
+ pdf.fill if layer.fill
264
+ end
265
+ end
266
+
267
+ pdf.restore_graphics_state
268
+ end
269
+ end
270
+
271
+ # Draws the given template
272
+ def _draw_template(pdf, template)
273
+ if pdf.kind_of?(Prawn::Document) && template.visible
274
+ pdf.save_graphics_state
275
+
276
+ if template.visible
277
+ pdf.stroke do
278
+ unless template.elliptical
279
+ pdf.rounded_rectangle(pdf.bounds.top_left, template.width, template.height, template.corner_radius)
280
+ else
281
+ x = pdf.bounds.left + (pdf.bounds.width * 0.5)
282
+ y = pdf.bounds.bottom + (pdf.bounds.height * 0.5)
283
+ pdf.ellipse([x, y], template.width * 0.5, template.height * 0.5)
284
+ end
285
+ end
286
+ end
287
+
288
+ pdf.restore_graphics_state
289
+ end
290
+ end
291
+
292
+ # Draws the given text layer with optional content
293
+ def _draw_text(pdf, layer, content=nil)
294
+ if pdf.kind_of?(Prawn::Document) && layer.visible
295
+ pdf.save_graphics_state
296
+
297
+ pdf.font layer.font_family
298
+ pdf.fill_color layer.font_color
299
+
300
+ origin = {:x => layer.x, :y => pdf.bounds.top - layer.y}
301
+ center = {:x => origin[:x] + (layer.width * 0.5), :y => origin[:y] - (layer.height * 0.5)}
302
+
303
+ pdf.rotate(layer.rotation, :origin => [center[:x], center[:y]]) do
304
+ pdf.transparent layer.alpha do
305
+ style = :normal
306
+ style = :bold if layer.bold
307
+ style = :italic if layer.italic
308
+ style = :bold_italic if layer.bold && layer.italic
309
+
310
+ options = {
311
+ :at => [origin[:x], origin[:y]],
312
+ :width => layer.width,
313
+ :height => layer.height,
314
+ :overflow => :truncate,
315
+ :size => layer.font_size,
316
+ :align => layer.justification.to_sym,
317
+ :style => style
318
+ }
319
+ unless content.nil?
320
+ pdf.text_box content, options
321
+ else
322
+ pdf.text_box layer.content, options
323
+ end
324
+ end
325
+ end
326
+
327
+ pdf.restore_graphics_state
328
+ end
329
+ end
330
+ end
331
+ end
332
+ end
@@ -0,0 +1,35 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'labels/layer'
8
+
9
+ module Labels
10
+
11
+ # This class represents shape layers.
12
+ class Shape < Layer
13
+
14
+ # Whether or not the shape is elliptical
15
+ attr_accessor :elliptical
16
+
17
+ # Corner radius in pixels
18
+ attr_accessor :corner_radius
19
+
20
+ # Whether or not to fill the shape
21
+ attr_accessor :fill
22
+
23
+ # Whether or not to stroke the shape
24
+ attr_accessor :stroke
25
+
26
+ # Fill color in hex
27
+ attr_accessor :fill_color
28
+
29
+ # Stroke color in hex
30
+ attr_accessor :stroke_color
31
+
32
+ # Stroke weight in pixels
33
+ attr_accessor :stroke_weight
34
+ end
35
+ end
@@ -0,0 +1,68 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'prawn'
8
+
9
+ require 'labels/element'
10
+
11
+ module Labels
12
+
13
+ # This class represents template types and properties
14
+ class Template < Element
15
+ DEFAULT = {:title => 'Default', :description => 'Default template', :manufacturer => 'none', :category => 'Default', :visible => false, :width => 288, :height => 144, :columns => 2, :rows => 5, :left_margin => 13, :right_margin => 13, :top_margin => 36, :bottom_margin => 36, :horizontal_gutter => 0, :vertical_gutter => 10, :elliptical => false, :corner_radius => 18}
16
+
17
+ # Title of template
18
+ attr_accessor :title
19
+
20
+ # Description of template
21
+ attr_accessor :description
22
+
23
+ # Manufacturer of template
24
+ attr_accessor :manufacturer
25
+
26
+ # Category of template
27
+ attr_accessor :category
28
+
29
+ # Whether or not the template is visible when printed
30
+ attr_accessor :visible
31
+
32
+ # Width of template canvas area in pixels
33
+ attr_accessor :width
34
+
35
+ # Height of template canvas area in pixels
36
+ attr_accessor :height
37
+
38
+ # Number of columns in template
39
+ attr_accessor :columns
40
+
41
+ # Number of rows in template
42
+ attr_accessor :rows
43
+
44
+ # Left margin of template in pixels
45
+ attr_accessor :left_margin
46
+
47
+ # Right margin of template in pixels
48
+ attr_accessor :right_margin
49
+
50
+ # Top margin of template in pixels
51
+ attr_accessor :top_margin
52
+
53
+ # Bottom margin of template in pixels
54
+ attr_accessor :bottom_margin
55
+
56
+ # Horizontal gutter of template in pixels
57
+ attr_accessor :horizontal_gutter
58
+
59
+ # Vertical gutter of template in pixels
60
+ attr_accessor :vertical_gutter
61
+
62
+ # Whether or not the template canvas area is elliptical
63
+ attr_accessor :elliptical
64
+
65
+ # Corner radius of template canvas area in pixels
66
+ attr_accessor :corner_radius
67
+ end
68
+ end
@@ -0,0 +1,32 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ require 'labels/layer'
8
+
9
+ module Labels
10
+
11
+ # This class represents text layers.
12
+ class Text < Layer
13
+
14
+ # Font family name
15
+ attr_accessor :font_family
16
+
17
+ # Font size in pixels
18
+ attr_accessor :font_size
19
+
20
+ # Font color in hex
21
+ attr_accessor :font_color
22
+
23
+ # Whether or not text is bolded
24
+ attr_accessor :bold
25
+
26
+ # Whether or not text is italicized
27
+ attr_accessor :italic
28
+
29
+ # Justification of text
30
+ attr_accessor :justification
31
+ end
32
+ end
@@ -0,0 +1,10 @@
1
+ # A RubyGem for creating mailing, shipping, address, barcode and other labels and rendering as PDF's.
2
+ #
3
+ # Author:: Aaron Wright (mailto:acwrightdesign@gmail.com)
4
+ # Copyright:: Copyright (c) 2012 Infinite Token LLC
5
+ # License:: MIT License
6
+
7
+ #
8
+ module Labels
9
+ VERSION = "0.0.3"
10
+ end