davebenvenuti-prawn 0.11.1.pre

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 (291) hide show
  1. data/COPYING +340 -0
  2. data/HACKING +50 -0
  3. data/LICENSE +56 -0
  4. data/README +141 -0
  5. data/Rakefile +52 -0
  6. data/data/encodings/win_ansi.txt +29 -0
  7. data/data/fonts/Action Man.dfont +0 -0
  8. data/data/fonts/Activa.ttf +0 -0
  9. data/data/fonts/Chalkboard.ttf +0 -0
  10. data/data/fonts/Courier-Bold.afm +342 -0
  11. data/data/fonts/Courier-BoldOblique.afm +342 -0
  12. data/data/fonts/Courier-Oblique.afm +342 -0
  13. data/data/fonts/Courier.afm +342 -0
  14. data/data/fonts/DejaVuSans.ttf +0 -0
  15. data/data/fonts/Dustismo_Roman.ttf +0 -0
  16. data/data/fonts/Helvetica-Bold.afm +2827 -0
  17. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  18. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  19. data/data/fonts/Helvetica.afm +3051 -0
  20. data/data/fonts/MustRead.html +19 -0
  21. data/data/fonts/Symbol.afm +213 -0
  22. data/data/fonts/Times-Bold.afm +2588 -0
  23. data/data/fonts/Times-BoldItalic.afm +2384 -0
  24. data/data/fonts/Times-Italic.afm +2667 -0
  25. data/data/fonts/Times-Roman.afm +2419 -0
  26. data/data/fonts/ZapfDingbats.afm +225 -0
  27. data/data/fonts/comicsans.ttf +0 -0
  28. data/data/fonts/gkai00mp.ttf +0 -0
  29. data/data/images/16bit.alpha +0 -0
  30. data/data/images/16bit.dat +0 -0
  31. data/data/images/16bit.png +0 -0
  32. data/data/images/arrow.png +0 -0
  33. data/data/images/arrow2.png +0 -0
  34. data/data/images/barcode_issue.png +0 -0
  35. data/data/images/dice.alpha +0 -0
  36. data/data/images/dice.dat +0 -0
  37. data/data/images/dice.png +0 -0
  38. data/data/images/dice_interlaced.png +0 -0
  39. data/data/images/fractal.jpg +0 -0
  40. data/data/images/letterhead.jpg +0 -0
  41. data/data/images/page_white_text.alpha +0 -0
  42. data/data/images/page_white_text.dat +0 -0
  43. data/data/images/page_white_text.png +0 -0
  44. data/data/images/pigs.jpg +0 -0
  45. data/data/images/rails.dat +0 -0
  46. data/data/images/rails.png +0 -0
  47. data/data/images/ruport.png +0 -0
  48. data/data/images/ruport_data.dat +0 -0
  49. data/data/images/ruport_transparent.png +0 -0
  50. data/data/images/ruport_type0.png +0 -0
  51. data/data/images/stef.jpg +0 -0
  52. data/data/images/tru256.bmp +0 -0
  53. data/data/images/web-links.dat +1 -0
  54. data/data/images/web-links.png +0 -0
  55. data/data/pdfs/complex_template.pdf +0 -0
  56. data/data/pdfs/contains_ttf_font.pdf +0 -0
  57. data/data/pdfs/encrypted.pdf +0 -0
  58. data/data/pdfs/hexagon.pdf +61 -0
  59. data/data/pdfs/indirect_reference.pdf +86 -0
  60. data/data/pdfs/nested_pages.pdf +118 -0
  61. data/data/pdfs/page_without_mediabox.pdf +193 -0
  62. data/data/pdfs/resources_as_indirect_object.pdf +83 -0
  63. data/data/pdfs/two_hexagons.pdf +90 -0
  64. data/data/pdfs/version_1_6.pdf +61 -0
  65. data/data/shift_jis_text.txt +1 -0
  66. data/examples/bounding_box/bounding_boxes.rb +44 -0
  67. data/examples/bounding_box/indentation.rb +35 -0
  68. data/examples/bounding_box/russian_boxes.rb +37 -0
  69. data/examples/bounding_box/stretched_nesting.rb +68 -0
  70. data/examples/example_helper.rb +8 -0
  71. data/examples/general/background.rb +24 -0
  72. data/examples/general/canvas.rb +16 -0
  73. data/examples/general/context_sensitive_headers.rb +38 -0
  74. data/examples/general/float.rb +12 -0
  75. data/examples/general/margin.rb +37 -0
  76. data/examples/general/measurement_units.rb +52 -0
  77. data/examples/general/metadata-info.rb +17 -0
  78. data/examples/general/multi_page_layout.rb +19 -0
  79. data/examples/general/outlines.rb +67 -0
  80. data/examples/general/page_geometry.rb +32 -0
  81. data/examples/general/page_numbering.rb +16 -0
  82. data/examples/general/repeaters.rb +48 -0
  83. data/examples/general/stamp.rb +42 -0
  84. data/examples/general/templates.rb +14 -0
  85. data/examples/graphics/basic_images.rb +24 -0
  86. data/examples/graphics/cmyk.rb +13 -0
  87. data/examples/graphics/curves.rb +12 -0
  88. data/examples/graphics/hexagon.rb +14 -0
  89. data/examples/graphics/image_fit.rb +16 -0
  90. data/examples/graphics/image_flow.rb +38 -0
  91. data/examples/graphics/image_position.rb +18 -0
  92. data/examples/graphics/line.rb +33 -0
  93. data/examples/graphics/png_types.rb +23 -0
  94. data/examples/graphics/polygons.rb +17 -0
  95. data/examples/graphics/remote_images.rb +13 -0
  96. data/examples/graphics/rounded_polygons.rb +20 -0
  97. data/examples/graphics/rounded_rectangle.rb +21 -0
  98. data/examples/graphics/ruport_style_helpers.rb +20 -0
  99. data/examples/graphics/stroke_bounds.rb +21 -0
  100. data/examples/graphics/stroke_cap_and_join.rb +46 -0
  101. data/examples/graphics/stroke_dash.rb +43 -0
  102. data/examples/graphics/transformations.rb +53 -0
  103. data/examples/graphics/transparency.rb +27 -0
  104. data/examples/grid/bounding_boxes.rb +22 -0
  105. data/examples/grid/column_gutter_grid.rb +21 -0
  106. data/examples/grid/multi_boxes.rb +52 -0
  107. data/examples/grid/show_grid.rb +14 -0
  108. data/examples/grid/simple_grid.rb +21 -0
  109. data/examples/m17n/chinese_text_wrapping.rb +18 -0
  110. data/examples/m17n/euro.rb +16 -0
  111. data/examples/m17n/sjis.rb +29 -0
  112. data/examples/m17n/utf8.rb +14 -0
  113. data/examples/m17n/win_ansi_charset.rb +55 -0
  114. data/examples/security/hello_foo.rb +9 -0
  115. data/examples/table/bill.rb +54 -0
  116. data/examples/table/cell.rb +13 -0
  117. data/examples/table/checkerboard.rb +23 -0
  118. data/examples/table/header.rb +15 -0
  119. data/examples/table/inline_format_table.rb +13 -0
  120. data/examples/table/multi_page_table.rb +10 -0
  121. data/examples/table/simple_table.rb +25 -0
  122. data/examples/table/subtable.rb +13 -0
  123. data/examples/table/widths.rb +21 -0
  124. data/examples/text/alignment.rb +19 -0
  125. data/examples/text/character_spacing.rb +13 -0
  126. data/examples/text/dfont.rb +49 -0
  127. data/examples/text/family_based_styling.rb +25 -0
  128. data/examples/text/font_calculations.rb +92 -0
  129. data/examples/text/font_size.rb +34 -0
  130. data/examples/text/hyphenation.rb +46 -0
  131. data/examples/text/indent_paragraphs.rb +23 -0
  132. data/examples/text/inline_format.rb +104 -0
  133. data/examples/text/kerning.rb +31 -0
  134. data/examples/text/rotated.rb +99 -0
  135. data/examples/text/shaped_text_box.rb +32 -0
  136. data/examples/text/simple_text.rb +18 -0
  137. data/examples/text/simple_text_ttf.rb +18 -0
  138. data/examples/text/span.rb +30 -0
  139. data/examples/text/text_box.rb +89 -0
  140. data/examples/text/text_box_returning_excess.rb +52 -0
  141. data/examples/text/text_flow.rb +68 -0
  142. data/lib/prawn.rb +26 -0
  143. data/lib/prawn/compatibility.rb +51 -0
  144. data/lib/prawn/core.rb +85 -0
  145. data/lib/prawn/core/annotations.rb +61 -0
  146. data/lib/prawn/core/byte_string.rb +9 -0
  147. data/lib/prawn/core/destinations.rb +90 -0
  148. data/lib/prawn/core/document_state.rb +78 -0
  149. data/lib/prawn/core/literal_string.rb +16 -0
  150. data/lib/prawn/core/name_tree.rb +165 -0
  151. data/lib/prawn/core/object_store.rb +236 -0
  152. data/lib/prawn/core/page.rb +199 -0
  153. data/lib/prawn/core/pdf_object.rb +108 -0
  154. data/lib/prawn/core/reference.rb +112 -0
  155. data/lib/prawn/core/text.rb +140 -0
  156. data/lib/prawn/core/text/formatted/arranger.rb +266 -0
  157. data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
  158. data/lib/prawn/core/text/formatted/wrap.rb +112 -0
  159. data/lib/prawn/core/text/line_wrap.rb +211 -0
  160. data/lib/prawn/core/text/wrap.rb +82 -0
  161. data/lib/prawn/document.rb +575 -0
  162. data/lib/prawn/document/bounding_box.rb +428 -0
  163. data/lib/prawn/document/graphics_state.rb +48 -0
  164. data/lib/prawn/document/internals.rb +170 -0
  165. data/lib/prawn/document/page_geometry.rb +136 -0
  166. data/lib/prawn/document/snapshot.rb +87 -0
  167. data/lib/prawn/document/span.rb +55 -0
  168. data/lib/prawn/encoding.rb +121 -0
  169. data/lib/prawn/errors.rb +86 -0
  170. data/lib/prawn/font.rb +368 -0
  171. data/lib/prawn/font/afm.rb +225 -0
  172. data/lib/prawn/font/dfont.rb +42 -0
  173. data/lib/prawn/font/ttf.rb +350 -0
  174. data/lib/prawn/graphics.rb +325 -0
  175. data/lib/prawn/graphics/cap_style.rb +38 -0
  176. data/lib/prawn/graphics/color.rb +205 -0
  177. data/lib/prawn/graphics/dash.rb +71 -0
  178. data/lib/prawn/graphics/join_style.rb +38 -0
  179. data/lib/prawn/graphics/transformation.rb +156 -0
  180. data/lib/prawn/graphics/transparency.rb +99 -0
  181. data/lib/prawn/images.rb +217 -0
  182. data/lib/prawn/images/jpg.rb +85 -0
  183. data/lib/prawn/images/png.rb +356 -0
  184. data/lib/prawn/layout.rb +20 -0
  185. data/lib/prawn/layout/grid.rb +259 -0
  186. data/lib/prawn/measurement_extensions.rb +46 -0
  187. data/lib/prawn/measurements.rb +71 -0
  188. data/lib/prawn/outline.rb +326 -0
  189. data/lib/prawn/repeater.rb +129 -0
  190. data/lib/prawn/security.rb +262 -0
  191. data/lib/prawn/security/arcfour.rb +51 -0
  192. data/lib/prawn/stamp.rb +126 -0
  193. data/lib/prawn/table.rb +451 -0
  194. data/lib/prawn/table/cell.rb +395 -0
  195. data/lib/prawn/table/cell/in_table.rb +27 -0
  196. data/lib/prawn/table/cell/subtable.rb +65 -0
  197. data/lib/prawn/table/cell/text.rb +135 -0
  198. data/lib/prawn/table/cells.rb +206 -0
  199. data/lib/prawn/text.rb +449 -0
  200. data/lib/prawn/text/box.rb +397 -0
  201. data/lib/prawn/text/formatted.rb +4 -0
  202. data/lib/prawn/text/formatted/box.rb +222 -0
  203. data/lib/prawn/text/formatted/fragment.rb +181 -0
  204. data/lib/prawn/text/formatted/parser.rb +213 -0
  205. data/prawn.gemspec +28 -0
  206. data/spec/annotations_spec.rb +90 -0
  207. data/spec/bounding_box_spec.rb +190 -0
  208. data/spec/cell_spec.rb +430 -0
  209. data/spec/destinations_spec.rb +15 -0
  210. data/spec/document_spec.rb +476 -0
  211. data/spec/extensions/mocha.rb +32 -0
  212. data/spec/font_spec.rb +324 -0
  213. data/spec/formatted_text_arranger_spec.rb +426 -0
  214. data/spec/formatted_text_box_spec.rb +756 -0
  215. data/spec/formatted_text_fragment_spec.rb +211 -0
  216. data/spec/graphics_spec.rb +446 -0
  217. data/spec/grid_spec.rb +85 -0
  218. data/spec/images_spec.rb +119 -0
  219. data/spec/inline_formatted_text_parser_spec.rb +502 -0
  220. data/spec/jpg_spec.rb +25 -0
  221. data/spec/line_wrap_spec.rb +341 -0
  222. data/spec/measurement_units_spec.rb +23 -0
  223. data/spec/name_tree_spec.rb +112 -0
  224. data/spec/object_store_spec.rb +160 -0
  225. data/spec/outline_spec.rb +404 -0
  226. data/spec/pdf_object_spec.rb +170 -0
  227. data/spec/png_spec.rb +237 -0
  228. data/spec/reference_spec.rb +82 -0
  229. data/spec/repeater_spec.rb +96 -0
  230. data/spec/security_spec.rb +120 -0
  231. data/spec/snapshot_spec.rb +154 -0
  232. data/spec/span_spec.rb +49 -0
  233. data/spec/spec_helper.rb +34 -0
  234. data/spec/stamp_spec.rb +108 -0
  235. data/spec/stroke_styles_spec.rb +163 -0
  236. data/spec/table_spec.rb +687 -0
  237. data/spec/template_spec.rb +165 -0
  238. data/spec/text_at_spec.rb +125 -0
  239. data/spec/text_box_spec.rb +777 -0
  240. data/spec/text_spacing_spec.rb +75 -0
  241. data/spec/text_spec.rb +349 -0
  242. data/spec/text_with_inline_formatting_spec.rb +193 -0
  243. data/spec/transparency_spec.rb +89 -0
  244. data/vendor/pdf-inspector/README +18 -0
  245. data/vendor/pdf-inspector/lib/pdf/inspector.rb +26 -0
  246. data/vendor/pdf-inspector/lib/pdf/inspector/extgstate.rb +18 -0
  247. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +131 -0
  248. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +25 -0
  249. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +46 -0
  250. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
  251. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  252. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  253. data/vendor/ttfunk/example.rb +45 -0
  254. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  255. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  256. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  257. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  258. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  259. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  260. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  261. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  262. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +50 -0
  263. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  264. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  265. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +55 -0
  266. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  267. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  268. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  269. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  270. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  271. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
  272. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  273. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  274. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  275. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  276. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  277. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  278. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  279. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  280. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  281. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  282. data/vendor/ttfunk/lib/ttfunk/table/name.rb +125 -0
  283. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  284. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  285. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  286. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  287. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  288. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  289. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  290. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  291. metadata +379 -0
