prawn 0.13.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 (348) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +10 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -16
  6. data/Rakefile +17 -39
  7. data/lib/prawn/document/bounding_box.rb +85 -42
  8. data/lib/prawn/document/column_box.rb +21 -11
  9. data/lib/prawn/document/internals.rb +40 -147
  10. data/lib/prawn/document/span.rb +25 -17
  11. data/lib/prawn/document.rb +286 -245
  12. data/lib/prawn/encoding.rb +68 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +204 -155
  15. data/lib/prawn/font_metric_cache.rb +25 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +7 -13
  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 +142 -80
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +6 -5
  23. data/lib/prawn/graphics/color.rb +47 -44
  24. data/lib/prawn/graphics/dash.rb +30 -13
  25. data/lib/prawn/graphics/join_style.rb +13 -6
  26. data/lib/prawn/graphics/patterns.rb +221 -90
  27. data/lib/prawn/graphics/transformation.rb +21 -12
  28. data/lib/prawn/graphics/transparency.rb +21 -17
  29. data/lib/prawn/graphics.rb +155 -128
  30. data/lib/prawn/{layout/grid.rb → grid.rb} +110 -47
  31. data/lib/prawn/image_handler.rb +16 -2
  32. data/lib/prawn/images/image.rb +4 -2
  33. data/lib/prawn/images/jpg.rb +39 -30
  34. data/lib/prawn/images/png.rb +132 -169
  35. data/lib/prawn/images.rb +70 -62
  36. data/lib/prawn/measurement_extensions.rb +15 -10
  37. data/lib/prawn/measurements.rb +22 -23
  38. data/lib/prawn/outline.rb +301 -13
  39. data/lib/prawn/repeater.rb +19 -17
  40. data/lib/prawn/security/arcfour.rb +54 -0
  41. data/lib/prawn/security.rb +108 -86
  42. data/lib/prawn/soft_mask.rb +40 -41
  43. data/lib/prawn/stamp.rb +29 -12
  44. data/lib/prawn/text/box.rb +27 -29
  45. data/lib/prawn/text/formatted/arranger.rb +110 -67
  46. data/lib/prawn/text/formatted/box.rb +233 -165
  47. data/lib/prawn/text/formatted/fragment.rb +27 -27
  48. data/lib/prawn/text/formatted/line_wrap.rb +137 -97
  49. data/lib/prawn/text/formatted/parser.rb +149 -127
  50. data/lib/prawn/text/formatted/wrap.rb +57 -37
  51. data/lib/prawn/text/formatted.rb +6 -4
  52. data/lib/prawn/text.rb +105 -73
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +11 -21
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +42 -68
  58. data/{data/images/fractal.jpg → manual/absolute_position.pdf} +0 -0
  59. data/manual/basic_concepts/adding_pages.rb +9 -10
  60. data/manual/basic_concepts/basic_concepts.rb +33 -24
  61. data/manual/basic_concepts/creation.rb +10 -11
  62. data/manual/basic_concepts/cursor.rb +9 -10
  63. data/manual/basic_concepts/measurement.rb +10 -11
  64. data/manual/basic_concepts/origin.rb +8 -9
  65. data/manual/basic_concepts/other_cursor_helpers.rb +17 -18
  66. data/manual/basic_concepts/view.rb +48 -0
  67. data/manual/bounding_box/bounding_box.rb +31 -29
  68. data/manual/bounding_box/bounds.rb +17 -18
  69. data/manual/bounding_box/canvas.rb +8 -9
  70. data/manual/bounding_box/creation.rb +8 -9
  71. data/manual/bounding_box/indentation.rb +22 -23
  72. data/manual/bounding_box/nesting.rb +32 -25
  73. data/manual/bounding_box/russian_boxes.rb +19 -19
  74. data/manual/bounding_box/stretchy.rb +18 -20
  75. data/manual/contents.rb +35 -0
  76. data/manual/cover.rb +43 -0
  77. data/manual/document_and_page_options/background.rb +16 -14
  78. data/manual/document_and_page_options/document_and_page_options.rb +26 -23
  79. data/manual/document_and_page_options/metadata.rb +21 -19
  80. data/manual/document_and_page_options/page_margins.rb +20 -22
  81. data/manual/document_and_page_options/page_size.rb +15 -15
  82. data/manual/document_and_page_options/print_scaling.rb +23 -0
  83. data/manual/example_helper.rb +5 -408
  84. data/manual/graphics/blend_mode.rb +52 -0
  85. data/manual/graphics/circle_and_ellipse.rb +8 -9
  86. data/manual/graphics/color.rb +11 -13
  87. data/manual/graphics/common_lines.rb +13 -12
  88. data/manual/graphics/fill_and_stroke.rb +10 -11
  89. data/manual/graphics/fill_rules.rb +13 -12
  90. data/manual/graphics/gradients.rb +28 -22
  91. data/manual/graphics/graphics.rb +52 -46
  92. data/manual/graphics/helper.rb +20 -10
  93. data/manual/graphics/line_width.rb +13 -12
  94. data/manual/graphics/lines_and_curves.rb +13 -14
  95. data/manual/graphics/polygon.rb +10 -12
  96. data/manual/graphics/rectangle.rb +7 -8
  97. data/manual/graphics/rotate.rb +9 -12
  98. data/manual/graphics/scale.rb +19 -18
  99. data/manual/graphics/soft_masks.rb +5 -7
  100. data/manual/graphics/stroke_cap.rb +10 -11
  101. data/manual/graphics/stroke_dash.rb +16 -17
  102. data/manual/graphics/stroke_join.rb +10 -11
  103. data/manual/graphics/translate.rb +13 -13
  104. data/manual/graphics/transparency.rb +11 -13
  105. data/manual/{manual/how_to_read_this_manual.rb → how_to_read_this_manual.rb} +23 -25
  106. data/manual/images/absolute_position.rb +9 -10
  107. data/manual/images/fit.rb +9 -10
  108. data/manual/images/horizontal.rb +13 -14
  109. data/manual/images/images.rb +31 -30
  110. data/manual/images/plain_image.rb +6 -7
  111. data/manual/images/scale.rb +12 -13
  112. data/manual/images/vertical.rb +19 -17
  113. data/manual/images/width_and_height.rb +13 -14
  114. data/manual/layout/boxes.rb +14 -15
  115. data/manual/layout/content.rb +12 -13
  116. data/manual/layout/layout.rb +19 -20
  117. data/manual/layout/simple_grid.rb +8 -9
  118. data/manual/outline/add_subsection_to.rb +26 -27
  119. data/manual/outline/insert_section_after.rb +19 -20
  120. data/manual/outline/outline.rb +23 -22
  121. data/manual/outline/sections_and_pages.rb +24 -25
  122. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  123. data/manual/repeatable_content/page_numbering.rb +20 -19
  124. data/manual/repeatable_content/repeatable_content.rb +26 -22
  125. data/manual/repeatable_content/repeater.rb +18 -19
  126. data/manual/repeatable_content/stamp.rb +18 -19
  127. data/manual/security/encryption.rb +8 -11
  128. data/manual/security/permissions.rb +20 -15
  129. data/manual/security/security.rb +20 -20
  130. data/manual/table.rb +16 -0
  131. data/manual/text/alignment.rb +17 -18
  132. data/manual/text/color.rb +13 -13
  133. data/manual/text/column_box.rb +10 -12
  134. data/manual/text/fallback_fonts.rb +29 -25
  135. data/manual/text/font.rb +17 -18
  136. data/manual/text/font_size.rb +21 -22
  137. data/manual/text/font_style.rb +12 -10
  138. data/manual/text/formatted_callbacks.rb +36 -26
  139. data/manual/text/formatted_text.rb +41 -34
  140. data/manual/text/free_flowing_text.rb +28 -29
  141. data/manual/text/inline.rb +23 -26
  142. data/manual/text/kerning_and_character_spacing.rb +20 -21
  143. data/manual/text/leading.rb +10 -11
  144. data/manual/text/line_wrapping.rb +40 -21
  145. data/manual/text/paragraph_indentation.rb +17 -12
  146. data/manual/text/positioned_text.rb +19 -20
  147. data/manual/text/registering_families.rb +33 -30
  148. data/manual/text/rendering_and_color.rb +11 -12
  149. data/manual/text/right_to_left_text.rb +31 -20
  150. data/manual/text/rotation.rb +36 -27
  151. data/manual/text/single_usage.rb +13 -14
  152. data/manual/text/text.rb +62 -62
  153. data/manual/text/text_box_excess.rb +22 -19
  154. data/manual/text/text_box_extensions.rb +21 -18
  155. data/manual/text/text_box_overflow.rb +28 -21
  156. data/manual/text/utf8.rb +16 -17
  157. data/manual/text/win_ansi_charset.rb +29 -26
  158. data/prawn.gemspec +45 -43
  159. data/spec/extensions/encoding_helpers.rb +4 -3
  160. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  161. data/spec/prawn/document/column_box_spec.rb +75 -0
  162. data/spec/prawn/document/security_spec.rb +176 -0
  163. data/spec/prawn/document_annotations_spec.rb +76 -0
  164. data/spec/prawn/document_destinations_spec.rb +15 -0
  165. data/spec/prawn/document_grid_spec.rb +99 -0
  166. data/spec/prawn/document_reference_spec.rb +27 -0
  167. data/spec/prawn/document_span_spec.rb +44 -0
  168. data/spec/prawn/document_spec.rb +805 -0
  169. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  170. data/spec/prawn/font_spec.rb +544 -0
  171. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  172. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  173. data/spec/prawn/graphics_spec.rb +872 -0
  174. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  175. data/spec/prawn/image_handler_spec.rb +53 -0
  176. data/spec/prawn/images/jpg_spec.rb +20 -0
  177. data/spec/prawn/images/png_spec.rb +283 -0
  178. data/spec/prawn/images_spec.rb +229 -0
  179. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  180. data/spec/prawn/outline_spec.rb +512 -0
  181. data/spec/prawn/repeater_spec.rb +166 -0
  182. data/spec/prawn/soft_mask_spec.rb +74 -0
  183. data/spec/prawn/stamp_spec.rb +173 -0
  184. data/spec/prawn/text/box_spec.rb +1110 -0
  185. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  186. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  187. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  188. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  189. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  190. data/spec/prawn/text_draw_text_spec.rb +150 -0
  191. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  192. data/spec/prawn/text_spacing_spec.rb +95 -0
  193. data/spec/prawn/text_spec.rb +603 -0
  194. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  195. data/spec/prawn/transformation_stack_spec.rb +66 -0
  196. data/spec/prawn/view_spec.rb +63 -0
  197. data/spec/prawn_manual_spec.rb +35 -0
  198. data/spec/spec_helper.rb +22 -21
  199. data.tar.gz.sig +0 -0
  200. metadata +168 -307
  201. metadata.gz.sig +0 -0
  202. data/README.md +0 -109
  203. data/data/encodings/win_ansi.txt +0 -29
  204. data/data/images/16bit.alpha +0 -0
  205. data/data/images/16bit.dat +0 -0
  206. data/data/images/16bit.png +0 -0
  207. data/data/images/arrow.png +0 -0
  208. data/data/images/arrow2.png +0 -0
  209. data/data/images/barcode_issue.png +0 -0
  210. data/data/images/dice.alpha +0 -0
  211. data/data/images/dice.dat +0 -0
  212. data/data/images/dice.png +0 -0
  213. data/data/images/dice_interlaced.png +0 -0
  214. data/data/images/indexed_color.dat +0 -0
  215. data/data/images/indexed_color.png +0 -0
  216. data/data/images/letterhead.jpg +0 -0
  217. data/data/images/page_white_text.alpha +0 -0
  218. data/data/images/page_white_text.dat +0 -0
  219. data/data/images/page_white_text.png +0 -0
  220. data/data/images/pigs.jpg +0 -0
  221. data/data/images/prawn.png +0 -0
  222. data/data/images/ruport.png +0 -0
  223. data/data/images/ruport_data.dat +0 -0
  224. data/data/images/ruport_transparent.png +0 -0
  225. data/data/images/ruport_type0.png +0 -0
  226. data/data/images/stef.jpg +0 -0
  227. data/data/images/tru256.bmp +0 -0
  228. data/data/images/web-links.dat +0 -1
  229. data/data/images/web-links.png +0 -0
  230. data/data/pdfs/complex_template.pdf +0 -0
  231. data/data/pdfs/contains_ttf_font.pdf +0 -0
  232. data/data/pdfs/encrypted.pdf +0 -0
  233. data/data/pdfs/form.pdf +1 -819
  234. data/data/pdfs/hexagon.pdf +0 -61
  235. data/data/pdfs/indirect_reference.pdf +0 -86
  236. data/data/pdfs/multipage_template.pdf +0 -127
  237. data/data/pdfs/nested_pages.pdf +0 -118
  238. data/data/pdfs/page_without_mediabox.pdf +0 -193
  239. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  240. data/data/pdfs/two_hexagons.pdf +0 -90
  241. data/data/pdfs/version_1_6.pdf +0 -61
  242. data/data/shift_jis_text.txt +0 -1
  243. data/lib/pdf/core/annotations.rb +0 -60
  244. data/lib/pdf/core/byte_string.rb +0 -9
  245. data/lib/pdf/core/destinations.rb +0 -90
  246. data/lib/pdf/core/document_state.rb +0 -78
  247. data/lib/pdf/core/filter_list.rb +0 -51
  248. data/lib/pdf/core/filters.rb +0 -36
  249. data/lib/pdf/core/graphics_state.rb +0 -68
  250. data/lib/pdf/core/literal_string.rb +0 -16
  251. data/lib/pdf/core/name_tree.rb +0 -177
  252. data/lib/pdf/core/object_store.rb +0 -320
  253. data/lib/pdf/core/outline.rb +0 -315
  254. data/lib/pdf/core/page.rb +0 -212
  255. data/lib/pdf/core/page_geometry.rb +0 -126
  256. data/lib/pdf/core/pdf_object.rb +0 -124
  257. data/lib/pdf/core/reference.rb +0 -103
  258. data/lib/pdf/core/stream.rb +0 -98
  259. data/lib/pdf/core/text.rb +0 -275
  260. data/lib/pdf/core.rb +0 -35
  261. data/lib/prawn/compatibility.rb +0 -91
  262. data/lib/prawn/document/graphics_state.rb +0 -73
  263. data/lib/prawn/document/snapshot.rb +0 -89
  264. data/lib/prawn/font/afm.rb +0 -203
  265. data/lib/prawn/layout.rb +0 -20
  266. data/lib/prawn/table/cell/image.rb +0 -70
  267. data/lib/prawn/table/cell/in_table.rb +0 -27
  268. data/lib/prawn/table/cell/span_dummy.rb +0 -92
  269. data/lib/prawn/table/cell/subtable.rb +0 -65
  270. data/lib/prawn/table/cell/text.rb +0 -153
  271. data/lib/prawn/table/cell.rb +0 -770
  272. data/lib/prawn/table/cells.rb +0 -295
  273. data/lib/prawn/table.rb +0 -643
  274. data/manual/example_file.rb +0 -116
  275. data/manual/example_package.rb +0 -53
  276. data/manual/example_section.rb +0 -46
  277. data/manual/manual/cover.rb +0 -35
  278. data/manual/manual/foreword.rb +0 -85
  279. data/manual/manual/manual.rb +0 -35
  280. data/manual/syntax_highlight.rb +0 -52
  281. data/manual/table/basic_block.rb +0 -53
  282. data/manual/table/before_rendering_page.rb +0 -26
  283. data/manual/table/cell_border_lines.rb +0 -24
  284. data/manual/table/cell_borders_and_bg.rb +0 -31
  285. data/manual/table/cell_dimensions.rb +0 -30
  286. data/manual/table/cell_text.rb +0 -38
  287. data/manual/table/column_widths.rb +0 -30
  288. data/manual/table/content_and_subtables.rb +0 -39
  289. data/manual/table/creation.rb +0 -27
  290. data/manual/table/filtering.rb +0 -36
  291. data/manual/table/flow_and_header.rb +0 -17
  292. data/manual/table/image_cells.rb +0 -33
  293. data/manual/table/position.rb +0 -29
  294. data/manual/table/row_colors.rb +0 -20
  295. data/manual/table/span.rb +0 -30
  296. data/manual/table/style.rb +0 -22
  297. data/manual/table/table.rb +0 -52
  298. data/manual/table/width.rb +0 -27
  299. data/manual/templates/full_template.rb +0 -25
  300. data/manual/templates/page_template.rb +0 -48
  301. data/manual/templates/templates.rb +0 -27
  302. data/manual/text/group.rb +0 -29
  303. data/spec/acceptance/png.rb +0 -23
  304. data/spec/annotations_spec.rb +0 -74
  305. data/spec/bounding_box_spec.rb +0 -493
  306. data/spec/cell_spec.rb +0 -628
  307. data/spec/column_box_spec.rb +0 -33
  308. data/spec/destinations_spec.rb +0 -15
  309. data/spec/document_spec.rb +0 -761
  310. data/spec/extensions/mocha.rb +0 -44
  311. data/spec/filters_spec.rb +0 -34
  312. data/spec/font_metric_cache_spec.rb +0 -52
  313. data/spec/font_spec.rb +0 -464
  314. data/spec/formatted_text_arranger_spec.rb +0 -421
  315. data/spec/formatted_text_box_spec.rb +0 -650
  316. data/spec/formatted_text_fragment_spec.rb +0 -298
  317. data/spec/graphics_spec.rb +0 -651
  318. data/spec/grid_spec.rb +0 -85
  319. data/spec/image_handler_spec.rb +0 -42
  320. data/spec/images_spec.rb +0 -157
  321. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  322. data/spec/jpg_spec.rb +0 -25
  323. data/spec/line_wrap_spec.rb +0 -333
  324. data/spec/measurement_units_spec.rb +0 -23
  325. data/spec/name_tree_spec.rb +0 -112
  326. data/spec/object_store_spec.rb +0 -170
  327. data/spec/outline_spec.rb +0 -448
  328. data/spec/pdf_object_spec.rb +0 -172
  329. data/spec/png_spec.rb +0 -240
  330. data/spec/reference_spec.rb +0 -82
  331. data/spec/repeater_spec.rb +0 -158
  332. data/spec/security_spec.rb +0 -158
  333. data/spec/snapshot_spec.rb +0 -186
  334. data/spec/soft_mask_spec.rb +0 -117
  335. data/spec/span_spec.rb +0 -44
  336. data/spec/stamp_spec.rb +0 -158
  337. data/spec/stream_spec.rb +0 -58
  338. data/spec/stroke_styles_spec.rb +0 -211
  339. data/spec/table/span_dummy_spec.rb +0 -17
  340. data/spec/table_spec.rb +0 -1355
  341. data/spec/template_spec.rb +0 -351
  342. data/spec/text_at_spec.rb +0 -130
  343. data/spec/text_box_spec.rb +0 -1030
  344. data/spec/text_rendering_mode_spec.rb +0 -45
  345. data/spec/text_spacing_spec.rb +0 -93
  346. data/spec/text_spec.rb +0 -425
  347. data/spec/text_with_inline_formatting_spec.rb +0 -35
  348. data/spec/transparency_spec.rb +0 -89
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Document::ColumnBox do
6
+ let(:pdf) { create_pdf }
7
+
8
+ it 'has sensible left and right values' do
9
+ pdf.column_box(
10
+ [0, pdf.cursor],
11
+ width: pdf.bounds.width,
12
+ height: 200,
13
+ columns: 3,
14
+ spacer: 25
15
+ ) do
16
+ left = pdf.bounds.left
17
+ right = pdf.bounds.right
18
+
19
+ pdf.bounds.move_past_bottom # next column
20
+
21
+ expect(pdf.bounds.left).to be > left
22
+ expect(pdf.bounds.left).to be > right
23
+ expect(pdf.bounds.right).to be > pdf.bounds.left
24
+ end
25
+ end
26
+
27
+ it 'includes spacers between columns but not at the end' do
28
+ pdf.column_box(
29
+ [0, pdf.cursor],
30
+ width: 500,
31
+ height: 200,
32
+ columns: 3,
33
+ spacer: 25
34
+ ) do
35
+ expect(pdf.bounds.width).to eq(150) # (500 - (25 * 2)) / 3
36
+
37
+ pdf.bounds.move_past_bottom
38
+ pdf.bounds.move_past_bottom
39
+
40
+ expect(pdf.bounds.right).to eq(500)
41
+ end
42
+ end
43
+
44
+ it 'does not reset the top margin on a new page by default' do
45
+ page_top = pdf.cursor
46
+ pdf.move_down 50
47
+ init_column_top = pdf.cursor
48
+ pdf.column_box [0, pdf.cursor], width: 500, height: 200, columns: 2 do
49
+ pdf.bounds.move_past_bottom
50
+ pdf.bounds.move_past_bottom
51
+
52
+ expect(pdf.bounds.absolute_top).to eq(init_column_top)
53
+ expect(pdf.bounds.absolute_top).to_not eq(page_top)
54
+ end
55
+ end
56
+
57
+ it 'does reset the top margin when reflow_margins is set' do
58
+ page_top = pdf.cursor
59
+ pdf.move_down 50
60
+ init_column_top = pdf.cursor
61
+ pdf.column_box(
62
+ [0, pdf.cursor],
63
+ width: 500,
64
+ reflow_margins: true,
65
+ height: 200,
66
+ columns: 2
67
+ ) do
68
+ pdf.bounds.move_past_bottom
69
+ pdf.bounds.move_past_bottom
70
+
71
+ expect(pdf.bounds.absolute_top).to eq(page_top)
72
+ expect(pdf.bounds.absolute_top).to_not eq(init_column_top)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'tempfile'
5
+
6
+ describe Prawn::Document::Security do
7
+ describe 'Password padding' do
8
+ include described_class
9
+
10
+ it 'truncates long passwords' do
11
+ pw = 'Long long string' * 30
12
+ padded = pad_password(pw)
13
+ expect(padded.length).to eq(32)
14
+ expect(padded).to eq(pw[0, 32])
15
+ end
16
+
17
+ it 'pads short passwords' do
18
+ pw = 'abcd'
19
+ padded = pad_password(pw)
20
+ expect(padded.length).to eq(32)
21
+ expect(padded).to eq(
22
+ pw + Prawn::Document::Security::PASSWORD_PADDING[0, 28]
23
+ )
24
+ end
25
+
26
+ it 'fullies pad null passwords' do
27
+ pw = ''
28
+ padded = pad_password(pw)
29
+ expect(padded.length).to eq(32)
30
+ expect(padded).to eq(Prawn::Document::Security::PASSWORD_PADDING)
31
+ end
32
+ end
33
+
34
+ describe 'Setting permissions' do
35
+ def doc_with_permissions(permissions)
36
+ pdf = Prawn::Document.new
37
+
38
+ # Make things easier to test
39
+ pdf.singleton_class.__send__ :public, :permissions_value
40
+ # class << pdf
41
+ # public :permissions_value
42
+ # end
43
+
44
+ pdf.encrypt_document(permissions: permissions)
45
+ pdf
46
+ end
47
+
48
+ it 'defaults to full permissions' do
49
+ expect(doc_with_permissions({}).permissions_value).to eq(0xFFFFFFFF)
50
+ expect(doc_with_permissions(
51
+ print_document: true,
52
+ modify_contents: true,
53
+ copy_contents: true,
54
+ modify_annotations: true
55
+ ).permissions_value)
56
+ .to eq(0xFFFFFFFF)
57
+ end
58
+
59
+ it 'clears the appropriate bits for each permission flag' do
60
+ expect(doc_with_permissions(print_document: false).permissions_value)
61
+ .to eq(0b1111_1111_1111_1111_1111_1111_1111_1011)
62
+ expect(doc_with_permissions(modify_contents: false).permissions_value)
63
+ .to eq(0b1111_1111_1111_1111_1111_1111_1111_0111)
64
+ expect(doc_with_permissions(copy_contents: false).permissions_value)
65
+ .to eq(0b1111_1111_1111_1111_1111_1111_1110_1111)
66
+ expect(doc_with_permissions(modify_annotations: false).permissions_value)
67
+ .to eq(0b1111_1111_1111_1111_1111_1111_1101_1111)
68
+ end
69
+
70
+ it 'raise_errors ArgumentError if invalid option is provided' do
71
+ expect do
72
+ doc_with_permissions(modify_document: false)
73
+ end.to raise_error(ArgumentError)
74
+ end
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
+ let(:pdf) do
83
+ Prawn::Document.new do |pdf|
84
+ class << pdf
85
+ public :owner_password_hash, :user_password_hash, :user_encryption_key
86
+ end
87
+ pdf.encrypt_document(
88
+ user_password: 'foo',
89
+ owner_password: 'bar',
90
+ permissions: { print_document: false }
91
+ )
92
+ end
93
+ end
94
+
95
+ it 'calculates the correct owner hash' do
96
+ expect(pdf.owner_password_hash.unpack1('H*'))
97
+ .to match(/^61CA855012/i)
98
+ end
99
+
100
+ it 'calculates the correct user hash' do
101
+ expect(pdf.user_password_hash.unpack1('H*'))
102
+ .to match(/^6BC8C51031/i)
103
+ end
104
+
105
+ it 'calculates the correct user_encryption_key' do
106
+ expect(pdf.user_encryption_key.unpack1('H*').upcase)
107
+ .to eq('B100AB6429')
108
+ end
109
+ end
110
+
111
+ describe 'encrypted_pdf_object' do
112
+ it 'delegates to PdfObject for simple types' do
113
+ expect(PDF::Core.encrypted_pdf_object(true, nil, nil, nil)).to eq('true')
114
+ expect(PDF::Core.encrypted_pdf_object(42, nil, nil, nil)).to eq('42')
115
+ end
116
+
117
+ it 'encrypts strings properly' do
118
+ expect(PDF::Core.encrypted_pdf_object('foo', '12345', 123, 0))
119
+ .to eq('<4ad6e3>')
120
+ end
121
+
122
+ it 'encrypts literal strings properly' do
123
+ expect(PDF::Core.encrypted_pdf_object(
124
+ PDF::Core::LiteralString.new('foo'), '12345', 123, 0
125
+ )).to eq(bin_string("(J\xD6\xE3)"))
126
+ expect(PDF::Core.encrypted_pdf_object(
127
+ PDF::Core::LiteralString.new('lhfbqg3do5u0satu3fjf'), nil, 123, 0
128
+ )).to eq(bin_string(
129
+ "(\xF1\x8B\\(\b\xBB\xE18S\x130~4*#\\(%\x87\xE7\x8E\\\n)"
130
+ ))
131
+ end
132
+
133
+ it 'encrypts time properly' do
134
+ expect(PDF::Core.encrypted_pdf_object(
135
+ Time.utc(2050, 0o4, 26, 10, 17, 10), '12345', 123, 0
136
+ )).to eq(bin_string(
137
+ "(h\x83\xBE\xDC\xEC\x99\x0F\xD7\\)%\x13\xD4$\xB8\xF0\x16\xB8\x80\xC5"\
138
+ "\xE91+\xCF)"
139
+ ))
140
+ end
141
+
142
+ it 'properlies handle compound types' do
143
+ expect(PDF::Core.encrypted_pdf_object({ Bar: 'foo' }, '12345', 123, 0))
144
+ .to eq(
145
+ "<< /Bar <4ad6e3>\n>>"
146
+ )
147
+ expect(PDF::Core.encrypted_pdf_object(%w[foo bar], '12345', 123, 0))
148
+ .to eq('[<4ad6e3> <4ed8fe>]')
149
+ end
150
+ end
151
+
152
+ describe 'Reference#encrypted_object' do
153
+ it 'encrypts references properly' do
154
+ ref = PDF::Core::Reference.new(1, ['foo'])
155
+ expect(ref.encrypted_object(nil)).to eq("1 0 obj\n[<4fca3f>]\nendobj\n")
156
+ end
157
+
158
+ it 'encrypts references with streams properly' do
159
+ ref = PDF::Core::Reference.new(1, {})
160
+ ref << 'foo'
161
+ result = bin_string(
162
+ "1 0 obj\n<< /Length 3\n>>\nstream\nO\xCA?\nendstream\nendobj\n"
163
+ )
164
+ expect(ref.encrypted_object(nil)).to eq(result)
165
+ end
166
+ end
167
+
168
+ describe 'String#encrypted_object' do
169
+ it 'encrypts stream properly' do
170
+ stream = PDF::Core::Stream.new
171
+ stream << 'foo'
172
+ result = bin_string("stream\nO\xCA?\nendstream\n")
173
+ expect(stream.encrypted_object(nil, 1, 0)).to eq(result)
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Document do
6
+ let(:pdf) { create_pdf }
7
+
8
+ describe 'When creating annotations' do
9
+ it 'appends annotation to current page' do
10
+ pdf.start_new_page
11
+ pdf.annotate(
12
+ Rect: [0, 0, 10, 10],
13
+ Subtype: :Text,
14
+ Contents: 'Hello world!'
15
+ )
16
+ PDF::Reader.open(StringIO.new(pdf.render)) do |pdf|
17
+ expect(pdf.page(1).attributes[:Annots]).to be_nil
18
+ expect(pdf.page(2).attributes[:Annots].size).to eq(1)
19
+ end
20
+ end
21
+
22
+ it 'forces :Type to be :Annot' do
23
+ opts = pdf.annotate(
24
+ Rect: [0, 0, 10, 10],
25
+ Subtype: :Text,
26
+ Contents: 'Hello world!'
27
+ )
28
+ expect(opts[:Type]).to eq(:Annot)
29
+ opts = pdf.annotate(
30
+ Type: :Bogus,
31
+ Rect: [0, 0, 10, 10],
32
+ Subtype: :Text,
33
+ Contents: 'Hello world!'
34
+ )
35
+ expect(opts[:Type]).to eq(:Annot)
36
+ end
37
+ end
38
+
39
+ describe 'When creating text annotations' do
40
+ let(:rect) { [0, 0, 10, 10] }
41
+ let(:content) { 'Hello, world!' }
42
+
43
+ it 'builds appropriate annotation' do
44
+ opts = pdf.text_annotation(rect, content)
45
+ expect(opts[:Type]).to eq(:Annot)
46
+ expect(opts[:Subtype]).to eq(:Text)
47
+ expect(opts[:Rect]).to eq(rect)
48
+ expect(opts[:Contents]).to eq(content)
49
+ end
50
+
51
+ it 'merges extra options' do
52
+ opts = pdf.text_annotation(rect, content, Open: true, Subtype: :Bogus)
53
+ expect(opts[:Subtype]).to eq(:Text)
54
+ expect(opts[:Open]).to eq(true)
55
+ end
56
+ end
57
+
58
+ describe 'When creating link annotations' do
59
+ let(:rect) { [0, 0, 10, 10] }
60
+ let(:dest) { 'home' }
61
+
62
+ it 'builds appropriate annotation' do
63
+ opts = pdf.link_annotation(rect, Dest: dest)
64
+ expect(opts[:Type]).to eq(:Annot)
65
+ expect(opts[:Subtype]).to eq(:Link)
66
+ expect(opts[:Rect]).to eq(rect)
67
+ expect(opts[:Dest]).to eq(dest)
68
+ end
69
+
70
+ it 'merges extra options' do
71
+ opts = pdf.link_annotation(rect, Dest: dest, Subtype: :Bogus)
72
+ expect(opts[:Subtype]).to eq(:Link)
73
+ expect(opts[:Dest]).to eq(dest)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Document do
6
+ describe 'When creating destinations' do
7
+ let(:pdf) { create_pdf }
8
+
9
+ it 'adds entry to Dests name tree' do
10
+ expect(pdf.dests.data.empty?).to eq(true)
11
+ pdf.add_dest 'candy', 'chocolate'
12
+ expect(pdf.dests.data.size).to eq(1)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Document do
6
+ describe 'grid' do
7
+ let(:pdf) { described_class.new }
8
+
9
+ it 'allows definition of a grid' do
10
+ pdf.define_grid(columns: 5, rows: 8, gutter: 0.1)
11
+ expect(pdf.grid.columns).to eq(5)
12
+ expect(pdf.grid.rows).to eq(8)
13
+ expect(pdf.grid.gutter).to eq(0.1)
14
+ end
15
+
16
+ it 'allows re-definition of a grid' do
17
+ pdf.define_grid(columns: 5, rows: 8, gutter: 0.1)
18
+ expect(pdf.grid.columns).to eq(5)
19
+ expect(pdf.grid.rows).to eq(8)
20
+ expect(pdf.grid.gutter).to eq(0.1)
21
+ pdf.define_grid(columns: 3, rows: 6, gutter: 0.1)
22
+ expect(pdf.grid.columns).to eq(3)
23
+ expect(pdf.grid.rows).to eq(6)
24
+ expect(pdf.grid.gutter).to eq(0.1)
25
+ end
26
+
27
+ describe 'when a grid is defined' do
28
+ let(:num_columns) { 5 }
29
+ let(:num_rows) { 8 }
30
+ let(:gutter) { 10.0 }
31
+
32
+ before do
33
+ pdf.define_grid(
34
+ columns: num_columns,
35
+ rows: num_rows,
36
+ gutter: gutter
37
+ )
38
+ end
39
+
40
+ it 'computes the column width' do
41
+ expect(pdf.grid.column_width * num_columns.to_f +
42
+ gutter * (num_columns - 1).to_f).to eq(pdf.bounds.width)
43
+ end
44
+
45
+ it 'computes the row height' do
46
+ expect(pdf.grid.row_height * num_rows.to_f +
47
+ gutter * (num_rows - 1).to_f).to eq(pdf.bounds.height)
48
+ end
49
+
50
+ it 'gives the edges of a grid box' do
51
+ grid_width = (pdf.bounds.width.to_f -
52
+ (gutter * (num_columns - 1).to_f)) / num_columns.to_f
53
+ grid_height = (pdf.bounds.height.to_f -
54
+ (gutter * (num_rows - 1).to_f)) / num_rows.to_f
55
+
56
+ exp_tl_x = (grid_width + gutter.to_f) * 4.0
57
+ exp_tl_y = pdf.bounds.height.to_f - (grid_height + gutter.to_f)
58
+
59
+ expect(pdf.grid(1, 4).top_left).to eq([exp_tl_x, exp_tl_y])
60
+ expect(pdf.grid(1, 4).top_right).to eq [exp_tl_x + grid_width, exp_tl_y]
61
+ expect(pdf.grid(1, 4).bottom_left)
62
+ .to eq([exp_tl_x, exp_tl_y - grid_height])
63
+ expect(pdf.grid(1, 4).bottom_right)
64
+ .to eq([exp_tl_x + grid_width, exp_tl_y - grid_height])
65
+ end
66
+
67
+ it 'gives the edges of a multiple grid boxes' do
68
+ # Hand verified. Cheating a bit. Don't tell.
69
+ expect(pdf.grid([1, 3], [2, 5]).top_left).to eq([330.0, 628.75])
70
+ expect(pdf.grid([1, 3], [2, 5]).top_right).to eq([650.0, 628.75])
71
+ expect(pdf.grid([1, 3], [2, 5]).bottom_left).to eq([330.0, 456.25])
72
+ expect(pdf.grid([1, 3], [2, 5]).bottom_right).to eq([650.0, 456.25])
73
+ end
74
+
75
+ it 'draws outlines without changing global default colors' do
76
+ pdf.grid.show_all('cccccc')
77
+
78
+ colors = PDF::Inspector::Graphics::Color.analyze(pdf.render)
79
+ expect(colors.fill_color).to_not eq([0.8, 0.8, 0.8])
80
+ expect(colors.stroke_color).to_not eq([0.8, 0.8, 0.8])
81
+
82
+ # Hardcoded default color as I haven't been able to come up with
83
+ # a stable converter between fill_color without lots code.
84
+ expect(colors.stroke_color).to eq([0.0, 0.0, 0.0])
85
+ end
86
+
87
+ it 'draws outlines without curent color settings' do
88
+ pdf.fill_color 'ccff00'
89
+ pdf.stroke_color 'ffcc00'
90
+
91
+ pdf.grid.show_all
92
+
93
+ colors = PDF::Inspector::Graphics::Color.analyze(pdf.render)
94
+ expect(colors.fill_color).to eq([0.8, 1.0, 0.0])
95
+ expect(colors.stroke_color).to eq([1.0, 0.8, 0.0])
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Document do
6
+ describe 'A Reference object' do
7
+ describe 'generated via Prawn::Document' do
8
+ it 'returns a proper reference on ref!' do
9
+ pdf = described_class.new
10
+ expect(pdf.ref!({}).is_a?(PDF::Core::Reference)).to eq(true)
11
+ end
12
+
13
+ it 'returns an identifier on ref' do
14
+ pdf = described_class.new
15
+ r = pdf.ref({})
16
+ expect(r.is_a?(Integer)).to eq(true)
17
+ end
18
+
19
+ it 'has :Length of stream if it has one when compression disabled' do
20
+ pdf = described_class.new compress: false
21
+ ref = pdf.ref!({})
22
+ ref << 'Hello'
23
+ expect(ref.stream.data[:Length]).to eq(5)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Document do
6
+ let(:pdf) { create_pdf }
7
+
8
+ it 'onlies accept :position as option in debug mode' do
9
+ Prawn.debug = true
10
+ expect do
11
+ pdf.span(350, x: 3) do
12
+ # draw
13
+ end
14
+ end.to raise_error(Prawn::Errors::UnknownOption)
15
+ end
16
+
17
+ it 'has raise an error if :position is invalid' do
18
+ expect do
19
+ pdf.span(350, position: :x) do
20
+ # draw
21
+ end
22
+ end.to raise_error(ArgumentError)
23
+ end
24
+
25
+ it 'restores 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
+ expect(pdf.bounds).to eq(margin_box)
33
+ end
34
+
35
+ it 'does create a margin box' do
36
+ margin_box =
37
+ pdf.span(350, position: :center) do
38
+ pdf.text "Here's some centered text in a 350 point column. " * 100
39
+ end
40
+
41
+ expect(margin_box.top).to eq(792.0)
42
+ expect(margin_box.bottom).to eq(0)
43
+ end
44
+ end