prawn 1.1.0 → 2.4.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.
Files changed (309) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +1 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +9 -40
  7. data/lib/prawn/document/bounding_box.rb +54 -40
  8. data/lib/prawn/document/column_box.rb +8 -10
  9. data/lib/prawn/document/internals.rb +39 -146
  10. data/lib/prawn/document/span.rb +23 -17
  11. data/lib/prawn/document.rb +217 -182
  12. data/lib/prawn/encoding.rb +69 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +124 -104
  15. data/lib/prawn/font_metric_cache.rb +23 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +5 -12
  18. data/lib/prawn/fonts/otf.rb +11 -0
  19. data/lib/prawn/fonts/ttc.rb +36 -0
  20. data/lib/prawn/{font → fonts}/ttf.rb +140 -88
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +5 -5
  23. data/lib/prawn/graphics/color.rb +46 -44
  24. data/lib/prawn/graphics/dash.rb +27 -11
  25. data/lib/prawn/graphics/join_style.rb +11 -6
  26. data/lib/prawn/graphics/patterns.rb +220 -78
  27. data/lib/prawn/graphics/transformation.rb +20 -12
  28. data/lib/prawn/graphics/transparency.rb +20 -18
  29. data/lib/prawn/graphics.rb +153 -115
  30. data/lib/prawn/grid.rb +93 -50
  31. data/lib/prawn/image_handler.rb +4 -4
  32. data/lib/prawn/images/image.rb +3 -2
  33. data/lib/prawn/images/jpg.rb +31 -24
  34. data/lib/prawn/images/png.rb +101 -68
  35. data/lib/prawn/images.rb +64 -56
  36. data/lib/prawn/measurement_extensions.rb +10 -9
  37. data/lib/prawn/measurements.rb +20 -23
  38. data/lib/prawn/outline.rb +96 -75
  39. data/lib/prawn/repeater.rb +16 -16
  40. data/lib/prawn/security/arcfour.rb +2 -2
  41. data/lib/prawn/security.rb +100 -85
  42. data/lib/prawn/soft_mask.rb +37 -38
  43. data/lib/prawn/stamp.rb +28 -13
  44. data/lib/prawn/text/box.rb +24 -29
  45. data/lib/prawn/text/formatted/arranger.rb +108 -63
  46. data/lib/prawn/text/formatted/box.rb +187 -124
  47. data/lib/prawn/text/formatted/fragment.rb +24 -20
  48. data/lib/prawn/text/formatted/line_wrap.rb +133 -73
  49. data/lib/prawn/text/formatted/parser.rb +147 -127
  50. data/lib/prawn/text/formatted/wrap.rb +48 -35
  51. data/lib/prawn/text/formatted.rb +5 -5
  52. data/lib/prawn/text.rb +103 -68
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +10 -22
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +39 -54
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +34 -25
  60. data/manual/basic_concepts/creation.rb +10 -11
  61. data/manual/basic_concepts/cursor.rb +4 -5
  62. data/manual/basic_concepts/measurement.rb +8 -9
  63. data/manual/basic_concepts/origin.rb +5 -6
  64. data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
  65. data/manual/basic_concepts/view.rb +48 -0
  66. data/manual/bounding_box/bounding_box.rb +30 -28
  67. data/manual/bounding_box/bounds.rb +12 -13
  68. data/manual/bounding_box/canvas.rb +7 -8
  69. data/manual/bounding_box/creation.rb +6 -7
  70. data/manual/bounding_box/indentation.rb +14 -15
  71. data/manual/bounding_box/nesting.rb +25 -18
  72. data/manual/bounding_box/russian_boxes.rb +18 -18
  73. data/manual/bounding_box/stretchy.rb +12 -14
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -32
  76. data/manual/document_and_page_options/background.rb +15 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +24 -22
  78. data/manual/document_and_page_options/metadata.rb +20 -18
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -13
  81. data/manual/document_and_page_options/print_scaling.rb +18 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +52 -0
  84. data/manual/graphics/circle_and_ellipse.rb +4 -5
  85. data/manual/graphics/color.rb +7 -9
  86. data/manual/graphics/common_lines.rb +7 -8
  87. data/manual/graphics/fill_and_stroke.rb +5 -6
  88. data/manual/graphics/fill_rules.rb +12 -11
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +46 -40
  91. data/manual/graphics/helper.rb +19 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +8 -9
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -9
  97. data/manual/graphics/scale.rb +14 -13
  98. data/manual/graphics/soft_masks.rb +4 -6
  99. data/manual/graphics/stroke_cap.rb +7 -8
  100. data/manual/graphics/stroke_dash.rb +15 -16
  101. data/manual/graphics/stroke_join.rb +6 -7
  102. data/manual/graphics/translate.rb +10 -10
  103. data/manual/graphics/transparency.rb +7 -9
  104. data/manual/how_to_read_this_manual.rb +8 -9
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +10 -11
  108. data/manual/images/images.rb +28 -27
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +16 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +10 -11
  114. data/manual/layout/content.rb +9 -10
  115. data/manual/layout/layout.rb +17 -18
  116. data/manual/layout/simple_grid.rb +6 -7
  117. data/manual/outline/add_subsection_to.rb +20 -21
  118. data/manual/outline/insert_section_after.rb +15 -16
  119. data/manual/outline/outline.rb +22 -21
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +27 -23
  124. data/manual/repeatable_content/repeater.rb +15 -16
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +8 -11
  127. data/manual/security/permissions.rb +20 -15
  128. data/manual/security/security.rb +18 -18
  129. data/manual/table.rb +16 -0
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -12
  132. data/manual/text/column_box.rb +9 -11
  133. data/manual/text/fallback_fonts.rb +25 -21
  134. data/manual/text/font.rb +11 -12
  135. data/manual/text/font_size.rb +13 -14
  136. data/manual/text/font_style.rb +10 -8
  137. data/manual/text/formatted_callbacks.rb +33 -23
  138. data/manual/text/formatted_text.rb +36 -25
  139. data/manual/text/free_flowing_text.rb +22 -23
  140. data/manual/text/inline.rb +18 -19
  141. data/manual/text/kerning_and_character_spacing.rb +14 -15
  142. data/manual/text/leading.rb +7 -8
  143. data/manual/text/line_wrapping.rb +37 -18
  144. data/manual/text/paragraph_indentation.rb +15 -10
  145. data/manual/text/positioned_text.rb +16 -17
  146. data/manual/text/registering_families.rb +27 -24
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +30 -19
  149. data/manual/text/rotation.rb +33 -24
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +56 -54
  152. data/manual/text/text_box_excess.rb +20 -17
  153. data/manual/text/text_box_extensions.rb +18 -15
  154. data/manual/text/text_box_overflow.rb +24 -17
  155. data/manual/text/utf8.rb +12 -13
  156. data/manual/text/win_ansi_charset.rb +28 -25
  157. data/prawn.gemspec +45 -50
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  160. data/spec/prawn/document/column_box_spec.rb +75 -0
  161. data/spec/prawn/document/security_spec.rb +176 -0
  162. data/spec/prawn/document_annotations_spec.rb +76 -0
  163. data/spec/prawn/document_destinations_spec.rb +15 -0
  164. data/spec/prawn/document_grid_spec.rb +99 -0
  165. data/spec/prawn/document_reference_spec.rb +27 -0
  166. data/spec/prawn/document_span_spec.rb +44 -0
  167. data/spec/prawn/document_spec.rb +805 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +544 -0
  170. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  171. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  172. data/spec/prawn/graphics_spec.rb +872 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/prawn/image_handler_spec.rb +53 -0
  175. data/spec/prawn/images/jpg_spec.rb +20 -0
  176. data/spec/prawn/images/png_spec.rb +283 -0
  177. data/spec/prawn/images_spec.rb +229 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +512 -0
  180. data/spec/prawn/repeater_spec.rb +166 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +173 -0
  183. data/spec/prawn/text/box_spec.rb +1110 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +150 -0
  190. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  191. data/spec/prawn/text_spacing_spec.rb +95 -0
  192. data/spec/prawn/text_spec.rb +603 -0
  193. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  194. data/spec/prawn/transformation_stack_spec.rb +66 -0
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +19 -25
  198. data.tar.gz.sig +0 -0
  199. metadata +113 -276
  200. metadata.gz.sig +0 -0
  201. data/data/encodings/win_ansi.txt +0 -29
  202. data/data/images/16bit.alpha +0 -0
  203. data/data/images/16bit.color +0 -0
  204. data/data/images/16bit.png +0 -0
  205. data/data/images/arrow.png +0 -0
  206. data/data/images/arrow2.png +0 -0
  207. data/data/images/dice.alpha +0 -0
  208. data/data/images/dice.color +0 -0
  209. data/data/images/dice.png +0 -0
  210. data/data/images/dice_interlaced.png +0 -0
  211. data/data/images/fractal.jpg +0 -0
  212. data/data/images/indexed_color.dat +0 -0
  213. data/data/images/indexed_color.png +0 -0
  214. data/data/images/letterhead.jpg +0 -0
  215. data/data/images/license.md +0 -8
  216. data/data/images/page_white_text.alpha +0 -0
  217. data/data/images/page_white_text.color +0 -0
  218. data/data/images/page_white_text.png +0 -0
  219. data/data/images/pigs.jpg +0 -0
  220. data/data/images/prawn.png +0 -0
  221. data/data/images/ruport.png +0 -0
  222. data/data/images/ruport_data.dat +0 -0
  223. data/data/images/ruport_transparent.png +0 -0
  224. data/data/images/ruport_type0.png +0 -0
  225. data/data/images/stef.jpg +0 -0
  226. data/data/images/tru256.bmp +0 -0
  227. data/data/images/web-links.dat +0 -1
  228. data/data/images/web-links.png +0 -0
  229. data/data/pdfs/complex_template.pdf +0 -0
  230. data/data/pdfs/contains_ttf_font.pdf +0 -0
  231. data/data/pdfs/encrypted.pdf +0 -0
  232. data/data/pdfs/form.pdf +1 -819
  233. data/data/pdfs/hexagon.pdf +0 -61
  234. data/data/pdfs/indirect_reference.pdf +0 -86
  235. data/data/pdfs/multipage_template.pdf +0 -127
  236. data/data/pdfs/nested_pages.pdf +0 -118
  237. data/data/pdfs/page_without_mediabox.pdf +0 -193
  238. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  239. data/data/pdfs/two_hexagons.pdf +0 -90
  240. data/data/pdfs/version_1_6.pdf +0 -61
  241. data/data/shift_jis_text.txt +0 -1
  242. data/lib/prawn/document/graphics_state.rb +0 -73
  243. data/lib/prawn/font/afm.rb +0 -247
  244. data/lib/prawn/table/cell/image.rb +0 -69
  245. data/lib/prawn/table/cell/in_table.rb +0 -33
  246. data/lib/prawn/table/cell/span_dummy.rb +0 -93
  247. data/lib/prawn/table/cell/subtable.rb +0 -66
  248. data/lib/prawn/table/cell/text.rb +0 -154
  249. data/lib/prawn/table/cell.rb +0 -772
  250. data/lib/prawn/table/cells.rb +0 -255
  251. data/lib/prawn/table/column_width_calculator.rb +0 -182
  252. data/lib/prawn/table.rb +0 -644
  253. data/manual/table/basic_block.rb +0 -53
  254. data/manual/table/before_rendering_page.rb +0 -26
  255. data/manual/table/cell_border_lines.rb +0 -24
  256. data/manual/table/cell_borders_and_bg.rb +0 -31
  257. data/manual/table/cell_dimensions.rb +0 -30
  258. data/manual/table/cell_text.rb +0 -38
  259. data/manual/table/column_widths.rb +0 -30
  260. data/manual/table/content_and_subtables.rb +0 -39
  261. data/manual/table/creation.rb +0 -27
  262. data/manual/table/filtering.rb +0 -36
  263. data/manual/table/flow_and_header.rb +0 -17
  264. data/manual/table/image_cells.rb +0 -33
  265. data/manual/table/position.rb +0 -29
  266. data/manual/table/row_colors.rb +0 -20
  267. data/manual/table/span.rb +0 -30
  268. data/manual/table/style.rb +0 -22
  269. data/manual/table/table.rb +0 -52
  270. data/manual/table/width.rb +0 -27
  271. data/spec/acceptance/png.rb +0 -25
  272. data/spec/annotations_spec.rb +0 -74
  273. data/spec/bounding_box_spec.rb +0 -510
  274. data/spec/cell_spec.rb +0 -629
  275. data/spec/column_box_spec.rb +0 -65
  276. data/spec/destinations_spec.rb +0 -15
  277. data/spec/document_spec.rb +0 -730
  278. data/spec/extensions/mocha.rb +0 -46
  279. data/spec/font_metric_cache_spec.rb +0 -52
  280. data/spec/font_spec.rb +0 -449
  281. data/spec/formatted_text_arranger_spec.rb +0 -421
  282. data/spec/formatted_text_box_spec.rb +0 -639
  283. data/spec/formatted_text_fragment_spec.rb +0 -298
  284. data/spec/graphics_spec.rb +0 -669
  285. data/spec/grid_spec.rb +0 -96
  286. data/spec/image_handler_spec.rb +0 -54
  287. data/spec/images_spec.rb +0 -153
  288. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  289. data/spec/jpg_spec.rb +0 -25
  290. data/spec/line_wrap_spec.rb +0 -344
  291. data/spec/measurement_units_spec.rb +0 -25
  292. data/spec/outline_spec.rb +0 -430
  293. data/spec/png_spec.rb +0 -237
  294. data/spec/reference_spec.rb +0 -25
  295. data/spec/repeater_spec.rb +0 -160
  296. data/spec/security_spec.rb +0 -158
  297. data/spec/soft_mask_spec.rb +0 -79
  298. data/spec/span_spec.rb +0 -44
  299. data/spec/stamp_spec.rb +0 -160
  300. data/spec/stroke_styles_spec.rb +0 -211
  301. data/spec/table/span_dummy_spec.rb +0 -17
  302. data/spec/table_spec.rb +0 -1527
  303. data/spec/text_at_spec.rb +0 -115
  304. data/spec/text_box_spec.rb +0 -1034
  305. data/spec/text_rendering_mode_spec.rb +0 -45
  306. data/spec/text_spacing_spec.rb +0 -93
  307. data/spec/text_spec.rb +0 -437
  308. data/spec/text_with_inline_formatting_spec.rb +0 -35
  309. data/spec/transparency_spec.rb +0 -91
