prawn-core 0.7.2 → 0.8.4
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/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
|