labels 0.0.3

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