@@ -0,0 +1,756 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ describe "Text::Formatted::Box#extensions" do
6
+ it "should be able to override default line wrapping" do
7
+ create_pdf
8
+ Prawn::Text::Formatted::Box.extensions << TestFormattedWrapOverride
9
+ @pdf.formatted_text_box([{ :text => "hello world" }], {})
10
+ text = PDF::Inspector::Text.analyze(@pdf.render)
11
+ text.strings[0].should == "all your base are belong to us"
12
+ Prawn::Text::Formatted::Box.extensions.delete(TestFormattedWrapOverride)
13
+ end
14
+ it "overriding Text::Box line wrapping should not affect " +
15
+ "Text::Formatted::Box wrapping" do
16
+ create_pdf
17
+ Prawn::Text::Box.extensions << TestWrapOverride
18
+ @pdf.formatted_text_box([{ :text => "hello world" }], {})
19
+ text = PDF::Inspector::Text.analyze(@pdf.render)
20
+ text.strings[0].should == "hello world"
21
+ Prawn::Text::Box.extensions.delete(TestWrapOverride)
22
+ end
23
+ end
24
+
25
+ describe "Text::Formatted::Box#render" do
26
+ it "should handle newlines" do
27
+ create_pdf
28
+ array = [{ :text => "hello\nworld"}]
29
+ options = { :document => @pdf }
30
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
31
+ text_box.render
32
+ text_box.text.should == "hello\nworld"
33
+ end
34
+ it "should omit spaces from the beginning of the line" do
35
+ create_pdf
36
+ array = [{ :text => " hello\n world"}]
37
+ options = { :document => @pdf }
38
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
39
+ text_box.render
40
+ text_box.text.should == "hello\nworld"
41
+ end
42
+ it "should omit spaces from the end of the line" do
43
+ create_pdf
44
+ array = [{ :text => "hello \nworld "}]
45
+ options = { :document => @pdf }
46
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
47
+ text_box.render
48
+ text_box.text.should == "hello\nworld"
49
+ end
50
+ it "should be okay printing a line of whitespace" do
51
+ create_pdf
52
+ array = [{ :text => "hello\n \nworld "}]
53
+ options = { :document => @pdf }
54
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
55
+ text_box.render
56
+ text_box.text.should == "hello\n\nworld"
57
+ end
58
+ end
59
+
60
+ describe "Text::Formatted::Box#render with :align => :justify" do
61
+ it "should draw the word spacing to the document" do
62
+ create_pdf
63
+ array = [{ :text => "hello world " * 10}]
64
+ options = { :document => @pdf, :align => :justify }
65
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
66
+ text_box.render
67
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
68
+ contents.word_spacing[0].should.be > 0
69
+ end
70
+ end
71
+
72
+ describe "Text::Formatted::Box#height without leading" do
73
+ it "should equal the sum of the height of each line" do
74
+ create_pdf
75
+ format_array = [{ :text => "line 1" },
76
+ { :text => "\n" },
77
+ { :text => "line 2" }]
78
+ options = { :document => @pdf }
79
+ text_box = Prawn::Text::Formatted::Box.new(format_array, options)
80
+ text_box.render
81
+ text_box.height.should == @pdf.font.height * 2
82
+ end
83
+ end
84
+
85
+ describe "Text::Formatted::Box#height with leading" do
86
+ it "should equal the sum of the height of each line" +
87
+ " plus all but the last leading" do
88
+ create_pdf
89
+ format_array = [{ :text => "line 1" },
90
+ { :text => "\n" },
91
+ { :text => "line 2" }]
92
+ leading = 12
93
+ options = { :document => @pdf, :leading => leading }
94
+ text_box = Prawn::Text::Formatted::Box.new(format_array, options)
95
+ text_box.render
96
+ text_box.height.should == @pdf.font.height * 2 + leading
97
+ end
98
+ end
99
+
100
+ describe "Text::Formatted::Box#render(:single_line => true)" do
101
+ it "should draw only one line to the page" do
102
+ create_pdf
103
+ text = "Oh hai text rect. " * 10
104
+ format_array = [:text => text]
105
+ options = { :document => @pdf,
106
+ :single_line => true }
107
+ text_box = Prawn::Text::Formatted::Box.new(format_array, options)
108
+ text_box.render
109
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
110
+ contents.strings.length.should == 1
111
+ end
112
+ end
113
+
114
+ describe "Text::Formatted::Box#render(:dry_run => true)" do
115
+ it "should not draw any content to the page" do
116
+ create_pdf
117
+ text = "Oh hai text rect. " * 10
118
+ format_array = [:text => text]
119
+ options = { :document => @pdf }
120
+ text_box = Prawn::Text::Formatted::Box.new(format_array, options)
121
+ text_box.render(:dry_run => true)
122
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
123
+ contents.strings.should.be.empty
124
+ end
125
+ it "subsequent calls to render should not raise an ArgumentError exception" do
126
+ create_pdf
127
+ text = "™©"
128
+ format_array = [:text => text]
129
+ options = { :document => @pdf }
130
+ text_box = Prawn::Text::Formatted::Box.new(format_array, options)
131
+ text_box.render(:dry_run => true)
132
+ lambda { text_box.render }.should.not.raise(ArgumentError)
133
+ end
134
+ end
135
+
136
+ describe "Text::Formatted::Box#render" do
137
+ it "should be able to perform fragment callbacks" do
138
+ create_pdf
139
+ callback_object = TestFragmentCallback.new("something", 7,
140
+ :document => @pdf)
141
+ callback_object.expects(:render_behind).with(
142
+ kind_of(Prawn::Text::Formatted::Fragment))
143
+ callback_object.expects(:render_in_front).with(
144
+ kind_of(Prawn::Text::Formatted::Fragment))
145
+ array = [{ :text => "hello world " },
146
+ { :text => "callback now",
147
+ :callback => callback_object }]
148
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
149
+ text_box.render
150
+ end
151
+ it "should be able to perform fragment callbacks on multiple objects" do
152
+ create_pdf
153
+
154
+ callback_object = TestFragmentCallback.new("something", 7,
155
+ :document => @pdf)
156
+ callback_object.expects(:render_behind).with(
157
+ kind_of(Prawn::Text::Formatted::Fragment))
158
+ callback_object.expects(:render_in_front).with(
159
+ kind_of(Prawn::Text::Formatted::Fragment))
160
+
161
+ callback_object2 = TestFragmentCallback.new("something else", 14,
162
+ :document => @pdf)
163
+ callback_object2.expects(:render_behind).with(
164
+ kind_of(Prawn::Text::Formatted::Fragment))
165
+ callback_object2.expects(:render_in_front).with(
166
+ kind_of(Prawn::Text::Formatted::Fragment))
167
+
168
+ array = [{ :text => "hello world " },
169
+ { :text => "callback now",
170
+ :callback => [callback_object, callback_object2] }]
171
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
172
+ text_box.render
173
+ end
174
+ it "fragment callbacks should be able to define only the callback they need" do
175
+ create_pdf
176
+ behind = TestFragmentCallbackBehind.new("something", 7,
177
+ :document => @pdf)
178
+ in_front = TestFragmentCallbackInFront.new("something", 7,
179
+ :document => @pdf)
180
+ array = [{ :text => "hello world " },
181
+ { :text => "callback now",
182
+ :callback => [behind, in_front] }]
183
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
184
+ lambda { text_box.render }.should.not.raise(NoMethodError)
185
+ end
186
+ it "should be able to set the font" do
187
+ create_pdf
188
+ array = [{ :text => "this contains " },
189
+ { :text => "Times-Bold",
190
+ :styles => [:bold],
191
+ :font => "Times-Roman" },
192
+ { :text => " text" }]
193
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
194
+ text_box.render
195
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
196
+ fonts = contents.font_settings.map { |e| e[:name] }
197
+ fonts.should == [:Helvetica, :"Times-Bold", :Helvetica]
198
+ contents.strings[0].should == "this contains "
199
+ contents.strings[1].should == "Times-Bold"
200
+ contents.strings[2].should == " text"
201
+ end
202
+ it "should be able to set bold" do
203
+ create_pdf
204
+ array = [{ :text => "this contains " },
205
+ { :text => "bold", :styles => [:bold] },
206
+ { :text => " text" }]
207
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
208
+ text_box.render
209
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
210
+ fonts = contents.font_settings.map { |e| e[:name] }
211
+ fonts.should == [:Helvetica, :"Helvetica-Bold", :Helvetica]
212
+ contents.strings[0].should == "this contains "
213
+ contents.strings[1].should == "bold"
214
+ contents.strings[2].should == " text"
215
+ end
216
+ it "should be able to set italics" do
217
+ create_pdf
218
+ array = [{ :text => "this contains " },
219
+ { :text => "italic", :styles => [:italic] },
220
+ { :text => " text" }]
221
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
222
+ text_box.render
223
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
224
+ fonts = contents.font_settings.map { |e| e[:name] }
225
+ fonts.should == [:Helvetica, :"Helvetica-Oblique", :Helvetica]
226
+ end
227
+ it "should be able to set subscript" do
228
+ create_pdf
229
+ array = [{ :text => "this contains " },
230
+ { :text => "subscript", :styles => [:subscript] },
231
+ { :text => " text" }]
232
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
233
+ text_box.render
234
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
235
+ contents.font_settings[0][:size].should == 12
236
+ contents.font_settings[1][:size].should.be.close(12 * 0.583, 0.0001)
237
+ end
238
+ it "should be able to set superscript" do
239
+ create_pdf
240
+ array = [{ :text => "this contains " },
241
+ { :text => "superscript", :styles => [:superscript] },
242
+ { :text => " text" }]
243
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
244
+ text_box.render
245
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
246
+ contents.font_settings[0][:size].should == 12
247
+ contents.font_settings[1][:size].should.be.close(12 * 0.583, 0.0001)
248
+ end
249
+ it "should be able to set compound bold and italic text" do
250
+ create_pdf
251
+ array = [{ :text => "this contains " },
252
+ { :text => "bold italic", :styles => [:bold, :italic] },
253
+ { :text => " text" }]
254
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
255
+ text_box.render
256
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
257
+ fonts = contents.font_settings.map { |e| e[:name] }
258
+ fonts.should == [:Helvetica, :"Helvetica-BoldOblique", :Helvetica]
259
+ end
260
+ it "should be able to underline" do
261
+ create_pdf
262
+ array = [{ :text => "this contains " },
263
+ { :text => "underlined", :styles => [:underline] },
264
+ { :text => " text" }]
265
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
266
+ text_box.render
267
+ line_drawing = PDF::Inspector::Graphics::Line.analyze(@pdf.render)
268
+ line_drawing.points.length.should == 2
269
+ end
270
+ it "should be able to strikethrough" do
271
+ create_pdf
272
+ array = [{ :text => "this contains " },
273
+ { :text => "struckthrough", :styles => [:strikethrough] },
274
+ { :text => " text" }]
275
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
276
+ text_box.render
277
+ line_drawing = PDF::Inspector::Graphics::Line.analyze(@pdf.render)
278
+ line_drawing.points.length.should == 2
279
+ end
280
+ it "should be able to add URL links" do
281
+ create_pdf
282
+ @pdf.expects(:link_annotation).with(kind_of(Array), :Border => [0,0,0],
283
+ :A => { :Type => :Action, :S => :URI, :URI => "http://example.com" })
284
+ array = [{ :text => "click " },
285
+ { :text => "here", :link => "http://example.com" },
286
+ { :text => " to visit" }]
287
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
288
+ text_box.render
289
+ end
290
+ it "should be able to add destination links" do
291
+ create_pdf
292
+ @pdf.expects(:link_annotation).with(kind_of(Array), :Border => [0,0,0],
293
+ :Dest => "ToC")
294
+ array = [{ :text => "Go to the " },
295
+ { :text => "Table of Contents", :anchor => "ToC" }]
296
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
297
+ text_box.render
298
+ end
299
+ it "should be able to set font size" do
300
+ create_pdf
301
+ array = [{ :text => "this contains " },
302
+ { :text => "sized", :size => 24 },
303
+ { :text => " text" }]
304
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
305
+ text_box.render
306
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
307
+ contents.font_settings[0][:size].should == 12
308
+ contents.font_settings[1][:size].should == 24
309
+ end
310
+ it "should set the baseline based on the tallest fragment on a given line" do
311
+ create_pdf
312
+ array = [{ :text => "this contains " },
313
+ { :text => "sized", :size => 24 },
314
+ { :text => " text" }]
315
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
316
+ text_box.render
317
+ @pdf.font_size(24) do
318
+ text_box.height.should.be.close(@pdf.font.height, 0.001)
319
+ end
320
+ end
321
+ it "should be able to set color via an rgb hex string" do
322
+ create_pdf
323
+ array = [{ :text => "rgb",
324
+ :color => "ff0000" }]
325
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
326
+ text_box.render
327
+ colors = PDF::Inspector::Graphics::Color.analyze(@pdf.render)
328
+ colors.fill_color_count.should == 3
329
+ colors.stroke_color_count.should == 3
330
+ end
331
+ it "should be able to set color using a cmyk array" do
332
+ create_pdf
333
+ array = [{ :text => "cmyk",
334
+ :color => [100, 0, 0, 0] }]
335
+ text_box = Prawn::Text::Formatted::Box.new(array, :document => @pdf)
336
+ text_box.render
337
+ colors = PDF::Inspector::Graphics::Color.analyze(@pdf.render)
338
+ colors.fill_color_count.should == 3
339
+ colors.stroke_color_count.should == 3
340
+ end
341
+ end
342
+
343
+ describe "Text::Formatted::Box with text than can fit in the box" do
344
+ before(:each) do
345
+ create_pdf
346
+ @text = "Oh hai text rect. " * 10
347
+ @format_array = [:text => @text]
348
+ @options = {
349
+ :width => 162.0,
350
+ :height => 162.0,
351
+ :document => @pdf
352
+ }
353
+ end
354
+
355
+ it "printed text should match requested text, except for trailing or" +
356
+ " leading white space and that spaces may be replaced by newlines" do
357
+ text_box = Prawn::Text::Formatted::Box.new(@format_array, @options)
358
+ text_box.render
359
+ text_box.text.gsub("\n", " ").should == @text.strip
360
+ end
361
+
362
+ it "render should return an empty array because no text remains unprinted" do
363
+ text_box = Prawn::Text::Formatted::Box.new(@format_array, @options)
364
+ text_box.render.should == []
365
+ end
366
+
367
+ it "should be truncated when the leading is set high enough to prevent all" +
368
+ " the lines from being printed" do
369
+ @options[:leading] = 40
370
+ text_box = Prawn::Text::Formatted::Box.new(@format_array, @options)
371
+ text_box.render
372
+ text_box.text.gsub("\n", " ").should.not == @text.strip
373
+ end
374
+ end
375
+
376
+ describe "Text::Formatted::Box printing UTF-8 string with higher bit characters with" +
377
+ " inline styling" do
378
+ before(:each) do
379
+ create_pdf
380
+ @text = "©"
381
+ format_array = [:text => @text]
382
+ # not enough height to print any text, so we can directly compare against
383
+ # the input string
384
+ bounding_height = 1.0
385
+ options = {
386
+ :height => bounding_height,
387
+ :document => @pdf
388
+ }
389
+ @text_box = Prawn::Text::Formatted::Box.new(format_array, options)
390
+ end
391
+ describe "when using a TTF font" do
392
+ before(:each) do
393
+ file = "#{Prawn::BASEDIR}/data/fonts/Action Man.dfont"
394
+ @pdf.font_families["Action Man"] = {
395
+ :normal => { :file => file, :font => "ActionMan" },
396
+ :italic => { :file => file, :font => "ActionMan-Italic" },
397
+ :bold => { :file => file, :font => "ActionMan-Bold" },
398
+ :bold_italic => { :file => file, :font => "ActionMan-BoldItalic" }
399
+ }
400
+ end
401
+ it "unprinted text should be in UTF-8 encoding" do
402
+ @pdf.font("Action Man")
403
+ remaining_text = @text_box.render
404
+ remaining_text.first[:text].should == @text
405
+ end
406
+ it "subsequent calls to Text::Formatted::Box need not include the" +
407
+ " :skip_encoding => true option" do
408
+ @pdf.font("Action Man")
409
+ remaining_text = @text_box.render
410
+ lambda {
411
+ @pdf.formatted_text_box(remaining_text, :document => @pdf)
412
+ }.should.not.raise(ArgumentError)
413
+ end
414
+ end
415
+ describe "when using an AFM font" do
416
+ it "unprinted text should be in WinAnsi encoding" do
417
+ remaining_text = @text_box.render
418
+ remaining_text.first[:text].should == @pdf.font.normalize_encoding(@text)
419
+ end
420
+ it "subsequent calls to Text::Formatted::Box must include the" +
421
+ " :skip_encoding => true option" do
422
+ remaining_text = @text_box.render
423
+ lambda {
424
+ @pdf.formatted_text_box(remaining_text, :document => @pdf)
425
+ }.should.raise(ArgumentError)
426
+ lambda {
427
+ @pdf.formatted_text_box(remaining_text, :document => @pdf,
428
+ :skip_encoding => true)
429
+ }.should.not.raise(ArgumentError)
430
+ end
431
+ end
432
+ end
433
+
434
+
435
+ describe "Text::Formatted::Box with more text than can fit in the box" do
436
+ before(:each) do
437
+ create_pdf
438
+ @text = "Oh hai text rect. " * 30
439
+ @format_array = [:text => @text]
440
+ @bounding_height = 162.0
441
+ @options = {
442
+ :width => 162.0,
443
+ :height => @bounding_height,
444
+ :document => @pdf
445
+ }
446
+ end
447
+
448
+ context "truncated overflow" do
449
+ before(:each) do
450
+ @options[:overflow] = :truncate
451
+ @text_box = Prawn::Text::Formatted::Box.new(@format_array, @options)
452
+ end
453
+ it "should be truncated" do
454
+ @text_box.render
455
+ @text_box.text.gsub("\n", " ").should.not == @text.strip
456
+ end
457
+ it "render should not return an empty string because some text remains" +
458
+ " unprinted" do
459
+ @text_box.render.should.not == ""
460
+ end
461
+ it "#height should be no taller than the specified height" do
462
+ @text_box.render
463
+ @text_box.height.should.be <= @bounding_height
464
+ end
465
+ it "#height should be within one font height of the specified height" do
466
+ @text_box.render
467
+ @text_box.height.should.be.close(@bounding_height, @pdf.font.height)
468
+ end
469
+ end
470
+
471
+ context "ellipses overflow" do
472
+ it "should raise NotImplementedError" do
473
+ @options[:overflow] = :ellipses
474
+ lambda {
475
+ Prawn::Text::Formatted::Box.new(@format_array, @options)
476
+ }.should.raise(NotImplementedError)
477
+ end
478
+ end
479
+
480
+ context "expand overflow" do
481
+ before(:each) do
482
+ @options[:overflow] = :expand
483
+ @text_box = Prawn::Text::Formatted::Box.new(@format_array, @options)
484
+ end
485
+ it "height should expand to encompass all the text (but not exceed the" +
486
+ "height of the page)" do
487
+ @text_box.render
488
+ @text_box.height.should > @bounding_height
489
+ end
490
+ it "should display the entire string (as long as there was space" +
491
+ " remaining on the page to print all the text)" do
492
+ @text_box.render
493
+ @text_box.text.gsub("\n", " ").should == @text.strip
494
+ end
495
+ it "render should return an empty array because no text remains" +
496
+ " unprinted(as long as there was space remaining on the page to" +
497
+ " print all the text)" do
498
+ @text_box.render.should == []
499
+ end
500
+ end
501
+
502
+ context "shrink_to_fit overflow" do
503
+ before(:each) do
504
+ @options[:overflow] = :shrink_to_fit
505
+ @options[:min_font_size] = 2
506
+ @text_box = Prawn::Text::Formatted::Box.new(@format_array, @options)
507
+ end
508
+ it "should display the entire text" do
509
+ @text_box.render
510
+ @text_box.text.gsub("\n", " ").should == @text.strip
511
+ end
512
+ it "render should return an empty array because no text" +
513
+ " remains unprinted" do
514
+ @text_box.render.should == []
515
+ end
516
+ end
517
+ end
518
+
519
+ describe "Text::Formatted::Box#render with box level :character_spacing option" do
520
+ it "should draw the character spacing to the document only one time" do
521
+ create_pdf
522
+ array = [{ :text => "hello world" }]
523
+ options = { :document => @pdf,
524
+ :character_spacing => 7 }
525
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
526
+ text_box.render
527
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
528
+ contents.character_spacing[0].should == 7
529
+ contents.character_spacing.length.should == 2
530
+ end
531
+ it "should draw the character spacing to the document" do
532
+ create_pdf
533
+ array = [{ :text => "hello world",
534
+ :font => "Courier" }]
535
+ options = { :document => @pdf,
536
+ :width => 100,
537
+ :overflow => :expand,
538
+ :character_spacing => 10 }
539
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
540
+ text_box.render
541
+ text_box.text.should == "hello\nworld"
542
+ end
543
+ end
544
+
545
+ describe "Text::Formatted::Box#render with fragment level :character_spacing option" do
546
+ it "should draw the character spacing to the document" do
547
+ create_pdf
548
+ array = [{ :text => "hello world",
549
+ :character_spacing => 7 }]
550
+ options = { :document => @pdf }
551
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
552
+ text_box.render
553
+ contents = PDF::Inspector::Text.analyze(@pdf.render)
554
+ contents.character_spacing[0].should == 7
555
+ end
556
+ it "should draw the character spacing to the document" do
557
+ create_pdf
558
+ array = [{ :text => "hello world",
559
+ :font => "Courier",
560
+ :character_spacing => 10 }]
561
+ options = { :document => @pdf,
562
+ :width => 100,
563
+ :overflow => :expand }
564
+ text_box = Prawn::Text::Formatted::Box.new(array, options)
565
+ text_box.render
566
+ text_box.text.should == "hello\nworld"
567
+ end
568
+ end
569
+
570
+ describe "Text::Formatted::Box wrapping" do
571
+ before(:each) do
572
+ create_pdf
573
+ end
574
+
575
+ it "should wrap text" do
576
+ text = "Please wrap this text about HERE. More text that should be wrapped"
577
+ format_array = [:text => text]
578
+ expect = "Please wrap this text about\nHERE. " +
579
+ "More text that should be\nwrapped"
580
+
581
+ @pdf.font "Courier"
582
+ text_box = Prawn::Text::Formatted::Box.new(format_array,
583
+ :width => 220,
584
+ :overflow => :expand,
585
+ :document => @pdf)
586
+ text_box.render
587
+ text_box.text.should == expect
588
+ end
589
+
590
+ it "should respect end of line when wrapping text" do
591
+ text = "Please wrap only before\nTHIS word. Don't wrap this"
592
+ format_array = [:text => text]
593
+ expect = text
594
+
595
+ @pdf.font "Courier"
596
+ text_box = Prawn::Text::Formatted::Box.new(format_array,
597
+ :width => 220,
598
+ :overflow => :expand,
599
+ :document => @pdf)
600
+ text_box.render
601
+ text_box.text.should == expect
602
+ end
603
+
604
+ it "should respect multiple newlines when wrapping text" do
605
+ text = "Please wrap only before THIS\n\nword. Don't wrap this"
606
+ format_array = [:text => text]
607
+ expect= "Please wrap only before\nTHIS\n\nword. Don't wrap this"
608
+
609
+ @pdf.font "Courier"
610
+ text_box = Prawn::Text::Formatted::Box.new(format_array,
611
+ :width => 200,
612
+ :overflow => :expand,
613
+ :document => @pdf)
614
+ text_box.render
615
+ text_box.text.should == expect
616
+ end
617
+
618
+ it "should respect multiple newlines when wrapping text when those newlines" +
619
+ " coincide with a line break" do
620
+ text = "Please wrap only before\n\nTHIS word. Don't wrap this"
621
+ format_array = [:text => text]
622
+ expect = text
623
+
624
+ @pdf.font "Courier"
625
+ text_box = Prawn::Text::Formatted::Box.new(format_array,
626
+ :width => 220,
627
+ :overflow => :expand,
628
+ :document => @pdf)
629
+ text_box.render
630
+ text_box.text.should == expect
631
+ end
632
+
633
+ it "should respect initial newlines" do
634
+ text = "\nThis should be on line 2"
635
+ format_array = [:text => text]
636
+ expect = text
637
+
638
+ @pdf.font "Courier"
639
+ text_box = Prawn::Text::Formatted::Box.new(format_array,
640
+ :width => 220,
641
+ :overflow => :expand,
642
+ :document => @pdf)
643
+ text_box.render
644
+ text_box.text.should == expect
645
+ end
646
+
647
+ it "should wrap lines comprised of a single word of the bounds when" +
648
+ " wrapping text" do
649
+ text = "You_can_wrap_this_text_HERE"
650
+ format_array = [:text => text]
651
+ expect = "You_can_wrap_this_text_HE\nRE"
652
+
653
+ @pdf.font "Courier"
654
+ text_box = Prawn::Text::Formatted::Box.new(format_array,
655
+ :width => 180,
656
+ :overflow => :expand,
657
+ :document => @pdf)
658
+ text_box.render
659
+ text_box.text.should == expect
660
+ end
661
+
662
+ it "should wrap lines comprised of a single word of the bounds when" +
663
+ " wrapping text" do
664
+ text = "©" * 30
665
+ format_array = [:text => text]
666
+
667
+ @pdf.font "Courier"
668
+ text_box = Prawn::Text::Formatted::Box.new(format_array, :width => 180,
669
+ :overflow => :expand,
670
+ :document => @pdf)
671
+
672
+ text_box.render
673
+
674
+ expected = "©" * 25 + "\n" + "©" * 5
675
+ @pdf.font.normalize_encoding!(expected)
676
+
677
+ text_box.text.should == expected
678
+ end
679
+
680
+ it "should wrap non-unicode strings using single-byte word-wrapping" do
681
+ text = "continúa esforzandote " * 5
682
+ format_array = [:text => text]
683
+ text_box = Prawn::Text::Formatted::Box.new(format_array, :width => 180,
684
+ :document => @pdf)
685
+ text_box.render
686
+ results_with_accent = text_box.text
687
+
688
+ text = "continua esforzandote " * 5
689
+ format_array = [:text => text]
690
+ text_box = Prawn::Text::Formatted::Box.new(format_array, :width => 180,
691
+ :document => @pdf)
692
+ text_box.render
693
+ no_accent = text_box.text
694
+
695
+ results_with_accent.first_line.length.should == no_accent.first_line.length
696
+ end
697
+
698
+ end
699
+
700
+ def reduce_precision(float)
701
+ ("%.5f" % float).to_f
702
+ end
703
+
704
+ class TestFragmentCallback
705
+ def initialize(string, number, options)
706
+ @document = options[:document]
707
+ end
708
+
709
+ def render_behind(fragment)
710
+ end
711
+
712
+ def render_in_front(fragment)
713
+ end
714
+ end
715
+
716
+ class TestFragmentCallbackBehind
717
+ def initialize(string, number, options)
718
+ @document = options[:document]
719
+ end
720
+
721
+ def render_behind(fragment)
722
+ end
723
+ end
724
+
725
+ class TestFragmentCallbackInFront
726
+ def initialize(string, number, options)
727
+ @document = options[:document]
728
+ end
729
+
730
+ def render_in_front(fragment)
731
+ end
732
+ end
733
+
734
+ module TestFormattedWrapOverride
735
+ def wrap(string)
736
+ @text = nil
737
+ @line_height = @document.font.height
738
+ @descender = @document.font.descender
739
+ @ascender = @document.font.ascender
740
+ @baseline_y = -@ascender
741
+ draw_line("all your base are belong to us")
742
+ []
743
+ end
744
+ end
745
+
746
+ module TestWrapOverride
747
+ def wrap(string)
748
+ @text = nil
749
+ @line_height = @document.font.height
750
+ @descender = @document.font.descender
751
+ @ascender = @document.font.ascender
752
+ @baseline_y = -@ascender
753
+ draw_line("all your base are belong to us")
754
+ ""
755
+ end
756
+ end