prawn 2.0.1 → 2.0.2
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.
- checksums.yaml +4 -4
- data/Rakefile +7 -5
- data/lib/prawn.rb +4 -4
- data/lib/prawn/document.rb +47 -46
- data/lib/prawn/document/bounding_box.rb +13 -19
- data/lib/prawn/document/column_box.rb +3 -5
- data/lib/prawn/document/internals.rb +0 -1
- data/lib/prawn/document/span.rb +12 -12
- data/lib/prawn/errors.rb +32 -33
- data/lib/prawn/font.rb +29 -36
- data/lib/prawn/font/afm.rb +20 -20
- data/lib/prawn/font/dfont.rb +0 -1
- data/lib/prawn/font/ttf.rb +30 -27
- data/lib/prawn/font_metric_cache.rb +4 -8
- data/lib/prawn/graphics.rb +37 -42
- data/lib/prawn/graphics/cap_style.rb +1 -1
- data/lib/prawn/graphics/color.rb +21 -23
- data/lib/prawn/graphics/dash.rb +5 -6
- data/lib/prawn/graphics/join_style.rb +1 -2
- data/lib/prawn/graphics/patterns.rb +25 -21
- data/lib/prawn/graphics/transformation.rb +4 -5
- data/lib/prawn/graphics/transparency.rb +6 -8
- data/lib/prawn/grid.rb +21 -14
- data/lib/prawn/image_handler.rb +2 -2
- data/lib/prawn/images.rb +29 -31
- data/lib/prawn/images/image.rb +1 -1
- data/lib/prawn/images/jpg.rb +10 -12
- data/lib/prawn/images/png.rb +13 -13
- data/lib/prawn/measurements.rb +7 -14
- data/lib/prawn/outline.rb +6 -6
- data/lib/prawn/repeater.rb +1 -5
- data/lib/prawn/security.rb +17 -25
- data/lib/prawn/security/arcfour.rb +1 -1
- data/lib/prawn/soft_mask.rb +11 -12
- data/lib/prawn/stamp.rb +16 -8
- data/lib/prawn/text.rb +23 -20
- data/lib/prawn/text/box.rb +3 -6
- data/lib/prawn/text/formatted/arranger.rb +9 -12
- data/lib/prawn/text/formatted/box.rb +23 -22
- data/lib/prawn/text/formatted/fragment.rb +0 -4
- data/lib/prawn/text/formatted/line_wrap.rb +13 -24
- data/lib/prawn/text/formatted/parser.rb +16 -20
- data/lib/prawn/text/formatted/wrap.rb +2 -7
- data/lib/prawn/utilities.rb +6 -3
- data/lib/prawn/version.rb +1 -1
- data/manual/basic_concepts/basic_concepts.rb +0 -2
- data/manual/basic_concepts/view.rb +1 -1
- data/manual/bounding_box/bounding_box.rb +0 -3
- data/manual/bounding_box/russian_boxes.rb +7 -8
- data/manual/bounding_box/stretchy.rb +0 -1
- data/manual/contents.rb +2 -2
- data/manual/cover.rb +11 -12
- data/manual/document_and_page_options/document_and_page_options.rb +2 -5
- data/manual/document_and_page_options/metadata.rb +10 -10
- data/manual/document_and_page_options/page_size.rb +0 -1
- data/manual/graphics/fill_rules.rb +5 -4
- data/manual/graphics/graphics.rb +0 -3
- data/manual/graphics/lines_and_curves.rb +1 -1
- data/manual/graphics/rotate.rb +0 -2
- data/manual/graphics/scale.rb +4 -2
- data/manual/graphics/soft_masks.rb +0 -1
- data/manual/graphics/stroke_cap.rb +1 -1
- data/manual/graphics/stroke_join.rb +1 -1
- data/manual/graphics/translate.rb +3 -3
- data/manual/graphics/transparency.rb +0 -1
- data/manual/how_to_read_this_manual.rb +0 -1
- data/manual/images/images.rb +0 -3
- data/manual/layout/boxes.rb +5 -5
- data/manual/layout/content.rb +2 -2
- data/manual/layout/layout.rb +0 -3
- data/manual/outline/outline.rb +0 -3
- data/manual/repeatable_content/page_numbering.rb +1 -1
- data/manual/repeatable_content/repeatable_content.rb +0 -3
- data/manual/repeatable_content/repeater.rb +6 -6
- data/manual/security/encryption.rb +0 -2
- data/manual/security/permissions.rb +0 -2
- data/manual/security/security.rb +0 -3
- data/manual/text/alignment.rb +3 -3
- data/manual/text/color.rb +0 -1
- data/manual/text/column_box.rb +0 -1
- data/manual/text/fallback_fonts.rb +2 -2
- data/manual/text/formatted_callbacks.rb +3 -2
- data/manual/text/paragraph_indentation.rb +2 -3
- data/manual/text/registering_families.rb +13 -9
- data/manual/text/rotation.rb +0 -1
- data/manual/text/text.rb +0 -3
- data/manual/text/text_box_overflow.rb +7 -5
- data/manual/text/utf8.rb +1 -1
- data/manual/text/win_ansi_charset.rb +2 -2
- data/prawn.gemspec +4 -4
- data/spec/acceptance/png.rb +6 -7
- data/spec/annotations_spec.rb +21 -28
- data/spec/bounding_box_spec.rb +100 -109
- data/spec/column_box_spec.rb +26 -32
- data/spec/destinations_spec.rb +2 -4
- data/spec/document_spec.rb +145 -151
- data/spec/extensions/mocha.rb +0 -1
- data/spec/font_metric_cache_spec.rb +7 -7
- data/spec/font_spec.rb +103 -102
- data/spec/formatted_text_arranger_spec.rb +76 -74
- data/spec/formatted_text_box_spec.rb +170 -159
- data/spec/formatted_text_fragment_spec.rb +57 -56
- data/spec/graphics_spec.rb +158 -175
- data/spec/grid_spec.rb +28 -29
- data/spec/image_handler_spec.rb +4 -5
- data/spec/images_spec.rb +50 -36
- data/spec/inline_formatted_text_parser_spec.rb +397 -393
- data/spec/jpg_spec.rb +4 -6
- data/spec/line_wrap_spec.rb +54 -55
- data/spec/measurement_units_spec.rb +12 -15
- data/spec/outline_spec.rb +77 -98
- data/spec/png_spec.rb +55 -65
- data/spec/reference_spec.rb +3 -3
- data/spec/repeater_spec.rb +20 -26
- data/spec/security_spec.rb +42 -49
- data/spec/soft_mask_spec.rb +4 -5
- data/spec/span_spec.rb +5 -6
- data/spec/spec_helper.rb +2 -4
- data/spec/stamp_spec.rb +41 -22
- data/spec/stroke_styles_spec.rb +36 -39
- data/spec/text_at_spec.rb +28 -29
- data/spec/text_box_spec.rb +160 -165
- data/spec/text_rendering_mode_spec.rb +9 -9
- data/spec/text_spacing_spec.rb +13 -13
- data/spec/text_spec.rb +116 -124
- data/spec/text_with_inline_formatting_spec.rb +5 -5
- data/spec/transparency_spec.rb +20 -20
- data/spec/view_spec.rb +0 -1
- metadata +7 -7
data/spec/png_spec.rb
CHANGED
@@ -10,7 +10,6 @@
|
|
10
10
|
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
11
11
|
|
12
12
|
describe "When reading a greyscale PNG file (color type 0)" do
|
13
|
-
|
14
13
|
before(:each) do
|
15
14
|
@filename = "#{Prawn::DATADIR}/images/web-links.png"
|
16
15
|
@data_filename = "#{Prawn::DATADIR}/images/web-links.dat"
|
@@ -20,24 +19,23 @@ describe "When reading a greyscale PNG file (color type 0)" do
|
|
20
19
|
it "should read the attributes from the header chunk correctly" do
|
21
20
|
png = Prawn::Images::PNG.new(@img_data)
|
22
21
|
|
23
|
-
png.width.
|
24
|
-
png.height.
|
25
|
-
png.bits.
|
26
|
-
png.color_type.
|
27
|
-
png.compression_method.
|
28
|
-
png.filter_method.
|
29
|
-
png.interlace_method.
|
22
|
+
expect(png.width).to eq(21)
|
23
|
+
expect(png.height).to eq(14)
|
24
|
+
expect(png.bits).to eq(8)
|
25
|
+
expect(png.color_type).to eq(0)
|
26
|
+
expect(png.compression_method).to eq(0)
|
27
|
+
expect(png.filter_method).to eq(0)
|
28
|
+
expect(png.interlace_method).to eq(0)
|
30
29
|
end
|
31
30
|
|
32
31
|
it "should read the image data chunk correctly" do
|
33
32
|
png = Prawn::Images::PNG.new(@img_data)
|
34
33
|
data = Zlib::Inflate.inflate(File.binread(@data_filename))
|
35
|
-
png.img_data.
|
34
|
+
expect(png.img_data).to eq(data)
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
38
|
describe "When reading a greyscale PNG file with transparency (color type 0)" do
|
40
|
-
|
41
39
|
before(:each) do
|
42
40
|
@filename = "#{Prawn::DATADIR}/images/ruport_type0.png"
|
43
41
|
@img_data = File.binread(@filename)
|
@@ -49,12 +47,11 @@ describe "When reading a greyscale PNG file with transparency (color type 0)" do
|
|
49
47
|
# http://www.w3.org/TR/PNG/#11tRNS
|
50
48
|
it "should read the tRNS chunk correctly" do
|
51
49
|
png = Prawn::Images::PNG.new(@img_data)
|
52
|
-
png.transparency[:grayscale].
|
50
|
+
expect(png.transparency[:grayscale]).to eq(255)
|
53
51
|
end
|
54
52
|
end
|
55
53
|
|
56
54
|
describe "When reading an RGB PNG file (color type 2)" do
|
57
|
-
|
58
55
|
before(:each) do
|
59
56
|
@filename = "#{Prawn::DATADIR}/images/ruport.png"
|
60
57
|
@data_filename = "#{Prawn::DATADIR}/images/ruport_data.dat"
|
@@ -64,24 +61,23 @@ describe "When reading an RGB PNG file (color type 2)" do
|
|
64
61
|
it "should read the attributes from the header chunk correctly" do
|
65
62
|
png = Prawn::Images::PNG.new(@img_data)
|
66
63
|
|
67
|
-
png.width.
|
68
|
-
png.height.
|
69
|
-
png.bits.
|
70
|
-
png.color_type.
|
71
|
-
png.compression_method.
|
72
|
-
png.filter_method.
|
73
|
-
png.interlace_method.
|
64
|
+
expect(png.width).to eq(258)
|
65
|
+
expect(png.height).to eq(105)
|
66
|
+
expect(png.bits).to eq(8)
|
67
|
+
expect(png.color_type).to eq(2)
|
68
|
+
expect(png.compression_method).to eq(0)
|
69
|
+
expect(png.filter_method).to eq(0)
|
70
|
+
expect(png.interlace_method).to eq(0)
|
74
71
|
end
|
75
72
|
|
76
73
|
it "should read the image data chunk correctly" do
|
77
74
|
png = Prawn::Images::PNG.new(@img_data)
|
78
75
|
data = Zlib::Inflate.inflate(File.binread(@data_filename))
|
79
|
-
png.img_data.
|
76
|
+
expect(png.img_data).to eq(data)
|
80
77
|
end
|
81
78
|
end
|
82
79
|
|
83
80
|
describe "When reading an RGB PNG file with transparency (color type 2)" do
|
84
|
-
|
85
81
|
before(:each) do
|
86
82
|
@filename = "#{Prawn::DATADIR}/images/arrow2.png"
|
87
83
|
@img_data = File.binread(@filename)
|
@@ -94,22 +90,19 @@ describe "When reading an RGB PNG file with transparency (color type 2)" do
|
|
94
90
|
# http://www.w3.org/TR/PNG/#11tRNS
|
95
91
|
it "should read the tRNS chunk correctly" do
|
96
92
|
png = Prawn::Images::PNG.new(@img_data)
|
97
|
-
png.transparency[:rgb].
|
93
|
+
expect(png.transparency[:rgb]).to eq([0, 255, 0])
|
98
94
|
end
|
99
95
|
end
|
100
96
|
|
101
|
-
describe "When reading an indexed color PNG file "
|
102
|
-
"wiih transparency (color type 3)" do
|
103
|
-
|
97
|
+
describe "When reading an indexed color PNG file with transparency (color type 3)" do
|
104
98
|
it "raises a not supported error" do
|
105
99
|
bin = File.binread("#{Prawn::DATADIR}/images/pal_bk.png")
|
106
|
-
expect { Prawn::Images::PNG.new(bin)}.to(
|
100
|
+
expect { Prawn::Images::PNG.new(bin) }.to(
|
107
101
|
raise_error(Prawn::Errors::UnsupportedImageType))
|
108
102
|
end
|
109
103
|
end
|
110
104
|
|
111
105
|
describe "When reading an indexed color PNG file (color type 3)" do
|
112
|
-
|
113
106
|
before(:each) do
|
114
107
|
@filename = "#{Prawn::DATADIR}/images/indexed_color.png"
|
115
108
|
@data_filename = "#{Prawn::DATADIR}/images/indexed_color.dat"
|
@@ -119,24 +112,23 @@ describe "When reading an indexed color PNG file (color type 3)" do
|
|
119
112
|
it "should read the attributes from the header chunk correctly" do
|
120
113
|
png = Prawn::Images::PNG.new(@img_data)
|
121
114
|
|
122
|
-
png.width.
|
123
|
-
png.height.
|
124
|
-
png.bits.
|
125
|
-
png.color_type.
|
126
|
-
png.compression_method.
|
127
|
-
png.filter_method.
|
128
|
-
png.interlace_method.
|
115
|
+
expect(png.width).to eq(150)
|
116
|
+
expect(png.height).to eq(200)
|
117
|
+
expect(png.bits).to eq(8)
|
118
|
+
expect(png.color_type).to eq(3)
|
119
|
+
expect(png.compression_method).to eq(0)
|
120
|
+
expect(png.filter_method).to eq(0)
|
121
|
+
expect(png.interlace_method).to eq(0)
|
129
122
|
end
|
130
123
|
|
131
124
|
it "should read the image data chunk correctly" do
|
132
125
|
png = Prawn::Images::PNG.new(@img_data)
|
133
126
|
data = Zlib::Inflate.inflate(File.binread(@data_filename))
|
134
|
-
png.img_data.
|
127
|
+
expect(png.img_data).to eq(data)
|
135
128
|
end
|
136
129
|
end
|
137
130
|
|
138
131
|
describe "When reading a greyscale+alpha PNG file (color type 4)" do
|
139
|
-
|
140
132
|
before(:each) do
|
141
133
|
@filename = "#{Prawn::DATADIR}/images/page_white_text.png"
|
142
134
|
@color_data_filename = "#{Prawn::DATADIR}/images/page_white_text.color"
|
@@ -147,32 +139,31 @@ describe "When reading a greyscale+alpha PNG file (color type 4)" do
|
|
147
139
|
it "should read the attributes from the header chunk correctly" do
|
148
140
|
png = Prawn::Images::PNG.new(@img_data)
|
149
141
|
|
150
|
-
png.width.
|
151
|
-
png.height.
|
152
|
-
png.bits.
|
153
|
-
png.color_type.
|
154
|
-
png.compression_method.
|
155
|
-
png.filter_method.
|
156
|
-
png.interlace_method.
|
142
|
+
expect(png.width).to eq(16)
|
143
|
+
expect(png.height).to eq(16)
|
144
|
+
expect(png.bits).to eq(8)
|
145
|
+
expect(png.color_type).to eq(4)
|
146
|
+
expect(png.compression_method).to eq(0)
|
147
|
+
expect(png.filter_method).to eq(0)
|
148
|
+
expect(png.interlace_method).to eq(0)
|
157
149
|
end
|
158
150
|
|
159
151
|
it "should correctly return the raw image data (with no alpha channel) from the image data chunk" do
|
160
152
|
png = Prawn::Images::PNG.new(@img_data)
|
161
153
|
png.split_alpha_channel!
|
162
154
|
data = File.binread(@color_data_filename)
|
163
|
-
png.img_data.
|
155
|
+
expect(png.img_data).to eq(data)
|
164
156
|
end
|
165
157
|
|
166
158
|
it "should correctly extract the alpha channel data from the image data chunk" do
|
167
159
|
png = Prawn::Images::PNG.new(@img_data)
|
168
160
|
png.split_alpha_channel!
|
169
161
|
data = File.binread(@alpha_data_filename)
|
170
|
-
png.alpha_channel.
|
162
|
+
expect(png.alpha_channel).to eq(data)
|
171
163
|
end
|
172
164
|
end
|
173
165
|
|
174
166
|
describe "When reading an RGB+alpha PNG file (color type 6)" do
|
175
|
-
|
176
167
|
before(:each) do
|
177
168
|
@filename = "#{Prawn::DATADIR}/images/dice.png"
|
178
169
|
@color_data_filename = "#{Prawn::DATADIR}/images/dice.color"
|
@@ -183,32 +174,31 @@ describe "When reading an RGB+alpha PNG file (color type 6)" do
|
|
183
174
|
it "should read the attributes from the header chunk correctly" do
|
184
175
|
png = Prawn::Images::PNG.new(@img_data)
|
185
176
|
|
186
|
-
png.width.
|
187
|
-
png.height.
|
188
|
-
png.bits.
|
189
|
-
png.color_type.
|
190
|
-
png.compression_method.
|
191
|
-
png.filter_method.
|
192
|
-
png.interlace_method.
|
177
|
+
expect(png.width).to eq(320)
|
178
|
+
expect(png.height).to eq(240)
|
179
|
+
expect(png.bits).to eq(8)
|
180
|
+
expect(png.color_type).to eq(6)
|
181
|
+
expect(png.compression_method).to eq(0)
|
182
|
+
expect(png.filter_method).to eq(0)
|
183
|
+
expect(png.interlace_method).to eq(0)
|
193
184
|
end
|
194
185
|
|
195
186
|
it "should correctly return the raw image data (with no alpha channel) from the image data chunk" do
|
196
187
|
png = Prawn::Images::PNG.new(@img_data)
|
197
188
|
png.split_alpha_channel!
|
198
189
|
data = File.binread(@color_data_filename)
|
199
|
-
png.img_data.
|
190
|
+
expect(png.img_data).to eq(data)
|
200
191
|
end
|
201
192
|
|
202
193
|
it "should correctly extract the alpha channel data from the image data chunk" do
|
203
194
|
png = Prawn::Images::PNG.new(@img_data)
|
204
195
|
png.split_alpha_channel!
|
205
196
|
data = File.binread(@alpha_data_filename)
|
206
|
-
png.alpha_channel.
|
197
|
+
expect(png.alpha_channel).to eq(data)
|
207
198
|
end
|
208
199
|
end
|
209
200
|
|
210
201
|
describe "When reading a 16bit RGB+alpha PNG file (color type 6)" do
|
211
|
-
|
212
202
|
before(:each) do
|
213
203
|
@filename = "#{Prawn::DATADIR}/images/16bit.png"
|
214
204
|
@color_data_filename = "#{Prawn::DATADIR}/images/16bit.color"
|
@@ -220,26 +210,26 @@ describe "When reading a 16bit RGB+alpha PNG file (color type 6)" do
|
|
220
210
|
it "should read the attributes from the header chunk correctly" do
|
221
211
|
png = Prawn::Images::PNG.new(@img_data)
|
222
212
|
|
223
|
-
png.width.
|
224
|
-
png.height.
|
225
|
-
png.bits.
|
226
|
-
png.color_type.
|
227
|
-
png.compression_method.
|
228
|
-
png.filter_method.
|
229
|
-
png.interlace_method.
|
213
|
+
expect(png.width).to eq(32)
|
214
|
+
expect(png.height).to eq(32)
|
215
|
+
expect(png.bits).to eq(16)
|
216
|
+
expect(png.color_type).to eq(6)
|
217
|
+
expect(png.compression_method).to eq(0)
|
218
|
+
expect(png.filter_method).to eq(0)
|
219
|
+
expect(png.interlace_method).to eq(0)
|
230
220
|
end
|
231
221
|
|
232
222
|
it "should correctly return the raw image data (with no alpha channel) from the image data chunk" do
|
233
223
|
png = Prawn::Images::PNG.new(@img_data)
|
234
224
|
png.split_alpha_channel!
|
235
225
|
data = File.binread(@color_data_filename)
|
236
|
-
png.img_data.
|
226
|
+
expect(png.img_data).to eq(data)
|
237
227
|
end
|
238
228
|
|
239
229
|
it "should correctly extract the alpha channel data from the image data chunk" do
|
240
230
|
png = Prawn::Images::PNG.new(@img_data)
|
241
231
|
png.split_alpha_channel!
|
242
232
|
data = File.binread(@alpha_data_filename)
|
243
|
-
png.alpha_channel.
|
233
|
+
expect(png.alpha_channel).to eq(data)
|
244
234
|
end
|
245
235
|
end
|
data/spec/reference_spec.rb
CHANGED
@@ -6,20 +6,20 @@ describe "A Reference object" do
|
|
6
6
|
describe "generated via Prawn::Document" do
|
7
7
|
it "should return a proper reference on ref!" do
|
8
8
|
pdf = Prawn::Document.new
|
9
|
-
pdf.ref!({}).is_a?(PDF::Core::Reference).
|
9
|
+
expect(pdf.ref!({}).is_a?(PDF::Core::Reference)).to eq(true)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should return an identifier on ref" do
|
13
13
|
pdf = Prawn::Document.new
|
14
14
|
r = pdf.ref({})
|
15
|
-
r.is_a?(Integer).
|
15
|
+
expect(r.is_a?(Integer)).to eq(true)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should have :Length of stream if it has one when compression disabled" do
|
19
19
|
pdf = Prawn::Document.new :compress => false
|
20
20
|
ref = pdf.ref!({})
|
21
21
|
ref << 'Hello'
|
22
|
-
ref.stream.data[:Length].
|
22
|
+
expect(ref.stream.data[:Length]).to eq(5)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
data/spec/repeater_spec.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
4
4
|
|
5
5
|
describe "Repeaters" do
|
6
|
-
|
7
6
|
it "creates a stamp and increments Prawn::Repeater.count on initialize" do
|
8
7
|
orig_count = Prawn::Repeater.count
|
9
8
|
|
@@ -12,45 +11,45 @@ describe "Repeaters" do
|
|
12
11
|
|
13
12
|
r = repeater(doc, :all) { :do_nothing }
|
14
13
|
|
15
|
-
Prawn::Repeater.count.
|
14
|
+
expect(Prawn::Repeater.count).to eq(orig_count + 1)
|
16
15
|
end
|
17
16
|
|
18
17
|
it "must provide an :all filter" do
|
19
18
|
doc = sample_document
|
20
19
|
r = repeater(doc, :all) { :do_nothing }
|
21
20
|
|
22
|
-
(1..doc.page_count).all? { |i| r.match?(i) }.
|
21
|
+
expect((1..doc.page_count).all? { |i| r.match?(i) }).to be_true
|
23
22
|
end
|
24
23
|
|
25
24
|
it "must provide an :odd filter" do
|
26
25
|
doc = sample_document
|
27
26
|
r = repeater(doc, :odd) { :do_nothing }
|
28
27
|
|
29
|
-
odd, even = (1..doc.page_count).partition
|
28
|
+
odd, even = (1..doc.page_count).partition(&:odd?)
|
30
29
|
|
31
|
-
odd.all? { |i| r.match?(i) }.
|
32
|
-
even.any? { |i| r.match?(i) }.
|
30
|
+
expect(odd.all? { |i| r.match?(i) }).to be_true
|
31
|
+
expect(even.any? { |i| r.match?(i) }).to be_false
|
33
32
|
end
|
34
33
|
|
35
34
|
it "must be able to filter by an array of page numbers" do
|
36
35
|
doc = sample_document
|
37
|
-
r = repeater(doc, [1,2,7]) { :do_nothing }
|
36
|
+
r = repeater(doc, [1, 2, 7]) { :do_nothing }
|
38
37
|
|
39
|
-
(1..10).select { |i| r.match?(i) }.
|
38
|
+
expect((1..10).select { |i| r.match?(i) }).to eq([1, 2, 7])
|
40
39
|
end
|
41
40
|
|
42
41
|
it "must be able to filter by a range of page numbers" do
|
43
42
|
doc = sample_document
|
44
43
|
r = repeater(doc, 2..4) { :do_nothing }
|
45
44
|
|
46
|
-
(1..10).select { |i| r.match?(i) }.
|
45
|
+
expect((1..10).select { |i| r.match?(i) }).to eq([2, 3, 4])
|
47
46
|
end
|
48
47
|
|
49
48
|
it "must be able to filter by an arbitrary proc" do
|
50
49
|
doc = sample_document
|
51
50
|
r = repeater(doc, lambda { |x| x == 1 or x % 3 == 0 })
|
52
51
|
|
53
|
-
(1..10).select { |i| r.match?(i) }.
|
52
|
+
expect((1..10).select { |i| r.match?(i) }).to eq([1, 3, 6, 9])
|
54
53
|
end
|
55
54
|
|
56
55
|
it "must try to run a stamp if the page number matches" do
|
@@ -71,21 +70,21 @@ describe "Repeaters" do
|
|
71
70
|
doc = sample_document
|
72
71
|
|
73
72
|
doc.expects(:stamp).never
|
74
|
-
(1..10).each { |p| repeater(doc, :all, true){:do_nothing}.run(p) }
|
73
|
+
(1..10).each { |p| repeater(doc, :all, true){ :do_nothing }.run(p) }
|
75
74
|
end
|
76
75
|
|
77
76
|
it "must try to run a block if the page number matches" do
|
78
77
|
doc = sample_document
|
79
78
|
|
80
79
|
doc.expects(:draw_text).twice
|
81
|
-
(1..10).each { |p| repeater(doc, [1,2], true){doc.draw_text "foo"}.run(p) }
|
80
|
+
(1..10).each { |p| repeater(doc, [1, 2], true){ doc.draw_text "foo" }.run(p) }
|
82
81
|
end
|
83
82
|
|
84
83
|
it "must not try to run a block unless the page number matches" do
|
85
84
|
doc = sample_document
|
86
85
|
|
87
86
|
doc.expects(:draw_text).never
|
88
|
-
repeater(doc, :odd, true){doc.draw_text "foo"}.run(2)
|
87
|
+
repeater(doc, :odd, true){ doc.draw_text "foo" }.run(2)
|
89
88
|
end
|
90
89
|
|
91
90
|
it "must treat any block as a closure" do
|
@@ -97,7 +96,7 @@ describe "Repeaters" do
|
|
97
96
|
end
|
98
97
|
|
99
98
|
text = PDF::Inspector::Text.analyze(doc.render)
|
100
|
-
text.strings.
|
99
|
+
expect(text.strings).to eq((1..10).to_a.map{ |p| "Page #{p}" })
|
101
100
|
end
|
102
101
|
|
103
102
|
it "must treat any block as a closure (Document.new instance_eval form)" do
|
@@ -112,7 +111,7 @@ describe "Repeaters" do
|
|
112
111
|
end
|
113
112
|
|
114
113
|
text = PDF::Inspector::Text.analyze(doc.render)
|
115
|
-
text.strings.
|
114
|
+
expect(text.strings).to eq((1..10).to_a.map{ |p| "Page #{p}" })
|
116
115
|
end
|
117
116
|
|
118
117
|
def sample_document
|
@@ -122,22 +121,20 @@ describe "Repeaters" do
|
|
122
121
|
end
|
123
122
|
|
124
123
|
def repeater(*args, &b)
|
125
|
-
Prawn::Repeater.new(*args
|
124
|
+
Prawn::Repeater.new(*args, &b)
|
126
125
|
end
|
127
126
|
|
128
127
|
context "graphic state" do
|
129
|
-
|
130
128
|
it "should not alter the graphic state stack color space" do
|
131
129
|
create_pdf
|
132
130
|
starting_color_space = @pdf.state.page.graphic_state.color_space.dup
|
133
131
|
@pdf.repeat :all do
|
134
132
|
@pdf.text "Testing", :size => 24, :style => :bold
|
135
133
|
end
|
136
|
-
@pdf.state.page.graphic_state.color_space.
|
134
|
+
expect(@pdf.state.page.graphic_state.color_space).to eq(starting_color_space)
|
137
135
|
end
|
138
136
|
|
139
137
|
context "dynamic repeaters" do
|
140
|
-
|
141
138
|
it "should preserve the graphic state at creation time" do
|
142
139
|
create_pdf
|
143
140
|
@pdf.repeat :all, :dynamic => true do
|
@@ -147,14 +144,11 @@ describe "Repeaters" do
|
|
147
144
|
@pdf.fill_color "666666"
|
148
145
|
@pdf.cap_style :round
|
149
146
|
text = PDF::Inspector::Text.analyze(@pdf.render)
|
150
|
-
text.strings.include?("fill_color: 666666").
|
151
|
-
text.strings.include?("fill_color: 000000").
|
152
|
-
text.strings.include?("cap_style: round").
|
153
|
-
text.strings.include?("cap_style: butt").
|
147
|
+
expect(text.strings.include?("fill_color: 666666")).to eq(false)
|
148
|
+
expect(text.strings.include?("fill_color: 000000")).to eq(true)
|
149
|
+
expect(text.strings.include?("cap_style: round")).to eq(false)
|
150
|
+
expect(text.strings.include?("cap_style: butt")).to eq(true)
|
154
151
|
end
|
155
|
-
|
156
152
|
end
|
157
|
-
|
158
153
|
end
|
159
|
-
|
160
154
|
end
|
data/spec/security_spec.rb
CHANGED
@@ -4,36 +4,32 @@ require "tempfile"
|
|
4
4
|
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
5
5
|
|
6
6
|
describe "Document encryption" do
|
7
|
-
|
8
7
|
describe "Password padding" do
|
9
|
-
|
10
8
|
include Prawn::Document::Security
|
11
9
|
|
12
10
|
it "should truncate long passwords" do
|
13
11
|
pw = "Long long string" * 30
|
14
12
|
padded = pad_password(pw)
|
15
|
-
padded.length.
|
16
|
-
padded.
|
13
|
+
expect(padded.length).to eq(32)
|
14
|
+
expect(padded).to eq(pw[0, 32])
|
17
15
|
end
|
18
16
|
|
19
17
|
it "should pad short passwords" do
|
20
18
|
pw = "abcd"
|
21
19
|
padded = pad_password(pw)
|
22
|
-
padded.length.
|
23
|
-
padded.
|
20
|
+
expect(padded.length).to eq(32)
|
21
|
+
expect(padded).to eq(pw + Prawn::Document::Security::PasswordPadding[0, 28])
|
24
22
|
end
|
25
23
|
|
26
24
|
it "should fully pad null passwords" do
|
27
25
|
pw = ""
|
28
26
|
padded = pad_password(pw)
|
29
|
-
padded.length.
|
30
|
-
padded.
|
27
|
+
expect(padded.length).to eq(32)
|
28
|
+
expect(padded).to eq(Prawn::Document::Security::PasswordPadding)
|
31
29
|
end
|
32
|
-
|
33
30
|
end
|
34
31
|
|
35
32
|
describe "Setting permissions" do
|
36
|
-
|
37
33
|
def doc_with_permissions(permissions)
|
38
34
|
pdf = Prawn::Document.new
|
39
35
|
|
@@ -47,31 +43,30 @@ describe "Document encryption" do
|
|
47
43
|
end
|
48
44
|
|
49
45
|
it "should default to full permissions" do
|
50
|
-
doc_with_permissions({}).permissions_value.
|
51
|
-
doc_with_permissions(:print_document => true,
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
46
|
+
expect(doc_with_permissions({}).permissions_value).to eq(0xFFFFFFFF)
|
47
|
+
expect(doc_with_permissions(:print_document => true,
|
48
|
+
:modify_contents => true,
|
49
|
+
:copy_contents => true,
|
50
|
+
:modify_annotations => true).permissions_value).
|
51
|
+
to eq(0xFFFFFFFF)
|
56
52
|
end
|
57
53
|
|
58
54
|
it "should clear the appropriate bits for each permission flag" do
|
59
|
-
doc_with_permissions(:print_document => false).permissions_value.
|
60
|
-
|
61
|
-
doc_with_permissions(:modify_contents => false).permissions_value.
|
62
|
-
|
63
|
-
doc_with_permissions(:copy_contents => false).permissions_value.
|
64
|
-
|
65
|
-
doc_with_permissions(:modify_annotations => false).permissions_value.
|
66
|
-
|
55
|
+
expect(doc_with_permissions(:print_document => false).permissions_value).
|
56
|
+
to eq(0b1111_1111_1111_1111_1111_1111_1111_1011)
|
57
|
+
expect(doc_with_permissions(:modify_contents => false).permissions_value).
|
58
|
+
to eq(0b1111_1111_1111_1111_1111_1111_1111_0111)
|
59
|
+
expect(doc_with_permissions(:copy_contents => false).permissions_value).
|
60
|
+
to eq(0b1111_1111_1111_1111_1111_1111_1110_1111)
|
61
|
+
expect(doc_with_permissions(:modify_annotations => false).permissions_value).
|
62
|
+
to eq(0b1111_1111_1111_1111_1111_1111_1101_1111)
|
67
63
|
end
|
68
64
|
|
69
65
|
it "should raise_error ArgumentError if invalid option is provided" do
|
70
|
-
|
66
|
+
expect {
|
71
67
|
doc_with_permissions(:modify_document => false)
|
72
|
-
}.
|
68
|
+
}.to raise_error(ArgumentError)
|
73
69
|
end
|
74
|
-
|
75
70
|
end
|
76
71
|
|
77
72
|
describe "Encryption keys" do
|
@@ -84,65 +79,64 @@ describe "Document encryption" do
|
|
84
79
|
class << @pdf
|
85
80
|
public :owner_password_hash, :user_password_hash, :user_encryption_key
|
86
81
|
end
|
87
|
-
@pdf.encrypt_document :user_password => 'foo',
|
88
|
-
|
82
|
+
@pdf.encrypt_document :user_password => 'foo',
|
83
|
+
:owner_password => 'bar',
|
84
|
+
:permissions => { :print_document => false }
|
89
85
|
end
|
90
86
|
|
91
87
|
it "should calculate the correct owner hash" do
|
92
|
-
@pdf.owner_password_hash.unpack("H*").first.
|
88
|
+
expect(@pdf.owner_password_hash.unpack("H*").first).to match(/^61CA855012/i)
|
93
89
|
end
|
94
90
|
|
95
91
|
it "should calculate the correct user hash" do
|
96
|
-
@pdf.user_password_hash.unpack("H*").first.
|
92
|
+
expect(@pdf.user_password_hash.unpack("H*").first).to match(/^6BC8C51031/i)
|
97
93
|
end
|
98
94
|
|
99
95
|
it "should calculate the correct user_encryption_key" do
|
100
|
-
@pdf.user_encryption_key.unpack("H*").first.upcase.
|
96
|
+
expect(@pdf.user_encryption_key.unpack("H*").first.upcase).to eq("B100AB6429")
|
101
97
|
end
|
102
|
-
|
103
|
-
|
104
98
|
end
|
105
99
|
|
106
100
|
describe "EncryptedPdfObject" do
|
107
|
-
|
108
101
|
it "should delegate to PdfObject for simple types" do
|
109
|
-
PDF::Core::EncryptedPdfObject(true, nil, nil, nil).
|
110
|
-
PDF::Core::EncryptedPdfObject(42, nil, nil, nil).
|
102
|
+
expect(PDF::Core::EncryptedPdfObject(true, nil, nil, nil)).to eq("true")
|
103
|
+
expect(PDF::Core::EncryptedPdfObject(42, nil, nil, nil)).to eq("42")
|
111
104
|
end
|
112
105
|
|
113
106
|
it "should encrypt strings properly" do
|
114
|
-
PDF::Core::EncryptedPdfObject("foo", "12345", 123, 0).
|
107
|
+
expect(PDF::Core::EncryptedPdfObject("foo", "12345", 123, 0)).to eq("<4ad6e3>")
|
115
108
|
end
|
116
109
|
|
117
110
|
it "should encrypt literal strings properly" do
|
118
|
-
|
119
|
-
|
111
|
+
expect(PDF::Core::EncryptedPdfObject(PDF::Core::LiteralString.new("foo"), "12345", 123, 0)).to eq(bin_string("(J\xD6\xE3)"))
|
112
|
+
expect(PDF::Core::EncryptedPdfObject(PDF::Core::LiteralString.new("lhfbqg3do5u0satu3fjf"), nil, 123, 0)).to eq(bin_string("(\xF1\x8B\\(\b\xBB\xE18S\x130~4*#\\(%\x87\xE7\x8E\\\n)"))
|
120
113
|
end
|
121
114
|
|
122
115
|
it "should encrypt time properly" do
|
123
|
-
|
116
|
+
expect(PDF::Core::EncryptedPdfObject(Time.utc(2050, 04, 26, 10, 17, 10), "12345", 123, 0)).to eq(bin_string("(h\x83\xBE\xDC\xEC\x99\x0F\xD7\\)%\x13\xD4$\xB8\xF0\x16\xB8\x80\xC5\xE91+\xCF)"))
|
124
117
|
end
|
125
118
|
|
126
119
|
it "should properly handle compound types" do
|
127
|
-
PDF::Core::EncryptedPdfObject({:Bar => "foo"}, "12345", 123, 0).
|
120
|
+
expect(PDF::Core::EncryptedPdfObject({ :Bar => "foo" }, "12345", 123, 0)).to eq(
|
128
121
|
"<< /Bar <4ad6e3>\n>>"
|
129
|
-
|
122
|
+
)
|
123
|
+
expect(PDF::Core::EncryptedPdfObject(["foo", "bar"], "12345", 123, 0)).to eq(
|
130
124
|
"[<4ad6e3> <4ed8fe>]"
|
125
|
+
)
|
131
126
|
end
|
132
|
-
|
133
127
|
end
|
134
128
|
|
135
129
|
describe "Reference#encrypted_object" do
|
136
130
|
it "should encrypt references properly" do
|
137
|
-
ref = PDF::Core::Reference(1,["foo"])
|
138
|
-
ref.encrypted_object(nil).
|
131
|
+
ref = PDF::Core::Reference(1, ["foo"])
|
132
|
+
expect(ref.encrypted_object(nil)).to eq("1 0 obj\n[<4fca3f>]\nendobj\n")
|
139
133
|
end
|
140
134
|
|
141
135
|
it "should encrypt references with streams properly" do
|
142
136
|
ref = PDF::Core::Reference(1, {})
|
143
137
|
ref << 'foo'
|
144
138
|
result = bin_string("1 0 obj\n<< /Length 3\n>>\nstream\nO\xCA?\nendstream\nendobj\n")
|
145
|
-
ref.encrypted_object(nil).
|
139
|
+
expect(ref.encrypted_object(nil)).to eq(result)
|
146
140
|
end
|
147
141
|
end
|
148
142
|
|
@@ -151,8 +145,7 @@ describe "Document encryption" do
|
|
151
145
|
stream = PDF::Core::Stream.new
|
152
146
|
stream << "foo"
|
153
147
|
result = bin_string("stream\nO\xCA?\nendstream\n")
|
154
|
-
stream.encrypted_object(nil, 1, 0).
|
148
|
+
expect(stream.encrypted_object(nil, 1, 0)).to eq(result)
|
155
149
|
end
|
156
150
|
end
|
157
|
-
|
158
151
|
end
|