@@ -1,160 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
-
5
- describe "Repeaters" do
6
-
7
- it "creates a stamp and increments Prawn::Repeater.count on initialize" do
8
- orig_count = Prawn::Repeater.count
9
-
10
- doc = sample_document
11
- doc.expects(:create_stamp).with("prawn_repeater(#{orig_count})")
12
-
13
- r = repeater(doc, :all) { :do_nothing }
14
-
15
- Prawn::Repeater.count.should == orig_count + 1
16
- end
17
-
18
- it "must provide an :all filter" do
19
- doc = sample_document
20
- r = repeater(doc, :all) { :do_nothing }
21
-
22
- (1..doc.page_count).all? { |i| r.match?(i) }.should be_true
23
- end
24
-
25
- it "must provide an :odd filter" do
26
- doc = sample_document
27
- r = repeater(doc, :odd) { :do_nothing }
28
-
29
- odd, even = (1..doc.page_count).partition { |e| e % 2 == 1 }
30
-
31
- odd.all? { |i| r.match?(i) }.should be_true
32
- even.any? { |i| r.match?(i) }.should be_false
33
- end
34
-
35
- it "must be able to filter by an array of page numbers" do
36
- doc = sample_document
37
- r = repeater(doc, [1,2,7]) { :do_nothing }
38
-
39
- (1..10).select { |i| r.match?(i) }.should == [1,2,7]
40
- end
41
-
42
- it "must be able to filter by a range of page numbers" do
43
- doc = sample_document
44
- r = repeater(doc, 2..4) { :do_nothing }
45
-
46
- (1..10).select { |i| r.match?(i) }.should == [2,3,4]
47
- end
48
-
49
- it "must be able to filter by an arbitrary proc" do
50
- doc = sample_document
51
- r = repeater(doc, lambda { |x| x == 1 or x % 3 == 0 })
52
-
53
- (1..10).select { |i| r.match?(i) }.should == [1,3,6,9]
54
- end
55
-
56
- it "must try to run a stamp if the page number matches" do
57
- doc = sample_document
58
- doc.expects(:stamp)
59
-
60
- repeater(doc, :odd).run(3)
61
- end
62
-
63
- it "must not try to run a stamp unless the page number matches" do
64
- doc = sample_document
65
-
66
- doc.expects(:stamp).never
67
- repeater(doc, :odd).run(2)
68
- end
69
-
70
- it "must not try to run a stamp if dynamic is selected" do
71
- doc = sample_document
72
-
73
- doc.expects(:stamp).never
74
- (1..10).each { |p| repeater(doc, :all, true){:do_nothing}.run(p) }
75
- end
76
-
77
- it "must try to run a block if the page number matches" do
78
- doc = sample_document
79
-
80
- doc.expects(:draw_text).twice
81
- (1..10).each { |p| repeater(doc, [1,2], true){doc.draw_text "foo"}.run(p) }
82
- end
83
-
84
- it "must not try to run a block unless the page number matches" do
85
- doc = sample_document
86
-
87
- doc.expects(:draw_text).never
88
- repeater(doc, :odd, true){doc.draw_text "foo"}.run(2)
89
- end
90
-
91
- it "must treat any block as a closure" do
92
- doc = sample_document
93
-
94
- @page = "Page" # ensure access to ivars
95
- doc.repeat(:all, :dynamic => true) do
96
- doc.draw_text "#@page #{doc.page_number}", :at => [500, 0]
97
- end
98
-
99
- text = PDF::Inspector::Text.analyze(doc.render)
100
- text.strings.should == (1..10).to_a.map{|p| "Page #{p}"}
101
- end
102
-
103
- it "must treat any block as a closure (Document.new instance_eval form)" do
104
- doc = Prawn::Document.new(:skip_page_creation => true) do
105
- 10.times { start_new_page }
106
-
107
- @page = "Page"
108
- repeat(:all, :dynamic => true) do
109
- # ensure self is accessible here
110
- draw_text "#@page #{page_number}", :at => [500, 0]
111
- end
112
- end
113
-
114
- text = PDF::Inspector::Text.analyze(doc.render)
115
- text.strings.should == (1..10).to_a.map{|p| "Page #{p}"}
116
- end
117
-
118
- def sample_document
119
- doc = Prawn::Document.new(:skip_page_creation => true)
120
- 10.times { |e| doc.start_new_page }
121
- doc
122
- end
123
-
124
- def repeater(*args, &b)
125
- Prawn::Repeater.new(*args,&b)
126
- end
127
-
128
- context "graphic state" do
129
-
130
- it "should not alter the graphic state stack color space" do
131
- create_pdf
132
- starting_color_space = @pdf.state.page.graphic_state.color_space.dup
133
- @pdf.repeat :all do
134
- @pdf.text "Testing", :size => 24, :style => :bold
135
- end
136
- @pdf.state.page.graphic_state.color_space.should == starting_color_space
137
- end
138
-
139
- context "dynamic repeaters" do
140
-
141
- it "should preserve the graphic state at creation time" do
142
- create_pdf
143
- @pdf.repeat :all, :dynamic => true do
144
- @pdf.text "fill_color: #{@pdf.graphic_state.fill_color}"
145
- @pdf.text "cap_style: #{@pdf.graphic_state.cap_style}"
146
- end
147
- @pdf.fill_color "666666"
148
- @pdf.cap_style :round
149
- text = PDF::Inspector::Text.analyze(@pdf.render)
150
- text.strings.include?("fill_color: 666666").should == false
151
- text.strings.include?("fill_color: 000000").should == true
152
- text.strings.include?("cap_style: round").should == false
153
- text.strings.include?("cap_style: butt").should == true
154
- end
155
-
156
- end
157
-
158
- end
159
-
160
- end
@@ -1,158 +0,0 @@
1
- # encoding: utf-8
2
- require "tempfile"
3
-
4
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
5
-
6
- describe "Document encryption" do
7
-
8
- describe "Password padding" do
9
-
10
- include Prawn::Document::Security
11
-
12
- it "should truncate long passwords" do
13
- pw = "Long long string" * 30
14
- padded = pad_password(pw)
15
- padded.length.should == 32
16
- padded.should == pw[0, 32]
17
- end
18
-
19
- it "should pad short passwords" do
20
- pw = "abcd"
21
- padded = pad_password(pw)
22
- padded.length.should == 32
23
- padded.should == pw + Prawn::Document::Security::PasswordPadding[0, 28]
24
- end
25
-
26
- it "should fully pad null passwords" do
27
- pw = ""
28
- padded = pad_password(pw)
29
- padded.length.should == 32
30
- padded.should == Prawn::Document::Security::PasswordPadding
31
- end
32
-
33
- end
34
-
35
- describe "Setting permissions" do
36
-
37
- def doc_with_permissions(permissions)
38
- pdf = Prawn::Document.new
39
-
40
- class << pdf
41
- # Make things easier to test
42
- public :permissions_value
43
- end
44
-
45
- pdf.encrypt_document(:permissions => permissions)
46
- pdf
47
- end
48
-
49
- it "should default to full permissions" do
50
- doc_with_permissions({}).permissions_value.should == 0xFFFFFFFF
51
- doc_with_permissions(:print_document => true,
52
- :modify_contents => true,
53
- :copy_contents => true,
54
- :modify_annotations => true).permissions_value.
55
- should == 0xFFFFFFFF
56
- end
57
-
58
- it "should clear the appropriate bits for each permission flag" do
59
- doc_with_permissions(:print_document => false).permissions_value.
60
- should == 0b1111_1111_1111_1111_1111_1111_1111_1011
61
- doc_with_permissions(:modify_contents => false).permissions_value.
62
- should == 0b1111_1111_1111_1111_1111_1111_1111_0111
63
- doc_with_permissions(:copy_contents => false).permissions_value.
64
- should == 0b1111_1111_1111_1111_1111_1111_1110_1111
65
- doc_with_permissions(:modify_annotations => false).permissions_value.
66
- should == 0b1111_1111_1111_1111_1111_1111_1101_1111
67
- end
68
-
69
- it "should raise_error ArgumentError if invalid option is provided" do
70
- lambda {
71
- doc_with_permissions(:modify_document => false)
72
- }.should raise_error(ArgumentError)
73
- end
74
-
75
- end
76
-
77
- describe "Encryption keys" do
78
- # Since PDF::Reader doesn't read encrypted PDF files, we just take the
79
- # roundabout method of verifying each step of the encryption. This works
80
- # fine because the encryption method is deterministic.
81
-
82
- before(:each) do
83
- @pdf = Prawn::Document.new
84
- class << @pdf
85
- public :owner_password_hash, :user_password_hash, :user_encryption_key
86
- end
87
- @pdf.encrypt_document :user_password => 'foo', :owner_password => 'bar',
88
- :permissions => { :print_document => false }
89
- end
90
-
91
- it "should calculate the correct owner hash" do
92
- @pdf.owner_password_hash.unpack("H*").first.should match(/^61CA855012/i)
93
- end
94
-
95
- it "should calculate the correct user hash" do
96
- @pdf.user_password_hash.unpack("H*").first.should =~ /^6BC8C51031/i
97
- end
98
-
99
- it "should calculate the correct user_encryption_key" do
100
- @pdf.user_encryption_key.unpack("H*").first.upcase.should == "B100AB6429"
101
- end
102
-
103
-
104
- end
105
-
106
- describe "EncryptedPdfObject" do
107
-
108
- it "should delegate to PdfObject for simple types" do
109
- PDF::Core::EncryptedPdfObject(true, nil, nil, nil).should == "true"
110
- PDF::Core::EncryptedPdfObject(42, nil, nil, nil).should == "42"
111
- end
112
-
113
- it "should encrypt strings properly" do
114
- PDF::Core::EncryptedPdfObject("foo", "12345", 123, 0).should == "<4ad6e3>"
115
- end
116
-
117
- it "should encrypt literal strings properly" do
118
- PDF::Core::EncryptedPdfObject(PDF::Core::LiteralString.new("foo"), "12345", 123, 0).should == bin_string("(J\xD6\xE3)")
119
- PDF::Core::EncryptedPdfObject(PDF::Core::LiteralString.new("lhfbqg3do5u0satu3fjf"), nil, 123, 0).should == bin_string("(\xF1\x8B\\(\b\xBB\xE18S\x130~4*#\\(%\x87\xE7\x8E\\\n)")
120
- end
121
-
122
- it "should encrypt time properly" do
123
- PDF::Core::EncryptedPdfObject(Time.utc(2050, 04, 26, 10, 17, 10), "12345", 123, 0).should == bin_string("(h\x83\xBE\xDC\xEC\x99\x0F\xD7\\)%\x13\xD4$\xB8\xF0\x16\xB8\x80\xC5\xE91+\xCF)")
124
- end
125
-
126
- it "should properly handle compound types" do
127
- PDF::Core::EncryptedPdfObject({:Bar => "foo"}, "12345", 123, 0).should ==
128
- "<< /Bar <4ad6e3>\n>>"
129
- PDF::Core::EncryptedPdfObject(["foo", "bar"], "12345", 123, 0).should ==
130
- "[<4ad6e3> <4ed8fe>]"
131
- end
132
-
133
- end
134
-
135
- describe "Reference#encrypted_object" do
136
- it "should encrypt references properly" do
137
- ref = PDF::Core::Reference(1,["foo"])
138
- ref.encrypted_object(nil).should == "1 0 obj\n[<4fca3f>]\nendobj\n"
139
- end
140
-
141
- it "should encrypt references with streams properly" do
142
- ref = PDF::Core::Reference(1, {})
143
- ref << 'foo'
144
- result = bin_string("1 0 obj\n<< /Length 3\n>>\nstream\nO\xCA?\nendstream\nendobj\n")
145
- ref.encrypted_object(nil).should == result
146
- end
147
- end
148
-
149
- describe "String#encrypted_object" do
150
- it "should encrypt stream properly" do
151
- stream = PDF::Core::Stream.new
152
- stream << "foo"
153
- result = bin_string("stream\nO\xCA?\nendstream\n")
154
- stream.encrypted_object(nil, 1, 0).should == result
155
- end
156
- end
157
-
158
- end
@@ -1,79 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
-
5
- module SoftMaskHelper
6
- def make_soft_mask
7
- @pdf.save_graphics_state do
8
- @pdf.soft_mask do
9
- if block_given?
10
- yield
11
- else
12
- @pdf.fill_color '808080'
13
- @pdf.fill_rectangle [100, 100], 200, 200
14
- end
15
- end
16
-
17
- @pdf.fill_color '000000'
18
- @pdf.fill_rectangle [0, 0], 200, 200
19
- end
20
- end
21
- end
22
-
23
- describe "Document with soft masks" do
24
-
25
- include SoftMaskHelper
26
-
27
- it "should have PDF version at least 1.4" do
28
- create_pdf
29
- make_soft_mask
30
- str = @pdf.render
31
- str[0,8].should == "%PDF-1.4"
32
- end
33
-
34
- it "should create a new extended graphics state for each unique soft mask" do
35
- create_pdf
36
-
37
- make_soft_mask do
38
- @pdf.fill_color '808080'
39
- @pdf.fill_rectangle [100, 100], 200, 200
40
- end
41
-
42
- make_soft_mask do
43
- @pdf.fill_color '808080'
44
- @pdf.fill_rectangle [10, 10], 200, 200
45
- end
46
-
47
- extgstates = PDF::Inspector::ExtGState.analyze(@pdf.render).extgstates
48
- extgstates.length.should == 2
49
- end
50
-
51
- it "a new extended graphics state should contain soft mask with drawing instructions" do
52
- create_pdf
53
-
54
- make_soft_mask do
55
- @pdf.fill_color '808080'
56
- @pdf.fill_rectangle [100, 100], 200, 200
57
- end
58
-
59
- extgstate = PDF::Inspector::ExtGState.analyze(@pdf.render).extgstates.first
60
- extgstate[:soft_mask][:G].data.should == "q\n/DeviceRGB cs\n0.000 0.000 0.000 scn\n/DeviceRGB CS\n0.000 0.000 0.000 SCN\n1 w\n0 J\n0 j\n[ ] 0 d\n/DeviceRGB cs\n0.502 0.502 0.502 scn\n100.000 -100.000 200.000 200.000 re\nf\nQ\n"
61
- end
62
-
63
- it "should not create duplicate extended graphics states" do
64
- create_pdf
65
-
66
- make_soft_mask do
67
- @pdf.fill_color '808080'
68
- @pdf.fill_rectangle [100, 100], 200, 200
69
- end
70
-
71
- make_soft_mask do
72
- @pdf.fill_color '808080'
73
- @pdf.fill_rectangle [100, 100], 200, 200
74
- end
75
-
76
- extgstates = PDF::Inspector::ExtGState.analyze(@pdf.render).extgstates
77
- extgstates.length.should == 1
78
- end
79
- end
data/spec/span_spec.rb DELETED
@@ -1,44 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
-
5
- describe "drawing span" do
6
-
7
- before do
8
- Prawn.debug = false
9
- create_pdf
10
- end
11
-
12
- after do
13
- Prawn.debug = true
14
- end
15
-
16
- it "should only accept :position as option in debug mode" do
17
- Prawn.debug = true
18
- lambda { @pdf.span(350, {:x => 3}) {} }.should raise_error(Prawn::Errors::UnknownOption)
19
- end
20
-
21
- it "should have raise an error if :position is invalid" do
22
- lambda { @pdf.span(350, :position => :x) {} }.should raise_error(ArgumentError)
23
- end
24
-
25
- it "should restore the margin box when bounding box exits" do
26
- margin_box = @pdf.bounds
27
-
28
- @pdf.span(350, :position => :center) do
29
- @pdf.text "Here's some centered text in a 350 point column. " * 100
30
- end
31
-
32
- @pdf.bounds.should == margin_box
33
- end
34
-
35
- it "should do create a margin box" do
36
- y = @pdf.y
37
- margin_box = @pdf.span(350, :position => :center) do
38
- @pdf.text "Here's some centered text in a 350 point column. " * 100
39
- end
40
-
41
- margin_box.top.should == 792.0
42
- margin_box.bottom.should == 0
43
- end
44
- end
data/spec/stamp_spec.rb DELETED
@@ -1,160 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
-
5
- describe "create_stamp before any page is added" do
6
- it "should work with the font class" do
7
- @pdf = Prawn::Document.new(:skip_page_creation => true)
8
-
9
- # If anything goes wrong, Prawn::Errors::NotOnPage will be raised
10
- @pdf.create_stamp("my_stamp") do
11
- @pdf.font.height
12
- end
13
- end
14
-
15
- it "should work with setting color" do
16
- @pdf = Prawn::Document.new(:skip_page_creation => true)
17
-
18
- # If anything goes wrong, Prawn::Errors::NotOnPage will be raised
19
- @pdf.create_stamp("my_stamp") do
20
- @pdf.fill_color = 'ff0000'
21
- end
22
- end
23
- end
24
-
25
- describe "#stamp_at" do
26
- it "should work" do
27
- create_pdf
28
- @pdf.create_stamp("MyStamp")
29
- @pdf.stamp_at("MyStamp", [100, 200])
30
- # I had modified PDF::Inspector::XObject to receive the
31
- # invoke_xobject message and count the number of times it was
32
- # called, but it was only called once, so I reverted checking the
33
- # output with a regular expression
34
- @pdf.render.should =~ /\/Stamp1 Do.*?/m
35
- end
36
- end
37
-
38
- describe "Document with a stamp" do
39
- it "should raise_error NameTaken error when attempt to create stamp "+
40
- "with same name as an existing stamp" do
41
- create_pdf
42
- @pdf.create_stamp("MyStamp")
43
- lambda {
44
- @pdf.create_stamp("MyStamp")
45
- }.should raise_error(Prawn::Errors::NameTaken)
46
- end
47
-
48
- it "should raise_error InvalidName error when attempt to create "+
49
- "stamp with a blank name" do
50
- create_pdf
51
- lambda {
52
- @pdf.create_stamp("")
53
- }.should raise_error(Prawn::Errors::InvalidName)
54
- end
55
-
56
- it "a new XObject should be defined for each stamp created" do
57
- create_pdf
58
- @pdf.create_stamp("MyStamp")
59
- @pdf.create_stamp("AnotherStamp")
60
- @pdf.stamp("MyStamp")
61
- @pdf.stamp("AnotherStamp")
62
-
63
- inspector = PDF::Inspector::XObject.analyze(@pdf.render)
64
- xobjects = inspector.page_xobjects.last
65
- xobjects.length.should == 2
66
- end
67
-
68
- it "calling stamp with a name that does not match an existing stamp "+
69
- "should raise_error UndefinedObjectName" do
70
- create_pdf
71
- @pdf.create_stamp("MyStamp")
72
- lambda {
73
- @pdf.stamp("OtherStamp")
74
- }.should raise_error(Prawn::Errors::UndefinedObjectName)
75
- end
76
-
77
- it "stamp should be drawn into the document each time stamp is called" do
78
- create_pdf
79
- @pdf.create_stamp("MyStamp")
80
- @pdf.stamp("MyStamp")
81
- @pdf.stamp("MyStamp")
82
- @pdf.stamp("MyStamp")
83
- # I had modified PDF::Inspector::XObject to receive the
84
- # invoke_xobject message and count the number of times it was
85
- # called, but it was only called once, so I reverted checking the
86
- # output with a regular expression
87
- @pdf.render.should =~ /(\/Stamp1 Do.*?){3}/m
88
- end
89
-
90
- it "resources added during stamp creation should be added to the "+
91
- "stamp XObject, not the page" do
92
- create_pdf
93
- @pdf.create_stamp("MyStamp") do
94
- @pdf.transparent(0.5) { @pdf.circle([100, 100], 10)}
95
- end
96
- @pdf.stamp("MyStamp")
97
-
98
- # Inspector::XObject does not give information about resources, so
99
- # resorting to string matching
100
-
101
- output = @pdf.render
102
- objects = output.split("endobj")
103
- objects.each do |object|
104
- if object =~ /\/Type \/Page$/
105
- object.should_not =~ /\/ExtGState/
106
- elsif object =~ /\/Type \/XObject$/
107
- object.should =~ /\/ExtGState/
108
- end
109
- end
110
- end
111
-
112
- it "stamp stream should be wrapped in a graphic state" do
113
- create_pdf
114
- @pdf.create_stamp("MyStamp") do
115
- @pdf.text "This should have a 'q' before it and a 'Q' after it"
116
- end
117
- @pdf.stamp("MyStamp")
118
- stamps = PDF::Inspector::XObject.analyze(@pdf.render)
119
- stamps.xobject_streams[:Stamp1].data.chomp.should =~ /q(.|\s)*Q\Z/
120
- end
121
-
122
- it "should not add to the page graphic state stack " do
123
- create_pdf
124
- @pdf.state.page.stack.stack.size.should == 1
125
-
126
- @pdf.create_stamp("MyStamp") do
127
- @pdf.save_graphics_state
128
- @pdf.save_graphics_state
129
- @pdf.save_graphics_state
130
- @pdf.text "This should have a 'q' before it and a 'Q' after it"
131
- @pdf.restore_graphics_state
132
- end
133
- @pdf.state.page.stack.stack.size.should == 1
134
- end
135
-
136
- it "should be able to change fill and stroke colors within the stamp stream" do
137
- create_pdf
138
- @pdf.create_stamp("MyStamp") do
139
- @pdf.fill_color(100, 100, 20, 0)
140
- @pdf.stroke_color(100, 100, 20, 0)
141
- end
142
- @pdf.stamp("MyStamp")
143
- stamps = PDF::Inspector::XObject.analyze(@pdf.render)
144
- stamp_stream = stamps.xobject_streams[:Stamp1].data
145
- stamp_stream.should include("/DeviceCMYK cs\n1.000 1.000 0.200 0.000 scn")
146
- stamp_stream.should include("/DeviceCMYK CS\n1.000 1.000 0.200 0.000 SCN")
147
- end
148
-
149
- it "should save the color space even when same as current page color space" do
150
- create_pdf
151
- @pdf.stroke_color(100, 100, 20, 0)
152
- @pdf.create_stamp("MyStamp") do
153
- @pdf.stroke_color(100, 100, 20, 0)
154
- end
155
- @pdf.stamp("MyStamp")
156
- stamps = PDF::Inspector::XObject.analyze(@pdf.render)
157
- stamp_stream = stamps.xobject_streams[:Stamp1].data
158
- stamp_stream.should include("/DeviceCMYK CS\n1.000 1.000 0.200 0.000 SCN")
159
- end
160
- end