alphasights-prawn 0.10.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 (244) 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/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/examples/bounding_box/bounding_boxes.rb +43 -0
  66. data/examples/bounding_box/indentation.rb +34 -0
  67. data/examples/bounding_box/russian_boxes.rb +36 -0
  68. data/examples/bounding_box/stretched_nesting.rb +67 -0
  69. data/examples/builder/simple.rb +28 -0
  70. data/examples/example_helper.rb +4 -0
  71. data/examples/general/background.rb +23 -0
  72. data/examples/general/canvas.rb +15 -0
  73. data/examples/general/context_sensitive_headers.rb +37 -0
  74. data/examples/general/float.rb +11 -0
  75. data/examples/general/margin.rb +36 -0
  76. data/examples/general/measurement_units.rb +51 -0
  77. data/examples/general/metadata-info.rb +16 -0
  78. data/examples/general/multi_page_layout.rb +18 -0
  79. data/examples/general/outlines.rb +50 -0
  80. data/examples/general/page_geometry.rb +31 -0
  81. data/examples/general/page_numbering.rb +15 -0
  82. data/examples/general/repeaters.rb +47 -0
  83. data/examples/general/stamp.rb +41 -0
  84. data/examples/general/templates.rb +13 -0
  85. data/examples/graphics/basic_images.rb +23 -0
  86. data/examples/graphics/chunkable.rb +38 -0
  87. data/examples/graphics/cmyk.rb +12 -0
  88. data/examples/graphics/curves.rb +11 -0
  89. data/examples/graphics/hexagon.rb +13 -0
  90. data/examples/graphics/image_fit.rb +15 -0
  91. data/examples/graphics/image_flow.rb +37 -0
  92. data/examples/graphics/image_position.rb +17 -0
  93. data/examples/graphics/line.rb +32 -0
  94. data/examples/graphics/png_types.rb +22 -0
  95. data/examples/graphics/polygons.rb +16 -0
  96. data/examples/graphics/remote_images.rb +12 -0
  97. data/examples/graphics/rounded_polygons.rb +19 -0
  98. data/examples/graphics/rounded_rectangle.rb +20 -0
  99. data/examples/graphics/ruport_style_helpers.rb +19 -0
  100. data/examples/graphics/stroke_bounds.rb +20 -0
  101. data/examples/graphics/stroke_cap_and_join.rb +45 -0
  102. data/examples/graphics/stroke_dash.rb +42 -0
  103. data/examples/graphics/transformations.rb +52 -0
  104. data/examples/graphics/transparency.rb +26 -0
  105. data/examples/m17n/chinese_text_wrapping.rb +17 -0
  106. data/examples/m17n/euro.rb +15 -0
  107. data/examples/m17n/sjis.rb +28 -0
  108. data/examples/m17n/utf8.rb +13 -0
  109. data/examples/m17n/win_ansi_charset.rb +54 -0
  110. data/examples/security/hello_foo.rb +8 -0
  111. data/examples/table/bill.rb +53 -0
  112. data/examples/table/cell.rb +12 -0
  113. data/examples/table/checkerboard.rb +22 -0
  114. data/examples/table/header.rb +14 -0
  115. data/examples/table/inline_format_table.rb +12 -0
  116. data/examples/table/multi_page_table.rb +9 -0
  117. data/examples/table/simple_table.rb +24 -0
  118. data/examples/table/subtable.rb +12 -0
  119. data/examples/table/widths.rb +20 -0
  120. data/examples/text/alignment.rb +18 -0
  121. data/examples/text/character_spacing.rb +12 -0
  122. data/examples/text/dfont.rb +48 -0
  123. data/examples/text/family_based_styling.rb +24 -0
  124. data/examples/text/font_calculations.rb +91 -0
  125. data/examples/text/font_size.rb +33 -0
  126. data/examples/text/hyphenation.rb +45 -0
  127. data/examples/text/indent_paragraphs.rb +22 -0
  128. data/examples/text/inline_format.rb +103 -0
  129. data/examples/text/kerning.rb +30 -0
  130. data/examples/text/rotated.rb +98 -0
  131. data/examples/text/shaped_text_box.rb +31 -0
  132. data/examples/text/simple_text.rb +17 -0
  133. data/examples/text/simple_text_ttf.rb +17 -0
  134. data/examples/text/text_box.rb +88 -0
  135. data/examples/text/text_box_returning_excess.rb +51 -0
  136. data/examples/text/text_flow.rb +67 -0
  137. data/lib/prawn.rb +27 -0
  138. data/lib/prawn/canvas.rb +119 -0
  139. data/lib/prawn/chunkable.rb +37 -0
  140. data/lib/prawn/compatibility.rb +51 -0
  141. data/lib/prawn/core.rb +85 -0
  142. data/lib/prawn/core/annotations.rb +61 -0
  143. data/lib/prawn/core/byte_string.rb +9 -0
  144. data/lib/prawn/core/chunk.rb +36 -0
  145. data/lib/prawn/core/destinations.rb +90 -0
  146. data/lib/prawn/core/document_state.rb +78 -0
  147. data/lib/prawn/core/literal_string.rb +16 -0
  148. data/lib/prawn/core/name_tree.rb +165 -0
  149. data/lib/prawn/core/object_store.rb +236 -0
  150. data/lib/prawn/core/page.rb +179 -0
  151. data/lib/prawn/core/pdf_object.rb +108 -0
  152. data/lib/prawn/core/reference.rb +112 -0
  153. data/lib/prawn/core/text.rb +140 -0
  154. data/lib/prawn/core/text/formatted/arranger.rb +266 -0
  155. data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
  156. data/lib/prawn/core/text/formatted/wrap.rb +112 -0
  157. data/lib/prawn/core/text/line_wrap.rb +209 -0
  158. data/lib/prawn/core/text/wrap.rb +80 -0
  159. data/lib/prawn/document.rb +573 -0
  160. data/lib/prawn/document/bounding_box.rb +425 -0
  161. data/lib/prawn/document/graphics_state.rb +48 -0
  162. data/lib/prawn/document/internals.rb +170 -0
  163. data/lib/prawn/document/page_geometry.rb +136 -0
  164. data/lib/prawn/document/snapshot.rb +87 -0
  165. data/lib/prawn/document_builder.rb +51 -0
  166. data/lib/prawn/document_builder/command.rb +38 -0
  167. data/lib/prawn/document_builder/constructs.rb +2 -0
  168. data/lib/prawn/document_builder/constructs/flowing_text_construct.rb +18 -0
  169. data/lib/prawn/document_builder/constructs/path_construct.rb +9 -0
  170. data/lib/prawn/document_builder/layout.rb +25 -0
  171. data/lib/prawn/document_builder/modifications.rb +2 -0
  172. data/lib/prawn/document_builder/modifications/layout_modification.rb +9 -0
  173. data/lib/prawn/document_builder/modifications/path_modification.rb +9 -0
  174. data/lib/prawn/encoding.rb +121 -0
  175. data/lib/prawn/errors.rb +94 -0
  176. data/lib/prawn/font.rb +341 -0
  177. data/lib/prawn/font/afm.rb +225 -0
  178. data/lib/prawn/font/dfont.rb +42 -0
  179. data/lib/prawn/font/ttf.rb +350 -0
  180. data/lib/prawn/graphics.rb +325 -0
  181. data/lib/prawn/graphics/cap_style.rb +38 -0
  182. data/lib/prawn/graphics/color.rb +205 -0
  183. data/lib/prawn/graphics/dash.rb +71 -0
  184. data/lib/prawn/graphics/join_style.rb +38 -0
  185. data/lib/prawn/graphics/transformation.rb +156 -0
  186. data/lib/prawn/graphics/transparency.rb +99 -0
  187. data/lib/prawn/images.rb +348 -0
  188. data/lib/prawn/images/jpg.rb +46 -0
  189. data/lib/prawn/images/png.rb +226 -0
  190. data/lib/prawn/measurement_extensions.rb +46 -0
  191. data/lib/prawn/measurements.rb +71 -0
  192. data/lib/prawn/outline.rb +278 -0
  193. data/lib/prawn/repeater.rb +129 -0
  194. data/lib/prawn/security.rb +262 -0
  195. data/lib/prawn/security/arcfour.rb +51 -0
  196. data/lib/prawn/stamp.rb +126 -0
  197. data/lib/prawn/table.rb +421 -0
  198. data/lib/prawn/table/accessors.rb +180 -0
  199. data/lib/prawn/table/cell.rb +350 -0
  200. data/lib/prawn/table/cell/in_table.rb +27 -0
  201. data/lib/prawn/table/cell/subtable.rb +65 -0
  202. data/lib/prawn/table/cell/text.rb +125 -0
  203. data/lib/prawn/text.rb +449 -0
  204. data/lib/prawn/text/box.rb +392 -0
  205. data/lib/prawn/text/formatted.rb +4 -0
  206. data/lib/prawn/text/formatted/box.rb +228 -0
  207. data/lib/prawn/text/formatted/fragment.rb +181 -0
  208. data/lib/prawn/text/formatted/parser.rb +213 -0
  209. data/spec/annotations_spec.rb +90 -0
  210. data/spec/bounding_box_spec.rb +190 -0
  211. data/spec/cell_spec.rb +348 -0
  212. data/spec/destinations_spec.rb +15 -0
  213. data/spec/document_spec.rb +473 -0
  214. data/spec/font_spec.rb +324 -0
  215. data/spec/formatted_text_arranger_spec.rb +426 -0
  216. data/spec/formatted_text_box_spec.rb +756 -0
  217. data/spec/formatted_text_fragment_spec.rb +211 -0
  218. data/spec/graphics_spec.rb +446 -0
  219. data/spec/images_spec.rb +96 -0
  220. data/spec/inline_formatted_text_parser_spec.rb +502 -0
  221. data/spec/jpg_spec.rb +25 -0
  222. data/spec/line_wrap_spec.rb +341 -0
  223. data/spec/measurement_units_spec.rb +23 -0
  224. data/spec/name_tree_spec.rb +112 -0
  225. data/spec/object_store_spec.rb +160 -0
  226. data/spec/outline_spec.rb +269 -0
  227. data/spec/pdf_object_spec.rb +170 -0
  228. data/spec/png_spec.rb +237 -0
  229. data/spec/reference_spec.rb +82 -0
  230. data/spec/repeater_spec.rb +96 -0
  231. data/spec/security_spec.rb +120 -0
  232. data/spec/snapshot_spec.rb +138 -0
  233. data/spec/spec_helper.rb +26 -0
  234. data/spec/stamp_spec.rb +108 -0
  235. data/spec/stroke_styles_spec.rb +163 -0
  236. data/spec/table_spec.rb +598 -0
  237. data/spec/template_spec.rb +158 -0
  238. data/spec/text_at_spec.rb +119 -0
  239. data/spec/text_box_spec.rb +742 -0
  240. data/spec/text_spacing_spec.rb +75 -0
  241. data/spec/text_spec.rb +333 -0
  242. data/spec/text_with_inline_formatting_spec.rb +193 -0
  243. data/spec/transparency_spec.rb +89 -0
  244. metadata +331 -0
