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
@@ -1,761 +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 "Prawn::Document.new" do
7
- it "should not modify its argument" do
8
- options = {:page_layout => :landscape}
9
- Prawn::Document.new(options)
10
- options.should == {:page_layout => :landscape}
11
- end
12
- end
13
-
14
- describe "The cursor" do
15
- it "should == pdf.y - bounds.absolute_bottom" do
16
- pdf = Prawn::Document.new
17
- pdf.cursor.should == pdf.bounds.top
18
-
19
- pdf.y = 300
20
- pdf.cursor.should == pdf.y - pdf.bounds.absolute_bottom
21
- end
22
-
23
- it "should be able to move relative to the bottom margin" do
24
- pdf = Prawn::Document.new
25
- pdf.move_cursor_to(10)
26
-
27
- pdf.cursor.should == 10
28
- pdf.y.should == pdf.cursor + pdf.bounds.absolute_bottom
29
- end
30
- end
31
-
32
- describe "when generating a document with a custom text formatter" do
33
- it "should use the provided text formatter" do
34
- class TestTextFormatter
35
- def self.format(string)
36
- [
37
- {
38
- text: string.gsub("Dr. Who?", "Just 'The Doctor'."),
39
- styles: [],
40
- color: nil,
41
- link: nil,
42
- anchor: nil,
43
- local: nil,
44
- font: nil,
45
- size: nil,
46
- character_spacing: nil
47
- }
48
- ]
49
- end
50
- end
51
- pdf = Prawn::Document.new text_formatter: TestTextFormatter
52
- pdf.text "Dr. Who?", inline_format: true
53
- text = PDF::Inspector::Text.analyze(pdf.render)
54
- text.strings.first.should == "Just 'The Doctor'."
55
- end
56
- end
57
-
58
- describe "when generating a document from a subclass" do
59
- it "should be an instance of the subclass" do
60
- custom_document = Class.new(Prawn::Document)
61
- custom_document.generate(Tempfile.new("generate_test").path) do |e|
62
- e.class.should == custom_document
63
- e.should be_a_kind_of(Prawn::Document)
64
- end
65
- end
66
-
67
- it "should retain any extensions found on Prawn::Document" do
68
- mod1 = Module.new { attr_reader :test_extensions1 }
69
- mod2 = Module.new { attr_reader :test_extensions2 }
70
-
71
- Prawn::Document.extensions << mod1 << mod2
72
-
73
- custom_document = Class.new(Prawn::Document)
74
- custom_document.extensions.should == [mod1, mod2]
75
-
76
- # remove the extensions we added to prawn document
77
- Prawn::Document.extensions.delete(mod1)
78
- Prawn::Document.extensions.delete(mod2)
79
-
80
- Prawn::Document.new.respond_to?(:test_extensions1).should be_false
81
- Prawn::Document.new.respond_to?(:test_extensions2).should be_false
82
-
83
- # verify these still exist on custom class
84
- custom_document.extensions.should == [mod1, mod2]
85
-
86
- custom_document.new.respond_to?(:test_extensions1).should be_true
87
- custom_document.new.respond_to?(:test_extensions2).should be_true
88
- end
89
-
90
- end
91
-
92
-
93
- describe "When creating multi-page documents" do
94
-
95
- before(:each) { create_pdf }
96
-
97
- it "should initialize with a single page" do
98
- page_counter = PDF::Inspector::Page.analyze(@pdf.render)
99
-
100
- page_counter.pages.size.should == 1
101
- @pdf.page_count.should == 1
102
- end
103
-
104
- it "should provide an accurate page_count" do
105
- 3.times { @pdf.start_new_page }
106
- page_counter = PDF::Inspector::Page.analyze(@pdf.render)
107
-
108
- page_counter.pages.size.should == 4
109
- @pdf.page_count.should == 4
110
- end
111
-
112
- end
113
-
114
- describe "When beginning each new page" do
115
-
116
- describe "Background template feature" do
117
- before(:each) do
118
- @filename = "#{Prawn::DATADIR}/images/pigs.jpg"
119
- @pdf = Prawn::Document.new(:background => @filename)
120
- end
121
- it "should place a background image if it is in options block" do
122
- output = @pdf.render
123
- images = PDF::Inspector::XObject.analyze(output)
124
- # there should be 2 images in the page resources
125
- images.page_xobjects.first.size.should == 1
126
- end
127
- it "should place a background image if it is in options block" do
128
- @pdf.instance_variable_defined?(:@background).should == true
129
- @pdf.instance_variable_get(:@background).should == @filename
130
- end
131
-
132
-
133
- end
134
-
135
-
136
- end
137
-
138
- describe "Prawn::Document#float" do
139
- it "should restore the original y-position" do
140
- create_pdf
141
- orig_y = @pdf.y
142
- @pdf.float { @pdf.text "Foo" }
143
- @pdf.y.should == orig_y
144
- end
145
-
146
- it "should teleport across pages if necessary" do
147
- create_pdf
148
-
149
- @pdf.float do
150
- @pdf.text "Foo"
151
- @pdf.start_new_page
152
- @pdf.text "Bar"
153
- end
154
- @pdf.text "Baz"
155
-
156
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
157
- pages.size.should == 2
158
- pages[0][:strings].should == ["Foo", "Baz"]
159
- pages[1][:strings].should == ["Bar"]
160
- end
161
- end
162
-
163
- describe "The page_number method" do
164
- it "should be 1 for a new document" do
165
- pdf = Prawn::Document.new
166
- pdf.page_number.should == 1
167
- end
168
-
169
- it "should be 0 for documents with no pages" do
170
- pdf = Prawn::Document.new(:skip_page_creation => true)
171
- pdf.page_number.should == 0
172
- end
173
-
174
- it "should be changed by go_to_page" do
175
- pdf = Prawn::Document.new
176
- 10.times { pdf.start_new_page }
177
- pdf.go_to_page 3
178
- pdf.page_number.should == 3
179
- end
180
-
181
- end
182
-
183
- describe "on_page_create callback" do
184
- before do
185
- create_pdf
186
- end
187
-
188
- it "should be invoked with document" do
189
- called_with = nil
190
-
191
- @pdf.on_page_create { |*args| called_with = args }
192
-
193
- @pdf.start_new_page
194
-
195
- called_with.should == [@pdf]
196
- end
197
-
198
- it "should be invoked for each new page" do
199
- trigger = mock()
200
- trigger.expects(:fire).times(5)
201
-
202
- @pdf.on_page_create { trigger.fire }
203
-
204
- 5.times { @pdf.start_new_page }
205
- end
206
-
207
- it "should be replaceable" do
208
- trigger1 = mock()
209
- trigger1.expects(:fire).times(1)
210
-
211
- trigger2 = mock()
212
- trigger2.expects(:fire).times(1)
213
-
214
- @pdf.on_page_create { trigger1.fire }
215
-
216
- @pdf.start_new_page
217
-
218
- @pdf.on_page_create { trigger2.fire }
219
-
220
- @pdf.start_new_page
221
- end
222
-
223
- it "should be clearable by calling on_page_create without a block" do
224
- trigger = mock()
225
- trigger.expects(:fire).times(1)
226
-
227
- @pdf.on_page_create { trigger.fire }
228
-
229
- @pdf.start_new_page
230
-
231
- @pdf.on_page_create
232
-
233
- @pdf.start_new_page
234
- end
235
-
236
- end
237
-
238
- describe "Document compression" do
239
-
240
- it "should not compress the page content stream if compression is disabled" do
241
-
242
- pdf = Prawn::Document.new(:compress => false)
243
- pdf.page.content.stream.stubs(:compress!).returns(true)
244
- pdf.page.content.stream.expects(:compress!).never
245
-
246
- pdf.text "Hi There" * 20
247
- pdf.render
248
- end
249
-
250
- it "should compress the page content stream if compression is enabled" do
251
-
252
- pdf = Prawn::Document.new(:compress => true)
253
- pdf.page.content.stream.stubs(:compress!).returns(true)
254
- pdf.page.content.stream.expects(:compress!).once
255
-
256
- pdf.text "Hi There" * 20
257
- pdf.render
258
- end
259
-
260
- it "should result in a smaller file size when compressed" do
261
- doc_uncompressed = Prawn::Document.new
262
- doc_compressed = Prawn::Document.new(:compress => true)
263
- [doc_compressed, doc_uncompressed].each do |pdf|
264
- pdf.font "#{Prawn::DATADIR}/fonts/gkai00mp.ttf"
265
- pdf.text "更可怕的是,同质化竞争对手可以按照URL中后面这个ID来遍历" * 10
266
- end
267
-
268
- doc_compressed.render.length.should be < doc_uncompressed.render.length
269
- end
270
-
271
- end
272
-
273
- describe "Document metadata" do
274
- it "should output strings as UTF-16 with a byte order mark" do
275
- pdf = Prawn::Document.new(:info => {:Author => "Lóránt"})
276
- pdf.state.store.info.object.should =~
277
- # UTF-16: BOM L ó r á n t
278
- %r{/Author\s*<feff004c00f3007200e1006e0074>}i
279
- end
280
- end
281
-
282
- describe "When reopening pages" do
283
- it "should modify the content stream size" do
284
- @pdf = Prawn::Document.new do |pdf|
285
- pdf.text "Page 1"
286
- pdf.start_new_page
287
- pdf.text "Page 2"
288
- pdf.go_to_page 1
289
- pdf.text "More for page 1"
290
- end
291
-
292
- # Indirectly verify that the actual length does not match dictionary length.
293
- # If it isn't, a MalformedPDFError will be raised
294
- PDF::Inspector::Page.analyze(@pdf.render)
295
- end
296
-
297
- it "should insert pages after the current page when calling start_new_page" do
298
- pdf = Prawn::Document.new
299
- 3.times { |i| pdf.text "Old page #{i+1}"; pdf.start_new_page }
300
- pdf.go_to_page 1
301
- pdf.start_new_page
302
- pdf.text "New page 2"
303
-
304
- pdf.page_number.should == 2
305
-
306
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
307
- pages.size.should == 5
308
- pages[1][:strings].should == ["New page 2"]
309
- pages[2][:strings].should == ["Old page 2"]
310
- end
311
-
312
- it "should update the bounding box to the new page's margin box" do
313
- Prawn::Document.new do
314
- start_new_page :layout => :landscape
315
- lsize = [bounds.width, bounds.height]
316
- go_to_page 1
317
- [bounds.width, bounds.height].should == lsize.reverse
318
- end
319
- end
320
- end
321
-
322
- describe "When setting page size" do
323
- it "should default to LETTER" do
324
- @pdf = Prawn::Document.new
325
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
326
- pages.first[:size].should == PDF::Core::PageGeometry::SIZES["LETTER"]
327
- end
328
-
329
- (PDF::Core::PageGeometry::SIZES.keys - ["LETTER"]).each do |k|
330
- it "should provide #{k} geometry" do
331
- @pdf = Prawn::Document.new(:page_size => k)
332
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
333
- pages.first[:size].should == PDF::Core::PageGeometry::SIZES[k]
334
- end
335
- end
336
-
337
- it "should allow custom page size" do
338
- @pdf = Prawn::Document.new(:page_size => [1920, 1080] )
339
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
340
- pages.first[:size].should == [1920, 1080]
341
- end
342
-
343
-
344
- it "should retain page size by default when starting a new page" do
345
- @pdf = Prawn::Document.new(:page_size => "LEGAL")
346
- @pdf.start_new_page
347
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
348
- pages.each do |page|
349
- page[:size].should == PDF::Core::PageGeometry::SIZES["LEGAL"]
350
- end
351
- end
352
-
353
- end
354
-
355
- describe "When setting page layout" do
356
- it "should reverse coordinates for landscape" do
357
- @pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
358
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
359
- pages.first[:size].should == PDF::Core::PageGeometry::SIZES["A4"].reverse
360
- end
361
-
362
- it "should retain page layout by default when starting a new page" do
363
- @pdf = Prawn::Document.new(:page_layout => :landscape)
364
- @pdf.start_new_page(:trace => true)
365
- pages = PDF::Inspector::Page.analyze(@pdf.render).pages
366
- pages.each do |page|
367
- page[:size].should == PDF::Core::PageGeometry::SIZES["LETTER"].reverse
368
- end
369
- end
370
-
371
- it "should swap the bounds when starting a new page with different layout" do
372
- @pdf = Prawn::Document.new
373
- size = [@pdf.bounds.width, @pdf.bounds.height]
374
- @pdf.start_new_page(:layout => :landscape)
375
- [@pdf.bounds.width, @pdf.bounds.height].should == size.reverse
376
- end
377
- end
378
-
379
- describe "The mask() feature" do
380
- it "should allow transactional restoration of attributes" do
381
- @pdf = Prawn::Document.new
382
- y, line_width = @pdf.y, @pdf.line_width
383
- @pdf.mask(:y, :line_width) do
384
- @pdf.y = y + 1
385
- @pdf.line_width = line_width + 1
386
- @pdf.y.should_not == y
387
- @pdf.line_width.should_not == line_width
388
- end
389
- @pdf.y.should == y
390
- @pdf.line_width.should == line_width
391
- end
392
- end
393
-
394
- describe "The group() feature" do
395
- it "should return a true value if the content fits on one page" do
396
- pdf = Prawn::Document.new do
397
- val = group { text "Hello"; text "World" }
398
- (!!val).should == true
399
- end
400
- end
401
-
402
- it "should group a simple block on a single page" do
403
- pdf = Prawn::Document.new do
404
- self.y = 50
405
- val = group do
406
- text "Hello"
407
- text "World"
408
- end
409
-
410
- # group should return a false value since a new page was started
411
- (!!val).should == false
412
- end
413
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
414
- pages.size.should == 2
415
- pages[0][:strings].should == []
416
- pages[1][:strings].should == ["Hello", "World"]
417
- end
418
-
419
- it "should raise_error CannotGroup if the content is too tall" do
420
- lambda {
421
- Prawn::Document.new do
422
- group do
423
- 100.times { text "Too long" }
424
- end
425
- end.render
426
- }.should raise_error(Prawn::Errors::CannotGroup)
427
- end
428
-
429
- it "should group within individual column boxes" do
430
- pdf = Prawn::Document.new do
431
- # Set up columns with grouped blocks of 0..49. 0 to 49 is slightly short
432
- # of the height of one page / column, so each column should get its own
433
- # group (every column should start with zero).
434
- column_box([0, bounds.top], :width => bounds.width, :columns => 7) do
435
- 10.times do
436
- group { 50.times { |i| text(i.to_s) } }
437
- end
438
- end
439
- end
440
-
441
- # Second page should start with a 0 because it's a new group.
442
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
443
- pages.size.should == 2
444
- pages[1][:strings].first.should == '0'
445
- end
446
-
447
- end
448
-
449
- describe "The render() feature" do
450
- if "spec".respond_to?(:encode!)
451
- it "should return a 8 bit encoded string on a m17n aware VM" do
452
- @pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
453
- @pdf.line [100,100], [200,200]
454
- str = @pdf.render
455
- str.encoding.to_s.should == "ASCII-8BIT"
456
- end
457
- end
458
-
459
- it "should trigger before_render callbacks just before rendering" do
460
- pdf = Prawn::Document.new
461
-
462
- seq = sequence("callback_order")
463
-
464
- # Verify the order: finalize -> fire callbacks -> render body
465
- pdf.expects(:finalize_all_page_contents).in_sequence(seq)
466
- trigger = mock()
467
- trigger.expects(:fire).in_sequence(seq)
468
-
469
- # Store away the render_body method to be called below
470
- render_body = pdf.method(:render_body)
471
- pdf.expects(:render_body).in_sequence(seq)
472
-
473
- pdf.before_render{ trigger.fire }
474
-
475
- # Render the body to set up object offsets
476
- render_body.call(StringIO.new)
477
- pdf.render
478
- end
479
-
480
- it "should be idempotent" do
481
- pdf = Prawn::Document.new
482
-
483
- contents = pdf.render
484
- contents2 = pdf.render
485
- contents2.should == contents
486
- end
487
- end
488
-
489
- describe "The :optimize_objects option" do
490
- before(:all) do
491
- @wasteful_doc = lambda do |pdf|
492
- pdf.transaction do
493
- pdf.start_new_page
494
- pdf.text "Hidden text"
495
- pdf.rollback
496
- end
497
-
498
- pdf.text "Hello world"
499
- end
500
- end
501
-
502
- it "should result in fewer objects when enabled" do
503
- wasteful_pdf = Prawn::Document.new(&@wasteful_doc)
504
- frugal_pdf = Prawn::Document.new(:optimize_objects => true,
505
- &@wasteful_doc)
506
- frugal_pdf.render.size.should be < wasteful_pdf.render.size
507
- end
508
-
509
- it "should default to :false" do
510
- default_pdf = Prawn::Document.new(&@wasteful_doc)
511
- wasteful_pdf = Prawn::Document.new(:optimize_objects => false,
512
- &@wasteful_doc)
513
- default_pdf.render.size.should == wasteful_pdf.render.size
514
- end
515
-
516
- end
517
-
518
- describe "PDF file versions" do
519
- it "should default to 1.3" do
520
- @pdf = Prawn::Document.new
521
- str = @pdf.render
522
- str[0,8].should == "%PDF-1.3"
523
- end
524
-
525
- it "should allow the default to be changed" do
526
- @pdf = Prawn::Document.new
527
- @pdf.__send__(:min_version, 1.4)
528
- str = @pdf.render
529
- str[0,8].should == "%PDF-1.4"
530
- end
531
- end
532
-
533
- describe "Documents that use go_to_page" do
534
- it "should have 2 pages after calling start_new_page and go_to_page" do
535
- @pdf = Prawn::Document.new
536
- @pdf.text "James"
537
- @pdf.start_new_page
538
- @pdf.text "Anthony"
539
- @pdf.go_to_page(1)
540
- @pdf.text "Healy"
541
-
542
- page_counter = PDF::Inspector::Page.analyze(@pdf.render)
543
- page_counter.pages.size.should == 2
544
- end
545
-
546
- it "should correctly add text to pages" do
547
- @pdf = Prawn::Document.new
548
- @pdf.text "James"
549
- @pdf.start_new_page
550
- @pdf.text "Anthony"
551
- @pdf.go_to_page(1)
552
- @pdf.text "Healy"
553
-
554
- text = PDF::Inspector::Text.analyze(@pdf.render)
555
-
556
- text.strings.size.should == 3
557
- text.strings.include?("James").should == true
558
- text.strings.include?("Anthony").should == true
559
- text.strings.include?("Healy").should == true
560
- end
561
- end
562
-
563
- describe "content stream characteristics" do
564
- it "should have 1 single content stream for a single page PDF with no templates" do
565
- @pdf = Prawn::Document.new
566
- @pdf.text "James"
567
- output = StringIO.new(@pdf.render)
568
- hash = PDF::Reader::ObjectHash.new(output)
569
-
570
- streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
571
-
572
- streams.size.should == 1
573
- end
574
-
575
- it "should have 1 single content stream for a single page PDF with no templates, even if go_to_page is used" do
576
- @pdf = Prawn::Document.new
577
- @pdf.text "James"
578
- @pdf.go_to_page(1)
579
- @pdf.text "Healy"
580
- output = StringIO.new(@pdf.render)
581
- hash = PDF::Reader::ObjectHash.new(output)
582
-
583
- streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
584
-
585
- streams.size.should == 1
586
- end
587
- end
588
-
589
- describe "The number_pages method" do
590
- before do
591
- @pdf = Prawn::Document.new(:skip_page_creation => true)
592
- end
593
-
594
- it "replaces the '<page>' string with the proper page number" do
595
- @pdf.start_new_page
596
- @pdf.expects(:text_box).with("1, test", { :height => 50 })
597
- @pdf.number_pages "<page>, test", {:page_filter => :all}
598
- end
599
-
600
- it "replaces the '<total>' string with the total page count" do
601
- @pdf.start_new_page
602
- @pdf.expects(:text_box).with("test, 1", { :height => 50 })
603
- @pdf.number_pages "test, <total>", {:page_filter => :all}
604
- end
605
-
606
- it "must print each page if given the :all page_filter" do
607
- 10.times { @pdf.start_new_page }
608
- @pdf.expects(:text_box).times(10)
609
- @pdf.number_pages "test", {:page_filter => :all}
610
- end
611
-
612
- it "must print each page if no :page_filter is specified" do
613
- 10.times { @pdf.start_new_page }
614
- @pdf.expects(:text_box).times(10)
615
- @pdf.number_pages "test"
616
- end
617
-
618
- it "must not print the page number if given a nil filter" do
619
- 10.times { @pdf.start_new_page }
620
- @pdf.expects(:text_box).never
621
- @pdf.number_pages "test", {:page_filter => nil}
622
- end
623
-
624
- context "start_count_at option" do
625
- [1, 2].each do |startat|
626
- context "equal to #{startat}" do
627
- it "increments the pages" do
628
- 2.times { @pdf.start_new_page }
629
- options = {:page_filter => :all, :start_count_at => startat}
630
- @pdf.expects(:text_box).with("#{startat} 2", { :height => 50 })
631
- @pdf.expects(:text_box).with("#{startat+1} 2", { :height => 50 })
632
- @pdf.number_pages "<page> <total>", options
633
- end
634
- end
635
- end
636
-
637
- [0, nil].each do |val|
638
- context "equal to #{val}" do
639
- it "defaults to start at page 1" do
640
- 3.times { @pdf.start_new_page }
641
- options = {:page_filter => :all, :start_count_at => val}
642
- @pdf.expects(:text_box).with("1 3", { :height => 50 })
643
- @pdf.expects(:text_box).with("2 3", { :height => 50 })
644
- @pdf.expects(:text_box).with("3 3", { :height => 50 })
645
- @pdf.number_pages "<page> <total>", options
646
- end
647
- end
648
- end
649
- end
650
-
651
- context "total_pages option" do
652
- it "allows the total pages count to be overridden" do
653
- 2.times { @pdf.start_new_page }
654
- @pdf.expects(:text_box).with("1 10", { :height => 50 })
655
- @pdf.expects(:text_box).with("2 10", { :height => 50 })
656
- @pdf.number_pages "<page> <total>", :page_filter => :all, :total_pages => 10
657
- end
658
- end
659
-
660
- context "special page filter" do
661
- context "such as :odd" do
662
- it "increments the pages" do
663
- 3.times { @pdf.start_new_page }
664
- @pdf.expects(:text_box).with("1 3", { :height => 50 })
665
- @pdf.expects(:text_box).with("3 3", { :height => 50 })
666
- @pdf.expects(:text_box).with("2 3", { :height => 50 }).never
667
- @pdf.number_pages "<page> <total>", :page_filter => :odd
668
- end
669
- end
670
- context "missing" do
671
- it "does not print any page numbers" do
672
- 3.times { @pdf.start_new_page }
673
- @pdf.expects(:text_box).never
674
- @pdf.number_pages "<page> <total>", :page_filter => nil
675
- end
676
- end
677
- end
678
-
679
- context "given both a special page filter and a start_count_at parameter" do
680
- context "such as :odd and 7" do
681
- it "increments the pages" do
682
- 3.times { @pdf.start_new_page }
683
- @pdf.expects(:text_box).with("1 3", { :height => 50 }).never
684
- @pdf.expects(:text_box).with("5 3", { :height => 50 }) # page 1
685
- @pdf.expects(:text_box).with("6 3", { :height => 50 }).never # page 2
686
- @pdf.expects(:text_box).with("7 3", { :height => 50 }) # page 3
687
- @pdf.number_pages "<page> <total>", :page_filter => :odd, :start_count_at => 5
688
- end
689
- end
690
- context "some crazy proc and 2" do
691
- it "increments the pages" do
692
- 6.times { @pdf.start_new_page }
693
- options = {:page_filter => lambda {|p| p != 2 && p != 5}, :start_count_at => 4}
694
- @pdf.expects(:text_box).with("4 6", { :height => 50 }) # page 1
695
- @pdf.expects(:text_box).with("5 6", { :height => 50 }).never # page 2
696
- @pdf.expects(:text_box).with("6 6", { :height => 50 }) # page 3
697
- @pdf.expects(:text_box).with("7 6", { :height => 50 }) # page 4
698
- @pdf.expects(:text_box).with("8 6", { :height => 50 }).never # page 5
699
- @pdf.expects(:text_box).with("9 6", { :height => 50 }) # page 6
700
- @pdf.number_pages "<page> <total>", options
701
- end
702
- end
703
- end
704
-
705
- context "height option" do
706
- before do
707
- @pdf.start_new_page
708
- end
709
-
710
- it "with 10 height" do
711
- @pdf.expects(:text_box).with("1 1", { :height => 10 })
712
- @pdf.number_pages "<page> <total>", :height => 10
713
- end
714
-
715
- it "with nil height" do
716
- @pdf.expects(:text_box).with("1 1", { :height => nil })
717
- @pdf.number_pages "<page> <total>", :height => nil
718
- end
719
-
720
- it "with no height" do
721
- @pdf.expects(:text_box).with("1 1", { :height => 50 })
722
- @pdf.number_pages "<page> <total>"
723
- end
724
- end
725
- end
726
-
727
- describe "The page_match? method" do
728
- before do
729
- @pdf = Prawn::Document.new(:skip_page_creation => true)
730
- 10.times {@pdf.start_new_page}
731
- end
732
-
733
- it "returns nil given no filter" do
734
- @pdf.page_match?(:nil, 1).should be_false
735
- end
736
-
737
- it "must provide an :all filter" do
738
- (1..@pdf.page_count).all? { |i| @pdf.page_match?(:all, i) }.should be_true
739
- end
740
-
741
- it "must provide an :odd filter" do
742
- odd, even = (1..@pdf.page_count).partition { |e| e % 2 == 1 }
743
- odd.all? { |i| @pdf.page_match?(:odd, i) }.should be_true
744
- even.any? { |i| @pdf.page_match?(:odd, i) }.should be_false
745
- end
746
-
747
- it "must be able to filter by an array of page numbers" do
748
- fltr = [1,2,7]
749
- (1..10).select { |i| @pdf.page_match?(fltr, i) }.should == [1,2,7]
750
- end
751
-
752
- it "must be able to filter by a range of page numbers" do
753
- fltr = 2..4
754
- (1..10).select { |i| @pdf.page_match?(fltr, i) }.should == [2,3,4]
755
- end
756
-
757
- it "must be able to filter by an arbitrary proc" do
758
- fltr = lambda { |x| x == 1 or x % 3 == 0 }
759
- (1..10).select { |i| @pdf.page_match?(fltr, i) }.should == [1,3,6,9]
760
- end
761
- end