prawn 1.1.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +1 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +9 -40
  7. data/lib/prawn/document/bounding_box.rb +54 -40
  8. data/lib/prawn/document/column_box.rb +8 -10
  9. data/lib/prawn/document/internals.rb +39 -146
  10. data/lib/prawn/document/span.rb +23 -17
  11. data/lib/prawn/document.rb +217 -182
  12. data/lib/prawn/encoding.rb +69 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +124 -104
  15. data/lib/prawn/font_metric_cache.rb +23 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +5 -12
  18. data/lib/prawn/fonts/otf.rb +11 -0
  19. data/lib/prawn/fonts/ttc.rb +36 -0
  20. data/lib/prawn/{font → fonts}/ttf.rb +140 -88
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +5 -5
  23. data/lib/prawn/graphics/color.rb +46 -44
  24. data/lib/prawn/graphics/dash.rb +27 -11
  25. data/lib/prawn/graphics/join_style.rb +11 -6
  26. data/lib/prawn/graphics/patterns.rb +220 -78
  27. data/lib/prawn/graphics/transformation.rb +20 -12
  28. data/lib/prawn/graphics/transparency.rb +20 -18
  29. data/lib/prawn/graphics.rb +153 -115
  30. data/lib/prawn/grid.rb +93 -50
  31. data/lib/prawn/image_handler.rb +4 -4
  32. data/lib/prawn/images/image.rb +3 -2
  33. data/lib/prawn/images/jpg.rb +31 -24
  34. data/lib/prawn/images/png.rb +101 -68
  35. data/lib/prawn/images.rb +64 -56
  36. data/lib/prawn/measurement_extensions.rb +10 -9
  37. data/lib/prawn/measurements.rb +20 -23
  38. data/lib/prawn/outline.rb +96 -75
  39. data/lib/prawn/repeater.rb +16 -16
  40. data/lib/prawn/security/arcfour.rb +2 -2
  41. data/lib/prawn/security.rb +100 -85
  42. data/lib/prawn/soft_mask.rb +37 -38
  43. data/lib/prawn/stamp.rb +28 -13
  44. data/lib/prawn/text/box.rb +24 -29
  45. data/lib/prawn/text/formatted/arranger.rb +108 -63
  46. data/lib/prawn/text/formatted/box.rb +187 -124
  47. data/lib/prawn/text/formatted/fragment.rb +24 -20
  48. data/lib/prawn/text/formatted/line_wrap.rb +133 -73
  49. data/lib/prawn/text/formatted/parser.rb +147 -127
  50. data/lib/prawn/text/formatted/wrap.rb +48 -35
  51. data/lib/prawn/text/formatted.rb +5 -5
  52. data/lib/prawn/text.rb +103 -68
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +10 -22
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +39 -54
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +34 -25
  60. data/manual/basic_concepts/creation.rb +10 -11
  61. data/manual/basic_concepts/cursor.rb +4 -5
  62. data/manual/basic_concepts/measurement.rb +8 -9
  63. data/manual/basic_concepts/origin.rb +5 -6
  64. data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
  65. data/manual/basic_concepts/view.rb +48 -0
  66. data/manual/bounding_box/bounding_box.rb +30 -28
  67. data/manual/bounding_box/bounds.rb +12 -13
  68. data/manual/bounding_box/canvas.rb +7 -8
  69. data/manual/bounding_box/creation.rb +6 -7
  70. data/manual/bounding_box/indentation.rb +14 -15
  71. data/manual/bounding_box/nesting.rb +25 -18
  72. data/manual/bounding_box/russian_boxes.rb +18 -18
  73. data/manual/bounding_box/stretchy.rb +12 -14
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -32
  76. data/manual/document_and_page_options/background.rb +15 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +24 -22
  78. data/manual/document_and_page_options/metadata.rb +20 -18
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -13
  81. data/manual/document_and_page_options/print_scaling.rb +18 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +52 -0
  84. data/manual/graphics/circle_and_ellipse.rb +4 -5
  85. data/manual/graphics/color.rb +7 -9
  86. data/manual/graphics/common_lines.rb +7 -8
  87. data/manual/graphics/fill_and_stroke.rb +5 -6
  88. data/manual/graphics/fill_rules.rb +12 -11
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +46 -40
  91. data/manual/graphics/helper.rb +19 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +8 -9
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -9
  97. data/manual/graphics/scale.rb +14 -13
  98. data/manual/graphics/soft_masks.rb +4 -6
  99. data/manual/graphics/stroke_cap.rb +7 -8
  100. data/manual/graphics/stroke_dash.rb +15 -16
  101. data/manual/graphics/stroke_join.rb +6 -7
  102. data/manual/graphics/translate.rb +10 -10
  103. data/manual/graphics/transparency.rb +7 -9
  104. data/manual/how_to_read_this_manual.rb +8 -9
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +10 -11
  108. data/manual/images/images.rb +28 -27
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +16 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +10 -11
  114. data/manual/layout/content.rb +9 -10
  115. data/manual/layout/layout.rb +17 -18
  116. data/manual/layout/simple_grid.rb +6 -7
  117. data/manual/outline/add_subsection_to.rb +20 -21
  118. data/manual/outline/insert_section_after.rb +15 -16
  119. data/manual/outline/outline.rb +22 -21
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +27 -23
  124. data/manual/repeatable_content/repeater.rb +15 -16
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +8 -11
  127. data/manual/security/permissions.rb +20 -15
  128. data/manual/security/security.rb +18 -18
  129. data/manual/table.rb +16 -0
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -12
  132. data/manual/text/column_box.rb +9 -11
  133. data/manual/text/fallback_fonts.rb +25 -21
  134. data/manual/text/font.rb +11 -12
  135. data/manual/text/font_size.rb +13 -14
  136. data/manual/text/font_style.rb +10 -8
  137. data/manual/text/formatted_callbacks.rb +33 -23
  138. data/manual/text/formatted_text.rb +36 -25
  139. data/manual/text/free_flowing_text.rb +22 -23
  140. data/manual/text/inline.rb +18 -19
  141. data/manual/text/kerning_and_character_spacing.rb +14 -15
  142. data/manual/text/leading.rb +7 -8
  143. data/manual/text/line_wrapping.rb +37 -18
  144. data/manual/text/paragraph_indentation.rb +15 -10
  145. data/manual/text/positioned_text.rb +16 -17
  146. data/manual/text/registering_families.rb +27 -24
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +30 -19
  149. data/manual/text/rotation.rb +33 -24
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +56 -54
  152. data/manual/text/text_box_excess.rb +20 -17
  153. data/manual/text/text_box_extensions.rb +18 -15
  154. data/manual/text/text_box_overflow.rb +24 -17
  155. data/manual/text/utf8.rb +12 -13
  156. data/manual/text/win_ansi_charset.rb +28 -25
  157. data/prawn.gemspec +45 -50
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  160. data/spec/prawn/document/column_box_spec.rb +75 -0
  161. data/spec/prawn/document/security_spec.rb +176 -0
  162. data/spec/prawn/document_annotations_spec.rb +76 -0
  163. data/spec/prawn/document_destinations_spec.rb +15 -0
  164. data/spec/prawn/document_grid_spec.rb +99 -0
  165. data/spec/prawn/document_reference_spec.rb +27 -0
  166. data/spec/prawn/document_span_spec.rb +44 -0
  167. data/spec/prawn/document_spec.rb +805 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +544 -0
  170. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  171. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  172. data/spec/prawn/graphics_spec.rb +872 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/prawn/image_handler_spec.rb +53 -0
  175. data/spec/prawn/images/jpg_spec.rb +20 -0
  176. data/spec/prawn/images/png_spec.rb +283 -0
  177. data/spec/prawn/images_spec.rb +229 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +512 -0
  180. data/spec/prawn/repeater_spec.rb +166 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +173 -0
  183. data/spec/prawn/text/box_spec.rb +1110 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +150 -0
  190. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  191. data/spec/prawn/text_spacing_spec.rb +95 -0
  192. data/spec/prawn/text_spec.rb +603 -0
  193. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  194. data/spec/prawn/transformation_stack_spec.rb +66 -0
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +19 -25
  198. data.tar.gz.sig +0 -0
  199. metadata +113 -276
  200. metadata.gz.sig +0 -0
  201. data/data/encodings/win_ansi.txt +0 -29
  202. data/data/images/16bit.alpha +0 -0
  203. data/data/images/16bit.color +0 -0
  204. data/data/images/16bit.png +0 -0
  205. data/data/images/arrow.png +0 -0
  206. data/data/images/arrow2.png +0 -0
  207. data/data/images/dice.alpha +0 -0
  208. data/data/images/dice.color +0 -0
  209. data/data/images/dice.png +0 -0
  210. data/data/images/dice_interlaced.png +0 -0
  211. data/data/images/fractal.jpg +0 -0
  212. data/data/images/indexed_color.dat +0 -0
  213. data/data/images/indexed_color.png +0 -0
  214. data/data/images/letterhead.jpg +0 -0
  215. data/data/images/license.md +0 -8
  216. data/data/images/page_white_text.alpha +0 -0
  217. data/data/images/page_white_text.color +0 -0
  218. data/data/images/page_white_text.png +0 -0
  219. data/data/images/pigs.jpg +0 -0
  220. data/data/images/prawn.png +0 -0
  221. data/data/images/ruport.png +0 -0
  222. data/data/images/ruport_data.dat +0 -0
  223. data/data/images/ruport_transparent.png +0 -0
  224. data/data/images/ruport_type0.png +0 -0
  225. data/data/images/stef.jpg +0 -0
  226. data/data/images/tru256.bmp +0 -0
  227. data/data/images/web-links.dat +0 -1
  228. data/data/images/web-links.png +0 -0
  229. data/data/pdfs/complex_template.pdf +0 -0
  230. data/data/pdfs/contains_ttf_font.pdf +0 -0
  231. data/data/pdfs/encrypted.pdf +0 -0
  232. data/data/pdfs/form.pdf +1 -819
  233. data/data/pdfs/hexagon.pdf +0 -61
  234. data/data/pdfs/indirect_reference.pdf +0 -86
  235. data/data/pdfs/multipage_template.pdf +0 -127
  236. data/data/pdfs/nested_pages.pdf +0 -118
  237. data/data/pdfs/page_without_mediabox.pdf +0 -193
  238. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  239. data/data/pdfs/two_hexagons.pdf +0 -90
  240. data/data/pdfs/version_1_6.pdf +0 -61
  241. data/data/shift_jis_text.txt +0 -1
  242. data/lib/prawn/document/graphics_state.rb +0 -73
  243. data/lib/prawn/font/afm.rb +0 -247
  244. data/lib/prawn/table/cell/image.rb +0 -69
  245. data/lib/prawn/table/cell/in_table.rb +0 -33
  246. data/lib/prawn/table/cell/span_dummy.rb +0 -93
  247. data/lib/prawn/table/cell/subtable.rb +0 -66
  248. data/lib/prawn/table/cell/text.rb +0 -154
  249. data/lib/prawn/table/cell.rb +0 -772
  250. data/lib/prawn/table/cells.rb +0 -255
  251. data/lib/prawn/table/column_width_calculator.rb +0 -182
  252. data/lib/prawn/table.rb +0 -644
  253. data/manual/table/basic_block.rb +0 -53
  254. data/manual/table/before_rendering_page.rb +0 -26
  255. data/manual/table/cell_border_lines.rb +0 -24
  256. data/manual/table/cell_borders_and_bg.rb +0 -31
  257. data/manual/table/cell_dimensions.rb +0 -30
  258. data/manual/table/cell_text.rb +0 -38
  259. data/manual/table/column_widths.rb +0 -30
  260. data/manual/table/content_and_subtables.rb +0 -39
  261. data/manual/table/creation.rb +0 -27
  262. data/manual/table/filtering.rb +0 -36
  263. data/manual/table/flow_and_header.rb +0 -17
  264. data/manual/table/image_cells.rb +0 -33
  265. data/manual/table/position.rb +0 -29
  266. data/manual/table/row_colors.rb +0 -20
  267. data/manual/table/span.rb +0 -30
  268. data/manual/table/style.rb +0 -22
  269. data/manual/table/table.rb +0 -52
  270. data/manual/table/width.rb +0 -27
  271. data/spec/acceptance/png.rb +0 -25
  272. data/spec/annotations_spec.rb +0 -74
  273. data/spec/bounding_box_spec.rb +0 -510
  274. data/spec/cell_spec.rb +0 -629
  275. data/spec/column_box_spec.rb +0 -65
  276. data/spec/destinations_spec.rb +0 -15
  277. data/spec/document_spec.rb +0 -730
  278. data/spec/extensions/mocha.rb +0 -46
  279. data/spec/font_metric_cache_spec.rb +0 -52
  280. data/spec/font_spec.rb +0 -449
  281. data/spec/formatted_text_arranger_spec.rb +0 -421
  282. data/spec/formatted_text_box_spec.rb +0 -639
  283. data/spec/formatted_text_fragment_spec.rb +0 -298
  284. data/spec/graphics_spec.rb +0 -669
  285. data/spec/grid_spec.rb +0 -96
  286. data/spec/image_handler_spec.rb +0 -54
  287. data/spec/images_spec.rb +0 -153
  288. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  289. data/spec/jpg_spec.rb +0 -25
  290. data/spec/line_wrap_spec.rb +0 -344
  291. data/spec/measurement_units_spec.rb +0 -25
  292. data/spec/outline_spec.rb +0 -430
  293. data/spec/png_spec.rb +0 -237
  294. data/spec/reference_spec.rb +0 -25
  295. data/spec/repeater_spec.rb +0 -160
  296. data/spec/security_spec.rb +0 -158
  297. data/spec/soft_mask_spec.rb +0 -79
  298. data/spec/span_spec.rb +0 -44
  299. data/spec/stamp_spec.rb +0 -160
  300. data/spec/stroke_styles_spec.rb +0 -211
  301. data/spec/table/span_dummy_spec.rb +0 -17
  302. data/spec/table_spec.rb +0 -1527
  303. data/spec/text_at_spec.rb +0 -115
  304. data/spec/text_box_spec.rb +0 -1034
  305. data/spec/text_rendering_mode_spec.rb +0 -45
  306. data/spec/text_spacing_spec.rb +0 -93
  307. data/spec/text_spec.rb +0 -437
  308. data/spec/text_with_inline_formatting_spec.rb +0 -35
  309. data/spec/transparency_spec.rb +0 -91