@@ -0,0 +1,324 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+ require 'iconv'
5
+
6
+ describe "Font behavior" do
7
+
8
+ it "should default to Helvetica if no font is specified" do
9
+ @pdf = Prawn::Document.new
10
+ @pdf.font.name.should == "Helvetica"
11
+ end
12
+
13
+ end
14
+
15
+ describe "#width_of" do
16
+ it "should take character spacing into account" do
17
+ create_pdf
18
+ original_width = @pdf.width_of("hello world")
19
+ @pdf.character_spacing(7) do
20
+ @pdf.width_of("hello world").should == original_width + 11 * 7
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#font_size" do
26
+ it "should allow setting font size in DSL style" do
27
+ create_pdf
28
+ @pdf.font_size 20
29
+ @pdf.font_size.should == 20
30
+ end
31
+ end
32
+
33
+ describe "font style support" do
34
+ before(:each) { create_pdf }
35
+
36
+ it "should complain if there is no @current_page" do
37
+ pdf_without_page = Prawn::Document.new(:skip_page_creation => true)
38
+
39
+ lambda{ pdf_without_page.font "Helvetica" }.
40
+ should.raise(Prawn::Errors::NotOnPage)
41
+ end
42
+
43
+ it "should allow specifying font style by style name and font family" do
44
+ @pdf.font "Courier", :style => :bold
45
+ @pdf.text "In Courier bold"
46
+
47
+ @pdf.font "Courier", :style => :bold_italic
48
+ @pdf.text "In Courier bold-italic"
49
+
50
+ @pdf.font "Courier", :style => :italic
51
+ @pdf.text "In Courier italic"
52
+
53
+ @pdf.font "Courier", :style => :normal
54
+ @pdf.text "In Normal Courier"
55
+
56
+ @pdf.font "Helvetica"
57
+ @pdf.text "In Normal Helvetica"
58
+
59
+ text = PDF::Inspector::Text.analyze(@pdf.render)
60
+ text.font_settings.map { |e| e[:name] }.should ==
61
+ [:"Courier-Bold", :"Courier-BoldOblique", :"Courier-Oblique",
62
+ :Courier, :Helvetica]
63
+ end
64
+
65
+ it "should allow font familes to be defined in a single dfont" do
66
+ file = "#{Prawn::BASEDIR}/data/fonts/Action Man.dfont"
67
+ @pdf.font_families["Action Man"] = {
68
+ :normal => { :file => file, :font => "ActionMan" },
69
+ :italic => { :file => file, :font => "ActionMan-Italic" },
70
+ :bold => { :file => file, :font => "ActionMan-Bold" },
71
+ :bold_italic => { :file => file, :font => "ActionMan-BoldItalic" }
72
+ }
73
+
74
+ @pdf.font "Action Man", :style => :italic
75
+ @pdf.text "In ActionMan-Italic"
76
+
77
+ text = PDF::Inspector::Text.analyze(@pdf.render)
78
+ name = text.font_settings.map { |e| e[:name] }.first.to_s
79
+ name = name.sub(/\w+\+/, "subset+")
80
+ name.should == "subset+ActionMan-Italic"
81
+ end
82
+ end
83
+
84
+ describe "Transactional font handling" do
85
+ before(:each) { create_pdf }
86
+
87
+ it "should allow setting of size directly when font is created" do
88
+ @pdf.font "Courier", :size => 16
89
+ @pdf.font_size.should == 16
90
+ end
91
+
92
+ it "should allow temporary setting of a new font using a transaction" do
93
+ @pdf.font "Helvetica", :size => 12
94
+
95
+ @pdf.font "Courier", :size => 16 do
96
+ @pdf.font.name.should == "Courier"
97
+ @pdf.font_size.should == 16
98
+ end
99
+
100
+ @pdf.font.name.should == "Helvetica"
101
+ @pdf.font_size.should == 12
102
+ end
103
+
104
+ it "should mask font size when using a transacation" do
105
+ @pdf.font "Courier", :size => 16 do
106
+ @pdf.font_size.should == 16
107
+ end
108
+
109
+ @pdf.font "Times-Roman"
110
+ @pdf.font "Courier"
111
+
112
+ @pdf.font_size.should == 12
113
+ end
114
+
115
+ end
116
+
117
+ describe "Document#page_fonts" do
118
+ before(:each) { create_pdf }
119
+
120
+ it "should register fonts properly by page" do
121
+ @pdf.font "Courier"; @pdf.text("hello")
122
+ @pdf.font "Helvetica"; @pdf.text("hello")
123
+ @pdf.font "Times-Roman"; @pdf.text("hello")
124
+ ["Courier","Helvetica","Times-Roman"].each { |f|
125
+ page_should_include_font(f)
126
+ }
127
+
128
+ @pdf.start_new_page
129
+ @pdf.font "Helvetica"; @pdf.text("hello")
130
+ page_should_include_font("Helvetica")
131
+ page_should_not_include_font("Courier")
132
+ page_should_not_include_font("Times-Roman")
133
+ end
134
+
135
+ def page_includes_font?(font)
136
+ @pdf.page.fonts.values.map { |e| e.data[:BaseFont] }.include?(font.to_sym)
137
+ end
138
+
139
+ def page_should_include_font(font)
140
+ assert_block("Expected page to include font: #{font}") do
141
+ page_includes_font?(font)
142
+ end
143
+ end
144
+
145
+ def page_should_not_include_font(font)
146
+ assert_block("Did not expect page to include font: #{font}") do
147
+ not page_includes_font?(font)
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ describe "AFM fonts" do
154
+
155
+ setup do
156
+ create_pdf
157
+ @times = @pdf.find_font "Times-Roman"
158
+ @iconv = ::Iconv.new('Windows-1252', 'utf-8')
159
+ end
160
+
161
+ it "should calculate string width taking into account accented characters" do
162
+ @times.compute_width_of(@iconv.iconv("é"), :size => 12).should == @times.compute_width_of("e", :size => 12)
163
+ end
164
+
165
+ it "should calculate string width taking into account kerning pairs" do
166
+ @times.compute_width_of(@iconv.iconv("To"), :size => 12).should == 13.332
167
+ @times.compute_width_of(@iconv.iconv("To"), :size => 12, :kerning => true).should == 12.372
168
+ @times.compute_width_of(@iconv.iconv("Tö"), :size => 12, :kerning => true).should == 12.372
169
+ end
170
+
171
+ it "should encode text without kerning by default" do
172
+ @times.encode_text(@iconv.iconv("To")).should == [[0, "To"]]
173
+ @times.encode_text(@iconv.iconv("Télé")).should == [[0, @iconv.iconv("Télé")]]
174
+ @times.encode_text(@iconv.iconv("Technology")).should == [[0, "Technology"]]
175
+ @times.encode_text(@iconv.iconv("Technology...")).should == [[0, "Technology..."]]
176
+ end
177
+
178
+ it "should encode text with kerning if requested" do
179
+ @times.encode_text(@iconv.iconv("To"), :kerning => true).should == [[0, ["T", 80, "o"]]]
180
+ @times.encode_text(@iconv.iconv("Télé"), :kerning => true).should == [[0, ["T", 70, @iconv.iconv("élé")]]]
181
+ @times.encode_text(@iconv.iconv("Technology"), :kerning => true).should == [[0, ["T", 70, "echnology"]]]
182
+ @times.encode_text(@iconv.iconv("Technology..."), :kerning => true).should == [[0, ["T", 70, "echnology", 65, "..."]]]
183
+ end
184
+
185
+ describe "when normalizing encoding" do
186
+
187
+ it "should not modify the original string when normalize_encoding() is used" do
188
+ original = "Foo"
189
+ normalized = @times.normalize_encoding(original)
190
+ assert ! original.equal?(normalized)
191
+ end
192
+
193
+ it "should modify the original string when normalize_encoding!() is used" do
194
+ original = "Foo"
195
+ normalized = @times.normalize_encoding!(original)
196
+ assert original.equal?(normalized)
197
+ end
198
+
199
+ end
200
+
201
+ it "should omit /Encoding for symbolic fonts" do
202
+ zapf = @pdf.find_font "ZapfDingbats"
203
+ font_dict = zapf.send(:register, nil)
204
+ font_dict.data[:Encoding].should == nil
205
+ end
206
+
207
+ end
208
+
209
+ describe "TTF fonts" do
210
+
211
+ setup do
212
+ create_pdf
213
+ @activa = @pdf.find_font "#{Prawn::BASEDIR}/data/fonts/Activa.ttf"
214
+ end
215
+
216
+ it "should calculate string width taking into account accented characters" do
217
+ @activa.compute_width_of("é", :size => 12).should == @activa.compute_width_of("e", :size => 12)
218
+ end
219
+
220
+ it "should calculate string width taking into account kerning pairs" do
221
+ @activa.compute_width_of("To", :size => 12).should == 15.228
222
+ @activa.compute_width_of("To", :size => 12, :kerning => true).should == 12.996
223
+ end
224
+
225
+ it "should encode text without kerning by default" do
226
+ @activa.encode_text("To").should == [[0, "To"]]
227
+ @activa.encode_text("Télé").should == [[0, "T\216l\216"]]
228
+ @activa.encode_text("Technology").should == [[0, "Technology"]]
229
+ @activa.encode_text("Technology...").should == [[0, "Technology..."]]
230
+ @activa.encode_text("Teχnology...").should == [[0, "Te"], [1, "!"], [0, "nology..."]]
231
+ end
232
+
233
+ it "should encode text with kerning if requested" do
234
+ @activa.encode_text("To", :kerning => true).should == [[0, ["T", 186.0, "o"]]]
235
+ @activa.encode_text("To", :kerning => true).should == [[0, ["T", 186.0, "o"]]]
236
+ @activa.encode_text("Technology", :kerning => true).should == [[0, ["T", 186.0, "echnology"]]]
237
+ @activa.encode_text("Technology...", :kerning => true).should == [[0, ["T", 186.0, "echnology", 88.0, "..."]]]
238
+ @activa.encode_text("Teχnology...", :kerning => true).should == [[0, ["T", 186.0, "e"]], [1, "!"], [0, ["nology", 88.0, "..."]]]
239
+ end
240
+
241
+ describe "when normalizing encoding" do
242
+
243
+ it "should not modify the original string when normalize_encoding() is used" do
244
+ original = "Foo"
245
+ normalized = @activa.normalize_encoding(original)
246
+ assert ! original.equal?(normalized)
247
+ end
248
+
249
+ it "should modify the original string when normalize_encoding!() is used" do
250
+ original = "Foo"
251
+ normalized = @activa.normalize_encoding!(original)
252
+ assert original.equal?(normalized)
253
+ end
254
+
255
+ end
256
+
257
+ describe "when used with snapshots or transactions" do
258
+
259
+ it "should allow TTF fonts to be used alongside document transactions" do
260
+ lambda {
261
+ Prawn::Document.new do
262
+ font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
263
+ text "Hi there"
264
+ transaction { text "Nice, thank you" }
265
+ end
266
+ }.should.not.raise
267
+ end
268
+
269
+ it "should allow TTF fonts to be used inside transactions" do
270
+ pdf = Prawn::Document.new do
271
+ transaction do
272
+ font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
273
+ text "Hi there"
274
+ end
275
+ end
276
+
277
+ text = PDF::Inspector::Text.analyze(pdf.render)
278
+ name = text.font_settings.map { |e| e[:name] }.first.to_s
279
+ name = name.sub(/\w+\+/, "subset+")
280
+ name.should == "subset+DejaVuSans"
281
+ end
282
+
283
+ end
284
+
285
+ end
286
+
287
+ describe "DFont fonts" do
288
+ setup do
289
+ create_pdf
290
+ @file = "#{Prawn::BASEDIR}/data/fonts/Action Man.dfont"
291
+ end
292
+
293
+ it "should list all named fonts" do
294
+ list = Prawn::Font::DFont.named_fonts(@file)
295
+ list.sort.should == %w(ActionMan ActionMan-Italic ActionMan-Bold ActionMan-BoldItalic).sort
296
+ end
297
+
298
+ it "should count the number of fonts in the file" do
299
+ Prawn::Font::DFont.font_count(@file).should == 4
300
+ end
301
+
302
+ it "should default selected font to the first one if not specified" do
303
+ font = @pdf.find_font(@file)
304
+ font.basename.should == "ActionMan"
305
+ end
306
+
307
+ it "should allow font to be selected by index" do
308
+ font = @pdf.find_font(@file, :font => 2)
309
+ font.basename.should == "ActionMan-Italic"
310
+ end
311
+
312
+ it "should allow font to be selected by name" do
313
+ font = @pdf.find_font(@file, :font => "ActionMan-BoldItalic")
314
+ font.basename.should == "ActionMan-BoldItalic"
315
+ end
316
+
317
+ it "should cache font object based on selected font" do
318
+ f1 = @pdf.find_font(@file, :font => "ActionMan")
319
+ f2 = @pdf.find_font(@file, :font => "ActionMan-Bold")
320
+ assert_not_equal f1.object_id, f2.object_id
321
+ assert_equal f1.object_id, @pdf.find_font(@file, :font => "ActionMan").object_id
322
+ assert_equal f2.object_id, @pdf.find_font(@file, :font => "ActionMan-Bold").object_id
323
+ end
324
+ end
@@ -0,0 +1,426 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
+
5
+ describe "Core::Text::Formatted::Arranger#format_array" do
6
+ it "should populate unconsumed array" do
7
+ create_pdf
8
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
9
+ array = [{ :text => "hello " },
10
+ { :text => "world how ", :styles => [:bold] },
11
+ { :text => "are", :styles => [:bold, :italic] },
12
+ { :text => " you?" }]
13
+ arranger.format_array = array
14
+ arranger.unconsumed[0].should == { :text => "hello " }
15
+ arranger.unconsumed[1].should == { :text => "world how ",
16
+ :styles => [:bold] }
17
+ arranger.unconsumed[2].should == { :text => "are",
18
+ :styles => [:bold, :italic] }
19
+ arranger.unconsumed[3].should == { :text => " you?" }
20
+ end
21
+ it "should split newlines into their own elements" do
22
+ create_pdf
23
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
24
+ array = [{ :text => "\nhello\nworld" }]
25
+ arranger.format_array = array
26
+ arranger.unconsumed[0].should == { :text => "\n" }
27
+ arranger.unconsumed[1].should == { :text => "hello" }
28
+ arranger.unconsumed[2].should == { :text => "\n" }
29
+ arranger.unconsumed[3].should == { :text => "world" }
30
+ end
31
+ end
32
+ describe "Core::Text::Formatted::Arranger#preview_next_string" do
33
+ it "should not populate the consumed array" do
34
+ create_pdf
35
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
36
+ array = [{ :text => "hello" }]
37
+ arranger.format_array = array
38
+ arranger.preview_next_string
39
+ arranger.consumed.should == []
40
+ end
41
+ it "should not consumed array" do
42
+ create_pdf
43
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
44
+ array = [{ :text => "hello" }]
45
+ arranger.format_array = array
46
+ arranger.preview_next_string.should == "hello"
47
+ end
48
+ end
49
+ describe "Core::Text::Formatted::Arranger#next_string" do
50
+ before(:each) do
51
+ create_pdf
52
+ @arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
53
+ array = [{ :text => "hello " },
54
+ { :text => "world how ", :styles => [:bold] },
55
+ { :text => "are", :styles => [:bold, :italic] },
56
+ { :text => " you?" }]
57
+ @arranger.format_array = array
58
+ end
59
+ it "should raise an error if called after a line was finalized and" +
60
+ " before a new line was initialized" do
61
+ @arranger.finalize_line
62
+ lambda do
63
+ @arranger.next_string
64
+ end.should.raise(RuntimeError)
65
+ end
66
+ it "should populate consumed array" do
67
+ while string = @arranger.next_string
68
+ end
69
+ @arranger.consumed[0].should == { :text => "hello " }
70
+ @arranger.consumed[1].should == { :text => "world how ",
71
+ :styles => [:bold] }
72
+ @arranger.consumed[2].should == { :text => "are",
73
+ :styles => [:bold, :italic] }
74
+ @arranger.consumed[3].should == { :text => " you?" }
75
+ end
76
+ it "should populate current_format_state array" do
77
+ create_pdf
78
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
79
+ array = [{ :text => "hello " },
80
+ { :text => "world how ", :styles => [:bold] },
81
+ { :text => "are", :styles => [:bold, :italic] },
82
+ { :text => " you?" }]
83
+ arranger.format_array = array
84
+ counter = 0
85
+ while string = arranger.next_string
86
+ case counter
87
+ when 0
88
+ arranger.current_format_state.should == { }
89
+ when 1
90
+ arranger.current_format_state.should == { :styles => [:bold] }
91
+ when 2
92
+ arranger.current_format_state.should == { :styles => [:bold, :italic] }
93
+ when 3
94
+ arranger.current_format_state.should == { }
95
+ end
96
+ counter += 1
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "Core::Text::Formatted::Arranger#retrieve_fragment" do
102
+ it "should raise an error if called before finalize_line was called" do
103
+ create_pdf
104
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
105
+ array = [{ :text => "hello " },
106
+ { :text => "world how ", :styles => [:bold] },
107
+ { :text => "are", :styles => [:bold, :italic] },
108
+ { :text => " you?" }]
109
+ arranger.format_array = array
110
+ while string = arranger.next_string
111
+ end
112
+ lambda do
113
+ arranger.retrieve_fragment
114
+ end.should.raise(RuntimeError)
115
+ end
116
+ it "should return the consumed fragments in order of consumption" +
117
+ " and update" do
118
+ create_pdf
119
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
120
+ array = [{ :text => "hello " },
121
+ { :text => "world how ", :styles => [:bold] },
122
+ { :text => "are", :styles => [:bold, :italic] },
123
+ { :text => " you?" }]
124
+ arranger.format_array = array
125
+ while string = arranger.next_string
126
+ end
127
+ arranger.finalize_line
128
+ arranger.retrieve_fragment.text.should == "hello "
129
+ arranger.retrieve_fragment.text.should == "world how "
130
+ arranger.retrieve_fragment.text.should == "are"
131
+ arranger.retrieve_fragment.text.should == " you?"
132
+ end
133
+ it "should never return a fragment whose text is an empty string" do
134
+ create_pdf
135
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
136
+ array = [{ :text => "hello\nworld\n\n\nhow are you?" },
137
+ { :text => "\n" },
138
+ { :text => "\n" },
139
+ { :text => "\n" },
140
+ { :text => "" },
141
+ { :text => "fine, thanks." },
142
+ { :text => "" },
143
+ { :text => "\n" },
144
+ { :text => "" }]
145
+ arranger.format_array = array
146
+ while string = arranger.next_string
147
+ end
148
+ arranger.finalize_line
149
+ while fragment = arranger.retrieve_fragment
150
+ fragment.text.should.not.be.empty
151
+ end
152
+ end
153
+ it "should not alter the current font style" do
154
+ create_pdf
155
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
156
+ array = [{ :text => "hello " },
157
+ { :text => "world how ", :styles => [:bold] },
158
+ { :text => "are", :styles => [:bold, :italic] },
159
+ { :text => " you?" }]
160
+ arranger.format_array = array
161
+ while string = arranger.next_string
162
+ end
163
+ arranger.finalize_line
164
+ arranger.retrieve_fragment
165
+ arranger.current_format_state[:styles].should.be.nil
166
+ end
167
+ end
168
+
169
+ describe "Core::Text::Formatted::Arranger#update_last_string" do
170
+ it "should update the last retrieved string with what actually fit on" +
171
+ "the line and the list of unconsumed with what did not" do
172
+ create_pdf
173
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
174
+ array = [{ :text => "hello " },
175
+ { :text => "world how ", :styles => [:bold] },
176
+ { :text => "are", :styles => [:bold, :italic] },
177
+ { :text => " you now?", :styles => [:bold, :italic] }]
178
+ arranger.format_array = array
179
+ while string = arranger.next_string
180
+ end
181
+ arranger.update_last_string(" you", " now?")
182
+ arranger.consumed[3].should == { :text => " you",
183
+ :styles => [:bold, :italic] }
184
+ arranger.unconsumed.should == [{ :text => " now?",
185
+ :styles => [:bold, :italic] }]
186
+ end
187
+ context "when the entire string was used" do
188
+ it "should not push empty string onto unconsumed" do
189
+ create_pdf
190
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
191
+ array = [{ :text => "hello " },
192
+ { :text => "world how ", :styles => [:bold] },
193
+ { :text => "are", :styles => [:bold, :italic] },
194
+ { :text => " you now?" }]
195
+ arranger.format_array = array
196
+ while string = arranger.next_string
197
+ end
198
+ arranger.update_last_string(" you now?", "")
199
+ arranger.unconsumed.should == []
200
+ end
201
+ end
202
+ end
203
+ describe "Core::Text::Formatted::Arranger#space_count" do
204
+ before(:each) do
205
+ create_pdf
206
+ @arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
207
+ array = [{ :text => "hello " },
208
+ { :text => "world how ", :styles => [:bold] },
209
+ { :text => "are", :styles => [:bold, :italic] },
210
+ { :text => " you?" }]
211
+ @arranger.format_array = array
212
+ while string = @arranger.next_string
213
+ end
214
+ end
215
+ it "should raise an error if called before finalize_line was called" do
216
+ lambda do
217
+ @arranger.space_count
218
+ end.should.raise(RuntimeError)
219
+ end
220
+ it "should return the total number of spaces in all fragments" do
221
+ @arranger.finalize_line
222
+ @arranger.space_count.should == 4
223
+ end
224
+ end
225
+ describe "Core::Text::Formatted::Arranger#finalize_line" do
226
+ it "should make it so the last consumed fragment ends with non-white-space" do
227
+ create_pdf
228
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
229
+ array = [{ :text => "hello " },
230
+ { :text => "world how ", :styles => [:bold] },
231
+ { :text => " ", :styles => [:bold, :italic] }]
232
+ arranger.format_array = array
233
+ while string = arranger.next_string
234
+ end
235
+ arranger.finalize_line
236
+ arranger.fragments.length.should == 2
237
+ arranger.retrieve_fragment.text
238
+ arranger.retrieve_fragment.text.should == "world how"
239
+ end
240
+ end
241
+
242
+ describe "Core::Text::Formatted::Arranger#line_width" do
243
+ before(:each) do
244
+ create_pdf
245
+ @arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
246
+ array = [{ :text => "hello " },
247
+ { :text => "world", :styles => [:bold] }]
248
+ @arranger.format_array = array
249
+ while string = @arranger.next_string
250
+ end
251
+ end
252
+ it "should raise an error if called before finalize_line was called" do
253
+ lambda do
254
+ @arranger.line_width
255
+ end.should.raise(RuntimeError)
256
+ end
257
+ it "should return the width of the complete line" do
258
+ @arranger.finalize_line
259
+ @arranger.line_width.should.be > 0
260
+ end
261
+ end
262
+
263
+ describe "Core::Text::Formatted::Arranger#line_width with character_spacing > 0" do
264
+ it "should return a width greater than a line without a character_spacing" do
265
+ create_pdf
266
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
267
+
268
+ array = [{ :text => "hello " },
269
+ { :text => "world", :styles => [:bold] }]
270
+ arranger.format_array = array
271
+ while string = arranger.next_string
272
+ end
273
+ arranger.finalize_line
274
+
275
+ base_line_width = arranger.line_width
276
+
277
+
278
+ array = [{ :text => "hello " },
279
+ { :text => "world", :styles => [:bold],
280
+ :character_spacing => 7}]
281
+ arranger.format_array = array
282
+ while string = arranger.next_string
283
+ end
284
+ arranger.finalize_line
285
+ arranger.line_width.should.be > base_line_width
286
+ end
287
+ end
288
+
289
+ describe "Core::Text::Formatted::Arranger#line" do
290
+ before(:each) do
291
+ create_pdf
292
+ @arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
293
+ array = [{ :text => "hello " },
294
+ { :text => "world", :styles => [:bold] }]
295
+ @arranger.format_array = array
296
+ while string = @arranger.next_string
297
+ end
298
+ end
299
+ it "should raise an error if called before finalize_line was called" do
300
+ lambda do
301
+ @arranger.line
302
+ end.should.raise(RuntimeError)
303
+ end
304
+ it "should return the complete line" do
305
+ @arranger.finalize_line
306
+ @arranger.line.should == "hello world"
307
+ end
308
+ end
309
+
310
+ describe "Core::Text::Formatted::Arranger#unconsumed" do
311
+ it "should return the original array if nothing was consumed" do
312
+ create_pdf
313
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
314
+ array = [{ :text => "hello " },
315
+ { :text => "world how ", :styles => [:bold] },
316
+ { :text => "are", :styles => [:bold, :italic] },
317
+ { :text => " you now?" }]
318
+ arranger.format_array = array
319
+ arranger.unconsumed.should == array
320
+ end
321
+ it "should return an empty array if everything was consumed" do
322
+ create_pdf
323
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
324
+ array = [{ :text => "hello " },
325
+ { :text => "world how ", :styles => [:bold] },
326
+ { :text => "are", :styles => [:bold, :italic] },
327
+ { :text => " you now?" }]
328
+ arranger.format_array = array
329
+ while string = arranger.next_string
330
+ end
331
+ arranger.unconsumed.should == []
332
+ end
333
+ end
334
+
335
+ describe "Core::Text::Formatted::Arranger#finished" do
336
+ it "should be false if anything was not printed" do
337
+ create_pdf
338
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
339
+ array = [{ :text => "hello " },
340
+ { :text => "world how ", :styles => [:bold] },
341
+ { :text => "are", :styles => [:bold, :italic] },
342
+ { :text => " you now?" }]
343
+ arranger.format_array = array
344
+ while string = arranger.next_string
345
+ end
346
+ arranger.update_last_string(" you", "now?")
347
+ arranger.should.not.be.finished
348
+ end
349
+ it "should be false if everything was printed" do
350
+ create_pdf
351
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
352
+ array = [{ :text => "hello " },
353
+ { :text => "world how ", :styles => [:bold] },
354
+ { :text => "are", :styles => [:bold, :italic] },
355
+ { :text => " you now?" }]
356
+ arranger.format_array = array
357
+ while string = arranger.next_string
358
+ end
359
+ arranger.should.be.finished
360
+ end
361
+ end
362
+
363
+ describe "Core::Text::Formatted::Arranger#unfinished" do
364
+ it "should be false if anything was not printed" do
365
+ create_pdf
366
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
367
+ array = [{ :text => "hello " },
368
+ { :text => "world how ", :styles => [:bold] },
369
+ { :text => "are", :styles => [:bold, :italic] },
370
+ { :text => " you now?" }]
371
+ arranger.format_array = array
372
+ while string = arranger.next_string
373
+ end
374
+ arranger.update_last_string(" you", "now?")
375
+ arranger.should.be.unfinished
376
+ end
377
+ it "should be false if everything was printed" do
378
+ create_pdf
379
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
380
+ array = [{ :text => "hello " },
381
+ { :text => "world how ", :styles => [:bold] },
382
+ { :text => "are", :styles => [:bold, :italic] },
383
+ { :text => " you now?" }]
384
+ arranger.format_array = array
385
+ while string = arranger.next_string
386
+ end
387
+ arranger.should.not.be.unfinished
388
+ end
389
+ end
390
+
391
+ describe "Core::Text::Formatted::Arranger.max_line_height" do
392
+ it "should be the height of the maximum consumed fragment" do
393
+ create_pdf
394
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
395
+ array = [{ :text => "hello " },
396
+ { :text => "world how ", :styles => [:bold] },
397
+ { :text => "are", :styles => [:bold, :italic] },
398
+ { :text => " you now?" }]
399
+ arranger.format_array = array
400
+ while string = arranger.next_string
401
+ end
402
+ arranger.update_last_string(" you", "now?")
403
+ arranger.should.be.unfinished
404
+ end
405
+ end
406
+
407
+ describe "Core::Text::Formatted::Arranger#repack_unretrieved" do
408
+ it "should restore part of the original string" do
409
+ create_pdf
410
+ arranger = Prawn::Core::Text::Formatted::Arranger.new(@pdf)
411
+ array = [{ :text => "hello " },
412
+ { :text => "world how ", :styles => [:bold] },
413
+ { :text => "are", :styles => [:bold, :italic] },
414
+ { :text => " you now?" }]
415
+ arranger.format_array = array
416
+ while string = arranger.next_string
417
+ end
418
+ arranger.finalize_line
419
+ arranger.retrieve_fragment
420
+ arranger.retrieve_fragment
421
+ arranger.repack_unretrieved
422
+ arranger.unconsumed.should == [
423
+ { :text => "are", :styles => [:bold, :italic] },
424
+ { :text => " you now?" }]
425
+ end
426
+ end