prawn 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +16 -2
- data/Rakefile +3 -3
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/examples/cell.rb +14 -3
- data/examples/chinese_text_wrapping.rb +17 -0
- data/examples/family_based_styling.rb +21 -0
- data/examples/fancy_table.rb +4 -4
- data/examples/flowing_text_with_header_and_footer.rb +72 -0
- data/examples/font_size.rb +2 -2
- data/examples/lazy_bounding_boxes.rb +19 -0
- data/examples/table.rb +13 -11
- data/examples/text_flow.rb +1 -1
- data/lib/prawn.rb +44 -15
- data/lib/prawn/compatibility.rb +20 -7
- data/lib/prawn/document.rb +72 -122
- data/lib/prawn/document/bounding_box.rb +124 -24
- data/lib/prawn/document/internals.rb +107 -0
- data/lib/prawn/document/table.rb +99 -70
- data/lib/prawn/document/text.rb +92 -314
- data/lib/prawn/errors.rb +13 -2
- data/lib/prawn/font.rb +312 -1
- data/lib/prawn/font/cmap.rb +1 -1
- data/lib/prawn/font/metrics.rb +52 -49
- data/lib/prawn/font/wrapping.rb +14 -12
- data/lib/prawn/graphics.rb +23 -74
- data/lib/prawn/graphics/cell.rb +30 -25
- data/lib/prawn/graphics/color.rb +132 -0
- data/lib/prawn/images.rb +37 -16
- data/lib/prawn/images/png.rb +29 -24
- data/lib/prawn/pdf_object.rb +3 -1
- data/spec/bounding_box_spec.rb +12 -3
- data/spec/document_spec.rb +40 -72
- data/spec/font_spec.rb +97 -0
- data/spec/graphics_spec.rb +46 -99
- data/spec/images_spec.rb +4 -21
- data/spec/pdf_object_spec.rb +8 -8
- data/spec/png_spec.rb +47 -12
- data/spec/spec_helper.rb +5 -24
- data/spec/table_spec.rb +53 -59
- data/spec/text_spec.rb +28 -93
- data/vendor/pdf-inspector/README +18 -0
- data/vendor/pdf-inspector/lib/pdf/inspector.rb +25 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +80 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +16 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +31 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
- metadata +63 -38
- data/examples/on_page_start.rb +0 -17
- data/examples/table_bench.rb +0 -92
- data/spec/box_calculation_spec.rb +0 -17
data/lib/prawn/font/wrapping.rb
CHANGED
@@ -6,40 +6,42 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
module Prawn
|
9
|
-
|
10
|
-
module Wrapping #:nodoc:
|
9
|
+
class Font #:nodoc:
|
10
|
+
module Wrapping #:nodoc:
|
11
|
+
ruby_18 { $KCODE="U" }
|
11
12
|
|
12
13
|
# TODO: Replace with TeX optimal algorithm
|
13
14
|
def naive_wrap(string, line_width, font_size, options = {})
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
accumulated_width = 0
|
16
|
+
scan_pattern = options[:mode] == :character ? /./ : /\S+|\s+/
|
17
|
+
|
18
|
+
output = ""
|
19
|
+
string.lines.each do |line|
|
20
|
+
segments = line.scan(scan_pattern)
|
18
21
|
|
19
22
|
segments.each do |segment|
|
20
23
|
segment_width = string_width(segment, font_size,
|
21
24
|
:kerning => options[:kerning])
|
22
25
|
|
23
26
|
if (accumulated_width + segment_width).round > line_width.round
|
24
|
-
output
|
27
|
+
output = "#{output.rstrip}\n"
|
25
28
|
|
26
|
-
if segment =~ /\s/
|
29
|
+
if segment =~ /\s/
|
27
30
|
accumulated_width = 0
|
28
31
|
else
|
29
32
|
output << segment
|
30
33
|
accumulated_width = segment_width
|
31
34
|
end
|
32
|
-
else
|
35
|
+
else
|
33
36
|
output << segment
|
34
37
|
accumulated_width += segment_width
|
35
38
|
end
|
36
|
-
end
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
output
|
40
43
|
end
|
41
44
|
|
42
|
-
end
|
43
|
-
|
45
|
+
end
|
44
46
|
end
|
45
47
|
end
|
data/lib/prawn/graphics.rb
CHANGED
@@ -7,7 +7,8 @@
|
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
|
9
9
|
require "enumerator"
|
10
|
-
require "prawn/graphics/cell"
|
10
|
+
require "prawn/graphics/cell"
|
11
|
+
require "prawn/graphics/color"
|
11
12
|
|
12
13
|
module Prawn
|
13
14
|
|
@@ -17,9 +18,10 @@ module Prawn
|
|
17
18
|
# This file lifts and modifies several of PDF::Writer's graphics functions
|
18
19
|
# ruby-pdf.rubyforge.org
|
19
20
|
#
|
20
|
-
module Graphics
|
21
|
-
|
22
|
-
|
21
|
+
module Graphics
|
22
|
+
|
23
|
+
include Color
|
24
|
+
|
23
25
|
#######################################################################
|
24
26
|
# Low level drawing operations must translate to absolute coords! #
|
25
27
|
#######################################################################
|
@@ -84,8 +86,12 @@ module Prawn
|
|
84
86
|
|
85
87
|
# The current line thickness
|
86
88
|
#
|
87
|
-
def line_width
|
88
|
-
|
89
|
+
def line_width(width=nil)
|
90
|
+
if width
|
91
|
+
self.line_width = width
|
92
|
+
else
|
93
|
+
@line_width || 1
|
94
|
+
end
|
89
95
|
end
|
90
96
|
|
91
97
|
# Draws a line from one point to another. Points may be specified as
|
@@ -104,7 +110,7 @@ module Prawn
|
|
104
110
|
# current <tt>y</tt> position.
|
105
111
|
#
|
106
112
|
def horizontal_line(x1,x2)
|
107
|
-
line(x1,y,x2,y)
|
113
|
+
line(x1,y-bounds.absolute_bottom,x2,y-bounds.absolute_bottom)
|
108
114
|
end
|
109
115
|
|
110
116
|
# Draws a horizontal line from the left border to the right border of the
|
@@ -191,95 +197,38 @@ module Prawn
|
|
191
197
|
line_to(*p2)
|
192
198
|
end
|
193
199
|
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
200
|
|
207
|
-
#
|
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.
|
201
|
+
# Strokes and closes the current path. See Graphic::Color for color details
|
220
202
|
#
|
221
203
|
def stroke
|
222
204
|
yield if block_given?
|
223
205
|
add_content "S"
|
224
206
|
end
|
225
207
|
|
226
|
-
# Fills and closes the current path
|
208
|
+
# Fills and closes the current path. See Graphic::Color for color details
|
227
209
|
#
|
228
210
|
def fill
|
229
211
|
yield if block_given?
|
230
212
|
add_content "f"
|
231
213
|
end
|
232
|
-
|
233
|
-
# Fills, strokes, and closes the current path.
|
214
|
+
|
215
|
+
# Fills, strokes, and closes the current path. See Graphic::Color for color details
|
234
216
|
#
|
235
217
|
def fill_and_stroke
|
236
218
|
yield if block_given?
|
237
219
|
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
|
220
|
+
end
|
257
221
|
|
258
|
-
private
|
222
|
+
private
|
259
223
|
|
260
224
|
def translate(*point)
|
261
225
|
x,y = point.flatten
|
262
226
|
[@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
|
227
|
+
end
|
276
228
|
|
277
|
-
def
|
278
|
-
|
279
|
-
|
280
|
-
set_fill_color
|
281
|
-
set_stroke_color
|
282
|
-
end
|
229
|
+
def translate!(point)
|
230
|
+
point.replace(translate(point))
|
231
|
+
end
|
283
232
|
|
284
233
|
end
|
285
234
|
end
|
data/lib/prawn/graphics/cell.rb
CHANGED
@@ -54,7 +54,8 @@ module Prawn
|
|
54
54
|
@document = options[:document]
|
55
55
|
@text = options[:text].to_s
|
56
56
|
@width = options[:width]
|
57
|
-
@
|
57
|
+
@borders = options[:borders]
|
58
|
+
@border_width = options[:border_width] || 1
|
58
59
|
@border_style = options[:border_style] || :all
|
59
60
|
@background_color = options[:background_color]
|
60
61
|
@align = options[:align] || :left
|
@@ -67,9 +68,10 @@ module Prawn
|
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
70
|
-
attr_accessor :point, :border_style, :
|
71
|
-
:document, :horizontal_padding, :vertical_padding,
|
72
|
-
:
|
71
|
+
attr_accessor :point, :border_style, :border_width, :background_color,
|
72
|
+
:document, :horizontal_padding, :vertical_padding, :align,
|
73
|
+
:borders
|
74
|
+
|
73
75
|
attr_writer :height, :width #:nodoc:
|
74
76
|
|
75
77
|
# Returns the cell's text as a string.
|
@@ -87,22 +89,20 @@ module Prawn
|
|
87
89
|
# The width of the cell in PDF points
|
88
90
|
#
|
89
91
|
def width
|
90
|
-
@width || (@document.
|
91
|
-
@document.
|
92
|
+
@width || (@document.font.metrics.string_width(@text,
|
93
|
+
@document.font.size)) + 2*@horizontal_padding
|
92
94
|
end
|
93
95
|
|
94
96
|
# The height of the cell in PDF points
|
95
97
|
#
|
96
|
-
def height
|
98
|
+
def height
|
97
99
|
@height || text_area_height + 2*@vertical_padding
|
98
100
|
end
|
99
101
|
|
100
102
|
# The height of the text area excluding the vertical padding
|
101
103
|
#
|
102
104
|
def text_area_height
|
103
|
-
@document.
|
104
|
-
:font_size => @document.font_size,
|
105
|
-
:line_width => text_area_width)
|
105
|
+
@document.font.height_of(@text, :line_width => text_area_width)
|
106
106
|
end
|
107
107
|
|
108
108
|
# Draws the cell onto the PDF document
|
@@ -113,32 +113,33 @@ module Prawn
|
|
113
113
|
if @background_color
|
114
114
|
@document.mask(:fill_color) do
|
115
115
|
@document.fill_color @background_color
|
116
|
-
h = borders.include?(:bottom) ?
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
h = borders.include?(:bottom) ?
|
117
|
+
height - border_width : height + border_width / 2.0
|
118
|
+
@document.fill_rectangle [rel_point[0] + border_width / 2.0,
|
119
|
+
rel_point[1] - border_width / 2.0 ],
|
120
|
+
width - border_width, h
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
123
|
-
if @
|
124
|
+
if @border_width > 0
|
124
125
|
@document.mask(:line_width) do
|
125
|
-
@document.line_width = @
|
126
|
+
@document.line_width = @border_width
|
126
127
|
|
127
128
|
if borders.include?(:left)
|
128
|
-
@document.stroke_line [rel_point[0], rel_point[1] + (@
|
129
|
-
[rel_point[0], rel_point[1] - height - @
|
129
|
+
@document.stroke_line [rel_point[0], rel_point[1] + (@border_width / 2.0)],
|
130
|
+
[rel_point[0], rel_point[1] - height - @border_width / 2.0 ]
|
130
131
|
end
|
131
132
|
|
132
133
|
if borders.include?(:right)
|
133
134
|
@document.stroke_line(
|
134
|
-
[rel_point[0] + width, rel_point[1] + (@
|
135
|
-
[rel_point[0] + width, rel_point[1] - height - @
|
135
|
+
[rel_point[0] + width, rel_point[1] + (@border_width / 2.0)],
|
136
|
+
[rel_point[0] + width, rel_point[1] - height - @border_width / 2.0] )
|
136
137
|
end
|
137
138
|
|
138
139
|
if borders.include?(:top)
|
139
140
|
@document.stroke_line(
|
140
|
-
[ rel_point[0] + @
|
141
|
-
[ rel_point[0] - @
|
141
|
+
[ rel_point[0] + @border_width / 2.0, rel_point[1] ],
|
142
|
+
[ rel_point[0] - @border_width / 2.0 + width, rel_point[1] ])
|
142
143
|
end
|
143
144
|
|
144
145
|
if borders.include?(:bottom)
|
@@ -214,13 +215,17 @@ module Prawn
|
|
214
215
|
@document.y = y - @height
|
215
216
|
end
|
216
217
|
|
217
|
-
def
|
218
|
-
@cells[0].
|
218
|
+
def border_width
|
219
|
+
@cells[0].border_width
|
219
220
|
end
|
220
221
|
|
221
222
|
def border_style=(s)
|
222
223
|
@cells.each { |e| e.border_style = s }
|
223
|
-
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def align=(align)
|
227
|
+
@cells.each { |e| e.align = align }
|
228
|
+
end
|
224
229
|
|
225
230
|
def border_style
|
226
231
|
@cells[0].border_style
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Prawn
|
2
|
+
module Graphics
|
3
|
+
module Color
|
4
|
+
|
5
|
+
# Sets the fill color.
|
6
|
+
#
|
7
|
+
# If a single argument is provided, it should be a 6 digit HTML color
|
8
|
+
# code.
|
9
|
+
#
|
10
|
+
# pdf.fill_color "f0ffc1"
|
11
|
+
#
|
12
|
+
# If 4 arguments are provided, the color is assumed to be a CMYK value
|
13
|
+
# Values range from 0 - 100.
|
14
|
+
#
|
15
|
+
# pdf.fill_color 0, 99, 95, 0
|
16
|
+
#
|
17
|
+
def fill_color(*color)
|
18
|
+
return @fill_color if color.empty?
|
19
|
+
@fill_color = process_color(*color)
|
20
|
+
set_fill_color
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method :fill_color=, :fill_color
|
24
|
+
|
25
|
+
# Sets the line stroking color. 6 digit HTML color codes are used.
|
26
|
+
#
|
27
|
+
# If a single argument is provided, it should be a 6 digit HTML color
|
28
|
+
# code.
|
29
|
+
#
|
30
|
+
# pdf.fill_color "f0ffc1"
|
31
|
+
#
|
32
|
+
# If 4 arguments are provided, the color is assumed to be a CMYK value
|
33
|
+
# Values range from 0 - 100.
|
34
|
+
#
|
35
|
+
# pdf.fill_color 0, 99, 95, 0
|
36
|
+
#
|
37
|
+
def stroke_color(*color)
|
38
|
+
return @stroke_color if color.empty?
|
39
|
+
@stroke_color = process_color(*color)
|
40
|
+
set_stroke_color
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :stroke_color=, :stroke_color
|
44
|
+
|
45
|
+
# Provides the following shortcuts:
|
46
|
+
#
|
47
|
+
# stroke_some_method(*args) #=> some_method(*args); stroke
|
48
|
+
# fill_some_method(*args) #=> some_method(*args); fill
|
49
|
+
#
|
50
|
+
def method_missing(id,*args,&block)
|
51
|
+
case(id.to_s)
|
52
|
+
when /^fill_and_stroke_(.*)/
|
53
|
+
send($1,*args,&block); fill_and_stroke
|
54
|
+
when /^stroke_(.*)/
|
55
|
+
send($1,*args,&block); stroke
|
56
|
+
when /^fill_(.*)/
|
57
|
+
send($1,*args,&block); fill
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module_function
|
64
|
+
|
65
|
+
# Converts RGB value array to hex string suitable for use with fill_color
|
66
|
+
# and stroke_color
|
67
|
+
#
|
68
|
+
# >> Prawn::Graphics::Color.rgb2hex([255,120,8])
|
69
|
+
# => "ff7808"
|
70
|
+
#
|
71
|
+
def rgb2hex(rgb)
|
72
|
+
rgb.map { |e| "%02x" % e }.join
|
73
|
+
end
|
74
|
+
|
75
|
+
# Converts hex string into RGB value array:
|
76
|
+
#
|
77
|
+
# >> Prawn::Graphics::Color.hex2rgb("ff7808")
|
78
|
+
# => [255, 120, 8]
|
79
|
+
#
|
80
|
+
def hex2rgb(hex)
|
81
|
+
r,g,b = hex[0..1], hex[2..3], hex[4..5]
|
82
|
+
[r,g,b].map { |e| e.to_i(16) }
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def process_color(*color)
|
88
|
+
case(color.size)
|
89
|
+
when 1
|
90
|
+
color[0]
|
91
|
+
when 4
|
92
|
+
color
|
93
|
+
else
|
94
|
+
raise ArgumentError, 'wrong number of arguments supplied'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def set_fill_color
|
99
|
+
case @fill_color
|
100
|
+
when String
|
101
|
+
r,g,b = hex2rgb(@fill_color)
|
102
|
+
add_content "%.3f %.3f %.3f rg" %
|
103
|
+
[r / 255.0, g / 255.0, b / 255.0]
|
104
|
+
when Array
|
105
|
+
c,m,y,k = *@fill_color
|
106
|
+
add_content "%.3f %.3f %.3f %.3f k" %
|
107
|
+
[c / 100.0, m / 100.0, y / 100.0, k / 100.0]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def set_stroke_color
|
112
|
+
case @stroke_color
|
113
|
+
when String
|
114
|
+
r,g,b = hex2rgb(@stroke_color)
|
115
|
+
add_content "%.3f %.3f %.3f RG" %
|
116
|
+
[r / 255.0, g / 255.0, b / 255.0]
|
117
|
+
when Array
|
118
|
+
c,m,y,k = *@stroke_color
|
119
|
+
add_content "%.3f %.3f %.3f %.3f K" %
|
120
|
+
[c / 100.0, m / 100.0, y / 100.0, k / 100.0]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def update_colors
|
125
|
+
@fill_color ||= "000000"
|
126
|
+
@stroke_color ||= "000000"
|
127
|
+
set_fill_color
|
128
|
+
set_stroke_color
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|