@@ -1,730 +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
- xit "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
- xit "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
- xit "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
- xit "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
- it "should return a 8 bit encoded string on a m17n aware VM" do
451
- @pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
452
- @pdf.line [100,100], [200,200]
453
- str = @pdf.render
454
- str.encoding.to_s.should == "ASCII-8BIT"
455
- end
456
-
457
- it "should trigger before_render callbacks just before rendering" do
458
- pdf = Prawn::Document.new
459
-
460
- seq = sequence("callback_order")
461
-
462
- # Verify the order: finalize -> fire callbacks -> render body
463
- pdf.expects(:finalize_all_page_contents).in_sequence(seq)
464
- trigger = mock()
465
- trigger.expects(:fire).in_sequence(seq)
466
-
467
- # Store away the render_body method to be called below
468
- render_body = pdf.method(:render_body)
469
- pdf.expects(:render_body).in_sequence(seq)
470
-
471
- pdf.before_render{ trigger.fire }
472
-
473
- # Render the body to set up object offsets
474
- render_body.call(StringIO.new)
475
- pdf.render
476
- end
477
-
478
- it "should be idempotent" do
479
- pdf = Prawn::Document.new
480
-
481
- contents = pdf.render
482
- contents2 = pdf.render
483
- contents2.should == contents
484
- end
485
- end
486
-
487
- describe "PDF file versions" do
488
- it "should default to 1.3" do
489
- @pdf = Prawn::Document.new
490
- str = @pdf.render
491
- str[0,8].should == "%PDF-1.3"
492
- end
493
-
494
- it "should allow the default to be changed" do
495
- @pdf = Prawn::Document.new
496
- @pdf.__send__(:min_version, 1.4)
497
- str = @pdf.render
498
- str[0,8].should == "%PDF-1.4"
499
- end
500
- end
501
-
502
- describe "Documents that use go_to_page" do
503
- it "should have 2 pages after calling start_new_page and go_to_page" do
504
- @pdf = Prawn::Document.new
505
- @pdf.text "James"
506
- @pdf.start_new_page
507
- @pdf.text "Anthony"
508
- @pdf.go_to_page(1)
509
- @pdf.text "Healy"
510
-
511
- page_counter = PDF::Inspector::Page.analyze(@pdf.render)
512
- page_counter.pages.size.should == 2
513
- end
514
-
515
- it "should correctly add text to pages" do
516
- @pdf = Prawn::Document.new
517
- @pdf.text "James"
518
- @pdf.start_new_page
519
- @pdf.text "Anthony"
520
- @pdf.go_to_page(1)
521
- @pdf.text "Healy"
522
-
523
- text = PDF::Inspector::Text.analyze(@pdf.render)
524
-
525
- text.strings.size.should == 3
526
- text.strings.include?("James").should == true
527
- text.strings.include?("Anthony").should == true
528
- text.strings.include?("Healy").should == true
529
- end
530
- end
531
-
532
- describe "content stream characteristics" do
533
- it "should have 1 single content stream for a single page PDF with no templates" do
534
- @pdf = Prawn::Document.new
535
- @pdf.text "James"
536
- output = StringIO.new(@pdf.render)
537
- hash = PDF::Reader::ObjectHash.new(output)
538
-
539
- streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
540
-
541
- streams.size.should == 1
542
- end
543
-
544
- it "should have 1 single content stream for a single page PDF with no templates, even if go_to_page is used" do
545
- @pdf = Prawn::Document.new
546
- @pdf.text "James"
547
- @pdf.go_to_page(1)
548
- @pdf.text "Healy"
549
- output = StringIO.new(@pdf.render)
550
- hash = PDF::Reader::ObjectHash.new(output)
551
-
552
- streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
553
-
554
- streams.size.should == 1
555
- end
556
- end
557
-
558
- describe "The number_pages method" do
559
- before do
560
- @pdf = Prawn::Document.new(:skip_page_creation => true)
561
- end
562
-
563
- it "replaces the '<page>' string with the proper page number" do
564
- @pdf.start_new_page
565
- @pdf.expects(:text_box).with("1, test", { :height => 50 })
566
- @pdf.number_pages "<page>, test", {:page_filter => :all}
567
- end
568
-
569
- it "replaces the '<total>' string with the total page count" do
570
- @pdf.start_new_page
571
- @pdf.expects(:text_box).with("test, 1", { :height => 50 })
572
- @pdf.number_pages "test, <total>", {:page_filter => :all}
573
- end
574
-
575
- it "must print each page if given the :all page_filter" do
576
- 10.times { @pdf.start_new_page }
577
- @pdf.expects(:text_box).times(10)
578
- @pdf.number_pages "test", {:page_filter => :all}
579
- end
580
-
581
- it "must print each page if no :page_filter is specified" do
582
- 10.times { @pdf.start_new_page }
583
- @pdf.expects(:text_box).times(10)
584
- @pdf.number_pages "test"
585
- end
586
-
587
- it "must not print the page number if given a nil filter" do
588
- 10.times { @pdf.start_new_page }
589
- @pdf.expects(:text_box).never
590
- @pdf.number_pages "test", {:page_filter => nil}
591
- end
592
-
593
- context "start_count_at option" do
594
- [1, 2].each do |startat|
595
- context "equal to #{startat}" do
596
- it "increments the pages" do
597
- 2.times { @pdf.start_new_page }
598
- options = {:page_filter => :all, :start_count_at => startat}
599
- @pdf.expects(:text_box).with("#{startat} 2", { :height => 50 })
600
- @pdf.expects(:text_box).with("#{startat+1} 2", { :height => 50 })
601
- @pdf.number_pages "<page> <total>", options
602
- end
603
- end
604
- end
605
-
606
- [0, nil].each do |val|
607
- context "equal to #{val}" do
608
- it "defaults to start at page 1" do
609
- 3.times { @pdf.start_new_page }
610
- options = {:page_filter => :all, :start_count_at => val}
611
- @pdf.expects(:text_box).with("1 3", { :height => 50 })
612
- @pdf.expects(:text_box).with("2 3", { :height => 50 })
613
- @pdf.expects(:text_box).with("3 3", { :height => 50 })
614
- @pdf.number_pages "<page> <total>", options
615
- end
616
- end
617
- end
618
- end
619
-
620
- context "total_pages option" do
621
- it "allows the total pages count to be overridden" do
622
- 2.times { @pdf.start_new_page }
623
- @pdf.expects(:text_box).with("1 10", { :height => 50 })
624
- @pdf.expects(:text_box).with("2 10", { :height => 50 })
625
- @pdf.number_pages "<page> <total>", :page_filter => :all, :total_pages => 10
626
- end
627
- end
628
-
629
- context "special page filter" do
630
- context "such as :odd" do
631
- it "increments the pages" do
632
- 3.times { @pdf.start_new_page }
633
- @pdf.expects(:text_box).with("1 3", { :height => 50 })
634
- @pdf.expects(:text_box).with("3 3", { :height => 50 })
635
- @pdf.expects(:text_box).with("2 3", { :height => 50 }).never
636
- @pdf.number_pages "<page> <total>", :page_filter => :odd
637
- end
638
- end
639
- context "missing" do
640
- it "does not print any page numbers" do
641
- 3.times { @pdf.start_new_page }
642
- @pdf.expects(:text_box).never
643
- @pdf.number_pages "<page> <total>", :page_filter => nil
644
- end
645
- end
646
- end
647
-
648
- context "given both a special page filter and a start_count_at parameter" do
649
- context "such as :odd and 7" do
650
- it "increments the pages" do
651
- 3.times { @pdf.start_new_page }
652
- @pdf.expects(:text_box).with("1 3", { :height => 50 }).never
653
- @pdf.expects(:text_box).with("5 3", { :height => 50 }) # page 1
654
- @pdf.expects(:text_box).with("6 3", { :height => 50 }).never # page 2
655
- @pdf.expects(:text_box).with("7 3", { :height => 50 }) # page 3
656
- @pdf.number_pages "<page> <total>", :page_filter => :odd, :start_count_at => 5
657
- end
658
- end
659
- context "some crazy proc and 2" do
660
- it "increments the pages" do
661
- 6.times { @pdf.start_new_page }
662
- options = {:page_filter => lambda {|p| p != 2 && p != 5}, :start_count_at => 4}
663
- @pdf.expects(:text_box).with("4 6", { :height => 50 }) # page 1
664
- @pdf.expects(:text_box).with("5 6", { :height => 50 }).never # page 2
665
- @pdf.expects(:text_box).with("6 6", { :height => 50 }) # page 3
666
- @pdf.expects(:text_box).with("7 6", { :height => 50 }) # page 4
667
- @pdf.expects(:text_box).with("8 6", { :height => 50 }).never # page 5
668
- @pdf.expects(:text_box).with("9 6", { :height => 50 }) # page 6
669
- @pdf.number_pages "<page> <total>", options
670
- end
671
- end
672
- end
673
-
674
- context "height option" do
675
- before do
676
- @pdf.start_new_page
677
- end
678
-
679
- it "with 10 height" do
680
- @pdf.expects(:text_box).with("1 1", { :height => 10 })
681
- @pdf.number_pages "<page> <total>", :height => 10
682
- end
683
-
684
- it "with nil height" do
685
- @pdf.expects(:text_box).with("1 1", { :height => nil })
686
- @pdf.number_pages "<page> <total>", :height => nil
687
- end
688
-
689
- it "with no height" do
690
- @pdf.expects(:text_box).with("1 1", { :height => 50 })
691
- @pdf.number_pages "<page> <total>"
692
- end
693
- end
694
- end
695
-
696
- describe "The page_match? method" do
697
- before do
698
- @pdf = Prawn::Document.new(:skip_page_creation => true)
699
- 10.times {@pdf.start_new_page}
700
- end
701
-
702
- it "returns nil given no filter" do
703
- @pdf.page_match?(:nil, 1).should be_false
704
- end
705
-
706
- it "must provide an :all filter" do
707
- (1..@pdf.page_count).all? { |i| @pdf.page_match?(:all, i) }.should be_true
708
- end
709
-
710
- it "must provide an :odd filter" do
711
- odd, even = (1..@pdf.page_count).partition { |e| e % 2 == 1 }
712
- odd.all? { |i| @pdf.page_match?(:odd, i) }.should be_true
713
- even.any? { |i| @pdf.page_match?(:odd, i) }.should be_false
714
- end
715
-
716
- it "must be able to filter by an array of page numbers" do
717
- fltr = [1,2,7]
718
- (1..10).select { |i| @pdf.page_match?(fltr, i) }.should == [1,2,7]
719
- end
720
-
721
- it "must be able to filter by a range of page numbers" do
722
- fltr = 2..4
723
- (1..10).select { |i| @pdf.page_match?(fltr, i) }.should == [2,3,4]
724
- end
725
-
726
- it "must be able to filter by an arbitrary proc" do
727
- fltr = lambda { |x| x == 1 or x % 3 == 0 }
728
- (1..10).select { |i| @pdf.page_match?(fltr, i) }.should == [1,3,6,9]
729
- end
730
- end