prawn 0.1.0
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.
- data/COPYING +340 -0
- data/LICENSE +56 -0
- data/README +30 -0
- data/Rakefile +83 -0
- data/data/fonts/Activa.ttf +0 -0
- data/data/fonts/Chalkboard.ttf +0 -0
- data/data/fonts/Courier-Bold.afm +342 -0
- data/data/fonts/Courier-BoldOblique.afm +342 -0
- data/data/fonts/Courier-Oblique.afm +342 -0
- data/data/fonts/Courier.afm +342 -0
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/Helvetica-Bold.afm +2827 -0
- data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/data/fonts/Helvetica-Oblique.afm +3051 -0
- data/data/fonts/Helvetica.afm +3051 -0
- data/data/fonts/MustRead.html +19 -0
- data/data/fonts/Symbol.afm +213 -0
- data/data/fonts/Times-Bold.afm +2588 -0
- data/data/fonts/Times-BoldItalic.afm +2384 -0
- data/data/fonts/Times-Italic.afm +2667 -0
- data/data/fonts/Times-Roman.afm +2419 -0
- data/data/fonts/ZapfDingbats.afm +225 -0
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/shift_jis_text.txt +1 -0
- data/examples/addressbook.csv +6 -0
- data/examples/alignment.rb +16 -0
- data/examples/bounding_boxes.pdf +62 -0
- data/examples/bounding_boxes.rb +30 -0
- data/examples/canvas.pdf +81 -0
- data/examples/canvas.rb +12 -0
- data/examples/cell.rb +27 -0
- data/examples/currency.csv +1834 -0
- data/examples/curves.rb +10 -0
- data/examples/fancy_table.rb +48 -0
- data/examples/font_size.rb +19 -0
- data/examples/hexagon.rb +14 -0
- data/examples/image.pdf +0 -0
- data/examples/image.rb +23 -0
- data/examples/image2.rb +13 -0
- data/examples/inline_styles.pdf +117 -0
- data/examples/kerning.rb +27 -0
- data/examples/line.rb +31 -0
- data/examples/multi_page_layout.rb +14 -0
- data/examples/on_page_start.rb +17 -0
- data/examples/page_geometry.rb +28 -0
- data/examples/polygons.rb +16 -0
- data/examples/ruport_formatter.rb +47 -0
- data/examples/ruport_helpers.rb +17 -0
- data/examples/russian_boxes.rb +34 -0
- data/examples/simple_text.rb +15 -0
- data/examples/simple_text_ttf.rb +16 -0
- data/examples/sjis.rb +19 -0
- data/examples/table.rb +45 -0
- data/examples/table_bench.rb +92 -0
- data/examples/text_flow.rb +65 -0
- data/examples/utf8.rb +12 -0
- data/lib/prawn.rb +33 -0
- data/lib/prawn/compatibility.rb +33 -0
- data/lib/prawn/document.rb +334 -0
- data/lib/prawn/document/bounding_box.rb +253 -0
- data/lib/prawn/document/page_geometry.rb +78 -0
- data/lib/prawn/document/table.rb +253 -0
- data/lib/prawn/document/text.rb +346 -0
- data/lib/prawn/errors.rb +33 -0
- data/lib/prawn/font.rb +5 -0
- data/lib/prawn/font/cmap.rb +59 -0
- data/lib/prawn/font/metrics.rb +414 -0
- data/lib/prawn/font/wrapping.rb +45 -0
- data/lib/prawn/graphics.rb +285 -0
- data/lib/prawn/graphics/cell.rb +226 -0
- data/lib/prawn/images.rb +241 -0
- data/lib/prawn/images/jpg.rb +43 -0
- data/lib/prawn/images/png.rb +178 -0
- data/lib/prawn/pdf_object.rb +64 -0
- data/lib/prawn/reference.rb +47 -0
- data/spec/bounding_box_spec.rb +120 -0
- data/spec/box_calculation_spec.rb +17 -0
- data/spec/document_spec.rb +152 -0
- data/spec/graphics_spec.rb +250 -0
- data/spec/images_spec.rb +42 -0
- data/spec/jpg_spec.rb +25 -0
- data/spec/metrics_spec.rb +60 -0
- data/spec/pdf_object_spec.rb +102 -0
- data/spec/png_spec.rb +35 -0
- data/spec/reference_spec.rb +29 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/table_spec.rb +145 -0
- data/spec/text_spec.rb +190 -0
- data/vendor/font_ttf/ttf.rb +20 -0
- data/vendor/font_ttf/ttf/datatypes.rb +189 -0
- data/vendor/font_ttf/ttf/encodings.rb +140 -0
- data/vendor/font_ttf/ttf/exceptions.rb +28 -0
- data/vendor/font_ttf/ttf/file.rb +290 -0
- data/vendor/font_ttf/ttf/fontchunk.rb +77 -0
- data/vendor/font_ttf/ttf/table/cmap.rb +408 -0
- data/vendor/font_ttf/ttf/table/cvt.rb +49 -0
- data/vendor/font_ttf/ttf/table/fpgm.rb +48 -0
- data/vendor/font_ttf/ttf/table/gasp.rb +88 -0
- data/vendor/font_ttf/ttf/table/glyf.rb +452 -0
- data/vendor/font_ttf/ttf/table/head.rb +86 -0
- data/vendor/font_ttf/ttf/table/hhea.rb +96 -0
- data/vendor/font_ttf/ttf/table/hmtx.rb +98 -0
- data/vendor/font_ttf/ttf/table/kern.rb +186 -0
- data/vendor/font_ttf/ttf/table/loca.rb +75 -0
- data/vendor/font_ttf/ttf/table/maxp.rb +81 -0
- data/vendor/font_ttf/ttf/table/name.rb +222 -0
- data/vendor/font_ttf/ttf/table/os2.rb +172 -0
- data/vendor/font_ttf/ttf/table/post.rb +120 -0
- data/vendor/font_ttf/ttf/table/prep.rb +27 -0
- data/vendor/font_ttf/ttf/table/vhea.rb +45 -0
- data/vendor/font_ttf/ttf/table/vmtx.rb +36 -0
- metadata +180 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# wrapping.rb : Implementation of naive text wrap
|
|
4
|
+
#
|
|
5
|
+
# Copyright May 2008, Michael Daines. All Rights Reserved.
|
|
6
|
+
#
|
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
|
8
|
+
module Prawn
|
|
9
|
+
module Font #:nodoc:
|
|
10
|
+
module Wrapping #:nodoc:
|
|
11
|
+
|
|
12
|
+
# TODO: Replace with TeX optimal algorithm
|
|
13
|
+
def naive_wrap(string, line_width, font_size, options = {})
|
|
14
|
+
output = ""
|
|
15
|
+
string.lines.each do |line|
|
|
16
|
+
accumulated_width = 0
|
|
17
|
+
segments = line.scan(/\S+|\s+/)
|
|
18
|
+
|
|
19
|
+
segments.each do |segment|
|
|
20
|
+
segment_width = string_width(segment, font_size,
|
|
21
|
+
:kerning => options[:kerning])
|
|
22
|
+
|
|
23
|
+
if (accumulated_width + segment_width).round > line_width.round
|
|
24
|
+
output << "\n"
|
|
25
|
+
|
|
26
|
+
if segment =~ /\s/
|
|
27
|
+
accumulated_width = 0
|
|
28
|
+
else
|
|
29
|
+
output << segment
|
|
30
|
+
accumulated_width = segment_width
|
|
31
|
+
end
|
|
32
|
+
else
|
|
33
|
+
output << segment
|
|
34
|
+
accumulated_width += segment_width
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
output
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# graphics.rb : Implements PDF drawing primitives
|
|
4
|
+
#
|
|
5
|
+
# Copyright April 2008, Gregory Brown. All Rights Reserved.
|
|
6
|
+
#
|
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
|
8
|
+
|
|
9
|
+
require "enumerator"
|
|
10
|
+
require "prawn/graphics/cell"
|
|
11
|
+
|
|
12
|
+
module Prawn
|
|
13
|
+
|
|
14
|
+
# Implements the drawing facilities for Prawn::Document.
|
|
15
|
+
# Use this to draw the most beautiful imaginable things.
|
|
16
|
+
#
|
|
17
|
+
# This file lifts and modifies several of PDF::Writer's graphics functions
|
|
18
|
+
# ruby-pdf.rubyforge.org
|
|
19
|
+
#
|
|
20
|
+
module Graphics
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#######################################################################
|
|
24
|
+
# Low level drawing operations must translate to absolute coords! #
|
|
25
|
+
#######################################################################
|
|
26
|
+
|
|
27
|
+
# Moves the drawing position to a given point. The point can be
|
|
28
|
+
# specified as a tuple or a flattened argument list
|
|
29
|
+
#
|
|
30
|
+
# pdf.move_to [100,50]
|
|
31
|
+
# pdf.move_to(100,50)
|
|
32
|
+
#
|
|
33
|
+
def move_to(*point)
|
|
34
|
+
x,y = translate(point)
|
|
35
|
+
add_content("%.3f %.3f m" % [ x, y ])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Draws a line from the current drawing position to the specified point.
|
|
39
|
+
# The destination may be described as a tuple or a flattened list:
|
|
40
|
+
#
|
|
41
|
+
# pdf.line_to [50,50]
|
|
42
|
+
# pdf.line_to(50,50)
|
|
43
|
+
#
|
|
44
|
+
def line_to(*point)
|
|
45
|
+
x,y = translate(point)
|
|
46
|
+
add_content("%.3f %.3f l" % [ x, y ])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Draws a Bezier curve from the current drawing position to the
|
|
50
|
+
# specified point, bounded by two additional points.
|
|
51
|
+
#
|
|
52
|
+
# pdf.curve_to [100,100], :bounds => [[90,90],[75,75]]
|
|
53
|
+
#
|
|
54
|
+
def curve_to(dest,options={})
|
|
55
|
+
options[:bounds] or raise Prawn::Errors::InvalidGraphicsPath,
|
|
56
|
+
"Bounding points for bezier curve must be specified "+
|
|
57
|
+
"as :bounds => [[x1,y1],[x2,y2]]"
|
|
58
|
+
|
|
59
|
+
curve_points = (options[:bounds] << dest).map { |e| translate(e) }
|
|
60
|
+
add_content("%.3f %.3f %.3f %.3f %.3f %.3f c" %
|
|
61
|
+
curve_points.flatten )
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Draws a rectangle given <tt>point</tt>, <tt>width</tt> and
|
|
65
|
+
# <tt>height</tt>. The rectangle is bounded by its upper-left corner.
|
|
66
|
+
#
|
|
67
|
+
# pdf.rectangle [300,300], 100, 200
|
|
68
|
+
#
|
|
69
|
+
def rectangle(point,width,height)
|
|
70
|
+
x,y = translate(point)
|
|
71
|
+
add_content("%.3f %.3f %.3f %.3f re" % [ x, y - height, width, height ])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
###########################################################
|
|
75
|
+
# Higher level functions: May use relative coords #
|
|
76
|
+
###########################################################
|
|
77
|
+
|
|
78
|
+
# Sets line thickness to the <tt>width</tt> specified.
|
|
79
|
+
#
|
|
80
|
+
def line_width=(width)
|
|
81
|
+
@line_width = width
|
|
82
|
+
add_content("#{width} w")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The current line thickness
|
|
86
|
+
#
|
|
87
|
+
def line_width
|
|
88
|
+
@line_width || 1
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Draws a line from one point to another. Points may be specified as
|
|
92
|
+
# tuples or flattened argument list:
|
|
93
|
+
#
|
|
94
|
+
# pdf.line [100,100], [200,250]
|
|
95
|
+
# pdf.line(100,100,200,250)
|
|
96
|
+
#
|
|
97
|
+
def line(*points)
|
|
98
|
+
x0,y0,x1,y1 = points.flatten
|
|
99
|
+
move_to(x0, y0)
|
|
100
|
+
line_to(x1, y1)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Draws a horizontal line from <tt>x1</tt> to <tt>x2</tt> at the
|
|
104
|
+
# current <tt>y</tt> position.
|
|
105
|
+
#
|
|
106
|
+
def horizontal_line(x1,x2)
|
|
107
|
+
line(x1,y,x2,y)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Draws a horizontal line from the left border to the right border of the
|
|
111
|
+
# bounding box at the current <tt>y</tt> position.
|
|
112
|
+
#
|
|
113
|
+
def horizontal_rule
|
|
114
|
+
horizontal_line(bounds.left, bounds.right)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Draws a vertical line at the given x position from y1 to y2.
|
|
118
|
+
#
|
|
119
|
+
def vertical_line_at(x,y1,y2)
|
|
120
|
+
line(x,y1,x,y2)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Draws a Bezier curve between two points, bounded by two additional
|
|
124
|
+
# points
|
|
125
|
+
#
|
|
126
|
+
# pdf.curve [50,100], [100,100], :bounds => [[90,90],[75,75]]
|
|
127
|
+
#
|
|
128
|
+
def curve(origin,dest, options={})
|
|
129
|
+
move_to *origin
|
|
130
|
+
curve_to(dest,options)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# This constant is used to approximate a symmetrical arc using a cubic
|
|
134
|
+
# Bezier curve.
|
|
135
|
+
#
|
|
136
|
+
KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
|
|
137
|
+
|
|
138
|
+
# Draws a circle of radius <tt>:radius</tt> with the centre-point at <tt>point</tt>
|
|
139
|
+
# as a complete subpath. The drawing point will be moved to the
|
|
140
|
+
# centre-point upon completion of the drawing the circle.
|
|
141
|
+
#
|
|
142
|
+
# pdf.circle_at [100,100], :radius => 25
|
|
143
|
+
#
|
|
144
|
+
def circle_at(point, options)
|
|
145
|
+
x,y = point
|
|
146
|
+
ellipse_at [x, y], options[:radius]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
|
|
150
|
+
# with the centre-point at <tt>point</tt> as a complete subpath. The
|
|
151
|
+
# drawing point will be moved to the centre-point upon completion of the
|
|
152
|
+
# drawing the ellipse.
|
|
153
|
+
#
|
|
154
|
+
# # draws an ellipse with x-radius 25 and y-radius 50
|
|
155
|
+
# pdf.ellipse_at [100,100], 25, 50
|
|
156
|
+
#
|
|
157
|
+
def ellipse_at(point, r1, r2 = r1)
|
|
158
|
+
x, y = point
|
|
159
|
+
l1 = r1 * KAPPA
|
|
160
|
+
l2 = r2 * KAPPA
|
|
161
|
+
|
|
162
|
+
move_to(x + r1, y)
|
|
163
|
+
|
|
164
|
+
# Upper right hand corner
|
|
165
|
+
curve_to [x, y + r2],
|
|
166
|
+
:bounds => [[x + r1, y + l1], [x + l2, y + r2]]
|
|
167
|
+
|
|
168
|
+
# Upper left hand corner
|
|
169
|
+
curve_to [x - r1, y],
|
|
170
|
+
:bounds => [[x - l2, y + r2], [x - r1, y + l1]]
|
|
171
|
+
|
|
172
|
+
# Lower left hand corner
|
|
173
|
+
curve_to [x, y - r2],
|
|
174
|
+
:bounds => [[x - r1, y - l1], [x - l2, y - r2]]
|
|
175
|
+
|
|
176
|
+
# Lower right hand corner
|
|
177
|
+
curve_to [x + r1, y],
|
|
178
|
+
:bounds => [[x + l2, y - r2], [x + r1, y - l1]]
|
|
179
|
+
|
|
180
|
+
move_to(x, y)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Draws a polygon from the specified points.
|
|
184
|
+
#
|
|
185
|
+
# # draws a snazzy triangle
|
|
186
|
+
# pdf.polygon [100,100], [100,200], [200,200]
|
|
187
|
+
#
|
|
188
|
+
def polygon(*points)
|
|
189
|
+
move_to points[0]
|
|
190
|
+
(points << points[0]).each_cons(2) do |p1,p2|
|
|
191
|
+
line_to(*p2)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Sets the fill color. 6 digit HTML color codes are used.
|
|
196
|
+
#
|
|
197
|
+
# pdf.fill_color "f0ffc1"
|
|
198
|
+
#
|
|
199
|
+
def fill_color(color=nil)
|
|
200
|
+
return @fill_color unless color
|
|
201
|
+
@fill_color = color
|
|
202
|
+
set_fill_color
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
alias_method :fill_color=, :fill_color
|
|
206
|
+
|
|
207
|
+
# Sets the line stroking color. 6 digit HTML color codes are used.
|
|
208
|
+
#
|
|
209
|
+
# pdf.stroke_color "cc2fde"
|
|
210
|
+
#
|
|
211
|
+
def stroke_color(color=nil)
|
|
212
|
+
return @stroke_color unless color
|
|
213
|
+
@stroke_color = color
|
|
214
|
+
set_stroke_color
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
alias_method :stroke_color=, :stroke_color
|
|
218
|
+
|
|
219
|
+
# Strokes and closes the current path.
|
|
220
|
+
#
|
|
221
|
+
def stroke
|
|
222
|
+
yield if block_given?
|
|
223
|
+
add_content "S"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Fills and closes the current path
|
|
227
|
+
#
|
|
228
|
+
def fill
|
|
229
|
+
yield if block_given?
|
|
230
|
+
add_content "f"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Fills, strokes, and closes the current path.
|
|
234
|
+
#
|
|
235
|
+
def fill_and_stroke
|
|
236
|
+
yield if block_given?
|
|
237
|
+
add_content "b"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Provides the following shortcuts:
|
|
241
|
+
#
|
|
242
|
+
# stroke_some_method(*args) #=> some_method(*args); stroke
|
|
243
|
+
# fill_some_method(*args) #=> some_method(*args); fill
|
|
244
|
+
#
|
|
245
|
+
def method_missing(id,*args,&block)
|
|
246
|
+
case(id.to_s)
|
|
247
|
+
when /^fill_and_stroke_(.*)/
|
|
248
|
+
send($1,*args,&block); fill_and_stroke
|
|
249
|
+
when /^stroke_(.*)/
|
|
250
|
+
send($1,*args,&block); stroke
|
|
251
|
+
when /^fill_(.*)/
|
|
252
|
+
send($1,*args,&block); fill
|
|
253
|
+
else
|
|
254
|
+
super
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
private
|
|
259
|
+
|
|
260
|
+
def translate(*point)
|
|
261
|
+
x,y = point.flatten
|
|
262
|
+
[@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def set_fill_color
|
|
266
|
+
r,g,b = [@fill_color[0..1], @fill_color[2..3], @fill_color[4..5]].
|
|
267
|
+
map { |e| e.to_i(16) }
|
|
268
|
+
add_content "%.3f %.3f %.3f rg" % [r / 255.0, g / 255.0, b / 255.0]
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def set_stroke_color
|
|
272
|
+
r,g,b = [@stroke_color[0..1], @stroke_color[2..3], @stroke_color[4..5]].
|
|
273
|
+
map { |e| e.to_i(16) }
|
|
274
|
+
add_content "%.3f %.3f %.3f RG" % [r / 255.0, g / 255.0, b / 255.0]
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def update_colors
|
|
278
|
+
@fill_color ||= "000000"
|
|
279
|
+
@stroke_color ||= "000000"
|
|
280
|
+
set_fill_color
|
|
281
|
+
set_stroke_color
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
end
|
|
285
|
+
end
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Prawn
|
|
4
|
+
|
|
5
|
+
class Document
|
|
6
|
+
# Builds and renders a Graphics::Cell. A cell is essentially a
|
|
7
|
+
# special-purpose bounding box designed for flowing text within a bordered
|
|
8
|
+
# area. For available options, see Graphics::Cell#new.
|
|
9
|
+
#
|
|
10
|
+
# Prawn::Document.generate("cell.pdf") do
|
|
11
|
+
# cell [100,500],
|
|
12
|
+
# :width => 200,
|
|
13
|
+
# :text => "The rain in Spain falls mainly on the plains"
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
def cell(point, options={})
|
|
17
|
+
Prawn::Graphics::Cell.new(
|
|
18
|
+
options.merge(:document => self, :point => point)).draw
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module Graphics
|
|
23
|
+
# A cell is a special-purpose bounding box designed to flow text within a
|
|
24
|
+
# bordered area. This is used by Prawn's Document::Table implementation but
|
|
25
|
+
# can also be used standalone for drawing text boxes via Document#cell
|
|
26
|
+
#
|
|
27
|
+
class Cell
|
|
28
|
+
|
|
29
|
+
# Creates a new cell object. Generally used indirectly via Document#cell
|
|
30
|
+
#
|
|
31
|
+
# Of the available options listed below, <tt>:point</tt>, <tt>:width</tt>,
|
|
32
|
+
# and <tt>:text</tt> must be provided. If you are not using the
|
|
33
|
+
# Document#cell shortcut, the <tt>:document</tt> must also be provided.
|
|
34
|
+
#
|
|
35
|
+
# <tt>:point</tt>:: Absolute [x,y] coordinate of the top-left corner of the cell.
|
|
36
|
+
# <tt>:document</tt>:: The Prawn::Document object to render on.
|
|
37
|
+
# <tt>:text</tt>:: The text to be flowed within the cell
|
|
38
|
+
# <tt>:width</tt>:: The width in PDF points of the cell.
|
|
39
|
+
# <tt>:border</tt>:: The border line width. If omitted, no border will be drawn.
|
|
40
|
+
# <tt>:horizontal_padding</tt>:: The horizontal padding in PDF points
|
|
41
|
+
# <tt>:vertical_padding</tt>:: The vertical padding in PDF points
|
|
42
|
+
# <tt>:padding</tt>:: Overrides both horizontal and vertical padding
|
|
43
|
+
# <tt>:border_style</tt>:: One of <tt>:all</tt>, <tt>:no_top</tt>, <tt>:no_bottom</tt>, <tt>:sides</tt>
|
|
44
|
+
# <tt>:align</tt>:: One of <tt>:left</tt>, <tt>:right</tt>, <tt>:center</tt>
|
|
45
|
+
#
|
|
46
|
+
def initialize(options={})
|
|
47
|
+
@point = options[:point]
|
|
48
|
+
@document = options[:document]
|
|
49
|
+
@text = options[:text].to_s
|
|
50
|
+
@width = options[:width]
|
|
51
|
+
@border = options[:border] || 1
|
|
52
|
+
@border_style = options[:border_style] || :all
|
|
53
|
+
@background_color = options[:background_color]
|
|
54
|
+
@align = options[:align] || :left
|
|
55
|
+
|
|
56
|
+
@horizontal_padding = options[:horizontal_padding] || 0
|
|
57
|
+
@vertical_padding = options[:vertical_padding] || 0
|
|
58
|
+
|
|
59
|
+
if options[:padding]
|
|
60
|
+
@horizontal_padding = @vertical_padding = options[:padding]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
attr_accessor :point, :border_style, :border, :background_color,
|
|
65
|
+
:document, :horizontal_padding, :vertical_padding,
|
|
66
|
+
:align
|
|
67
|
+
attr_writer :height, :width #:nodoc:
|
|
68
|
+
|
|
69
|
+
# Returns the cell's text as a string.
|
|
70
|
+
#
|
|
71
|
+
def to_s
|
|
72
|
+
@text
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# The width of the text area excluding the horizonal padding
|
|
76
|
+
#
|
|
77
|
+
def text_area_width
|
|
78
|
+
width - 2*@horizontal_padding
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The width of the cell in PDF points
|
|
82
|
+
#
|
|
83
|
+
def width
|
|
84
|
+
@width || (@document.font_metrics.string_width(@text,
|
|
85
|
+
@document.font_size)) + 2*@horizontal_padding
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# The height of the cell in PDF points
|
|
89
|
+
#
|
|
90
|
+
def height
|
|
91
|
+
@height || text_area_height + 2*@vertical_padding
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# The height of the text area excluding the vertical padding
|
|
95
|
+
#
|
|
96
|
+
def text_area_height
|
|
97
|
+
@document.font_metrics.string_height(@text,
|
|
98
|
+
:font_size => @document.font_size,
|
|
99
|
+
:line_width => text_area_width)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Draws the cell onto the PDF document
|
|
103
|
+
#
|
|
104
|
+
def draw
|
|
105
|
+
rel_point = @point
|
|
106
|
+
|
|
107
|
+
if @background_color
|
|
108
|
+
@document.mask(:fill_color) do
|
|
109
|
+
@document.fill_color @background_color
|
|
110
|
+
h = borders.include?(:bottom) ? height - border : height + border / 2.0
|
|
111
|
+
@document.fill_rectangle [rel_point[0] + border / 2.0,
|
|
112
|
+
rel_point[1] - border / 2.0 ],
|
|
113
|
+
width - border, h
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if @border > 0
|
|
118
|
+
@document.mask(:line_width) do
|
|
119
|
+
@document.line_width = @border
|
|
120
|
+
|
|
121
|
+
if borders.include?(:left)
|
|
122
|
+
@document.stroke_line [rel_point[0], rel_point[1] + (@border / 2.0)],
|
|
123
|
+
[rel_point[0], rel_point[1] - height - @border / 2.0 ]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if borders.include?(:right)
|
|
127
|
+
@document.stroke_line(
|
|
128
|
+
[rel_point[0] + width, rel_point[1] + (@border / 2.0)],
|
|
129
|
+
[rel_point[0] + width, rel_point[1] - height - @border / 2.0] )
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if borders.include?(:top)
|
|
133
|
+
@document.stroke_line(
|
|
134
|
+
[ rel_point[0] + @border / 2.0, rel_point[1] ],
|
|
135
|
+
[ rel_point[0] - @border / 2.0 + width, rel_point[1] ])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if borders.include?(:bottom)
|
|
139
|
+
@document.stroke_line [rel_point[0], rel_point[1] - height ],
|
|
140
|
+
[rel_point[0] + width, rel_point[1] - height]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
borders
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
@document.bounding_box( [@point[0] + @horizontal_padding,
|
|
150
|
+
@point[1] - @vertical_padding],
|
|
151
|
+
:width => text_area_width,
|
|
152
|
+
:height => height - @vertical_padding) do
|
|
153
|
+
@document.text @text, :align => @align
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
def borders
|
|
160
|
+
@borders ||= case @border_style
|
|
161
|
+
when :all
|
|
162
|
+
[:top,:left,:right,:bottom]
|
|
163
|
+
when :sides
|
|
164
|
+
[:left,:right]
|
|
165
|
+
when :no_top
|
|
166
|
+
[:left,:right,:bottom]
|
|
167
|
+
when :no_bottom
|
|
168
|
+
[:left,:right,:top]
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
class CellBlock #:nodoc:
|
|
175
|
+
|
|
176
|
+
# Not sure if this class is something I want to expose in the public API.
|
|
177
|
+
|
|
178
|
+
def initialize(document)
|
|
179
|
+
@document = document
|
|
180
|
+
@cells = []
|
|
181
|
+
@width = 0
|
|
182
|
+
@height = 0
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
attr_reader :width, :height
|
|
186
|
+
attr_accessor :background_color
|
|
187
|
+
|
|
188
|
+
def <<(cell)
|
|
189
|
+
@cells << cell
|
|
190
|
+
@height = cell.height if cell.height > @height
|
|
191
|
+
@width += cell.width
|
|
192
|
+
self
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def draw
|
|
196
|
+
y = @document.y
|
|
197
|
+
x = @document.bounds.absolute_left
|
|
198
|
+
|
|
199
|
+
@cells.each do |e|
|
|
200
|
+
e.point = [x - @document.bounds.absolute_left,
|
|
201
|
+
y - @document.bounds.absolute_bottom]
|
|
202
|
+
e.height = @height
|
|
203
|
+
e.background_color ||= @background_color
|
|
204
|
+
e.draw
|
|
205
|
+
x += e.width
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
@document.y = y - @height
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def border
|
|
212
|
+
@cells[0].border
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def border_style=(s)
|
|
216
|
+
@cells.each { |e| e.border_style = s }
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def border_style
|
|
220
|
+
@cells[0].border_style
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
end
|