prawn 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/prawn/document/bounding_box.rb +213 -141
  4. data/lib/prawn/document/column_box.rb +61 -26
  5. data/lib/prawn/document/internals.rb +25 -16
  6. data/lib/prawn/document/span.rb +20 -18
  7. data/lib/prawn/document.rb +257 -171
  8. data/lib/prawn/encoding.rb +2 -5
  9. data/lib/prawn/errors.rb +23 -34
  10. data/lib/prawn/font.rb +248 -135
  11. data/lib/prawn/font_metric_cache.rb +11 -10
  12. data/lib/prawn/fonts/afm.rb +85 -45
  13. data/lib/prawn/fonts/dfont.rb +7 -1
  14. data/lib/prawn/fonts/otf.rb +4 -1
  15. data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  16. data/lib/prawn/fonts/ttc.rb +7 -2
  17. data/lib/prawn/fonts/ttf.rb +305 -93
  18. data/lib/prawn/fonts.rb +14 -0
  19. data/lib/prawn/graphics/blend_mode.rb +25 -28
  20. data/lib/prawn/graphics/cap_style.rb +9 -12
  21. data/lib/prawn/graphics/color.rb +57 -34
  22. data/lib/prawn/graphics/dash.rb +45 -42
  23. data/lib/prawn/graphics/join_style.rb +17 -11
  24. data/lib/prawn/graphics/patterns.rb +190 -69
  25. data/lib/prawn/graphics/transformation.rb +48 -41
  26. data/lib/prawn/graphics/transparency.rb +16 -40
  27. data/lib/prawn/graphics.rb +363 -253
  28. data/lib/prawn/grid.rb +184 -57
  29. data/lib/prawn/image_handler.rb +27 -10
  30. data/lib/prawn/images/image.rb +8 -10
  31. data/lib/prawn/images/jpg.rb +42 -19
  32. data/lib/prawn/images/png.rb +92 -41
  33. data/lib/prawn/images.rb +44 -57
  34. data/lib/prawn/measurement_extensions.rb +39 -8
  35. data/lib/prawn/measurements.rb +60 -5
  36. data/lib/prawn/outline.rb +114 -108
  37. data/lib/prawn/repeater.rb +51 -35
  38. data/lib/prawn/security/arcfour.rb +4 -4
  39. data/lib/prawn/security.rb +75 -70
  40. data/lib/prawn/soft_mask.rb +42 -30
  41. data/lib/prawn/stamp.rb +38 -42
  42. data/lib/prawn/text/box.rb +146 -96
  43. data/lib/prawn/text/formatted/arranger.rb +87 -26
  44. data/lib/prawn/text/formatted/box.rb +221 -150
  45. data/lib/prawn/text/formatted/fragment.rb +130 -14
  46. data/lib/prawn/text/formatted/line_wrap.rb +33 -24
  47. data/lib/prawn/text/formatted/parser.rb +112 -72
  48. data/lib/prawn/text/formatted/wrap.rb +12 -17
  49. data/lib/prawn/text/formatted.rb +75 -0
  50. data/lib/prawn/text.rb +441 -196
  51. data/lib/prawn/transformation_stack.rb +29 -10
  52. data/lib/prawn/utilities.rb +13 -13
  53. data/lib/prawn/version.rb +2 -1
  54. data/lib/prawn/view.rb +68 -53
  55. data/lib/prawn.rb +23 -18
  56. data.tar.gz.sig +0 -0
  57. metadata +54 -177
  58. metadata.gz.sig +0 -0
  59. data/.yardopts +0 -10
  60. data/Gemfile +0 -5
  61. data/Rakefile +0 -25
  62. data/manual/absolute_position.pdf +0 -0
  63. data/manual/basic_concepts/adding_pages.rb +0 -26
  64. data/manual/basic_concepts/basic_concepts.rb +0 -43
  65. data/manual/basic_concepts/creation.rb +0 -38
  66. data/manual/basic_concepts/cursor.rb +0 -32
  67. data/manual/basic_concepts/measurement.rb +0 -24
  68. data/manual/basic_concepts/origin.rb +0 -37
  69. data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
  70. data/manual/basic_concepts/view.rb +0 -48
  71. data/manual/bounding_box/bounding_box.rb +0 -41
  72. data/manual/bounding_box/bounds.rb +0 -48
  73. data/manual/bounding_box/canvas.rb +0 -23
  74. data/manual/bounding_box/creation.rb +0 -22
  75. data/manual/bounding_box/indentation.rb +0 -45
  76. data/manual/bounding_box/nesting.rb +0 -52
  77. data/manual/bounding_box/russian_boxes.rb +0 -40
  78. data/manual/bounding_box/stretchy.rb +0 -29
  79. data/manual/contents.rb +0 -35
  80. data/manual/cover.rb +0 -43
  81. data/manual/document_and_page_options/background.rb +0 -29
  82. data/manual/document_and_page_options/document_and_page_options.rb +0 -34
  83. data/manual/document_and_page_options/metadata.rb +0 -25
  84. data/manual/document_and_page_options/page_margins.rb +0 -36
  85. data/manual/document_and_page_options/page_size.rb +0 -34
  86. data/manual/document_and_page_options/print_scaling.rb +0 -23
  87. data/manual/example_helper.rb +0 -8
  88. data/manual/graphics/blend_mode.rb +0 -52
  89. data/manual/graphics/circle_and_ellipse.rb +0 -21
  90. data/manual/graphics/color.rb +0 -22
  91. data/manual/graphics/common_lines.rb +0 -29
  92. data/manual/graphics/fill_and_stroke.rb +0 -41
  93. data/manual/graphics/fill_rules.rb +0 -38
  94. data/manual/graphics/gradients.rb +0 -43
  95. data/manual/graphics/graphics.rb +0 -64
  96. data/manual/graphics/helper.rb +0 -34
  97. data/manual/graphics/line_width.rb +0 -36
  98. data/manual/graphics/lines_and_curves.rb +0 -40
  99. data/manual/graphics/polygon.rb +0 -27
  100. data/manual/graphics/rectangle.rb +0 -20
  101. data/manual/graphics/rotate.rb +0 -25
  102. data/manual/graphics/scale.rb +0 -42
  103. data/manual/graphics/soft_masks.rb +0 -44
  104. data/manual/graphics/stroke_cap.rb +0 -30
  105. data/manual/graphics/stroke_dash.rb +0 -47
  106. data/manual/graphics/stroke_join.rb +0 -29
  107. data/manual/graphics/translate.rb +0 -29
  108. data/manual/graphics/transparency.rb +0 -33
  109. data/manual/how_to_read_this_manual.rb +0 -39
  110. data/manual/images/absolute_position.rb +0 -22
  111. data/manual/images/fit.rb +0 -20
  112. data/manual/images/horizontal.rb +0 -24
  113. data/manual/images/images.rb +0 -41
  114. data/manual/images/plain_image.rb +0 -17
  115. data/manual/images/scale.rb +0 -21
  116. data/manual/images/vertical.rb +0 -30
  117. data/manual/images/width_and_height.rb +0 -24
  118. data/manual/layout/boxes.rb +0 -26
  119. data/manual/layout/content.rb +0 -24
  120. data/manual/layout/layout.rb +0 -27
  121. data/manual/layout/simple_grid.rb +0 -22
  122. data/manual/outline/add_subsection_to.rb +0 -60
  123. data/manual/outline/insert_section_after.rb +0 -46
  124. data/manual/outline/outline.rb +0 -33
  125. data/manual/outline/sections_and_pages.rb +0 -66
  126. data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
  127. data/manual/repeatable_content/page_numbering.rb +0 -55
  128. data/manual/repeatable_content/repeatable_content.rb +0 -35
  129. data/manual/repeatable_content/repeater.rb +0 -54
  130. data/manual/repeatable_content/stamp.rb +0 -40
  131. data/manual/security/encryption.rb +0 -28
  132. data/manual/security/permissions.rb +0 -43
  133. data/manual/security/security.rb +0 -28
  134. data/manual/table.rb +0 -16
  135. data/manual/text/alignment.rb +0 -43
  136. data/manual/text/color.rb +0 -24
  137. data/manual/text/column_box.rb +0 -30
  138. data/manual/text/fallback_fonts.rb +0 -41
  139. data/manual/text/font.rb +0 -40
  140. data/manual/text/font_size.rb +0 -44
  141. data/manual/text/font_style.rb +0 -25
  142. data/manual/text/formatted_callbacks.rb +0 -70
  143. data/manual/text/formatted_text.rb +0 -61
  144. data/manual/text/free_flowing_text.rb +0 -50
  145. data/manual/text/inline.rb +0 -40
  146. data/manual/text/kerning_and_character_spacing.rb +0 -38
  147. data/manual/text/leading.rb +0 -24
  148. data/manual/text/line_wrapping.rb +0 -60
  149. data/manual/text/paragraph_indentation.rb +0 -31
  150. data/manual/text/positioned_text.rb +0 -37
  151. data/manual/text/registering_families.rb +0 -51
  152. data/manual/text/rendering_and_color.rb +0 -36
  153. data/manual/text/right_to_left_text.rb +0 -54
  154. data/manual/text/rotation.rb +0 -52
  155. data/manual/text/single_usage.rb +0 -36
  156. data/manual/text/text.rb +0 -75
  157. data/manual/text/text_box_excess.rb +0 -35
  158. data/manual/text/text_box_extensions.rb +0 -48
  159. data/manual/text/text_box_overflow.rb +0 -51
  160. data/manual/text/utf8.rb +0 -27
  161. data/manual/text/win_ansi_charset.rb +0 -62
  162. data/prawn.gemspec +0 -51
  163. data/spec/data/curves.pdf +0 -66
  164. data/spec/extensions/encoding_helpers.rb +0 -11
  165. data/spec/prawn/document/bounding_box_spec.rb +0 -550
  166. data/spec/prawn/document/column_box_spec.rb +0 -75
  167. data/spec/prawn/document/security_spec.rb +0 -176
  168. data/spec/prawn/document_annotations_spec.rb +0 -76
  169. data/spec/prawn/document_destinations_spec.rb +0 -15
  170. data/spec/prawn/document_grid_spec.rb +0 -99
  171. data/spec/prawn/document_reference_spec.rb +0 -27
  172. data/spec/prawn/document_span_spec.rb +0 -44
  173. data/spec/prawn/document_spec.rb +0 -805
  174. data/spec/prawn/font_metric_cache_spec.rb +0 -54
  175. data/spec/prawn/font_spec.rb +0 -544
  176. data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
  177. data/spec/prawn/graphics/transparency_spec.rb +0 -81
  178. data/spec/prawn/graphics_spec.rb +0 -872
  179. data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
  180. data/spec/prawn/image_handler_spec.rb +0 -53
  181. data/spec/prawn/images/jpg_spec.rb +0 -20
  182. data/spec/prawn/images/png_spec.rb +0 -283
  183. data/spec/prawn/images_spec.rb +0 -229
  184. data/spec/prawn/measurements_extensions_spec.rb +0 -24
  185. data/spec/prawn/outline_spec.rb +0 -512
  186. data/spec/prawn/repeater_spec.rb +0 -166
  187. data/spec/prawn/soft_mask_spec.rb +0 -74
  188. data/spec/prawn/stamp_spec.rb +0 -173
  189. data/spec/prawn/text/box_spec.rb +0 -1110
  190. data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
  191. data/spec/prawn/text/formatted/box_spec.rb +0 -849
  192. data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
  193. data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -495
  194. data/spec/prawn/text/formatted/parser_spec.rb +0 -697
  195. data/spec/prawn/text_draw_text_spec.rb +0 -150
  196. data/spec/prawn/text_rendering_mode_spec.rb +0 -48
  197. data/spec/prawn/text_spacing_spec.rb +0 -95
  198. data/spec/prawn/text_spec.rb +0 -603
  199. data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
  200. data/spec/prawn/transformation_stack_spec.rb +0 -66
  201. data/spec/prawn/view_spec.rb +0 -63
  202. data/spec/prawn_manual_spec.rb +0 -35
  203. data/spec/spec_helper.rb +0 -48
