prawn-core 0.7.2 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/examples/general/background.rb +1 -1
- data/examples/general/measurement_units.rb +2 -2
- data/examples/general/outlines.rb +50 -0
- data/examples/general/repeaters.rb +11 -7
- data/examples/general/stamp.rb +6 -6
- data/examples/graphics/basic_images.rb +1 -1
- data/examples/graphics/curves.rb +1 -1
- data/examples/graphics/rounded_polygons.rb +19 -0
- data/examples/graphics/rounded_rectangle.rb +20 -0
- data/examples/graphics/transformations.rb +52 -0
- data/examples/m17n/win_ansi_charset.rb +1 -1
- data/examples/text/font_calculations.rb +3 -3
- data/examples/text/indent_paragraphs.rb +18 -0
- data/examples/text/kerning.rb +4 -4
- data/examples/text/rotated.rb +98 -0
- data/examples/text/simple_text.rb +3 -3
- data/examples/text/simple_text_ttf.rb +1 -1
- data/lib/prawn/byte_string.rb +1 -0
- data/lib/prawn/core.rb +12 -5
- data/lib/prawn/core/object_store.rb +99 -0
- data/lib/prawn/core/page.rb +96 -0
- data/lib/prawn/core/text.rb +75 -0
- data/lib/prawn/document.rb +71 -78
- data/lib/prawn/document/annotations.rb +2 -2
- data/lib/prawn/document/bounding_box.rb +19 -9
- data/lib/prawn/document/column_box.rb +13 -12
- data/lib/prawn/document/graphics_state.rb +49 -0
- data/lib/prawn/document/internals.rb +5 -40
- data/lib/prawn/document/page_geometry.rb +1 -18
- data/lib/prawn/document/snapshot.rb +12 -7
- data/lib/prawn/errors.rb +18 -0
- data/lib/prawn/font.rb +4 -2
- data/lib/prawn/font/afm.rb +8 -0
- data/lib/prawn/font/dfont.rb +12 -4
- data/lib/prawn/font/ttf.rb +9 -0
- data/lib/prawn/graphics.rb +66 -9
- data/lib/prawn/graphics/color.rb +1 -1
- data/lib/prawn/graphics/transformation.rb +156 -0
- data/lib/prawn/graphics/transparency.rb +3 -7
- data/lib/prawn/images.rb +4 -3
- data/lib/prawn/images/png.rb +2 -2
- data/lib/prawn/outline.rb +278 -0
- data/lib/prawn/pdf_object.rb +5 -3
- data/lib/prawn/repeater.rb +25 -13
- data/lib/prawn/stamp.rb +6 -29
- data/lib/prawn/text.rb +139 -121
- data/lib/prawn/text/box.rb +168 -102
- data/spec/bounding_box_spec.rb +7 -2
- data/spec/document_spec.rb +7 -5
- data/spec/font_spec.rb +9 -1
- data/spec/graphics_spec.rb +229 -0
- data/spec/object_store_spec.rb +5 -5
- data/spec/outline_spec.rb +229 -0
- data/spec/repeater_spec.rb +18 -1
- data/spec/snapshot_spec.rb +7 -7
- data/spec/span_spec.rb +6 -2
- data/spec/spec_helper.rb +7 -3
- data/spec/stamp_spec.rb +13 -0
- data/spec/text_at_spec.rb +119 -0
- data/spec/text_box_spec.rb +257 -4
- data/spec/text_spec.rb +278 -180
- data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +12 -0
- metadata +16 -3
- data/lib/prawn/object_store.rb +0 -92
data/spec/text_spec.rb
CHANGED
@@ -18,188 +18,218 @@ describe "#height_of" do
|
|
18
18
|
@pdf.height_of("text", :width => 1)
|
19
19
|
end.should.raise(Prawn::Errors::CannotFit)
|
20
20
|
end
|
21
|
+
|
22
|
+
it "should raise Prawn::Errors::UnknownOption if :indent_paragraphs option is provided" do
|
23
|
+
lambda {
|
24
|
+
@pdf.height_of("hai", :width => 300,
|
25
|
+
:indent_paragraphs => 60)
|
26
|
+
}.should.raise(Prawn::Errors::UnknownOption)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not raise Prawn::Errors::UnknownOption if :final_gap option is provided" do
|
30
|
+
lambda {
|
31
|
+
@pdf.height_of("hai", :width => 300,
|
32
|
+
:final_gap => true)
|
33
|
+
}.should.not.raise(Prawn::Errors::UnknownOption)
|
34
|
+
end
|
35
|
+
|
21
36
|
end
|
22
37
|
|
23
|
-
describe "
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
38
|
+
describe "#text" do
|
39
|
+
before(:each) { create_pdf }
|
40
|
+
|
41
|
+
it "should raise ArgumentError if :at option included" do
|
42
|
+
lambda { @pdf.text("hai", :at => [0, 0]) }.should.raise(ArgumentError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should advance down the document based on font_height" do
|
46
|
+
position = @pdf.y
|
47
|
+
@pdf.text "Foo"
|
48
|
+
|
49
|
+
@pdf.y.should.be.close(position - @pdf.font.height, 0.0001)
|
50
|
+
|
51
|
+
position = @pdf.y
|
52
|
+
@pdf.text "Foo\nBar\nBaz"
|
53
|
+
@pdf.y.should.be.close(position - 3*@pdf.font.height, 0.0001)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should advance down the document based on font_height" +
|
57
|
+
" with size option" do
|
58
|
+
position = @pdf.y
|
59
|
+
@pdf.text "Foo", :size => 15
|
60
|
+
|
61
|
+
@pdf.font_size = 15
|
62
|
+
@pdf.y.should.be.close(position - @pdf.font.height, 0.0001)
|
63
|
+
|
64
|
+
position = @pdf.y
|
65
|
+
@pdf.text "Foo\nBar\nBaz"
|
66
|
+
@pdf.y.should.be.close(position - 3*@pdf.font.height, 0.0001)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should advance down the document based on font_height" +
|
70
|
+
" with leading option" do
|
71
|
+
position = @pdf.y
|
72
|
+
leading = 2
|
73
|
+
@pdf.text "Foo", :leading => leading
|
74
|
+
|
75
|
+
@pdf.y.should.be.close(position - @pdf.font.height - leading, 0.0001)
|
76
|
+
|
77
|
+
position = @pdf.y
|
78
|
+
@pdf.text "Foo\nBar\nBaz"
|
79
|
+
@pdf.y.should.be.close(position - 3*@pdf.font.height, 0.0001)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should advance down the document based on font ascender only "+
|
83
|
+
"if final_gap is given" do
|
84
|
+
position = @pdf.y
|
85
|
+
@pdf.text "Foo", :final_gap => false
|
86
|
+
|
87
|
+
@pdf.y.should.be.close(position - @pdf.font.ascender, 0.0001)
|
88
|
+
|
89
|
+
position = @pdf.y
|
90
|
+
@pdf.text "Foo\nBar\nBaz", :final_gap => false
|
91
|
+
@pdf.y.should.be.close(position - 2*@pdf.font.height - @pdf.font.ascender, 0.0001)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should default to 12 point helvetica" do
|
95
|
+
@pdf.text "Blah"
|
96
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
97
|
+
text.font_settings[0][:name].should == :Helvetica
|
98
|
+
text.font_settings[0][:size].should == 12
|
99
|
+
text.strings.first.should == "Blah"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should allow setting font size" do
|
103
|
+
@pdf.text "Blah", :size => 16
|
104
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
105
|
+
text.font_settings[0][:size].should == 16
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should allow setting a default font size" do
|
109
|
+
@pdf.font_size = 16
|
110
|
+
@pdf.text "Blah"
|
111
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
112
|
+
text.font_settings[0][:size].should == 16
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should allow overriding default font for a single instance" do
|
116
|
+
@pdf.font_size = 16
|
117
|
+
|
118
|
+
@pdf.text "Blah", :size => 11
|
119
|
+
@pdf.text "Blaz"
|
120
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
121
|
+
text.font_settings[0][:size].should == 11
|
122
|
+
text.font_settings[1][:size].should == 16
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should allow setting a font size transaction with a block" do
|
126
|
+
@pdf.font_size 16 do
|
127
|
+
@pdf.text 'Blah'
|
128
|
+
end
|
129
|
+
|
130
|
+
@pdf.text 'blah'
|
131
|
+
|
132
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
133
|
+
text.font_settings[0][:size].should == 16
|
134
|
+
text.font_settings[1][:size].should == 12
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should allow manual setting the font size " +
|
138
|
+
"when in a font size block" do
|
139
|
+
@pdf.font_size(16) do
|
140
|
+
@pdf.text 'Foo'
|
141
|
+
@pdf.text 'Blah', :size => 11
|
142
|
+
@pdf.text 'Blaz'
|
143
|
+
end
|
144
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
145
|
+
text.font_settings[0][:size].should == 16
|
146
|
+
text.font_settings[1][:size].should == 11
|
147
|
+
text.font_settings[2][:size].should == 16
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should allow registering of built-in font_settings on the fly" do
|
151
|
+
@pdf.font "Times-Roman"
|
152
|
+
@pdf.text "Blah"
|
153
|
+
@pdf.font "Courier"
|
154
|
+
@pdf.text "Blaz"
|
155
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
156
|
+
text.font_settings[0][:name].should == :"Times-Roman"
|
157
|
+
text.font_settings[1][:name].should == :Courier
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should utilise the same default font across multiple pages" do
|
161
|
+
@pdf.text "Blah"
|
162
|
+
@pdf.start_new_page
|
163
|
+
@pdf.text "Blaz"
|
164
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
165
|
+
|
166
|
+
text.font_settings.size.should == 2
|
167
|
+
text.font_settings[0][:name].should == :Helvetica
|
168
|
+
text.font_settings[1][:name].should == :Helvetica
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should raise an exception when an unknown font is used" do
|
172
|
+
lambda { @pdf.font "Pao bu" }.should.raise(Prawn::Errors::UnknownFont)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should correctly render a utf-8 string when using a built-in font" do
|
176
|
+
str = "©" # copyright symbol
|
177
|
+
@pdf.text str
|
178
|
+
|
179
|
+
# grab the text from the rendered PDF and ensure it matches
|
180
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
181
|
+
text.strings.first.should == str
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should correctly render a string with higher bit characters across" +
|
185
|
+
" a page break when using a built-in font" do
|
186
|
+
str = "©"
|
187
|
+
@pdf.move_cursor_to(@pdf.font.height)
|
188
|
+
@pdf.text(str + "\n" + str)
|
189
|
+
|
190
|
+
# grab the text from the rendered PDF and ensure it matches
|
191
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
192
|
+
text.strings[1].should == str.strip
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should correctly render a string with higher bit characters across" +
|
196
|
+
" a page break when using a built-in font and :indent_paragraphs option" do
|
197
|
+
str = "©"
|
198
|
+
@pdf.move_cursor_to(@pdf.font.height)
|
199
|
+
@pdf.text(str + "\n" + str, :indent_paragraphs => 20)
|
200
|
+
|
201
|
+
# grab the text from the rendered PDF and ensure it matches
|
202
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
203
|
+
text.strings[1].should == str.strip
|
204
|
+
end
|
205
|
+
|
206
|
+
if "spec".respond_to?(:encode!)
|
207
|
+
# Handle non utf-8 string encodings in a sane way on M17N aware VMs
|
208
|
+
it "should raise an exception when a utf-8 incompatible string is rendered" do
|
209
|
+
str = "Blah \xDD"
|
210
|
+
str.force_encoding("ASCII-8BIT")
|
211
|
+
lambda { @pdf.text str }.should.raise(ArgumentError)
|
212
|
+
end
|
213
|
+
it "should not raise an exception when a shift-jis string is rendered" do
|
214
|
+
datafile = "#{Prawn::BASEDIR}/data/shift_jis_text.txt"
|
215
|
+
sjis_str = File.open(datafile, "r:shift_jis") { |f| f.gets }
|
216
|
+
@pdf.font("#{Prawn::BASEDIR}/data/fonts/gkai00mp.ttf")
|
217
|
+
lambda { @pdf.text sjis_str }.should.not.raise(ArgumentError)
|
218
|
+
end
|
219
|
+
else
|
220
|
+
# Handle non utf-8 string encodings in a sane way on non-M17N aware VMs
|
221
|
+
it "should raise an exception when a corrupt utf-8 string is rendered" do
|
222
|
+
str = "Blah \xDD"
|
223
|
+
lambda { @pdf.text str }.should.raise(ArgumentError)
|
224
|
+
end
|
225
|
+
it "should raise an exception when a shift-jis string is rendered" do
|
226
|
+
sjis_str = File.read("#{Prawn::BASEDIR}/data/shift_jis_text.txt")
|
227
|
+
lambda { @pdf.text sjis_str }.should.raise(ArgumentError)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should call move_past_bottom when printing more text than can fit" +
|
232
|
+
" between the current document.y and bounds.bottom" do
|
203
233
|
@pdf.y = @pdf.font.height
|
204
234
|
@pdf.text "Hello"
|
205
235
|
@pdf.text "World"
|
@@ -208,4 +238,72 @@ describe "when drawing text" do
|
|
208
238
|
pages[0][:strings].should == ["Hello"]
|
209
239
|
pages[1][:strings].should == ["World"]
|
210
240
|
end
|
241
|
+
|
242
|
+
it "should be able to use a custom word-wrap object" do
|
243
|
+
hello = "hello " * 25
|
244
|
+
world = "world " * 25
|
245
|
+
@pdf.text(hello + "\n" + world, :line_wrap => TestWordWrap.new)
|
246
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
247
|
+
text.strings[0].should == hello.strip
|
248
|
+
text.strings[1].should == world.strip
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should be able to globally set the custom word-wrap object" do
|
252
|
+
hello = "hello " * 25
|
253
|
+
world = "world " * 25
|
254
|
+
@pdf.default_line_wrap = TestWordWrap.new
|
255
|
+
@pdf.text(hello + "\n" + world)
|
256
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
257
|
+
text.strings[0].should == hello.strip
|
258
|
+
text.strings[1].should == world.strip
|
259
|
+
end
|
260
|
+
|
261
|
+
describe "with :indent_paragraphs option" do
|
262
|
+
it "should indent the paragraphs" do
|
263
|
+
hello = "hello " * 50
|
264
|
+
hello2 = "hello " * 50
|
265
|
+
@pdf.text(hello + "\n" + hello2, :indent_paragraphs => 60)
|
266
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
267
|
+
text.strings[0].should == ("hello " * 19).strip
|
268
|
+
text.strings[1].should == ("hello " * 21).strip
|
269
|
+
text.strings[3].should == ("hello " * 19).strip
|
270
|
+
text.strings[4].should == ("hello " * 21).strip
|
271
|
+
end
|
272
|
+
describe "when wrap to new page, and first line of new page" +
|
273
|
+
" is not the start of a new paragraph, that line should" +
|
274
|
+
" not be indented" do
|
275
|
+
it "should indent the paragraphs" do
|
276
|
+
hello = "hello " * 50
|
277
|
+
hello2 = "hello " * 50
|
278
|
+
@pdf.move_cursor_to(@pdf.font.height)
|
279
|
+
@pdf.text(hello + "\n" + hello2, :indent_paragraphs => 60)
|
280
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
281
|
+
text.strings[0].should == ("hello " * 19).strip
|
282
|
+
text.strings[1].should == ("hello " * 21).strip
|
283
|
+
text.strings[3].should == ("hello " * 19).strip
|
284
|
+
text.strings[4].should == ("hello " * 21).strip
|
285
|
+
end
|
286
|
+
end
|
287
|
+
describe "when wrap to new page, and first line of new page" +
|
288
|
+
" is the start of a new paragraph, that line should" +
|
289
|
+
" be indented" do
|
290
|
+
it "should indent the paragraphs" do
|
291
|
+
hello = "hello " * 50
|
292
|
+
hello2 = "hello " * 50
|
293
|
+
@pdf.move_cursor_to(@pdf.font.height * 3)
|
294
|
+
@pdf.text(hello + "\n" + hello2, :indent_paragraphs => 60)
|
295
|
+
text = PDF::Inspector::Text.analyze(@pdf.render)
|
296
|
+
text.strings[0].should == ("hello " * 19).strip
|
297
|
+
text.strings[1].should == ("hello " * 21).strip
|
298
|
+
text.strings[3].should == ("hello " * 19).strip
|
299
|
+
text.strings[4].should == ("hello " * 21).strip
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
class TestWordWrap
|
306
|
+
def wrap_line(line, options)
|
307
|
+
line
|
308
|
+
end
|
211
309
|
end
|