prawn 2.1.0 → 2.2.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 (278) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -9
  5. data/Rakefile +12 -22
  6. data/lib/prawn.rb +29 -48
  7. data/lib/prawn/document.rb +148 -123
  8. data/lib/prawn/document/bounding_box.rb +33 -26
  9. data/lib/prawn/document/column_box.rb +5 -7
  10. data/lib/prawn/document/internals.rb +6 -6
  11. data/lib/prawn/document/span.rb +20 -17
  12. data/lib/prawn/encoding.rb +65 -67
  13. data/lib/prawn/errors.rb +10 -7
  14. data/lib/prawn/font.rb +78 -62
  15. data/lib/prawn/font/afm.rb +93 -66
  16. data/lib/prawn/font/dfont.rb +2 -10
  17. data/lib/prawn/font/ttc.rb +34 -0
  18. data/lib/prawn/font/ttf.rb +73 -65
  19. data/lib/prawn/font_metric_cache.rb +9 -8
  20. data/lib/prawn/graphics.rb +110 -70
  21. data/lib/prawn/graphics/blend_mode.rb +7 -8
  22. data/lib/prawn/graphics/cap_style.rb +2 -4
  23. data/lib/prawn/graphics/color.rb +23 -26
  24. data/lib/prawn/graphics/dash.rb +22 -12
  25. data/lib/prawn/graphics/join_style.rb +8 -4
  26. data/lib/prawn/graphics/patterns.rb +185 -96
  27. data/lib/prawn/graphics/transformation.rb +11 -9
  28. data/lib/prawn/graphics/transparency.rb +15 -13
  29. data/lib/prawn/grid.rb +20 -20
  30. data/lib/prawn/image_handler.rb +4 -6
  31. data/lib/prawn/images.rb +22 -15
  32. data/lib/prawn/images/image.rb +0 -1
  33. data/lib/prawn/images/jpg.rb +26 -22
  34. data/lib/prawn/images/png.rb +60 -57
  35. data/lib/prawn/measurement_extensions.rb +8 -9
  36. data/lib/prawn/measurements.rb +14 -15
  37. data/lib/prawn/outline.rb +96 -78
  38. data/lib/prawn/repeater.rb +12 -10
  39. data/lib/prawn/security.rb +66 -48
  40. data/lib/prawn/security/arcfour.rb +1 -3
  41. data/lib/prawn/soft_mask.rb +23 -25
  42. data/lib/prawn/stamp.rb +16 -12
  43. data/lib/prawn/text.rb +59 -45
  44. data/lib/prawn/text/box.rb +9 -8
  45. data/lib/prawn/text/formatted.rb +4 -6
  46. data/lib/prawn/text/formatted/arranger.rb +51 -30
  47. data/lib/prawn/text/formatted/box.rb +112 -88
  48. data/lib/prawn/text/formatted/fragment.rb +10 -15
  49. data/lib/prawn/text/formatted/line_wrap.rb +118 -61
  50. data/lib/prawn/text/formatted/parser.rb +134 -110
  51. data/lib/prawn/text/formatted/wrap.rb +42 -32
  52. data/lib/prawn/transformation_stack.rb +3 -4
  53. data/lib/prawn/utilities.rb +6 -21
  54. data/lib/prawn/version.rb +1 -3
  55. data/lib/prawn/view.rb +4 -2
  56. data/manual/basic_concepts/adding_pages.rb +4 -7
  57. data/manual/basic_concepts/basic_concepts.rb +29 -22
  58. data/manual/basic_concepts/creation.rb +8 -11
  59. data/manual/basic_concepts/cursor.rb +2 -5
  60. data/manual/basic_concepts/measurement.rb +3 -6
  61. data/manual/basic_concepts/origin.rb +3 -6
  62. data/manual/basic_concepts/other_cursor_helpers.rb +9 -12
  63. data/manual/basic_concepts/view.rb +20 -16
  64. data/manual/bounding_box/bounding_box.rb +27 -24
  65. data/manual/bounding_box/bounds.rb +9 -12
  66. data/manual/bounding_box/canvas.rb +2 -5
  67. data/manual/bounding_box/creation.rb +4 -7
  68. data/manual/bounding_box/indentation.rb +12 -15
  69. data/manual/bounding_box/nesting.rb +22 -17
  70. data/manual/bounding_box/russian_boxes.rb +8 -9
  71. data/manual/bounding_box/stretchy.rb +10 -13
  72. data/manual/contents.rb +26 -22
  73. data/manual/cover.rb +22 -20
  74. data/manual/document_and_page_options/background.rb +9 -13
  75. data/manual/document_and_page_options/document_and_page_options.rb +23 -20
  76. data/manual/document_and_page_options/metadata.rb +16 -16
  77. data/manual/document_and_page_options/page_margins.rb +16 -20
  78. data/manual/document_and_page_options/page_size.rb +11 -12
  79. data/manual/document_and_page_options/print_scaling.rb +15 -15
  80. data/manual/example_helper.rb +2 -4
  81. data/manual/graphics/blend_mode.rb +10 -9
  82. data/manual/graphics/circle_and_ellipse.rb +2 -5
  83. data/manual/graphics/color.rb +5 -9
  84. data/manual/graphics/common_lines.rb +5 -8
  85. data/manual/graphics/fill_and_stroke.rb +2 -5
  86. data/manual/graphics/fill_rules.rb +7 -10
  87. data/manual/graphics/gradients.rb +25 -21
  88. data/manual/graphics/graphics.rb +49 -43
  89. data/manual/graphics/helper.rb +10 -9
  90. data/manual/graphics/line_width.rb +5 -7
  91. data/manual/graphics/lines_and_curves.rb +5 -8
  92. data/manual/graphics/polygon.rb +4 -8
  93. data/manual/graphics/rectangle.rb +2 -5
  94. data/manual/graphics/rotate.rb +4 -7
  95. data/manual/graphics/scale.rb +12 -15
  96. data/manual/graphics/soft_masks.rb +1 -4
  97. data/manual/graphics/stroke_cap.rb +3 -6
  98. data/manual/graphics/stroke_dash.rb +9 -12
  99. data/manual/graphics/stroke_join.rb +2 -5
  100. data/manual/graphics/translate.rb +7 -10
  101. data/manual/graphics/transparency.rb +5 -8
  102. data/manual/how_to_read_this_manual.rb +4 -6
  103. data/manual/images/absolute_position.rb +4 -7
  104. data/manual/images/fit.rb +5 -8
  105. data/manual/images/horizontal.rb +6 -9
  106. data/manual/images/images.rb +25 -23
  107. data/manual/images/plain_image.rb +3 -6
  108. data/manual/images/scale.rb +7 -10
  109. data/manual/images/vertical.rb +10 -13
  110. data/manual/images/width_and_height.rb +8 -11
  111. data/manual/layout/boxes.rb +3 -6
  112. data/manual/layout/content.rb +5 -8
  113. data/manual/layout/layout.rb +16 -16
  114. data/manual/layout/simple_grid.rb +4 -7
  115. data/manual/outline/add_subsection_to.rb +18 -21
  116. data/manual/outline/insert_section_after.rb +13 -16
  117. data/manual/outline/outline.rb +19 -17
  118. data/manual/outline/sections_and_pages.rb +15 -18
  119. data/manual/repeatable_content/alternate_page_numbering.rb +19 -17
  120. data/manual/repeatable_content/page_numbering.rb +15 -16
  121. data/manual/repeatable_content/repeatable_content.rb +23 -19
  122. data/manual/repeatable_content/repeater.rb +12 -15
  123. data/manual/repeatable_content/stamp.rb +12 -15
  124. data/manual/security/encryption.rb +7 -10
  125. data/manual/security/permissions.rb +17 -14
  126. data/manual/security/security.rb +17 -16
  127. data/manual/table.rb +2 -4
  128. data/manual/text/alignment.rb +14 -17
  129. data/manual/text/color.rb +10 -11
  130. data/manual/text/column_box.rb +5 -8
  131. data/manual/text/fallback_fonts.rb +23 -21
  132. data/manual/text/font.rb +9 -12
  133. data/manual/text/font_size.rb +11 -14
  134. data/manual/text/font_style.rb +4 -7
  135. data/manual/text/formatted_callbacks.rb +23 -21
  136. data/manual/text/formatted_text.rb +31 -25
  137. data/manual/text/free_flowing_text.rb +18 -21
  138. data/manual/text/inline.rb +16 -19
  139. data/manual/text/kerning_and_character_spacing.rb +12 -15
  140. data/manual/text/leading.rb +5 -8
  141. data/manual/text/line_wrapping.rb +33 -17
  142. data/manual/text/paragraph_indentation.rb +11 -14
  143. data/manual/text/positioned_text.rb +13 -16
  144. data/manual/text/registering_families.rb +16 -19
  145. data/manual/text/rendering_and_color.rb +7 -10
  146. data/manual/text/right_to_left_text.rb +24 -19
  147. data/manual/text/rotation.rb +26 -23
  148. data/manual/text/single_usage.rb +6 -9
  149. data/manual/text/text.rb +56 -52
  150. data/manual/text/text_box_excess.rb +18 -17
  151. data/manual/text/text_box_extensions.rb +16 -15
  152. data/manual/text/text_box_overflow.rb +15 -18
  153. data/manual/text/utf8.rb +9 -12
  154. data/manual/text/win_ansi_charset.rb +18 -19
  155. data/prawn.gemspec +37 -27
  156. data/spec/extensions/encoding_helpers.rb +0 -2
  157. data/spec/manual_spec.rb +33 -0
  158. data/spec/prawn/document/bounding_box_spec.rb +546 -0
  159. data/spec/prawn/document/column_box_spec.rb +73 -0
  160. data/spec/prawn/document/security_spec.rb +173 -0
  161. data/spec/prawn/document_annotations_spec.rb +74 -0
  162. data/spec/prawn/document_destinations_spec.rb +13 -0
  163. data/spec/prawn/document_grid_spec.rb +96 -0
  164. data/spec/prawn/document_reference_spec.rb +25 -0
  165. data/spec/prawn/document_span_spec.rb +34 -0
  166. data/spec/prawn/document_spec.rb +751 -0
  167. data/spec/prawn/font_metric_cache_spec.rb +52 -0
  168. data/spec/prawn/font_spec.rb +513 -0
  169. data/spec/prawn/graphics/blend_mode_spec.rb +61 -0
  170. data/spec/prawn/graphics/transparency_spec.rb +79 -0
  171. data/spec/prawn/graphics_spec.rb +817 -0
  172. data/spec/prawn/graphics_stroke_styles_spec.rb +227 -0
  173. data/spec/{image_handler_spec.rb → prawn/image_handler_spec.rb} +13 -15
  174. data/spec/prawn/images/jpg_spec.rb +18 -0
  175. data/spec/prawn/images/png_spec.rb +281 -0
  176. data/spec/prawn/images_spec.rb +170 -0
  177. data/spec/prawn/measurements_extensions_spec.rb +22 -0
  178. data/spec/prawn/outline_spec.rb +408 -0
  179. data/spec/prawn/repeater_spec.rb +163 -0
  180. data/spec/prawn/soft_mask_spec.rb +72 -0
  181. data/spec/prawn/stamp_spec.rb +168 -0
  182. data/spec/prawn/text/box_spec.rb +1113 -0
  183. data/spec/prawn/text/formatted/arranger_spec.rb +464 -0
  184. data/spec/prawn/text/formatted/box_spec.rb +825 -0
  185. data/spec/prawn/text/formatted/fragment_spec.rb +341 -0
  186. data/spec/prawn/text/formatted/line_wrap_spec.rb +491 -0
  187. data/spec/prawn/text/formatted/parser_spec.rb +667 -0
  188. data/spec/prawn/text_draw_text_spec.rb +147 -0
  189. data/spec/prawn/text_rendering_mode_spec.rb +42 -0
  190. data/spec/prawn/text_spacing_spec.rb +93 -0
  191. data/spec/prawn/text_spec.rb +601 -0
  192. data/spec/prawn/text_with_inline_formatting_spec.rb +33 -0
  193. data/spec/{transformation_stack_spec.rb → prawn/transformation_stack_spec.rb} +21 -20
  194. data/spec/prawn/view_spec.rb +45 -0
  195. data/spec/spec_helper.rb +16 -16
  196. metadata +96 -151
  197. metadata.gz.sig +1 -0
  198. data/data/images/16bit.alpha +0 -0
  199. data/data/images/16bit.color +0 -0
  200. data/data/images/16bit.png +0 -0
  201. data/data/images/arrow.png +0 -0
  202. data/data/images/arrow2.png +0 -0
  203. data/data/images/blend_modes_bottom_layer.jpg +0 -0
  204. data/data/images/blend_modes_top_layer.jpg +0 -0
  205. data/data/images/dice.alpha +0 -0
  206. data/data/images/dice.color +0 -0
  207. data/data/images/dice.png +0 -0
  208. data/data/images/dice_interlaced.png +0 -0
  209. data/data/images/fractal.jpg +0 -0
  210. data/data/images/indexed_color.dat +0 -0
  211. data/data/images/indexed_color.png +0 -0
  212. data/data/images/indexed_transparency.png +0 -0
  213. data/data/images/indexed_transparency_alpha.dat +0 -0
  214. data/data/images/indexed_transparency_color.dat +0 -0
  215. data/data/images/letterhead.jpg +0 -0
  216. data/data/images/license.md +0 -8
  217. data/data/images/page_white_text.alpha +0 -0
  218. data/data/images/page_white_text.color +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/spec/acceptance/png_spec.rb +0 -35
  244. data/spec/annotations_spec.rb +0 -67
  245. data/spec/blend_mode_spec.rb +0 -71
  246. data/spec/bounding_box_spec.rb +0 -501
  247. data/spec/column_box_spec.rb +0 -59
  248. data/spec/destinations_spec.rb +0 -13
  249. data/spec/document_spec.rb +0 -738
  250. data/spec/font_metric_cache_spec.rb +0 -52
  251. data/spec/font_spec.rb +0 -475
  252. data/spec/formatted_text_arranger_spec.rb +0 -452
  253. data/spec/formatted_text_box_spec.rb +0 -716
  254. data/spec/formatted_text_fragment_spec.rb +0 -299
  255. data/spec/graphics_spec.rb +0 -705
  256. data/spec/grid_spec.rb +0 -95
  257. data/spec/images_spec.rb +0 -167
  258. data/spec/inline_formatted_text_parser_spec.rb +0 -568
  259. data/spec/jpg_spec.rb +0 -23
  260. data/spec/line_wrap_spec.rb +0 -366
  261. data/spec/measurement_units_spec.rb +0 -22
  262. data/spec/outline_spec.rb +0 -409
  263. data/spec/png_spec.rb +0 -257
  264. data/spec/reference_spec.rb +0 -25
  265. data/spec/repeater_spec.rb +0 -154
  266. data/spec/security_spec.rb +0 -151
  267. data/spec/soft_mask_spec.rb +0 -78
  268. data/spec/span_spec.rb +0 -43
  269. data/spec/stamp_spec.rb +0 -179
  270. data/spec/stroke_styles_spec.rb +0 -208
  271. data/spec/text_at_spec.rb +0 -142
  272. data/spec/text_box_spec.rb +0 -1042
  273. data/spec/text_rendering_mode_spec.rb +0 -45
  274. data/spec/text_spacing_spec.rb +0 -93
  275. data/spec/text_spec.rb +0 -543
  276. data/spec/text_with_inline_formatting_spec.rb +0 -35
  277. data/spec/transparency_spec.rb +0 -91
  278. data/spec/view_spec.rb +0 -42
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prawn::Document::ColumnBox do
4
+ let(:pdf) { create_pdf }
5
+
6
+ it 'has sensible left and right values' do
7
+ pdf.column_box(
8
+ [0, pdf.cursor],
9
+ width: pdf.bounds.width,
10
+ height: 200,
11
+ columns: 3,
12
+ spacer: 25
13
+ ) do
14
+ left = pdf.bounds.left
15
+ right = pdf.bounds.right
16
+
17
+ pdf.bounds.move_past_bottom # next column
18
+
19
+ expect(pdf.bounds.left).to be > left
20
+ expect(pdf.bounds.left).to be > right
21
+ expect(pdf.bounds.right).to be > pdf.bounds.left
22
+ end
23
+ end
24
+
25
+ it 'includes spacers between columns but not at the end' do
26
+ pdf.column_box(
27
+ [0, pdf.cursor],
28
+ width: 500,
29
+ height: 200,
30
+ columns: 3,
31
+ spacer: 25
32
+ ) do
33
+ expect(pdf.bounds.width).to eq(150) # (500 - (25 * 2)) / 3
34
+
35
+ pdf.bounds.move_past_bottom
36
+ pdf.bounds.move_past_bottom
37
+
38
+ expect(pdf.bounds.right).to eq(500)
39
+ end
40
+ end
41
+
42
+ it 'does not reset the top margin on a new page by default' do
43
+ page_top = pdf.cursor
44
+ pdf.move_down 50
45
+ init_column_top = pdf.cursor
46
+ pdf.column_box [0, pdf.cursor], width: 500, height: 200, columns: 2 do
47
+ pdf.bounds.move_past_bottom
48
+ pdf.bounds.move_past_bottom
49
+
50
+ expect(pdf.bounds.absolute_top).to eq(init_column_top)
51
+ expect(pdf.bounds.absolute_top).to_not eq(page_top)
52
+ end
53
+ end
54
+
55
+ it 'does reset the top margin when reflow_margins is set' do
56
+ page_top = pdf.cursor
57
+ pdf.move_down 50
58
+ init_column_top = pdf.cursor
59
+ pdf.column_box(
60
+ [0, pdf.cursor],
61
+ width: 500,
62
+ reflow_margins: true,
63
+ height: 200,
64
+ columns: 2
65
+ ) do
66
+ pdf.bounds.move_past_bottom
67
+ pdf.bounds.move_past_bottom
68
+
69
+ expect(pdf.bounds.absolute_top).to eq(page_top)
70
+ expect(pdf.bounds.absolute_top).to_not eq(init_column_top)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,173 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ describe Prawn::Document::Security do
5
+ describe 'Password padding' do
6
+ include described_class
7
+
8
+ it 'truncates long passwords' do
9
+ pw = 'Long long string' * 30
10
+ padded = pad_password(pw)
11
+ expect(padded.length).to eq(32)
12
+ expect(padded).to eq(pw[0, 32])
13
+ end
14
+
15
+ it 'pads short passwords' do
16
+ pw = 'abcd'
17
+ padded = pad_password(pw)
18
+ expect(padded.length).to eq(32)
19
+ expect(padded).to eq(
20
+ pw + Prawn::Document::Security::PasswordPadding[0, 28]
21
+ )
22
+ end
23
+
24
+ it 'fullies pad null passwords' do
25
+ pw = ''
26
+ padded = pad_password(pw)
27
+ expect(padded.length).to eq(32)
28
+ expect(padded).to eq(Prawn::Document::Security::PasswordPadding)
29
+ end
30
+ end
31
+
32
+ describe 'Setting permissions' do
33
+ def doc_with_permissions(permissions)
34
+ pdf = Prawn::Document.new
35
+
36
+ class << pdf
37
+ # Make things easier to test
38
+ public :permissions_value
39
+ end
40
+
41
+ pdf.encrypt_document(permissions: permissions)
42
+ pdf
43
+ end
44
+
45
+ it 'defaults to full permissions' do
46
+ expect(doc_with_permissions({}).permissions_value).to eq(0xFFFFFFFF)
47
+ expect(doc_with_permissions(
48
+ print_document: true,
49
+ modify_contents: true,
50
+ copy_contents: true,
51
+ modify_annotations: true
52
+ ).permissions_value)
53
+ .to eq(0xFFFFFFFF)
54
+ end
55
+
56
+ it 'clears the appropriate bits for each permission flag' do
57
+ expect(doc_with_permissions(print_document: false).permissions_value)
58
+ .to eq(0b1111_1111_1111_1111_1111_1111_1111_1011)
59
+ expect(doc_with_permissions(modify_contents: false).permissions_value)
60
+ .to eq(0b1111_1111_1111_1111_1111_1111_1111_0111)
61
+ expect(doc_with_permissions(copy_contents: false).permissions_value)
62
+ .to eq(0b1111_1111_1111_1111_1111_1111_1110_1111)
63
+ expect(doc_with_permissions(modify_annotations: false).permissions_value)
64
+ .to eq(0b1111_1111_1111_1111_1111_1111_1101_1111)
65
+ end
66
+
67
+ it 'raise_errors ArgumentError if invalid option is provided' do
68
+ expect do
69
+ doc_with_permissions(modify_document: false)
70
+ end.to raise_error(ArgumentError)
71
+ end
72
+ end
73
+
74
+ describe 'Encryption keys' do
75
+ # Since PDF::Reader doesn't read encrypted PDF files, we just take the
76
+ # roundabout method of verifying each step of the encryption. This works
77
+ # fine because the encryption method is deterministic.
78
+
79
+ let(:pdf) do
80
+ Prawn::Document.new do |pdf|
81
+ class << pdf
82
+ public :owner_password_hash, :user_password_hash, :user_encryption_key
83
+ end
84
+ pdf.encrypt_document(
85
+ user_password: 'foo',
86
+ owner_password: 'bar',
87
+ permissions: { print_document: false }
88
+ )
89
+ end
90
+ end
91
+
92
+ it 'calculates the correct owner hash' do
93
+ expect(pdf.owner_password_hash.unpack('H*').first)
94
+ .to match(/^61CA855012/i)
95
+ end
96
+
97
+ it 'calculates the correct user hash' do
98
+ expect(pdf.user_password_hash.unpack('H*').first)
99
+ .to match(/^6BC8C51031/i)
100
+ end
101
+
102
+ it 'calculates the correct user_encryption_key' do
103
+ expect(pdf.user_encryption_key.unpack('H*').first.upcase)
104
+ .to eq('B100AB6429')
105
+ end
106
+ end
107
+
108
+ describe 'encrypted_pdf_object' do
109
+ it 'delegates to PdfObject for simple types' do
110
+ expect(PDF::Core.encrypted_pdf_object(true, nil, nil, nil)).to eq('true')
111
+ expect(PDF::Core.encrypted_pdf_object(42, nil, nil, nil)).to eq('42')
112
+ end
113
+
114
+ it 'encrypts strings properly' do
115
+ expect(PDF::Core.encrypted_pdf_object('foo', '12345', 123, 0))
116
+ .to eq('<4ad6e3>')
117
+ end
118
+
119
+ it 'encrypts literal strings properly' do
120
+ expect(PDF::Core.encrypted_pdf_object(
121
+ PDF::Core::LiteralString.new('foo'), '12345', 123, 0
122
+ )).to eq(bin_string("(J\xD6\xE3)"))
123
+ expect(PDF::Core.encrypted_pdf_object(
124
+ PDF::Core::LiteralString.new('lhfbqg3do5u0satu3fjf'), nil, 123, 0
125
+ )).to eq(bin_string(
126
+ "(\xF1\x8B\\(\b\xBB\xE18S\x130~4*#\\(%\x87\xE7\x8E\\\n)"
127
+ ))
128
+ end
129
+
130
+ it 'encrypts time properly' do
131
+ expect(PDF::Core.encrypted_pdf_object(
132
+ Time.utc(2050, 0o4, 26, 10, 17, 10), '12345', 123, 0
133
+ )).to eq(bin_string(
134
+ "(h\x83\xBE\xDC\xEC\x99\x0F\xD7\\)%\x13\xD4$\xB8\xF0\x16\xB8\x80\xC5"\
135
+ "\xE91+\xCF)"
136
+ ))
137
+ end
138
+
139
+ it 'properlies handle compound types' do
140
+ expect(PDF::Core.encrypted_pdf_object({ Bar: 'foo' }, '12345', 123, 0))
141
+ .to eq(
142
+ "<< /Bar <4ad6e3>\n>>"
143
+ )
144
+ expect(PDF::Core.encrypted_pdf_object(%w[foo bar], '12345', 123, 0))
145
+ .to eq('[<4ad6e3> <4ed8fe>]')
146
+ end
147
+ end
148
+
149
+ describe 'Reference#encrypted_object' do
150
+ it 'encrypts references properly' do
151
+ ref = PDF::Core::Reference.new(1, ['foo'])
152
+ expect(ref.encrypted_object(nil)).to eq("1 0 obj\n[<4fca3f>]\nendobj\n")
153
+ end
154
+
155
+ it 'encrypts references with streams properly' do
156
+ ref = PDF::Core::Reference.new(1, {})
157
+ ref << 'foo'
158
+ result = bin_string(
159
+ "1 0 obj\n<< /Length 3\n>>\nstream\nO\xCA?\nendstream\nendobj\n"
160
+ )
161
+ expect(ref.encrypted_object(nil)).to eq(result)
162
+ end
163
+ end
164
+
165
+ describe 'String#encrypted_object' do
166
+ it 'encrypts stream properly' do
167
+ stream = PDF::Core::Stream.new
168
+ stream << 'foo'
169
+ result = bin_string("stream\nO\xCA?\nendstream\n")
170
+ expect(stream.encrypted_object(nil, 1, 0)).to eq(result)
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prawn::Document do
4
+ let(:pdf) { create_pdf }
5
+
6
+ describe 'When creating annotations' do
7
+ it 'appends annotation to current page' do
8
+ pdf.start_new_page
9
+ pdf.annotate(
10
+ Rect: [0, 0, 10, 10],
11
+ Subtype: :Text,
12
+ Contents: 'Hello world!'
13
+ )
14
+ PDF::Reader.open(StringIO.new(pdf.render)) do |pdf|
15
+ expect(pdf.page(1).attributes[:Annots]).to be_nil
16
+ expect(pdf.page(2).attributes[:Annots].size).to eq(1)
17
+ end
18
+ end
19
+
20
+ it 'forces :Type to be :Annot' do
21
+ opts = pdf.annotate(
22
+ Rect: [0, 0, 10, 10],
23
+ Subtype: :Text,
24
+ Contents: 'Hello world!'
25
+ )
26
+ expect(opts[:Type]).to eq(:Annot)
27
+ opts = pdf.annotate(
28
+ Type: :Bogus,
29
+ Rect: [0, 0, 10, 10],
30
+ Subtype: :Text,
31
+ Contents: 'Hello world!'
32
+ )
33
+ expect(opts[:Type]).to eq(:Annot)
34
+ end
35
+ end
36
+
37
+ describe 'When creating text annotations' do
38
+ let(:rect) { [0, 0, 10, 10] }
39
+ let(:content) { 'Hello, world!' }
40
+
41
+ it 'builds appropriate annotation' do
42
+ opts = pdf.text_annotation(rect, content)
43
+ expect(opts[:Type]).to eq(:Annot)
44
+ expect(opts[:Subtype]).to eq(:Text)
45
+ expect(opts[:Rect]).to eq(rect)
46
+ expect(opts[:Contents]).to eq(content)
47
+ end
48
+
49
+ it 'merges extra options' do
50
+ opts = pdf.text_annotation(rect, content, Open: true, Subtype: :Bogus)
51
+ expect(opts[:Subtype]).to eq(:Text)
52
+ expect(opts[:Open]).to eq(true)
53
+ end
54
+ end
55
+
56
+ describe 'When creating link annotations' do
57
+ let(:rect) { [0, 0, 10, 10] }
58
+ let(:dest) { 'home' }
59
+
60
+ it 'builds appropriate annotation' do
61
+ opts = pdf.link_annotation(rect, Dest: dest)
62
+ expect(opts[:Type]).to eq(:Annot)
63
+ expect(opts[:Subtype]).to eq(:Link)
64
+ expect(opts[:Rect]).to eq(rect)
65
+ expect(opts[:Dest]).to eq(dest)
66
+ end
67
+
68
+ it 'merges extra options' do
69
+ opts = pdf.link_annotation(rect, Dest: dest, Subtype: :Bogus)
70
+ expect(opts[:Subtype]).to eq(:Link)
71
+ expect(opts[:Dest]).to eq(dest)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prawn::Document do
4
+ describe 'When creating destinations' do
5
+ let(:pdf) { create_pdf }
6
+
7
+ it 'adds entry to Dests name tree' do
8
+ expect(pdf.dests.data.empty?).to eq(true)
9
+ pdf.add_dest 'candy', 'chocolate'
10
+ expect(pdf.dests.data.size).to eq(1)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prawn::Document do
4
+ describe 'grid' do
5
+ let(:pdf) { described_class.new }
6
+
7
+ it 'allows definition of a grid' do
8
+ pdf.define_grid(columns: 5, rows: 8, gutter: 0.1)
9
+ expect(pdf.grid.columns).to eq(5)
10
+ expect(pdf.grid.rows).to eq(8)
11
+ expect(pdf.grid.gutter).to eq(0.1)
12
+ end
13
+
14
+ it 'allows re-definition of a grid' do
15
+ pdf.define_grid(columns: 5, rows: 8, gutter: 0.1)
16
+ expect(pdf.grid.columns).to eq(5)
17
+ expect(pdf.grid.rows).to eq(8)
18
+ expect(pdf.grid.gutter).to eq(0.1)
19
+ pdf.define_grid(columns: 3, rows: 6, gutter: 0.1)
20
+ expect(pdf.grid.columns).to eq(3)
21
+ expect(pdf.grid.rows).to eq(6)
22
+ expect(pdf.grid.gutter).to eq(0.1)
23
+ end
24
+
25
+ describe 'when a grid is defined' do
26
+ let(:num_columns) { 5 }
27
+ let(:num_rows) { 8 }
28
+ let(:gutter) { 10.0 }
29
+ before do
30
+ pdf.define_grid(
31
+ columns: num_columns,
32
+ rows: num_rows,
33
+ gutter: gutter
34
+ )
35
+ end
36
+
37
+ it 'computes the column width' do
38
+ expect(pdf.grid.column_width * num_columns.to_f +
39
+ gutter * (num_columns - 1).to_f).to eq(pdf.bounds.width)
40
+ end
41
+
42
+ it 'computes the row height' do
43
+ expect(pdf.grid.row_height * num_rows.to_f +
44
+ gutter * (num_rows - 1).to_f).to eq(pdf.bounds.height)
45
+ end
46
+
47
+ it 'gives the edges of a grid box' do
48
+ grid_width = (pdf.bounds.width.to_f -
49
+ (gutter * (num_columns - 1).to_f)) / num_columns.to_f
50
+ grid_height = (pdf.bounds.height.to_f -
51
+ (gutter * (num_rows - 1).to_f)) / num_rows.to_f
52
+
53
+ exp_tl_x = (grid_width + gutter.to_f) * 4.0
54
+ exp_tl_y = pdf.bounds.height.to_f - (grid_height + gutter.to_f)
55
+
56
+ expect(pdf.grid(1, 4).top_left).to eq([exp_tl_x, exp_tl_y])
57
+ expect(pdf.grid(1, 4).top_right).to eq [exp_tl_x + grid_width, exp_tl_y]
58
+ expect(pdf.grid(1, 4).bottom_left)
59
+ .to eq([exp_tl_x, exp_tl_y - grid_height])
60
+ expect(pdf.grid(1, 4).bottom_right)
61
+ .to eq([exp_tl_x + grid_width, exp_tl_y - grid_height])
62
+ end
63
+
64
+ it 'gives the edges of a multiple grid boxes' do
65
+ # Hand verified. Cheating a bit. Don't tell.
66
+ expect(pdf.grid([1, 3], [2, 5]).top_left).to eq([330.0, 628.75])
67
+ expect(pdf.grid([1, 3], [2, 5]).top_right).to eq([650.0, 628.75])
68
+ expect(pdf.grid([1, 3], [2, 5]).bottom_left).to eq([330.0, 456.25])
69
+ expect(pdf.grid([1, 3], [2, 5]).bottom_right).to eq([650.0, 456.25])
70
+ end
71
+
72
+ it 'draws outlines without changing global default colors' do
73
+ pdf.grid.show_all('cccccc')
74
+
75
+ colors = PDF::Inspector::Graphics::Color.analyze(pdf.render)
76
+ expect(colors.fill_color).to_not eq([0.8, 0.8, 0.8])
77
+ expect(colors.stroke_color).to_not eq([0.8, 0.8, 0.8])
78
+
79
+ # Hardcoded default color as I haven't been able to come up with
80
+ # a stable converter between fill_color without lots code.
81
+ expect(colors.stroke_color).to eq([0.0, 0.0, 0.0])
82
+ end
83
+
84
+ it 'draws outlines without curent color settings' do
85
+ pdf.fill_color 'ccff00'
86
+ pdf.stroke_color 'ffcc00'
87
+
88
+ pdf.grid.show_all
89
+
90
+ colors = PDF::Inspector::Graphics::Color.analyze(pdf.render)
91
+ expect(colors.fill_color).to eq([0.8, 1.0, 0.0])
92
+ expect(colors.stroke_color).to eq([1.0, 0.8, 0.0])
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prawn::Document do
4
+ describe 'A Reference object' do
5
+ describe 'generated via Prawn::Document' do
6
+ it 'returns a proper reference on ref!' do
7
+ pdf = described_class.new
8
+ expect(pdf.ref!({}).is_a?(PDF::Core::Reference)).to eq(true)
9
+ end
10
+
11
+ it 'returns an identifier on ref' do
12
+ pdf = described_class.new
13
+ r = pdf.ref({})
14
+ expect(r.is_a?(Integer)).to eq(true)
15
+ end
16
+
17
+ it 'has :Length of stream if it has one when compression disabled' do
18
+ pdf = described_class.new compress: false
19
+ ref = pdf.ref!({})
20
+ ref << 'Hello'
21
+ expect(ref.stream.data[:Length]).to eq(5)
22
+ end
23
+ end
24
+ end
25
+ end