prawn-git 2.0.1

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 (252) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +10 -0
  3. data/COPYING +2 -0
  4. data/GPLv2 +340 -0
  5. data/GPLv3 +674 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +56 -0
  8. data/Rakefile +55 -0
  9. data/data/fonts/Courier-Bold.afm +342 -0
  10. data/data/fonts/Courier-BoldOblique.afm +342 -0
  11. data/data/fonts/Courier-Oblique.afm +342 -0
  12. data/data/fonts/Courier.afm +342 -0
  13. data/data/fonts/Helvetica-Bold.afm +2827 -0
  14. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  15. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  16. data/data/fonts/Helvetica.afm +3051 -0
  17. data/data/fonts/MustRead.html +19 -0
  18. data/data/fonts/Symbol.afm +213 -0
  19. data/data/fonts/Times-Bold.afm +2588 -0
  20. data/data/fonts/Times-BoldItalic.afm +2384 -0
  21. data/data/fonts/Times-Italic.afm +2667 -0
  22. data/data/fonts/Times-Roman.afm +2419 -0
  23. data/data/fonts/ZapfDingbats.afm +225 -0
  24. data/data/images/16bit.alpha +0 -0
  25. data/data/images/16bit.color +0 -0
  26. data/data/images/16bit.png +0 -0
  27. data/data/images/arrow.png +0 -0
  28. data/data/images/arrow2.png +0 -0
  29. data/data/images/dice.alpha +0 -0
  30. data/data/images/dice.color +0 -0
  31. data/data/images/dice.png +0 -0
  32. data/data/images/dice_interlaced.png +0 -0
  33. data/data/images/fractal.jpg +0 -0
  34. data/data/images/indexed_color.dat +0 -0
  35. data/data/images/indexed_color.png +0 -0
  36. data/data/images/letterhead.jpg +0 -0
  37. data/data/images/license.md +8 -0
  38. data/data/images/page_white_text.alpha +0 -0
  39. data/data/images/page_white_text.color +0 -0
  40. data/data/images/page_white_text.png +0 -0
  41. data/data/images/pal_bk.png +0 -0
  42. data/data/images/pigs.jpg +0 -0
  43. data/data/images/prawn.png +0 -0
  44. data/data/images/ruport.png +0 -0
  45. data/data/images/ruport_data.dat +0 -0
  46. data/data/images/ruport_transparent.png +0 -0
  47. data/data/images/ruport_type0.png +0 -0
  48. data/data/images/stef.jpg +0 -0
  49. data/data/images/tru256.bmp +0 -0
  50. data/data/images/web-links.dat +1 -0
  51. data/data/images/web-links.png +0 -0
  52. data/data/pdfs/complex_template.pdf +0 -0
  53. data/data/pdfs/contains_ttf_font.pdf +0 -0
  54. data/data/pdfs/encrypted.pdf +0 -0
  55. data/data/pdfs/form.pdf +820 -0
  56. data/data/pdfs/hexagon.pdf +61 -0
  57. data/data/pdfs/indirect_reference.pdf +86 -0
  58. data/data/pdfs/multipage_template.pdf +127 -0
  59. data/data/pdfs/nested_pages.pdf +118 -0
  60. data/data/pdfs/page_without_mediabox.pdf +193 -0
  61. data/data/pdfs/resources_as_indirect_object.pdf +83 -0
  62. data/data/pdfs/two_hexagons.pdf +90 -0
  63. data/data/pdfs/version_1_6.pdf +61 -0
  64. data/data/shift_jis_text.txt +1 -0
  65. data/lib/prawn.rb +89 -0
  66. data/lib/prawn/document.rb +706 -0
  67. data/lib/prawn/document/bounding_box.rb +539 -0
  68. data/lib/prawn/document/column_box.rb +144 -0
  69. data/lib/prawn/document/internals.rb +58 -0
  70. data/lib/prawn/document/span.rb +57 -0
  71. data/lib/prawn/encoding.rb +87 -0
  72. data/lib/prawn/errors.rb +80 -0
  73. data/lib/prawn/font.rb +413 -0
  74. data/lib/prawn/font/afm.rb +256 -0
  75. data/lib/prawn/font/dfont.rb +43 -0
  76. data/lib/prawn/font/ttf.rb +355 -0
  77. data/lib/prawn/font_metric_cache.rb +46 -0
  78. data/lib/prawn/graphics.rb +646 -0
  79. data/lib/prawn/graphics/cap_style.rb +47 -0
  80. data/lib/prawn/graphics/color.rb +232 -0
  81. data/lib/prawn/graphics/dash.rb +109 -0
  82. data/lib/prawn/graphics/join_style.rb +49 -0
  83. data/lib/prawn/graphics/patterns.rb +126 -0
  84. data/lib/prawn/graphics/transformation.rb +157 -0
  85. data/lib/prawn/graphics/transparency.rb +101 -0
  86. data/lib/prawn/grid.rb +279 -0
  87. data/lib/prawn/image_handler.rb +44 -0
  88. data/lib/prawn/images.rb +199 -0
  89. data/lib/prawn/images/image.rb +49 -0
  90. data/lib/prawn/images/jpg.rb +91 -0
  91. data/lib/prawn/images/png.rb +290 -0
  92. data/lib/prawn/measurement_extensions.rb +50 -0
  93. data/lib/prawn/measurements.rb +77 -0
  94. data/lib/prawn/outline.rb +289 -0
  95. data/lib/prawn/repeater.rb +124 -0
  96. data/lib/prawn/security.rb +288 -0
  97. data/lib/prawn/security/arcfour.rb +54 -0
  98. data/lib/prawn/soft_mask.rb +94 -0
  99. data/lib/prawn/stamp.rb +136 -0
  100. data/lib/prawn/text.rb +437 -0
  101. data/lib/prawn/text/box.rb +141 -0
  102. data/lib/prawn/text/formatted.rb +7 -0
  103. data/lib/prawn/text/formatted/arranger.rb +290 -0
  104. data/lib/prawn/text/formatted/box.rb +614 -0
  105. data/lib/prawn/text/formatted/fragment.rb +264 -0
  106. data/lib/prawn/text/formatted/line_wrap.rb +277 -0
  107. data/lib/prawn/text/formatted/parser.rb +224 -0
  108. data/lib/prawn/text/formatted/wrap.rb +160 -0
  109. data/lib/prawn/utilities.rb +46 -0
  110. data/lib/prawn/version.rb +5 -0
  111. data/lib/prawn/view.rb +91 -0
  112. data/manual/absolute_position.pdf +0 -0
  113. data/manual/basic_concepts/adding_pages.rb +27 -0
  114. data/manual/basic_concepts/basic_concepts.rb +36 -0
  115. data/manual/basic_concepts/creation.rb +39 -0
  116. data/manual/basic_concepts/cursor.rb +33 -0
  117. data/manual/basic_concepts/measurement.rb +25 -0
  118. data/manual/basic_concepts/origin.rb +38 -0
  119. data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
  120. data/manual/basic_concepts/view.rb +42 -0
  121. data/manual/bounding_box/bounding_box.rb +39 -0
  122. data/manual/bounding_box/bounds.rb +49 -0
  123. data/manual/bounding_box/canvas.rb +24 -0
  124. data/manual/bounding_box/creation.rb +23 -0
  125. data/manual/bounding_box/indentation.rb +46 -0
  126. data/manual/bounding_box/nesting.rb +45 -0
  127. data/manual/bounding_box/russian_boxes.rb +40 -0
  128. data/manual/bounding_box/stretchy.rb +31 -0
  129. data/manual/contents.rb +29 -0
  130. data/manual/cover.rb +39 -0
  131. data/manual/document_and_page_options/background.rb +27 -0
  132. data/manual/document_and_page_options/document_and_page_options.rb +32 -0
  133. data/manual/document_and_page_options/metadata.rb +23 -0
  134. data/manual/document_and_page_options/page_margins.rb +38 -0
  135. data/manual/document_and_page_options/page_size.rb +34 -0
  136. data/manual/document_and_page_options/print_scaling.rb +20 -0
  137. data/manual/example_helper.rb +7 -0
  138. data/manual/graphics/circle_and_ellipse.rb +22 -0
  139. data/manual/graphics/color.rb +24 -0
  140. data/manual/graphics/common_lines.rb +30 -0
  141. data/manual/graphics/fill_and_stroke.rb +42 -0
  142. data/manual/graphics/fill_rules.rb +37 -0
  143. data/manual/graphics/gradients.rb +37 -0
  144. data/manual/graphics/graphics.rb +58 -0
  145. data/manual/graphics/helper.rb +24 -0
  146. data/manual/graphics/line_width.rb +35 -0
  147. data/manual/graphics/lines_and_curves.rb +41 -0
  148. data/manual/graphics/polygon.rb +29 -0
  149. data/manual/graphics/rectangle.rb +21 -0
  150. data/manual/graphics/rotate.rb +28 -0
  151. data/manual/graphics/scale.rb +41 -0
  152. data/manual/graphics/soft_masks.rb +46 -0
  153. data/manual/graphics/stroke_cap.rb +31 -0
  154. data/manual/graphics/stroke_dash.rb +48 -0
  155. data/manual/graphics/stroke_join.rb +30 -0
  156. data/manual/graphics/translate.rb +29 -0
  157. data/manual/graphics/transparency.rb +35 -0
  158. data/manual/how_to_read_this_manual.rb +40 -0
  159. data/manual/images/absolute_position.rb +23 -0
  160. data/manual/images/fit.rb +21 -0
  161. data/manual/images/horizontal.rb +25 -0
  162. data/manual/images/images.rb +40 -0
  163. data/manual/images/plain_image.rb +18 -0
  164. data/manual/images/scale.rb +22 -0
  165. data/manual/images/vertical.rb +28 -0
  166. data/manual/images/width_and_height.rb +25 -0
  167. data/manual/layout/boxes.rb +27 -0
  168. data/manual/layout/content.rb +25 -0
  169. data/manual/layout/layout.rb +28 -0
  170. data/manual/layout/simple_grid.rb +23 -0
  171. data/manual/outline/add_subsection_to.rb +61 -0
  172. data/manual/outline/insert_section_after.rb +47 -0
  173. data/manual/outline/outline.rb +32 -0
  174. data/manual/outline/sections_and_pages.rb +67 -0
  175. data/manual/repeatable_content/alternate_page_numbering.rb +32 -0
  176. data/manual/repeatable_content/page_numbering.rb +54 -0
  177. data/manual/repeatable_content/repeatable_content.rb +32 -0
  178. data/manual/repeatable_content/repeater.rb +55 -0
  179. data/manual/repeatable_content/stamp.rb +41 -0
  180. data/manual/security/encryption.rb +31 -0
  181. data/manual/security/permissions.rb +38 -0
  182. data/manual/security/security.rb +28 -0
  183. data/manual/table.rb +16 -0
  184. data/manual/text/alignment.rb +44 -0
  185. data/manual/text/color.rb +24 -0
  186. data/manual/text/column_box.rb +32 -0
  187. data/manual/text/fallback_fonts.rb +37 -0
  188. data/manual/text/font.rb +41 -0
  189. data/manual/text/font_size.rb +45 -0
  190. data/manual/text/font_style.rb +23 -0
  191. data/manual/text/formatted_callbacks.rb +60 -0
  192. data/manual/text/formatted_text.rb +50 -0
  193. data/manual/text/free_flowing_text.rb +51 -0
  194. data/manual/text/inline.rb +41 -0
  195. data/manual/text/kerning_and_character_spacing.rb +39 -0
  196. data/manual/text/leading.rb +25 -0
  197. data/manual/text/line_wrapping.rb +41 -0
  198. data/manual/text/paragraph_indentation.rb +34 -0
  199. data/manual/text/positioned_text.rb +38 -0
  200. data/manual/text/registering_families.rb +48 -0
  201. data/manual/text/rendering_and_color.rb +37 -0
  202. data/manual/text/right_to_left_text.rb +47 -0
  203. data/manual/text/rotation.rb +43 -0
  204. data/manual/text/single_usage.rb +37 -0
  205. data/manual/text/text.rb +73 -0
  206. data/manual/text/text_box_excess.rb +32 -0
  207. data/manual/text/text_box_extensions.rb +45 -0
  208. data/manual/text/text_box_overflow.rb +48 -0
  209. data/manual/text/utf8.rb +28 -0
  210. data/manual/text/win_ansi_charset.rb +60 -0
  211. data/prawn.gemspec +45 -0
  212. data/spec/acceptance/png.rb +25 -0
  213. data/spec/annotations_spec.rb +74 -0
  214. data/spec/bounding_box_spec.rb +510 -0
  215. data/spec/column_box_spec.rb +65 -0
  216. data/spec/data/curves.pdf +66 -0
  217. data/spec/destinations_spec.rb +15 -0
  218. data/spec/document_spec.rb +748 -0
  219. data/spec/extensions/encoding_helpers.rb +11 -0
  220. data/spec/extensions/mocha.rb +46 -0
  221. data/spec/font_metric_cache_spec.rb +52 -0
  222. data/spec/font_spec.rb +474 -0
  223. data/spec/formatted_text_arranger_spec.rb +421 -0
  224. data/spec/formatted_text_box_spec.rb +705 -0
  225. data/spec/formatted_text_fragment_spec.rb +298 -0
  226. data/spec/graphics_spec.rb +683 -0
  227. data/spec/grid_spec.rb +96 -0
  228. data/spec/image_handler_spec.rb +54 -0
  229. data/spec/images_spec.rb +153 -0
  230. data/spec/inline_formatted_text_parser_spec.rb +564 -0
  231. data/spec/jpg_spec.rb +25 -0
  232. data/spec/line_wrap_spec.rb +367 -0
  233. data/spec/measurement_units_spec.rb +25 -0
  234. data/spec/outline_spec.rb +430 -0
  235. data/spec/png_spec.rb +245 -0
  236. data/spec/reference_spec.rb +25 -0
  237. data/spec/repeater_spec.rb +160 -0
  238. data/spec/security_spec.rb +158 -0
  239. data/spec/soft_mask_spec.rb +79 -0
  240. data/spec/span_spec.rb +44 -0
  241. data/spec/spec_helper.rb +54 -0
  242. data/spec/stamp_spec.rb +160 -0
  243. data/spec/stroke_styles_spec.rb +211 -0
  244. data/spec/text_at_spec.rb +143 -0
  245. data/spec/text_box_spec.rb +1043 -0
  246. data/spec/text_rendering_mode_spec.rb +45 -0
  247. data/spec/text_spacing_spec.rb +93 -0
  248. data/spec/text_spec.rb +557 -0
  249. data/spec/text_with_inline_formatting_spec.rb +35 -0
  250. data/spec/transparency_spec.rb +91 -0
  251. data/spec/view_spec.rb +43 -0
  252. metadata +509 -0
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
3
+
4
+ describe "A document's grid" do
5
+ before do
6
+ @pdf = Prawn::Document.new
7
+ end
8
+
9
+ it "should allow definition of a grid" do
10
+ @pdf.define_grid(:columns => 5, :rows => 8, :gutter => 0.1)
11
+ @pdf.grid.columns.should == 5
12
+ @pdf.grid.rows.should == 8
13
+ @pdf.grid.gutter.should == 0.1
14
+ end
15
+
16
+ it "should allow re-definition of a grid" do
17
+ @pdf.define_grid(:columns => 5, :rows => 8, :gutter => 0.1)
18
+ @pdf.grid.columns.should == 5
19
+ @pdf.grid.rows.should == 8
20
+ @pdf.grid.gutter.should == 0.1
21
+ @pdf.define_grid(:columns => 3, :rows => 6, :gutter => 0.1)
22
+ @pdf.grid.columns.should == 3
23
+ @pdf.grid.rows.should == 6
24
+ @pdf.grid.gutter.should == 0.1
25
+ end
26
+
27
+ describe "when a grid is defined" do
28
+ before do
29
+ @num_columns = 5
30
+ @num_rows = 8
31
+ @gutter = 10.0
32
+ @pdf.define_grid(
33
+ :columns => @num_columns,
34
+ :rows => @num_rows,
35
+ :gutter => @gutter
36
+ )
37
+ end
38
+
39
+ it "should compute the column width" do
40
+ (@pdf.grid.column_width * @num_columns.to_f +
41
+ @gutter * (@num_columns - 1).to_f).should == @pdf.bounds.width
42
+ end
43
+
44
+ it "should compute the row height" do
45
+ (@pdf.grid.row_height * @num_rows.to_f +
46
+ @gutter * (@num_rows - 1).to_f).should == @pdf.bounds.height
47
+ end
48
+
49
+ it "should give the edges of a grid box" do
50
+ grid_width = (@pdf.bounds.width.to_f -
51
+ (@gutter * (@num_columns - 1).to_f )) / @num_columns.to_f
52
+ grid_height = (@pdf.bounds.height.to_f -
53
+ (@gutter * (@num_rows - 1).to_f ))/ @num_rows.to_f
54
+
55
+ exp_tl_x = (grid_width + @gutter.to_f) * 4.0
56
+ exp_tl_y = @pdf.bounds.height.to_f - (grid_height + @gutter.to_f)
57
+
58
+ @pdf.grid(1,4).top_left.should == [exp_tl_x, exp_tl_y]
59
+ @pdf.grid(1,4).top_right.should == [exp_tl_x + grid_width, exp_tl_y]
60
+ @pdf.grid(1,4).bottom_left.should == [exp_tl_x, exp_tl_y - grid_height]
61
+ @pdf.grid(1,4).bottom_right.should == [exp_tl_x + grid_width, exp_tl_y - grid_height]
62
+ end
63
+
64
+ it "should give the edges of a multiple grid boxes" do
65
+ # Hand verified. Cheating a bit. Don't tell.
66
+ @pdf.grid([1,3], [2,5]).top_left.should == [330.0, 628.75]
67
+ @pdf.grid([1,3], [2,5]).top_right.should == [650.0, 628.75]
68
+ @pdf.grid([1,3], [2,5]).bottom_left.should == [330.0, 456.25]
69
+ @pdf.grid([1,3], [2,5]).bottom_right.should == [650.0, 456.25]
70
+ end
71
+
72
+ it "should draw outlines without changing global default colors to grid color" do
73
+ @pdf.grid.show_all('cccccc')
74
+
75
+ colors = PDF::Inspector::Graphics::Color.analyze(@pdf.render)
76
+ colors.fill_color.should_not == [0.8,0.8,0.8]
77
+ colors.stroke_color.should_not == [0.8,0.8,0.8]
78
+
79
+ # Hardcoded default color as I haven't been able to come up with a stable converter
80
+ # between fill_color without lots code.
81
+ #colors.fill_color.should == [0.0,0.0,0.0]
82
+ colors.stroke_color.should == [0.0,0.0,0.0]
83
+ end
84
+
85
+ it "should draw outlines without curent color settings" do
86
+ @pdf.fill_color "ccff00"
87
+ @pdf.stroke_color "ffcc00"
88
+
89
+ @pdf.grid.show_all
90
+
91
+ colors = PDF::Inspector::Graphics::Color.analyze(@pdf.render)
92
+ colors.fill_color.should == [0.8,1.0,0.0]
93
+ colors.stroke_color.should == [1.0,0.8,0.0]
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ describe "ImageHandler" do
6
+ let(:image_handler) { Prawn::ImageHandler.new }
7
+
8
+ let(:handler_a) { mock("Handler A") }
9
+ let(:handler_b) { mock("Handler B") }
10
+
11
+ it "finds the image handler for an image" do
12
+ handler_a.expects(:can_render? => true)
13
+
14
+ image_handler.register(handler_a)
15
+ image_handler.register(handler_b)
16
+
17
+ handler = image_handler.find("arbitrary blob")
18
+ handler.should == handler_a
19
+ end
20
+
21
+ it "can prepend handlers" do
22
+ handler_b.expects(:can_render? => true)
23
+
24
+ image_handler.register(handler_a)
25
+ image_handler.register!(handler_b)
26
+
27
+ handler = image_handler.find("arbitrary blob")
28
+ handler.should == handler_b
29
+ end
30
+
31
+ it "can unregister a handler" do
32
+ handler_b.expects(:can_render? => true)
33
+
34
+ image_handler.register(handler_a)
35
+ image_handler.register(handler_b)
36
+
37
+ image_handler.unregister(handler_a)
38
+
39
+ handler = image_handler.find('arbitrary blob')
40
+ handler.should == handler_b
41
+ end
42
+
43
+ it "raises an error when no matching handler is found" do
44
+ handler_a.expects(:can_render? => false)
45
+ handler_b.expects(:can_render? => false)
46
+
47
+ image_handler.register(handler_a)
48
+ image_handler.register(handler_b)
49
+
50
+ expect { image_handler.find("arbitrary blob") }.
51
+ to(raise_error(Prawn::Errors::UnsupportedImageType))
52
+ end
53
+
54
+ end
@@ -0,0 +1,153 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+ require 'set'
5
+ require 'pathname'
6
+
7
+ describe "the image() function" do
8
+
9
+ before(:each) do
10
+ @filename = "#{Prawn::DATADIR}/images/pigs.jpg"
11
+ create_pdf
12
+ end
13
+
14
+ it "should only embed an image once, even if it's added multiple times" do
15
+ @pdf.image @filename, :at => [100,100]
16
+ @pdf.image @filename, :at => [300,300]
17
+
18
+ output = @pdf.render
19
+ images = PDF::Inspector::XObject.analyze(output)
20
+ # there should be 2 images in the page resources
21
+ images.page_xobjects.first.size.should == 2
22
+ # but only 1 image xobject
23
+ output.scan(/\/Type \/XObject/).size.should == 1
24
+ end
25
+
26
+ it "should return the image info object" do
27
+ info = @pdf.image(@filename)
28
+
29
+ info.should be_a_kind_of(Prawn::Images::JPG)
30
+
31
+ info.height.should == 453
32
+ end
33
+
34
+ it "should accept IO objects" do
35
+ file = File.open(@filename, "rb")
36
+ info = @pdf.image(file)
37
+
38
+ info.height.should == 453
39
+ end
40
+
41
+ it "rewinds IO objects to be able to embed them multiply" do
42
+ file = File.open(@filename, "rb")
43
+
44
+ @pdf.image(file)
45
+ info = @pdf.image(file)
46
+ info.height.should == 453
47
+ end
48
+
49
+ it "should accept Pathname objects" do
50
+ info = @pdf.image(Pathname.new(@filename))
51
+ info.height.should == 453
52
+ end
53
+
54
+ context "setting the length of the bytestream" do
55
+ it "should correctly work with images from Pathname objects" do
56
+ info = @pdf.image(Pathname.new(@filename))
57
+ expect(@pdf).to have_parseable_xobjects
58
+ end
59
+
60
+ it "should correctly work with images from IO objects" do
61
+ info = @pdf.image(File.open(@filename, 'rb'))
62
+ expect(@pdf).to have_parseable_xobjects
63
+ end
64
+
65
+ it "should correctly work with images from IO objects not set to mode rb" do
66
+ info = @pdf.image(File.open(@filename, 'r'))
67
+ expect(@pdf).to have_parseable_xobjects
68
+ end
69
+ end
70
+
71
+ it "should raise_error an UnsupportedImageType if passed a BMP" do
72
+ filename = "#{Prawn::DATADIR}/images/tru256.bmp"
73
+ lambda { @pdf.image filename, :at => [100,100] }.should raise_error(Prawn::Errors::UnsupportedImageType)
74
+ end
75
+
76
+ it "should raise_error an UnsupportedImageType if passed an interlaced PNG" do
77
+ filename = "#{Prawn::DATADIR}/images/dice_interlaced.png"
78
+ lambda { @pdf.image filename, :at => [100,100] }.should raise_error(Prawn::Errors::UnsupportedImageType)
79
+ end
80
+
81
+ it "should bump PDF version to 1.5 or greater on embedding 16-bit PNGs" do
82
+ @pdf.image "#{Prawn::DATADIR}/images/16bit.png"
83
+ @pdf.state.version.should >= 1.5
84
+ end
85
+
86
+ it "should embed 16-bit alpha channels for 16-bit PNGs" do
87
+ @pdf.image "#{Prawn::DATADIR}/images/16bit.png"
88
+
89
+ output = @pdf.render
90
+ output.should =~ /\/BitsPerComponent 16/
91
+ output.should_not =~ /\/BitsPerComponent 8/
92
+ end
93
+
94
+ it "should flow an image to a new page if it will not fit on a page" do
95
+ @pdf.image @filename, :fit => [600, 600]
96
+ @pdf.image @filename, :fit => [600, 600]
97
+ output = StringIO.new(@pdf.render, 'r+')
98
+ hash = PDF::Reader::ObjectHash.new(output)
99
+ pages = hash.values.find {|obj| obj.is_a?(Hash) && obj[:Type] == :Pages}[:Kids]
100
+ pages.size.should == 2
101
+ hash[pages[0]][:Resources][:XObject].keys.should == [:I1]
102
+ hash[pages[1]][:Resources][:XObject].keys.should == [:I2]
103
+ end
104
+
105
+ it "should not flow an image to a new page if it will fit on one page" do
106
+ @pdf.image @filename, :fit => [400, 400]
107
+ @pdf.image @filename, :fit => [400, 400]
108
+ output = StringIO.new(@pdf.render, 'r+')
109
+ hash = PDF::Reader::ObjectHash.new(output)
110
+ pages = hash.values.find {|obj| obj.is_a?(Hash) && obj[:Type] == :Pages}[:Kids]
111
+ pages.size.should == 1
112
+ Set.new(hash[pages[0]][:Resources][:XObject].keys).should ==
113
+ Set.new([:I1, :I2])
114
+ end
115
+
116
+ it "should not start a new page just for a stretchy bounding box" do
117
+ @pdf.expects(:start_new_page).times(0)
118
+ @pdf.bounding_box([0, @pdf.cursor], :width => @pdf.bounds.width) do
119
+ @pdf.image @filename
120
+ end
121
+ end
122
+
123
+ describe ":fit option" do
124
+ it "should fit inside the defined constraints" do
125
+ info = @pdf.image @filename, :fit => [100,400]
126
+ info.scaled_width.should <= 100
127
+ info.scaled_height.should <= 400
128
+
129
+ info = @pdf.image @filename, :fit => [400,100]
130
+ info.scaled_width.should <= 400
131
+ info.scaled_height.should <= 100
132
+
133
+ info = @pdf.image @filename, :fit => [604,453]
134
+ info.scaled_width.should == 604
135
+ info.scaled_height.should == 453
136
+ end
137
+ it "should move text position" do
138
+ @y = @pdf.y
139
+ info = @pdf.image @filename, :fit => [100,400]
140
+ @pdf.y.should < @y
141
+ end
142
+ end
143
+
144
+ describe ":at option" do
145
+ it "should not move text position" do
146
+ @y = @pdf.y
147
+ info = @pdf.image @filename, :at => [100,400]
148
+ @pdf.y.should == @y
149
+ end
150
+ end
151
+
152
+ end
153
+
@@ -0,0 +1,564 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
3
+
4
+ describe "Text::Formatted::Parser#format" do
5
+ it "should handle sup" do
6
+ string = "<sup>superscript</sup>"
7
+ array = Prawn::Text::Formatted::Parser.format(string)
8
+ array[0].should == { :text => "superscript",
9
+ :styles => [:superscript],
10
+ :color => nil,
11
+ :link => nil,
12
+ :anchor => nil,
13
+ :local => nil,
14
+ :font => nil,
15
+ :size => nil,
16
+ :character_spacing => nil }
17
+ end
18
+ it "should handle sub" do
19
+ string = "<sub>subscript</sub>"
20
+ array = Prawn::Text::Formatted::Parser.format(string)
21
+ array[0].should == { :text => "subscript",
22
+ :styles => [:subscript],
23
+ :color => nil,
24
+ :link => nil,
25
+ :anchor => nil,
26
+ :local => nil,
27
+ :font => nil,
28
+ :size => nil,
29
+ :character_spacing => nil }
30
+ end
31
+ it "should handle rgb" do
32
+ string = "<color rgb='#ff0000'>red text</color>"
33
+ array = Prawn::Text::Formatted::Parser.format(string)
34
+ array[0].should == { :text => "red text",
35
+ :styles => [],
36
+ :color => "ff0000",
37
+ :link => nil,
38
+ :anchor => nil,
39
+ :local => nil,
40
+ :font => nil,
41
+ :size => nil,
42
+ :character_spacing => nil }
43
+ end
44
+ it "# should be optional in rgb" do
45
+ string = "<color rgb='ff0000'>red text</color>"
46
+ array = Prawn::Text::Formatted::Parser.format(string)
47
+ array[0].should == { :text => "red text",
48
+ :styles => [],
49
+ :color => "ff0000",
50
+ :link => nil,
51
+ :anchor => nil,
52
+ :local => nil,
53
+ :font => nil,
54
+ :size => nil,
55
+ :character_spacing => nil }
56
+ end
57
+ it "should handle cmyk" do
58
+ string = "<color c='0' m='100' y='0' k='0'>magenta text</color>"
59
+ array = Prawn::Text::Formatted::Parser.format(string)
60
+ array[0].should == { :text => "magenta text",
61
+ :styles => [],
62
+ :color => [0, 100, 0, 0],
63
+ :link => nil,
64
+ :anchor => nil,
65
+ :local => nil,
66
+ :font => nil,
67
+ :size => nil,
68
+ :character_spacing => nil }
69
+ end
70
+ it "should handle fonts" do
71
+ string = "<font name='Courier'>Courier text</font>"
72
+ array = Prawn::Text::Formatted::Parser.format(string)
73
+ array[0].should == { :text => "Courier text",
74
+ :styles => [],
75
+ :color => nil,
76
+ :link => nil,
77
+ :anchor => nil,
78
+ :local => nil,
79
+ :font => "Courier",
80
+ :size => nil,
81
+ :character_spacing => nil }
82
+ end
83
+ it "should handle size" do
84
+ string = "<font size='14'>14 point text</font>"
85
+ array = Prawn::Text::Formatted::Parser.format(string)
86
+ array[0].should == { :text => "14 point text",
87
+ :styles => [],
88
+ :color => nil,
89
+ :link => nil,
90
+ :anchor => nil,
91
+ :local => nil,
92
+ :font => nil,
93
+ :size => 14,
94
+ :character_spacing => nil }
95
+ end
96
+ it "should handle character_spacing" do
97
+ string = "<font character_spacing='2.5'>extra character spacing</font>"
98
+ array = Prawn::Text::Formatted::Parser.format(string)
99
+ array[0].should == { :text => "extra character spacing",
100
+ :styles => [],
101
+ :color => nil,
102
+ :link => nil,
103
+ :anchor => nil,
104
+ :local => nil,
105
+ :font => nil,
106
+ :size => nil,
107
+ :character_spacing => 2.5 }
108
+ end
109
+ it "should handle links" do
110
+ string = "<link href='http://example.com'>external link</link>"
111
+ array = Prawn::Text::Formatted::Parser.format(string)
112
+ array[0].should == { :text => "external link",
113
+ :styles => [],
114
+ :color => nil,
115
+ :link => "http://example.com",
116
+ :anchor => nil,
117
+ :local => nil,
118
+ :font => nil,
119
+ :size => nil,
120
+ :character_spacing => nil }
121
+ end
122
+ it "should handle local links" do
123
+ string = "<link local='/home/example/foo.bar'>local link</link>"
124
+ array = Prawn::Text::Formatted::Parser.format(string)
125
+ array[0].should == { :text => "local link",
126
+ :styles => [],
127
+ :color => nil,
128
+ :link => nil,
129
+ :anchor => nil,
130
+ :local => "/home/example/foo.bar",
131
+ :font => nil,
132
+ :size => nil,
133
+ :character_spacing => nil }
134
+ end
135
+ it "should handle anchors" do
136
+ string = "<link anchor='ToC'>internal link</link>"
137
+ array = Prawn::Text::Formatted::Parser.format(string)
138
+ array[0].should == { :text => "internal link",
139
+ :styles => [],
140
+ :color => nil,
141
+ :link => nil,
142
+ :anchor => "ToC",
143
+ :local => nil,
144
+ :font => nil,
145
+ :size => nil,
146
+ :character_spacing => nil }
147
+ end
148
+ it "should handle higher order characters properly" do
149
+ string = "<b>©\n©</b>"
150
+ array = Prawn::Text::Formatted::Parser.format(string)
151
+ array[0].should == { :text => "©",
152
+ :styles => [:bold],
153
+ :color => nil,
154
+ :link => nil,
155
+ :anchor => nil,
156
+ :local => nil,
157
+ :font => nil,
158
+ :size => nil,
159
+ :character_spacing => nil }
160
+ array[1].should == { :text => "\n",
161
+ :styles => [:bold],
162
+ :color => nil,
163
+ :link => nil,
164
+ :anchor => nil,
165
+ :local => nil,
166
+ :font => nil,
167
+ :size => nil,
168
+ :character_spacing => nil }
169
+ array[2].should == { :text => "©",
170
+ :styles => [:bold],
171
+ :color => nil,
172
+ :link => nil,
173
+ :anchor => nil,
174
+ :local => nil,
175
+ :font => nil,
176
+ :size => nil,
177
+ :character_spacing => nil }
178
+ end
179
+ it "should convert &lt; &gt;, and &amp; to <, >, and &, respectively" do
180
+ string = "hello <b>&lt;, &gt;, and &amp;</b>"
181
+ array = Prawn::Text::Formatted::Parser.format(string)
182
+ array[1].should == { :text => "<, >, and &",
183
+ :styles => [:bold],
184
+ :color => nil,
185
+ :link => nil,
186
+ :anchor => nil,
187
+ :local => nil,
188
+ :font => nil,
189
+ :size => nil,
190
+ :character_spacing => nil }
191
+ end
192
+ it "should handle double qoutes around tag attributes" do
193
+ string = 'some <font size="14">sized</font> text'
194
+ array = Prawn::Text::Formatted::Parser.format(string)
195
+ array[1].should == { :text => "sized",
196
+ :styles => [],
197
+ :color => nil,
198
+ :link => nil,
199
+ :anchor => nil,
200
+ :local => nil,
201
+ :font => nil,
202
+ :size => 14,
203
+ :character_spacing => nil }
204
+ end
205
+ it "should handle single qoutes around tag attributes" do
206
+ string = "some <font size='14'>sized</font> text"
207
+ array = Prawn::Text::Formatted::Parser.format(string)
208
+ array[1].should == { :text => "sized",
209
+ :styles => [],
210
+ :color => nil,
211
+ :link => nil,
212
+ :anchor => nil,
213
+ :local => nil,
214
+ :font => nil,
215
+ :size => 14,
216
+ :character_spacing => nil }
217
+ end
218
+ it "should construct a formatted text array from a string" do
219
+ string = "hello <b>world\nhow <i>are</i></b> you?"
220
+ array = Prawn::Text::Formatted::Parser.format(string)
221
+
222
+ array[0].should == { :text => "hello ",
223
+ :styles => [],
224
+ :color => nil,
225
+ :link => nil,
226
+ :anchor => nil,
227
+ :local => nil,
228
+ :font => nil,
229
+ :size => nil,
230
+ :character_spacing => nil }
231
+ array[1].should == { :text => "world",
232
+ :styles => [:bold],
233
+ :color => nil,
234
+ :link => nil,
235
+ :anchor => nil,
236
+ :local => nil,
237
+ :font => nil,
238
+ :size => nil,
239
+ :character_spacing => nil }
240
+ array[2].should == { :text => "\n",
241
+ :styles => [:bold],
242
+ :color => nil,
243
+ :link => nil,
244
+ :anchor => nil,
245
+ :local => nil,
246
+ :font => nil,
247
+ :size => nil,
248
+ :character_spacing => nil }
249
+ array[3].should == { :text => "how ",
250
+ :styles => [:bold],
251
+ :color => nil,
252
+ :link => nil,
253
+ :anchor => nil,
254
+ :local => nil,
255
+ :font => nil,
256
+ :size => nil,
257
+ :character_spacing => nil }
258
+ array[4].should == { :text => "are",
259
+ :styles => [:bold, :italic],
260
+ :color => nil,
261
+ :link => nil,
262
+ :anchor => nil,
263
+ :local => nil,
264
+ :font => nil,
265
+ :size => nil,
266
+ :character_spacing => nil }
267
+ array[5].should == { :text => " you?",
268
+ :styles => [],
269
+ :color => nil,
270
+ :link => nil,
271
+ :anchor => nil,
272
+ :local => nil,
273
+ :font => nil,
274
+ :size => nil,
275
+ :character_spacing => nil }
276
+ end
277
+ it "should accept <strong> as an alternative to <b>" do
278
+ string = "<strong>bold</strong> not bold"
279
+ array = Prawn::Text::Formatted::Parser.format(string)
280
+
281
+ array[0].should == { :text => "bold",
282
+ :styles => [:bold],
283
+ :color => nil,
284
+ :link => nil,
285
+ :anchor => nil,
286
+ :local => nil,
287
+ :font => nil,
288
+ :size => nil,
289
+ :character_spacing => nil }
290
+ array[1].should == { :text => " not bold",
291
+ :styles => [],
292
+ :color => nil,
293
+ :link => nil,
294
+ :anchor => nil,
295
+ :local => nil,
296
+ :font => nil,
297
+ :size => nil,
298
+ :character_spacing => nil }
299
+ end
300
+ it "should accept <em> as an alternative to <i>" do
301
+ string = "<em>italic</em> not italic"
302
+ array = Prawn::Text::Formatted::Parser.format(string)
303
+
304
+ array[0].should == { :text => "italic",
305
+ :styles => [:italic],
306
+ :color => nil,
307
+ :link => nil,
308
+ :anchor => nil,
309
+ :local => nil,
310
+ :font => nil,
311
+ :size => nil,
312
+ :character_spacing => nil }
313
+ array[1].should == { :text => " not italic",
314
+ :styles => [],
315
+ :color => nil,
316
+ :link => nil,
317
+ :anchor => nil,
318
+ :local => nil,
319
+ :font => nil,
320
+ :size => nil,
321
+ :character_spacing => nil }
322
+ end
323
+ it "should accept <a> as an alternative to <link>" do
324
+ string = "<a href='http://example.com'>link</a> not a link"
325
+ array = Prawn::Text::Formatted::Parser.format(string)
326
+
327
+ array[0].should == { :text => "link",
328
+ :styles => [],
329
+ :color => nil,
330
+ :link => "http://example.com",
331
+ :anchor => nil,
332
+ :local => nil,
333
+ :font => nil,
334
+ :size => nil,
335
+ :character_spacing => nil }
336
+ array[1].should == { :text => " not a link",
337
+ :styles => [],
338
+ :color => nil,
339
+ :link => nil,
340
+ :anchor => nil,
341
+ :local => nil,
342
+ :font => nil,
343
+ :size => nil,
344
+ :character_spacing => nil }
345
+ end
346
+
347
+ it "should turn <br>, <br/> into newline" do
348
+ array = Prawn::Text::Formatted::Parser.format("hello<br>big<br/>world")
349
+ array.map { |frag| frag[:text] }.join.should == "hello\nbig\nworld"
350
+ end
351
+ end
352
+
353
+
354
+ describe "Text::Formatted::Parser#to_string" do
355
+ it "should handle sup" do
356
+ string = "<sup>superscript</sup>"
357
+ array = [{ :text => "superscript",
358
+ :styles => [:superscript],
359
+ :color => nil,
360
+ :link => nil,
361
+ :anchor => nil,
362
+ :local => nil,
363
+ :font => nil,
364
+ :size => nil,
365
+ :character_spacing => nil }]
366
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
367
+ end
368
+ it "should handle sub" do
369
+ string = "<sub>subscript</sub>"
370
+ array = [{ :text => "subscript",
371
+ :styles => [:subscript],
372
+ :color => nil,
373
+ :link => nil,
374
+ :anchor => nil,
375
+ :local => nil,
376
+ :font => nil,
377
+ :size => nil,
378
+ :character_spacing => nil }]
379
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
380
+ end
381
+ it "should handle rgb" do
382
+ string = "<color rgb='ff0000'>red text</color>"
383
+ array = [{ :text => "red text",
384
+ :styles => [],
385
+ :color => "ff0000",
386
+ :link => nil,
387
+ :anchor => nil,
388
+ :local => nil,
389
+ :font => nil,
390
+ :size => nil,
391
+ :character_spacing => nil }]
392
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
393
+ end
394
+ it "should handle cmyk" do
395
+ string = "<color c='0' m='100' y='0' k='0'>magenta text</color>"
396
+ array = [{ :text => "magenta text",
397
+ :styles => [],
398
+ :color => [0, 100, 0, 0],
399
+ :link => nil,
400
+ :anchor => nil,
401
+ :local => nil,
402
+ :font => nil,
403
+ :size => nil,
404
+ :character_spacing => nil }]
405
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
406
+ end
407
+ it "should handle fonts" do
408
+ string = "<font name='Courier'>Courier text</font>"
409
+ array = [{ :text => "Courier text",
410
+ :styles => [],
411
+ :color => nil,
412
+ :link => nil,
413
+ :anchor => nil,
414
+ :local => nil,
415
+ :font => "Courier",
416
+ :size => nil,
417
+ :character_spacing => nil }]
418
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
419
+ end
420
+ it "should handle size" do
421
+ string = "<font size='14'>14 point text</font>"
422
+ array = [{ :text => "14 point text",
423
+ :styles => [],
424
+ :color => nil,
425
+ :link => nil,
426
+ :anchor => nil,
427
+ :local => nil,
428
+ :font => nil,
429
+ :size => 14,
430
+ :character_spacing => nil }]
431
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
432
+ end
433
+ it "should handle character spacing" do
434
+ string = "<font character_spacing='2.5'>2.5 extra character spacing</font>"
435
+ array = [{ :text => "2.5 extra character spacing",
436
+ :styles => [],
437
+ :color => nil,
438
+ :link => nil,
439
+ :anchor => nil,
440
+ :local => nil,
441
+ :font => nil,
442
+ :size => nil,
443
+ :character_spacing => 2.5 }]
444
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
445
+ end
446
+ it "should handle links" do
447
+ array = [{ :text => "external link",
448
+ :styles => [],
449
+ :color => nil,
450
+ :link => "http://example.com",
451
+ :anchor => nil,
452
+ :local => nil,
453
+ :font => nil,
454
+ :size => nil,
455
+ :character_spacing => nil }]
456
+ string = "<link href='http://example.com'>external link</link>"
457
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
458
+ end
459
+ it "should handle anchors" do
460
+ array = [{ :text => "internal link",
461
+ :styles => [],
462
+ :color => nil,
463
+ :link => nil,
464
+ :anchor => "ToC",
465
+ :font => nil,
466
+ :size => nil,
467
+ :character_spacing => nil }]
468
+ string = "<link anchor='ToC'>internal link</link>"
469
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
470
+ end
471
+ it "should convert <, >, and & to &lt; &gt;, and &amp;, respectively" do
472
+ array = [{ :text => "hello ",
473
+ :styles => [],
474
+ :color => nil,
475
+ :link => nil,
476
+ :font => nil,
477
+ :size => nil,
478
+ :character_spacing => nil },
479
+ { :text => "<, >, and &",
480
+ :styles => [:bold],
481
+ :color => nil,
482
+ :link => nil,
483
+ :font => nil,
484
+ :size => nil,
485
+ :character_spacing => nil }]
486
+ string = "hello <b>&lt;, &gt;, and &amp;</b>"
487
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
488
+ end
489
+ it "should construct an HTML-esque string from a formatted" +
490
+ " text array" do
491
+ array = [
492
+ { :text => "hello ",
493
+ :styles => [],
494
+ :color => nil,
495
+ :link => nil,
496
+ :font => nil,
497
+ :size => 14,
498
+ :character_spacing => nil },
499
+ { :text => "world",
500
+ :styles => [:bold],
501
+ :color => nil,
502
+ :link => nil,
503
+ :font => nil,
504
+ :size => nil,
505
+ :character_spacing => nil },
506
+ { :text => "\n",
507
+ :styles => [:bold],
508
+ :color => nil,
509
+ :link => nil,
510
+ :font => nil,
511
+ :size => nil,
512
+ :character_spacing => nil },
513
+ { :text => "how ",
514
+ :styles => [:bold],
515
+ :color => nil,
516
+ :link => nil,
517
+ :font => nil,
518
+ :size => nil,
519
+ :character_spacing => nil },
520
+ { :text => "are",
521
+ :styles => [:bold, :italic],
522
+ :color => nil,
523
+ :link => nil,
524
+ :font => nil,
525
+ :size => nil,
526
+ :character_spacing => nil },
527
+ { :text => " you?",
528
+ :styles => [],
529
+ :color => nil,
530
+ :link => nil,
531
+ :font => nil,
532
+ :size => nil,
533
+ :character_spacing => nil }
534
+ ]
535
+ string = "<font size='14'>hello </font><b>world</b><b>\n</b><b>how </b><b><i>are</i></b> you?"
536
+ Prawn::Text::Formatted::Parser.to_string(array).should == string
537
+ end
538
+ end
539
+
540
+ describe "Text::Formatted::Parser#array_paragraphs" do
541
+ it "should group fragments separated by newlines" do
542
+ array = [{ :text => "\nhello\nworld" },
543
+ { :text => "\n\n" },
544
+ { :text => "how" },
545
+ { :text => "are" },
546
+ { :text => "you" }]
547
+ target = [[{ :text => "\n"}],
548
+ [{ :text => "hello" }],
549
+ [{ :text => "world" }],
550
+ [{ :text => "\n"}],
551
+ [{ :text => "how" },
552
+ { :text => "are" },
553
+ { :text => "you" }]]
554
+ Prawn::Text::Formatted::Parser.array_paragraphs(array).should == target
555
+ end
556
+
557
+ it "should work properly if ending in an empty paragraph" do
558
+ array = [{ :text => "\nhello\nworld\n" }]
559
+ target = [[{ :text => "\n" }],
560
+ [{ :text => "hello" }],
561
+ [{ :text => "world" }]]
562
+ Prawn::Text::Formatted::Parser.array_paragraphs(array).should == target
563
+ end
564
+ end