@@ -1,603 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Prawn::Text do
6
- describe 'NBSP' do
7
- it 'is defined' do
8
- expect(Prawn::Text::NBSP).to eq("\u00a0")
9
- end
10
- end
11
-
12
- describe '#height_of' do
13
- let(:pdf) { create_pdf }
14
-
15
- it 'returns the height that would be required to print a' \
16
- 'particular string of text' do
17
- original_y = pdf.y
18
- pdf.text('Foo')
19
- new_y = pdf.y
20
- expect(pdf.height_of('Foo')).to be_within(0.0001).of(original_y - new_y)
21
- end
22
-
23
- it 'omits the gap below the last descender if :final_gap => false ' \
24
- 'is given' do
25
- original_y = pdf.y
26
- pdf.text('Foo', final_gap: false)
27
- new_y = pdf.y
28
- expect(pdf.height_of('Foo', final_gap: false))
29
- .to be_within(0.0001).of(original_y - new_y)
30
- end
31
-
32
- it 'raise_errors CannotFit if a too-small width is given' do
33
- expect do
34
- pdf.height_of('text', width: 1)
35
- end.to raise_error(Prawn::Errors::CannotFit)
36
- end
37
-
38
- it 'raises NotImplementedError if :indent_paragraphs option is provided' do
39
- expect do
40
- pdf.height_of(
41
- 'hai',
42
- width: 300,
43
- indent_paragraphs: 60
44
- )
45
- end.to raise_error(NotImplementedError)
46
- end
47
-
48
- it 'does not raise Prawn::Errors::UnknownOption if :final_gap option '\
49
- 'is provided' do
50
- expect do
51
- pdf.height_of('hai', width: 300, final_gap: true)
52
- end.to_not raise_error
53
- end
54
- end
55
-
56
- describe '#text' do
57
- let(:pdf) { create_pdf }
58
-
59
- it 'does not fail when @output is nil when '\
60
- 'PDF::Core::Text::LineWrap#finalize_line is called' do
61
- # need a document with margins for these particulars to produce the
62
- # condition that was throwing the error
63
- pdf = Prawn::Document.new
64
- pdf.text 'transparency ' * 150, size: 18
65
- end
66
-
67
- it 'allows drawing empty strings to the page' do
68
- pdf.text ' '
69
- text = PDF::Inspector::Text.analyze(pdf.render)
70
- # If anything is rendered to the page, it should be whitespace.
71
- expect(text.strings).to all(match(/\A\s*\z/))
72
- end
73
-
74
- it 'ignores call when string is nil' do
75
- expect(pdf.text(nil)).to eq false
76
- end
77
-
78
- it 'correctlies render empty paragraphs' do
79
- pdf.text "text\n\ntext"
80
- text = PDF::Inspector::Text.analyze(pdf.render)
81
- expect(pdf.page_count).to eq(1)
82
- expect(text.strings.reject(&:empty?)).to eq(%w[text text])
83
- end
84
-
85
- it 'correctlies render empty paragraphs with :indent_paragraphs' do
86
- pdf.text "text\n\ntext", indent_paragraphs: 5
87
- text = PDF::Inspector::Text.analyze(pdf.render)
88
- expect(pdf.page_count).to eq(1)
89
- expect(text.strings.reject(&:empty?)).to eq(%w[text text])
90
- end
91
-
92
- it 'correctly renders strings ending with empty paragraphs and ' \
93
- ':inline_format and :indent_paragraphs' do
94
- pdf.text "text\n\n", inline_format: true, indent_paragraphs: 5
95
- text = PDF::Inspector::Text.analyze(pdf.render)
96
- expect(pdf.page_count).to eq(1)
97
- expect(text.strings).to eq(['text'])
98
- end
99
-
100
- it 'defaults to use kerning information' do
101
- pdf.text 'hello world'
102
- text = PDF::Inspector::Text.analyze(pdf.render)
103
- expect(text.kerned[0]).to eq true
104
- end
105
-
106
- it 'is able to disable kerning with an option' do
107
- pdf.text 'hello world', kerning: false
108
- text = PDF::Inspector::Text.analyze(pdf.render)
109
- expect(text.kerned[0]).to eq false
110
- end
111
-
112
- it 'is able to disable kerning document-wide' do
113
- pdf.default_kerning(false)
114
- pdf.default_kerning = false
115
- pdf.text 'hello world'
116
- text = PDF::Inspector::Text.analyze(pdf.render)
117
- expect(text.kerned[0]).to eq false
118
- end
119
-
120
- it 'option should be able to override document-wide kerning disabling' do
121
- pdf.default_kerning = false
122
- pdf.text 'hello world', kerning: true
123
- text = PDF::Inspector::Text.analyze(pdf.render)
124
- expect(text.kerned[0]).to eq true
125
- end
126
-
127
- it 'raise_errors ArgumentError if :at option included' do
128
- expect { pdf.text('hai', at: [0, 0]) }.to raise_error(ArgumentError)
129
- end
130
-
131
- it 'advances down the document based on font_height' do
132
- position = pdf.y
133
- pdf.text 'Foo'
134
-
135
- expect(pdf.y).to be_within(0.0001).of(position - pdf.font.height)
136
-
137
- position = pdf.y
138
- pdf.text "Foo\nBar\nBaz"
139
- expect(pdf.y).to be_within(0.0001).of(position - 3 * pdf.font.height)
140
- end
141
-
142
- it 'advances down the document based on font_height with size option' do
143
- position = pdf.y
144
- pdf.text 'Foo', size: 15
145
-
146
- pdf.font_size = 15
147
- expect(pdf.y).to be_within(0.0001).of(position - pdf.font.height)
148
-
149
- position = pdf.y
150
- pdf.text "Foo\nBar\nBaz"
151
- expect(pdf.y).to be_within(0.0001).of(position - 3 * pdf.font.height)
152
- end
153
-
154
- it 'advances down the document based on font_height with leading option' do
155
- position = pdf.y
156
- leading = 2
157
- pdf.text 'Foo', leading: leading
158
-
159
- expect(pdf.y).to be_within(0.0001)
160
- .of(position - pdf.font.height - leading)
161
-
162
- position = pdf.y
163
- pdf.text "Foo\nBar\nBaz"
164
- expect(pdf.y).to be_within(0.0001).of(position - 3 * pdf.font.height)
165
- end
166
-
167
- it 'advances only to the bottom of the final descender if final_gap '\
168
- 'is false' do
169
- position = pdf.y
170
- pdf.text 'Foo', final_gap: false
171
-
172
- expect(pdf.y).to be_within(0.0001)
173
- .of(position - pdf.font.ascender - pdf.font.descender)
174
-
175
- position = pdf.y
176
- pdf.text "Foo\nBar\nBaz", final_gap: false
177
- expect(pdf.y).to be_within(0.0001)
178
- .of(
179
- position - 2 * pdf.font.height - pdf.font.ascender -
180
- pdf.font.descender
181
- )
182
- end
183
-
184
- it 'is able to print text starting at the last line of a page' do
185
- pdf.move_cursor_to(pdf.font.height)
186
- pdf.text('hello world')
187
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
188
- expect(pages.size).to eq(1)
189
- end
190
-
191
- it 'defaults to 12 point helvetica' do
192
- pdf.text 'Blah'
193
- text = PDF::Inspector::Text.analyze(pdf.render)
194
- expect(text.font_settings[0][:name]).to eq(:Helvetica)
195
- expect(text.font_settings[0][:size]).to eq(12)
196
- expect(text.strings.first).to eq('Blah')
197
- end
198
-
199
- it 'allows setting font size' do
200
- pdf.text 'Blah', size: 16
201
- text = PDF::Inspector::Text.analyze(pdf.render)
202
- expect(text.font_settings[0][:size]).to eq(16)
203
- end
204
-
205
- it 'allows setting a default font size' do
206
- pdf.font_size = 16
207
- pdf.text 'Blah'
208
- text = PDF::Inspector::Text.analyze(pdf.render)
209
- expect(text.font_settings[0][:size]).to eq(16)
210
- end
211
-
212
- it 'allows overriding default font for a single instance' do
213
- pdf.font_size = 16
214
-
215
- pdf.text 'Blah', size: 11
216
- pdf.text 'Blaz'
217
- text = PDF::Inspector::Text.analyze(pdf.render)
218
- expect(text.font_settings[0][:size]).to eq(11)
219
- expect(text.font_settings[1][:size]).to eq(16)
220
- end
221
-
222
- it 'allows setting a font size transaction with a block' do
223
- pdf.font_size 16 do
224
- pdf.text 'Blah'
225
- end
226
-
227
- pdf.text 'blah'
228
-
229
- text = PDF::Inspector::Text.analyze(pdf.render)
230
- expect(text.font_settings[0][:size]).to eq(16)
231
- expect(text.font_settings[1][:size]).to eq(12)
232
- end
233
-
234
- it 'allows manual setting the font size when in a font size block' do
235
- pdf.font_size(16) do
236
- pdf.text 'Foo'
237
- pdf.text 'Blah', size: 11
238
- pdf.text 'Blaz'
239
- end
240
- text = PDF::Inspector::Text.analyze(pdf.render)
241
- expect(text.font_settings[0][:size]).to eq(16)
242
- expect(text.font_settings[1][:size]).to eq(11)
243
- expect(text.font_settings[2][:size]).to eq(16)
244
- end
245
-
246
- it 'allows registering of built-in font_settings on the fly' do
247
- pdf.font 'Times-Roman'
248
- pdf.text 'Blah'
249
- pdf.font 'Courier'
250
- pdf.text 'Blaz'
251
- text = PDF::Inspector::Text.analyze(pdf.render)
252
- expect(text.font_settings[0][:name]).to eq(:"Times-Roman")
253
- expect(text.font_settings[1][:name]).to eq(:Courier)
254
- end
255
-
256
- it 'utilises the same default font across multiple pages' do
257
- pdf.text 'Blah'
258
- pdf.start_new_page
259
- pdf.text 'Blaz'
260
- text = PDF::Inspector::Text.analyze(pdf.render)
261
-
262
- expect(text.font_settings.size).to eq(2)
263
- expect(text.font_settings[0][:name]).to eq(:Helvetica)
264
- expect(text.font_settings[1][:name]).to eq(:Helvetica)
265
- end
266
-
267
- it 'raise_errors an exception when an unknown font is used' do
268
- expect { pdf.font 'Pao bu' }.to raise_error(Prawn::Errors::UnknownFont)
269
- end
270
-
271
- it 'does not raise an exception when providing Pathname instance as font' do
272
- pdf.font Pathname.new("#{Prawn::DATADIR}/fonts/DejaVuSans.ttf")
273
- end
274
-
275
- it 'correctlies render a utf-8 string when using a built-in font' do
276
- str = '©' # copyright symbol
277
- pdf.text str
278
-
279
- # grab the text from the rendered PDF and ensure it matches
280
- text = PDF::Inspector::Text.analyze(pdf.render)
281
- expect(text.strings.first).to eq(str)
282
- end
283
-
284
- it 'correctlies render a utf-8 string when using a TTF font' do
285
- str = '©' # copyright symbol
286
- pdf.font "#{Prawn::DATADIR}/fonts/DejaVuSans.ttf"
287
- pdf.text str
288
-
289
- # grab the text from the rendered PDF and ensure it matches
290
- text = PDF::Inspector::Text.analyze(pdf.render)
291
- expect(text.strings.first).to eq(str)
292
- end
293
-
294
- it 'subsets mixed low-ASCII and non-ASCII characters when they can '\
295
- 'be subsetted together' do
296
- str = 'It’s super effective!'
297
- pdf.font "#{Prawn::DATADIR}/fonts/DejaVuSans.ttf"
298
- pdf.text str
299
-
300
- text = PDF::Inspector::Text.analyze(pdf.render)
301
- expect(text.strings.first).to eq(str)
302
- end
303
-
304
- it 'correctly renders a string with higher bit characters across a page '\
305
- 'break when using a built-in font' do
306
- str = '©'
307
- pdf.move_cursor_to(pdf.font.height)
308
- pdf.text("#{str}\n#{str}")
309
-
310
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
311
- expect(pages.size).to eq(2)
312
- expect(pages[0][:strings]).to eq([str])
313
- expect(pages[1][:strings]).to eq([str])
314
- end
315
-
316
- it 'correctly renders a string with higher bit characters across ' \
317
- 'a page break when using a built-in font and :indent_paragraphs option' do
318
- str = '©'
319
- pdf.move_cursor_to(pdf.font.height)
320
- pdf.text("#{str}\n#{str}", indent_paragraphs: 20)
321
-
322
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
323
- expect(pages.size).to eq(2)
324
- expect(pages[0][:strings]).to eq([str])
325
- expect(pages[1][:strings]).to eq([str])
326
- end
327
-
328
- it 'raises an exception when a utf-8 incompatible string is rendered' do
329
- str = "Blah \xDD"
330
- expect { pdf.text str }.to raise_error(
331
- Prawn::Errors::IncompatibleStringEncoding
332
- )
333
- end
334
-
335
- it 'does not raise an exception when a shift-jis string is rendered' do
336
- datafile = "#{Prawn::DATADIR}/shift_jis_text.txt"
337
- sjis_str = File.open(datafile, 'r:shift_jis', &:gets)
338
- pdf.font("#{Prawn::DATADIR}/fonts/gkai00mp.ttf")
339
-
340
- # Expect that the call to text will not raise an encoding error
341
- pdf.text(sjis_str)
342
- end
343
-
344
- it 'calls move_past_bottom when printing more text than can fit' \
345
- ' between the current document.y and bounds.bottom' do
346
- pdf.y = pdf.font.height
347
- pdf.text 'Hello'
348
- pdf.text 'World'
349
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
350
- expect(pages.size).to eq(2)
351
- expect(pages[0][:strings]).to eq(['Hello'])
352
- expect(pages[1][:strings]).to eq(['World'])
353
- end
354
-
355
- describe 'with :indent_paragraphs option' do
356
- it 'indents the paragraphs' do
357
- hello = 'hello ' * 50
358
- hello2 = 'hello ' * 50
359
- pdf.text("#{hello}\n#{hello2}", indent_paragraphs: 60)
360
- text = PDF::Inspector::Text.analyze(pdf.render)
361
- expect(text.strings[0]).to eq(('hello ' * 19).strip)
362
- expect(text.strings[1]).to eq(('hello ' * 21).strip)
363
- expect(text.strings[3]).to eq(('hello ' * 19).strip)
364
- expect(text.strings[4]).to eq(('hello ' * 21).strip)
365
- end
366
-
367
- it 'indents from right side when using :rtl direction' do
368
- para1 = 'The rain in spain falls mainly on the plains ' * 3
369
- para2 = 'The rain in spain falls mainly on the plains ' * 3
370
-
371
- pdf.text("#{para1}\n#{para2}", indent_paragraphs: 60, direction: :rtl)
372
-
373
- text = PDF::Inspector::Text.analyze(pdf.render)
374
-
375
- lines = text.strings
376
- x_positions = text.positions.map { |e| e[0] }
377
-
378
- # NOTE: The code below reflects Prawn's current kerning behavior for RTL
379
- # text, which isn't necessarily correct. If we change that behavior,
380
- # this test will need to be updated.
381
-
382
- expect(x_positions[0]).to(
383
- be_within(0.001).of(pdf.bounds.absolute_right - 60 -
384
- pdf.width_of(lines[0].reverse, kerning: true))
385
- )
386
-
387
- expect(x_positions[1]).to(
388
- be_within(0.001).of(pdf.bounds.absolute_right -
389
- pdf.width_of(lines[1].reverse, kerning: true))
390
- )
391
-
392
- expect(x_positions[2]).to(
393
- be_within(0.001).of(pdf.bounds.absolute_right - 60 -
394
- pdf.width_of(lines[2].reverse, kerning: true))
395
- )
396
-
397
- expect(x_positions[3]).to(
398
- be_within(0.001).of(pdf.bounds.absolute_right -
399
- pdf.width_of(lines[3].reverse, kerning: true))
400
- )
401
- end
402
-
403
- it 'indents from right side when document has :rtl direction' do
404
- para1 = 'The rain in spain falls mainly on the plains ' * 3
405
- para2 = 'The rain in spain falls mainly on the plains ' * 3
406
-
407
- pdf.text_direction = :rtl
408
- pdf.text("#{para1}\n#{para2}", indent_paragraphs: 60)
409
-
410
- text = PDF::Inspector::Text.analyze(pdf.render)
411
-
412
- lines = text.strings
413
- x_positions = text.positions.map { |e| e[0] }
414
-
415
- # NOTE: The code below reflects Prawn's current kerning behavior for RTL
416
- # text, which isn't necessarily correct. If we change that behavior,
417
- # this test will need to be updated.
418
-
419
- expect(x_positions[0]).to(
420
- be_within(0.001).of(pdf.bounds.absolute_right - 60 -
421
- pdf.width_of(lines[0].reverse, kerning: true))
422
- )
423
-
424
- expect(x_positions[1]).to(
425
- be_within(0.001).of(pdf.bounds.absolute_right -
426
- pdf.width_of(lines[1].reverse, kerning: true))
427
- )
428
-
429
- expect(x_positions[2]).to(
430
- be_within(0.001).of(pdf.bounds.absolute_right - 60 -
431
- pdf.width_of(lines[2].reverse, kerning: true))
432
- )
433
-
434
- expect(x_positions[3]).to(
435
- be_within(0.001).of(pdf.bounds.absolute_right -
436
- pdf.width_of(lines[3].reverse, kerning: true))
437
- )
438
- end
439
-
440
- it 'indents from left side when using :ltr direction' do
441
- para1 = 'The rain in spain falls mainly on the plains ' * 3
442
- para2 = 'The rain in spain falls mainly on the plains ' * 3
443
-
444
- pdf.text("#{para1}\n#{para2}", indent_paragraphs: 60, direction: :ltr)
445
-
446
- text = PDF::Inspector::Text.analyze(pdf.render)
447
-
448
- x_positions = text.positions.map { |e| e[0] }
449
-
450
- expect(x_positions[0]).to eq(60)
451
- expect(x_positions[1]).to eq(0)
452
-
453
- expect(x_positions[2]).to eq(60)
454
- expect(x_positions[3]).to eq(0)
455
- end
456
-
457
- it 'indents from left side when document has :ltr direction' do
458
- para1 = 'The rain in spain falls mainly on the plains ' * 3
459
- para2 = 'The rain in spain falls mainly on the plains ' * 3
460
-
461
- pdf.text_direction = :ltr
462
- pdf.text("#{para1}\n#{para2}", indent_paragraphs: 60)
463
-
464
- text = PDF::Inspector::Text.analyze(pdf.render)
465
-
466
- x_positions = text.positions.map { |e| e[0] }
467
-
468
- expect(x_positions[0]).to eq(60)
469
- expect(x_positions[1]).to eq(0)
470
-
471
- expect(x_positions[2]).to eq(60)
472
- expect(x_positions[3]).to eq(0)
473
- end
474
-
475
- describe 'when paragraph has only one line, it should not add ' \
476
- 'additional leading' do
477
- let(:leading) { 100 }
478
-
479
- it 'adds leading only once' do
480
- original_y = pdf.y
481
- pdf.text('hello', indent_paragraphs: 10, leading: leading)
482
- expect(original_y - pdf.y).to be < leading * 2
483
- end
484
- end
485
-
486
- describe 'when wrap to new page, and first line of new page' \
487
- ' is not the start of a new paragraph, that line should' \
488
- ' not be indented' do
489
- it 'indents the paragraphs' do
490
- hello = 'hello ' * 50
491
- hello2 = 'hello ' * 50
492
- pdf.move_cursor_to(pdf.font.height)
493
- pdf.text("#{hello}\n#{hello2}", indent_paragraphs: 60)
494
- text = PDF::Inspector::Text.analyze(pdf.render)
495
- expect(text.strings[0]).to eq(('hello ' * 19).strip)
496
- expect(text.strings[1]).to eq(('hello ' * 21).strip)
497
- expect(text.strings[3]).to eq(('hello ' * 19).strip)
498
- expect(text.strings[4]).to eq(('hello ' * 21).strip)
499
- end
500
- end
501
-
502
- describe 'when wrap to new page, and first line of new page' \
503
- ' is the start of a new paragraph, that line should' \
504
- ' be indented' do
505
- it 'indents the paragraphs' do
506
- hello = 'hello ' * 50
507
- hello2 = 'hello ' * 50
508
- pdf.move_cursor_to(pdf.font.height * 3)
509
- pdf.text("#{hello}\n#{hello2}", indent_paragraphs: 60)
510
- text = PDF::Inspector::Text.analyze(pdf.render)
511
- expect(text.strings[0]).to eq(('hello ' * 19).strip)
512
- expect(text.strings[1]).to eq(('hello ' * 21).strip)
513
- expect(text.strings[3]).to eq(('hello ' * 19).strip)
514
- expect(text.strings[4]).to eq(('hello ' * 21).strip)
515
- end
516
- end
517
- end
518
-
519
- describe 'kerning' do
520
- it 'respects text kerning setting (document default)' do
521
- allow(pdf.font).to receive(:compute_width_of)
522
- .with('VAT', hash_including(kerning: true))
523
- .and_return(10)
524
-
525
- pdf.text 'VAT'
526
-
527
- expect(pdf.font).to have_received(:compute_width_of)
528
- .with('VAT', hash_including(kerning: true))
529
- end
530
-
531
- it 'respects text kerning setting (kerning=true)' do
532
- allow(pdf.font).to receive(:compute_width_of)
533
- .with('VAT', hash_including(kerning: true))
534
- .at_least(:once)
535
- .and_return(10)
536
- pdf.text 'VAT', kerning: true
537
-
538
- expect(pdf.font).to have_received(:compute_width_of)
539
- .with('VAT', hash_including(kerning: true))
540
- .at_least(:once)
541
- end
542
-
543
- it 'respects text kerning setting (kerning=false)' do
544
- allow(pdf.font).to receive(:compute_width_of)
545
- .with('VAT', hash_including(kerning: false))
546
- .at_least(:once)
547
- .and_return(10)
548
- pdf.text 'VAT', kerning: false
549
-
550
- expect(pdf.font).to have_received(:compute_width_of)
551
- .with('VAT', hash_including(kerning: false))
552
- .at_least(:once)
553
- end
554
- end
555
-
556
- describe '#shrink_to_fit with special utf-8 text' do
557
- it 'does not throw an exception', :unresolved, issue: 603 do
558
- expect do
559
- Prawn::Document.new(page_size: 'A4', margin: [2, 2, 2, 2]) do |pdf|
560
- add_unicode_fonts(pdf)
561
- pdf.bounding_box([1, 1], width: 90, height: 50) do
562
- pdf.text(
563
- "Sample Text\nSAMPLE SAMPLE SAMPLEoddělení ZMĚN\nSAMPLE",
564
- overflow: :shrink_to_fit
565
- )
566
- end
567
- end
568
- end.to_not raise_error
569
- end
570
- end
571
-
572
- def add_unicode_fonts(pdf)
573
- dejavu = "#{::Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
574
- pdf.font_families.update(
575
- 'dejavu' => {
576
- normal: dejavu,
577
- italic: dejavu,
578
- bold: dejavu,
579
- bold_italic: dejavu
580
- }
581
- )
582
- pdf.fallback_fonts = ['dejavu']
583
- end
584
-
585
- describe 'fallback_fonts' do
586
- it 'preserves font style' do
587
- create_pdf
588
-
589
- pdf.fallback_fonts ['Helvetica']
590
- pdf.font 'Times-Roman', style: :italic do
591
- pdf.text 'hello'
592
- end
593
-
594
- text = PDF::Inspector::Text.analyze(pdf.render)
595
- fonts_used = text.font_settings.map { |e| e[:name] }
596
-
597
- expect(fonts_used.length).to eq(1)
598
- expect(fonts_used[0]).to eq(:"Times-Italic")
599
- expect(text.strings[0]).to eq('hello')
600
- end
601
- end
602
- end
603
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Prawn::Text do
6
- let(:pdf) { create_pdf }
7
-
8
- describe '#formatted_text' do
9
- it 'draws text' do
10
- string = 'hello world'
11
- format_array = [{ text: string }]
12
- pdf.formatted_text(format_array)
13
- # grab the text from the rendered PDF and ensure it matches
14
- text = PDF::Inspector::Text.analyze(pdf.render)
15
- expect(text.strings.first).to eq(string)
16
- end
17
- end
18
-
19
- describe '#text with inline styling' do
20
- it 'automatically moves to a new page if the tallest fragment' \
21
- " on the next line won't fit in the available space" do
22
- pdf.move_cursor_to(pdf.font.height)
23
- formatted = "this contains <font size='24'>sized</font> text"
24
- pdf.text(formatted, inline_format: true)
25
- pages = PDF::Inspector::Page.analyze(pdf.render).pages
26
- expect(pages.size).to eq(2)
27
- end
28
-
29
- it 'embeds links as literal strings' do
30
- pdf.text "<link href='http://wiki.github.com/sandal/prawn/'>wiki</link>",
31
- inline_format: true
32
- expect(pdf.render).to match(%r{/URI\s+\(http://wiki\.github\.com})
33
- end
34
- end
35
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Prawn::TransformationStack do
6
- let(:pdf) do
7
- create_pdf do |document|
8
- document.add_to_transformation_stack(2, 0, 0, 2, 100, 100)
9
- end
10
- end
11
- let(:stack) { pdf.instance_variable_get(:@transformation_stack) }
12
-
13
- describe '#add_to_transformation_stack' do
14
- it 'creates and adds to the stack' do
15
- pdf.add_to_transformation_stack(1, 0, 0, 1, 20, 20)
16
-
17
- expect(stack).to eq [[[2, 0, 0, 2, 100, 100], [1, 0, 0, 1, 20, 20]]]
18
- end
19
-
20
- it 'adds to the last stack' do
21
- pdf.save_transformation_stack
22
- pdf.add_to_transformation_stack(1, 0, 0, 1, 20, 20)
23
-
24
- expect(stack).to eq [
25
- [[2, 0, 0, 2, 100, 100]],
26
- [[2, 0, 0, 2, 100, 100], [1, 0, 0, 1, 20, 20]]
27
- ]
28
- end
29
- end
30
-
31
- describe '#save_transformation_stack' do
32
- it 'clones the last stack' do
33
- pdf.save_transformation_stack
34
-
35
- expect(stack.length).to eq 2
36
- expect(stack.first).to eq stack.last
37
- expect(stack.first).to_not be stack.last
38
- end
39
- end
40
-
41
- describe '#restore_transformation_stack' do
42
- it 'pops off the last stack' do
43
- pdf.save_transformation_stack
44
- pdf.add_to_transformation_stack(1, 0, 0, 1, 20, 20)
45
- pdf.restore_transformation_stack
46
-
47
- expect(stack).to eq [[[2, 0, 0, 2, 100, 100]]]
48
- end
49
- end
50
-
51
- describe 'current_transformation_matrix_with_translation' do
52
- before do
53
- pdf.add_to_transformation_stack(1, 0, 0, 1, 20, 20)
54
- end
55
-
56
- it 'calculates the last transformation' do
57
- expect(pdf.current_transformation_matrix_with_translation)
58
- .to eq [2, 0, 0, 2, 140, 140]
59
- end
60
-
61
- it 'adds the supplied x and y coordinates to the transformation stack' do
62
- expect(pdf.current_transformation_matrix_with_translation(15, 15))
63
- .to eq [2, 0, 0, 2, 170, 170]
64
- end
65
- end
66
- end