prawn 0.13.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +10 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -16
  6. data/Rakefile +17 -39
  7. data/lib/prawn/document/bounding_box.rb +85 -42
  8. data/lib/prawn/document/column_box.rb +21 -11
  9. data/lib/prawn/document/internals.rb +40 -147
  10. data/lib/prawn/document/span.rb +25 -17
  11. data/lib/prawn/document.rb +286 -245
  12. data/lib/prawn/encoding.rb +68 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +204 -155
  15. data/lib/prawn/font_metric_cache.rb +25 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +7 -13
  18. data/lib/prawn/fonts/otf.rb +11 -0
  19. data/lib/prawn/fonts/ttc.rb +36 -0
  20. data/lib/prawn/{font → fonts}/ttf.rb +142 -80
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +6 -5
  23. data/lib/prawn/graphics/color.rb +47 -44
  24. data/lib/prawn/graphics/dash.rb +30 -13
  25. data/lib/prawn/graphics/join_style.rb +13 -6
  26. data/lib/prawn/graphics/patterns.rb +221 -90
  27. data/lib/prawn/graphics/transformation.rb +21 -12
  28. data/lib/prawn/graphics/transparency.rb +21 -17
  29. data/lib/prawn/graphics.rb +155 -128
  30. data/lib/prawn/{layout/grid.rb → grid.rb} +110 -47
  31. data/lib/prawn/image_handler.rb +16 -2
  32. data/lib/prawn/images/image.rb +4 -2
  33. data/lib/prawn/images/jpg.rb +39 -30
  34. data/lib/prawn/images/png.rb +132 -169
  35. data/lib/prawn/images.rb +70 -62
  36. data/lib/prawn/measurement_extensions.rb +15 -10
  37. data/lib/prawn/measurements.rb +22 -23
  38. data/lib/prawn/outline.rb +301 -13
  39. data/lib/prawn/repeater.rb +19 -17
  40. data/lib/prawn/security/arcfour.rb +54 -0
  41. data/lib/prawn/security.rb +108 -86
  42. data/lib/prawn/soft_mask.rb +40 -41
  43. data/lib/prawn/stamp.rb +29 -12
  44. data/lib/prawn/text/box.rb +27 -29
  45. data/lib/prawn/text/formatted/arranger.rb +110 -67
  46. data/lib/prawn/text/formatted/box.rb +233 -165
  47. data/lib/prawn/text/formatted/fragment.rb +27 -27
  48. data/lib/prawn/text/formatted/line_wrap.rb +137 -97
  49. data/lib/prawn/text/formatted/parser.rb +149 -127
  50. data/lib/prawn/text/formatted/wrap.rb +57 -37
  51. data/lib/prawn/text/formatted.rb +6 -4
  52. data/lib/prawn/text.rb +105 -73
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +11 -21
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +42 -68
  58. data/{data/images/fractal.jpg → manual/absolute_position.pdf} +0 -0
  59. data/manual/basic_concepts/adding_pages.rb +9 -10
  60. data/manual/basic_concepts/basic_concepts.rb +33 -24
  61. data/manual/basic_concepts/creation.rb +10 -11
  62. data/manual/basic_concepts/cursor.rb +9 -10
  63. data/manual/basic_concepts/measurement.rb +10 -11
  64. data/manual/basic_concepts/origin.rb +8 -9
  65. data/manual/basic_concepts/other_cursor_helpers.rb +17 -18
  66. data/manual/basic_concepts/view.rb +48 -0
  67. data/manual/bounding_box/bounding_box.rb +31 -29
  68. data/manual/bounding_box/bounds.rb +17 -18
  69. data/manual/bounding_box/canvas.rb +8 -9
  70. data/manual/bounding_box/creation.rb +8 -9
  71. data/manual/bounding_box/indentation.rb +22 -23
  72. data/manual/bounding_box/nesting.rb +32 -25
  73. data/manual/bounding_box/russian_boxes.rb +19 -19
  74. data/manual/bounding_box/stretchy.rb +18 -20
  75. data/manual/contents.rb +35 -0
  76. data/manual/cover.rb +43 -0
  77. data/manual/document_and_page_options/background.rb +16 -14
  78. data/manual/document_and_page_options/document_and_page_options.rb +26 -23
  79. data/manual/document_and_page_options/metadata.rb +21 -19
  80. data/manual/document_and_page_options/page_margins.rb +20 -22
  81. data/manual/document_and_page_options/page_size.rb +15 -15
  82. data/manual/document_and_page_options/print_scaling.rb +23 -0
  83. data/manual/example_helper.rb +5 -408
  84. data/manual/graphics/blend_mode.rb +52 -0
  85. data/manual/graphics/circle_and_ellipse.rb +8 -9
  86. data/manual/graphics/color.rb +11 -13
  87. data/manual/graphics/common_lines.rb +13 -12
  88. data/manual/graphics/fill_and_stroke.rb +10 -11
  89. data/manual/graphics/fill_rules.rb +13 -12
  90. data/manual/graphics/gradients.rb +28 -22
  91. data/manual/graphics/graphics.rb +52 -46
  92. data/manual/graphics/helper.rb +20 -10
  93. data/manual/graphics/line_width.rb +13 -12
  94. data/manual/graphics/lines_and_curves.rb +13 -14
  95. data/manual/graphics/polygon.rb +10 -12
  96. data/manual/graphics/rectangle.rb +7 -8
  97. data/manual/graphics/rotate.rb +9 -12
  98. data/manual/graphics/scale.rb +19 -18
  99. data/manual/graphics/soft_masks.rb +5 -7
  100. data/manual/graphics/stroke_cap.rb +10 -11
  101. data/manual/graphics/stroke_dash.rb +16 -17
  102. data/manual/graphics/stroke_join.rb +10 -11
  103. data/manual/graphics/translate.rb +13 -13
  104. data/manual/graphics/transparency.rb +11 -13
  105. data/manual/{manual/how_to_read_this_manual.rb → how_to_read_this_manual.rb} +23 -25
  106. data/manual/images/absolute_position.rb +9 -10
  107. data/manual/images/fit.rb +9 -10
  108. data/manual/images/horizontal.rb +13 -14
  109. data/manual/images/images.rb +31 -30
  110. data/manual/images/plain_image.rb +6 -7
  111. data/manual/images/scale.rb +12 -13
  112. data/manual/images/vertical.rb +19 -17
  113. data/manual/images/width_and_height.rb +13 -14
  114. data/manual/layout/boxes.rb +14 -15
  115. data/manual/layout/content.rb +12 -13
  116. data/manual/layout/layout.rb +19 -20
  117. data/manual/layout/simple_grid.rb +8 -9
  118. data/manual/outline/add_subsection_to.rb +26 -27
  119. data/manual/outline/insert_section_after.rb +19 -20
  120. data/manual/outline/outline.rb +23 -22
  121. data/manual/outline/sections_and_pages.rb +24 -25
  122. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  123. data/manual/repeatable_content/page_numbering.rb +20 -19
  124. data/manual/repeatable_content/repeatable_content.rb +26 -22
  125. data/manual/repeatable_content/repeater.rb +18 -19
  126. data/manual/repeatable_content/stamp.rb +18 -19
  127. data/manual/security/encryption.rb +8 -11
  128. data/manual/security/permissions.rb +20 -15
  129. data/manual/security/security.rb +20 -20
  130. data/manual/table.rb +16 -0
  131. data/manual/text/alignment.rb +17 -18
  132. data/manual/text/color.rb +13 -13
  133. data/manual/text/column_box.rb +10 -12
  134. data/manual/text/fallback_fonts.rb +29 -25
  135. data/manual/text/font.rb +17 -18
  136. data/manual/text/font_size.rb +21 -22
  137. data/manual/text/font_style.rb +12 -10
  138. data/manual/text/formatted_callbacks.rb +36 -26
  139. data/manual/text/formatted_text.rb +41 -34
  140. data/manual/text/free_flowing_text.rb +28 -29
  141. data/manual/text/inline.rb +23 -26
  142. data/manual/text/kerning_and_character_spacing.rb +20 -21
  143. data/manual/text/leading.rb +10 -11
  144. data/manual/text/line_wrapping.rb +40 -21
  145. data/manual/text/paragraph_indentation.rb +17 -12
  146. data/manual/text/positioned_text.rb +19 -20
  147. data/manual/text/registering_families.rb +33 -30
  148. data/manual/text/rendering_and_color.rb +11 -12
  149. data/manual/text/right_to_left_text.rb +31 -20
  150. data/manual/text/rotation.rb +36 -27
  151. data/manual/text/single_usage.rb +13 -14
  152. data/manual/text/text.rb +62 -62
  153. data/manual/text/text_box_excess.rb +22 -19
  154. data/manual/text/text_box_extensions.rb +21 -18
  155. data/manual/text/text_box_overflow.rb +28 -21
  156. data/manual/text/utf8.rb +16 -17
  157. data/manual/text/win_ansi_charset.rb +29 -26
  158. data/prawn.gemspec +45 -43
  159. data/spec/extensions/encoding_helpers.rb +4 -3
  160. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  161. data/spec/prawn/document/column_box_spec.rb +75 -0
  162. data/spec/prawn/document/security_spec.rb +176 -0
  163. data/spec/prawn/document_annotations_spec.rb +76 -0
  164. data/spec/prawn/document_destinations_spec.rb +15 -0
  165. data/spec/prawn/document_grid_spec.rb +99 -0
  166. data/spec/prawn/document_reference_spec.rb +27 -0
  167. data/spec/prawn/document_span_spec.rb +44 -0
  168. data/spec/prawn/document_spec.rb +805 -0
  169. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  170. data/spec/prawn/font_spec.rb +544 -0
  171. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  172. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  173. data/spec/prawn/graphics_spec.rb +872 -0
  174. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  175. data/spec/prawn/image_handler_spec.rb +53 -0
  176. data/spec/prawn/images/jpg_spec.rb +20 -0
  177. data/spec/prawn/images/png_spec.rb +283 -0
  178. data/spec/prawn/images_spec.rb +229 -0
  179. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  180. data/spec/prawn/outline_spec.rb +512 -0
  181. data/spec/prawn/repeater_spec.rb +166 -0
  182. data/spec/prawn/soft_mask_spec.rb +74 -0
  183. data/spec/prawn/stamp_spec.rb +173 -0
  184. data/spec/prawn/text/box_spec.rb +1110 -0
  185. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  186. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  187. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  188. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  189. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  190. data/spec/prawn/text_draw_text_spec.rb +150 -0
  191. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  192. data/spec/prawn/text_spacing_spec.rb +95 -0
  193. data/spec/prawn/text_spec.rb +603 -0
  194. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  195. data/spec/prawn/transformation_stack_spec.rb +66 -0
  196. data/spec/prawn/view_spec.rb +63 -0
  197. data/spec/prawn_manual_spec.rb +35 -0
  198. data/spec/spec_helper.rb +22 -21
  199. data.tar.gz.sig +0 -0
  200. metadata +168 -307
  201. metadata.gz.sig +0 -0
  202. data/README.md +0 -109
  203. data/data/encodings/win_ansi.txt +0 -29
  204. data/data/images/16bit.alpha +0 -0
  205. data/data/images/16bit.dat +0 -0
  206. data/data/images/16bit.png +0 -0
  207. data/data/images/arrow.png +0 -0
  208. data/data/images/arrow2.png +0 -0
  209. data/data/images/barcode_issue.png +0 -0
  210. data/data/images/dice.alpha +0 -0
  211. data/data/images/dice.dat +0 -0
  212. data/data/images/dice.png +0 -0
  213. data/data/images/dice_interlaced.png +0 -0
  214. data/data/images/indexed_color.dat +0 -0
  215. data/data/images/indexed_color.png +0 -0
  216. data/data/images/letterhead.jpg +0 -0
  217. data/data/images/page_white_text.alpha +0 -0
  218. data/data/images/page_white_text.dat +0 -0
  219. data/data/images/page_white_text.png +0 -0
  220. data/data/images/pigs.jpg +0 -0
  221. data/data/images/prawn.png +0 -0
  222. data/data/images/ruport.png +0 -0
  223. data/data/images/ruport_data.dat +0 -0
  224. data/data/images/ruport_transparent.png +0 -0
  225. data/data/images/ruport_type0.png +0 -0
  226. data/data/images/stef.jpg +0 -0
  227. data/data/images/tru256.bmp +0 -0
  228. data/data/images/web-links.dat +0 -1
  229. data/data/images/web-links.png +0 -0
  230. data/data/pdfs/complex_template.pdf +0 -0
  231. data/data/pdfs/contains_ttf_font.pdf +0 -0
  232. data/data/pdfs/encrypted.pdf +0 -0
  233. data/data/pdfs/form.pdf +1 -819
  234. data/data/pdfs/hexagon.pdf +0 -61
  235. data/data/pdfs/indirect_reference.pdf +0 -86
  236. data/data/pdfs/multipage_template.pdf +0 -127
  237. data/data/pdfs/nested_pages.pdf +0 -118
  238. data/data/pdfs/page_without_mediabox.pdf +0 -193
  239. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  240. data/data/pdfs/two_hexagons.pdf +0 -90
  241. data/data/pdfs/version_1_6.pdf +0 -61
  242. data/data/shift_jis_text.txt +0 -1
  243. data/lib/pdf/core/annotations.rb +0 -60
  244. data/lib/pdf/core/byte_string.rb +0 -9
  245. data/lib/pdf/core/destinations.rb +0 -90
  246. data/lib/pdf/core/document_state.rb +0 -78
  247. data/lib/pdf/core/filter_list.rb +0 -51
  248. data/lib/pdf/core/filters.rb +0 -36
  249. data/lib/pdf/core/graphics_state.rb +0 -68
  250. data/lib/pdf/core/literal_string.rb +0 -16
  251. data/lib/pdf/core/name_tree.rb +0 -177
  252. data/lib/pdf/core/object_store.rb +0 -320
  253. data/lib/pdf/core/outline.rb +0 -315
  254. data/lib/pdf/core/page.rb +0 -212
  255. data/lib/pdf/core/page_geometry.rb +0 -126
  256. data/lib/pdf/core/pdf_object.rb +0 -124
  257. data/lib/pdf/core/reference.rb +0 -103
  258. data/lib/pdf/core/stream.rb +0 -98
  259. data/lib/pdf/core/text.rb +0 -275
  260. data/lib/pdf/core.rb +0 -35
  261. data/lib/prawn/compatibility.rb +0 -91
  262. data/lib/prawn/document/graphics_state.rb +0 -73
  263. data/lib/prawn/document/snapshot.rb +0 -89
  264. data/lib/prawn/font/afm.rb +0 -203
  265. data/lib/prawn/layout.rb +0 -20
  266. data/lib/prawn/table/cell/image.rb +0 -70
  267. data/lib/prawn/table/cell/in_table.rb +0 -27
  268. data/lib/prawn/table/cell/span_dummy.rb +0 -92
  269. data/lib/prawn/table/cell/subtable.rb +0 -65
  270. data/lib/prawn/table/cell/text.rb +0 -153
  271. data/lib/prawn/table/cell.rb +0 -770
  272. data/lib/prawn/table/cells.rb +0 -295
  273. data/lib/prawn/table.rb +0 -643
  274. data/manual/example_file.rb +0 -116
  275. data/manual/example_package.rb +0 -53
  276. data/manual/example_section.rb +0 -46
  277. data/manual/manual/cover.rb +0 -35
  278. data/manual/manual/foreword.rb +0 -85
  279. data/manual/manual/manual.rb +0 -35
  280. data/manual/syntax_highlight.rb +0 -52
  281. data/manual/table/basic_block.rb +0 -53
  282. data/manual/table/before_rendering_page.rb +0 -26
  283. data/manual/table/cell_border_lines.rb +0 -24
  284. data/manual/table/cell_borders_and_bg.rb +0 -31
  285. data/manual/table/cell_dimensions.rb +0 -30
  286. data/manual/table/cell_text.rb +0 -38
  287. data/manual/table/column_widths.rb +0 -30
  288. data/manual/table/content_and_subtables.rb +0 -39
  289. data/manual/table/creation.rb +0 -27
  290. data/manual/table/filtering.rb +0 -36
  291. data/manual/table/flow_and_header.rb +0 -17
  292. data/manual/table/image_cells.rb +0 -33
  293. data/manual/table/position.rb +0 -29
  294. data/manual/table/row_colors.rb +0 -20
  295. data/manual/table/span.rb +0 -30
  296. data/manual/table/style.rb +0 -22
  297. data/manual/table/table.rb +0 -52
  298. data/manual/table/width.rb +0 -27
  299. data/manual/templates/full_template.rb +0 -25
  300. data/manual/templates/page_template.rb +0 -48
  301. data/manual/templates/templates.rb +0 -27
  302. data/manual/text/group.rb +0 -29
  303. data/spec/acceptance/png.rb +0 -23
  304. data/spec/annotations_spec.rb +0 -74
  305. data/spec/bounding_box_spec.rb +0 -493
  306. data/spec/cell_spec.rb +0 -628
  307. data/spec/column_box_spec.rb +0 -33
  308. data/spec/destinations_spec.rb +0 -15
  309. data/spec/document_spec.rb +0 -761
  310. data/spec/extensions/mocha.rb +0 -44
  311. data/spec/filters_spec.rb +0 -34
  312. data/spec/font_metric_cache_spec.rb +0 -52
  313. data/spec/font_spec.rb +0 -464
  314. data/spec/formatted_text_arranger_spec.rb +0 -421
  315. data/spec/formatted_text_box_spec.rb +0 -650
  316. data/spec/formatted_text_fragment_spec.rb +0 -298
  317. data/spec/graphics_spec.rb +0 -651
  318. data/spec/grid_spec.rb +0 -85
  319. data/spec/image_handler_spec.rb +0 -42
  320. data/spec/images_spec.rb +0 -157
  321. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  322. data/spec/jpg_spec.rb +0 -25
  323. data/spec/line_wrap_spec.rb +0 -333
  324. data/spec/measurement_units_spec.rb +0 -23
  325. data/spec/name_tree_spec.rb +0 -112
  326. data/spec/object_store_spec.rb +0 -170
  327. data/spec/outline_spec.rb +0 -448
  328. data/spec/pdf_object_spec.rb +0 -172
  329. data/spec/png_spec.rb +0 -240
  330. data/spec/reference_spec.rb +0 -82
  331. data/spec/repeater_spec.rb +0 -158
  332. data/spec/security_spec.rb +0 -158
  333. data/spec/snapshot_spec.rb +0 -186
  334. data/spec/soft_mask_spec.rb +0 -117
  335. data/spec/span_spec.rb +0 -44
  336. data/spec/stamp_spec.rb +0 -158
  337. data/spec/stream_spec.rb +0 -58
  338. data/spec/stroke_styles_spec.rb +0 -211
  339. data/spec/table/span_dummy_spec.rb +0 -17
  340. data/spec/table_spec.rb +0 -1355
  341. data/spec/template_spec.rb +0 -351
  342. data/spec/text_at_spec.rb +0 -130
  343. data/spec/text_box_spec.rb +0 -1030
  344. data/spec/text_rendering_mode_spec.rb +0 -45
  345. data/spec/text_spacing_spec.rb +0 -93
  346. data/spec/text_spec.rb +0 -425
  347. data/spec/text_with_inline_formatting_spec.rb +0 -35
  348. data/spec/transparency_spec.rb +0 -89
@@ -0,0 +1,466 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Prawn::Text::Formatted::Arranger do
6
+ let(:pdf) { create_pdf }
7
+ let(:arranger) { described_class.new pdf }
8
+
9
+ describe '#format_array' do
10
+ it 'populates the unconsumed array' do
11
+ array = [
12
+ { text: 'hello ' },
13
+ { text: 'world how ', styles: [:bold] },
14
+ { text: 'are', styles: %i[bold italic] },
15
+ { text: ' you?' }
16
+ ]
17
+
18
+ arranger.format_array = array
19
+
20
+ expect(arranger.unconsumed[0]).to eq(text: 'hello ')
21
+ expect(arranger.unconsumed[1]).to eq(text: 'world how ', styles: [:bold])
22
+ expect(arranger.unconsumed[2])
23
+ .to eq(text: 'are', styles: %i[bold italic])
24
+ expect(arranger.unconsumed[3]).to eq(text: ' you?')
25
+ end
26
+
27
+ it 'splits newlins into their own elements' do
28
+ array = [
29
+ { text: "\nhello\nworld" }
30
+ ]
31
+
32
+ arranger.format_array = array
33
+
34
+ expect(arranger.unconsumed[0]).to eq(text: "\n")
35
+ expect(arranger.unconsumed[1]).to eq(text: 'hello')
36
+ expect(arranger.unconsumed[2]).to eq(text: "\n")
37
+ expect(arranger.unconsumed[3]).to eq(text: 'world')
38
+ end
39
+ end
40
+
41
+ describe '#preview_next_string' do
42
+ context 'with a formatted array' do
43
+ let(:array) { [{ text: 'hello' }] }
44
+
45
+ before do
46
+ arranger.format_array = array
47
+ end
48
+
49
+ it 'does not populate the consumed array' do
50
+ arranger.preview_next_string
51
+ expect(arranger.consumed).to eq([])
52
+ end
53
+
54
+ it 'returns the text of the next unconsumed hash' do
55
+ expect(arranger.preview_next_string).to eq('hello')
56
+ end
57
+
58
+ it 'returns nil if there is no more unconsumed text' do
59
+ arranger.next_string
60
+ expect(arranger.preview_next_string).to be_nil
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#next_string' do
66
+ let(:array) do
67
+ [
68
+ { text: 'hello ' },
69
+ { text: 'world how ', styles: [:bold] },
70
+ { text: 'are', styles: %i[bold italic] },
71
+ { text: ' you?' }
72
+ ]
73
+ end
74
+
75
+ before do
76
+ arranger.format_array = array
77
+ end
78
+
79
+ it 'raises an error if called after a line was finalized' do
80
+ arranger.finalize_line
81
+ expect { arranger.next_string }.to raise_error(Prawn::Text::Formatted::Arranger::NotFinalized)
82
+ end
83
+
84
+ it 'populates the conumed array' do
85
+ while arranger.next_string
86
+ end
87
+
88
+ expect(arranger.consumed[0]).to eq(text: 'hello ')
89
+ expect(arranger.consumed[1]).to eq(text: 'world how ', styles: [:bold])
90
+ expect(arranger.consumed[2]).to eq(text: 'are', styles: %i[bold italic])
91
+ expect(arranger.consumed[3]).to eq(text: ' you?')
92
+ end
93
+
94
+ it 'populates the current_format_state array' do
95
+ arranger.next_string
96
+ expect(arranger.current_format_state).to eq({})
97
+
98
+ arranger.next_string
99
+ expect(arranger.current_format_state).to eq(styles: [:bold])
100
+
101
+ arranger.next_string
102
+ expect(arranger.current_format_state).to eq(styles: %i[bold italic])
103
+
104
+ arranger.next_string
105
+ expect(arranger.current_format_state).to eq({})
106
+ end
107
+
108
+ it 'returns the text of the newly consumed hash' do
109
+ expect(arranger.next_string).to eq('hello ')
110
+ end
111
+
112
+ it 'returns nil when there are no more unconsumed hashes' do
113
+ 4.times do
114
+ arranger.next_string
115
+ end
116
+
117
+ expect(arranger.next_string).to be_nil
118
+ end
119
+ end
120
+
121
+ describe '#retrieve_fragment' do
122
+ context 'with a formatted array whos text is an empty string' do
123
+ let(:array) do
124
+ [
125
+ { text: "hello\nworld\n\n\nhow are you?" },
126
+ { text: "\n" },
127
+ { text: "\n" },
128
+ { text: "\n" },
129
+ { text: '' },
130
+ { text: 'fine, thanks.' },
131
+ { text: '' },
132
+ { text: "\n" },
133
+ { text: '' }
134
+ ]
135
+ end
136
+
137
+ before do
138
+ arranger.format_array = array
139
+
140
+ while arranger.next_string
141
+ end
142
+
143
+ arranger.finalize_line
144
+ end
145
+
146
+ # rubocop: disable Lint/AssignmentInCondition
147
+ it 'never returns a fragment whose text is an empty string' do
148
+ while fragment = arranger.retrieve_fragment
149
+ expect(fragment.text).to_not be_empty
150
+ end
151
+ end
152
+ # rubocop: enable Lint/AssignmentInCondition
153
+ end
154
+
155
+ context 'with formatted array' do
156
+ let(:array) do
157
+ [
158
+ { text: 'hello ' },
159
+ { text: 'world how ', styles: [:bold] },
160
+ { text: 'are', styles: %i[bold italic] },
161
+ { text: ' you?' }
162
+ ]
163
+ end
164
+
165
+ before do
166
+ arranger.format_array = array
167
+ end
168
+
169
+ describe 'after all strings have been consumed' do
170
+ before do
171
+ while arranger.next_string
172
+ end
173
+ end
174
+
175
+ it 'raises an error if not finalized' do
176
+ expect { arranger.retrieve_fragment }.to raise_error(Prawn::Text::Formatted::Arranger::NotFinalized)
177
+ end
178
+
179
+ describe 'and finalized' do
180
+ before do
181
+ arranger.finalize_line
182
+ end
183
+
184
+ it 'returns the consumed fragments in order of consumption' do
185
+ expect(arranger.retrieve_fragment.text).to eq('hello ')
186
+ expect(arranger.retrieve_fragment.text).to eq('world how ')
187
+ expect(arranger.retrieve_fragment.text).to eq('are')
188
+ expect(arranger.retrieve_fragment.text).to eq(' you?')
189
+ end
190
+
191
+ it 'does not alter the current font style' do
192
+ arranger.retrieve_fragment
193
+ expect(arranger.current_format_state[:styles]).to be_nil
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ describe '#update_last_string' do
201
+ it 'updates the last retrieved string with what actually fit on the line '\
202
+ 'and the list of unconsumed with what did not' do
203
+ array = [
204
+ { text: 'hello ' },
205
+ { text: 'world how ', styles: [:bold] },
206
+ { text: 'are', styles: %i[bold italic] },
207
+ { text: ' you now?', styles: %i[bold italic] }
208
+ ]
209
+ arranger.format_array = array
210
+ while arranger.next_string
211
+ end
212
+ arranger.update_last_string(' you', ' now?', nil)
213
+ expect(arranger.consumed[3]).to eq(
214
+ text: ' you',
215
+ styles: %i[bold italic]
216
+ )
217
+ expect(arranger.unconsumed).to eq([
218
+ { text: ' now?', styles: %i[bold italic] }
219
+ ])
220
+ end
221
+
222
+ it 'sets the format state to the previously processed fragment' do
223
+ array = [
224
+ { text: 'hello ' },
225
+ { text: 'world how ', styles: [:bold] },
226
+ { text: 'are', styles: %i[bold italic] },
227
+ { text: ' you now?' }
228
+ ]
229
+ arranger.format_array = array
230
+ 3.times { arranger.next_string }
231
+ expect(arranger.current_format_state).to eq(styles: %i[bold italic])
232
+ arranger.update_last_string('', 'are', '-')
233
+ expect(arranger.current_format_state).to eq(styles: [:bold])
234
+ end
235
+
236
+ context 'when the entire string was used' do
237
+ it 'does not push empty string onto unconsumed' do
238
+ array = [
239
+ { text: 'hello ' },
240
+ { text: 'world how ', styles: [:bold] },
241
+ { text: 'are', styles: %i[bold italic] },
242
+ { text: ' you now?' }
243
+ ]
244
+ arranger.format_array = array
245
+ while arranger.next_string
246
+ end
247
+ arranger.update_last_string(' you now?', '', nil)
248
+ expect(arranger.unconsumed).to eq([])
249
+ end
250
+ end
251
+ end
252
+
253
+ describe '#space_count' do
254
+ before do
255
+ array = [
256
+ { text: 'hello ' },
257
+ { text: 'world how ', styles: [:bold] },
258
+ { text: 'are', styles: %i[bold italic] },
259
+ { text: ' you?' }
260
+ ]
261
+ arranger.format_array = array
262
+ while arranger.next_string
263
+ end
264
+ end
265
+
266
+ it 'raises an error if called before finalize_line was called' do
267
+ expect do
268
+ arranger.space_count
269
+ end.to raise_error(Prawn::Text::Formatted::Arranger::NotFinalized)
270
+ end
271
+
272
+ it 'returns the total number of spaces in all fragments' do
273
+ arranger.finalize_line
274
+ expect(arranger.space_count).to eq(4)
275
+ end
276
+ end
277
+
278
+ describe '#finalize_line' do
279
+ it 'makes it so that all trailing white space fragments exclude '\
280
+ 'trailing white space' do
281
+ array = [
282
+ { text: 'hello ' },
283
+ { text: 'world how ', styles: [:bold] },
284
+ { text: ' ', styles: %i[bold italic] }
285
+ ]
286
+ arranger.format_array = array
287
+ while arranger.next_string
288
+ end
289
+ arranger.finalize_line
290
+ expect(arranger.fragments.length).to eq(3)
291
+
292
+ fragment = arranger.retrieve_fragment
293
+ expect(fragment.text).to eq('hello ')
294
+
295
+ fragment = arranger.retrieve_fragment
296
+ expect(fragment.text).to eq('world how')
297
+
298
+ fragment = arranger.retrieve_fragment
299
+ expect(fragment.text).to eq('')
300
+ end
301
+ end
302
+
303
+ describe '#line_width' do
304
+ before do
305
+ array = [
306
+ { text: 'hello ' },
307
+ { text: 'world', styles: [:bold] }
308
+ ]
309
+ arranger.format_array = array
310
+ while arranger.next_string
311
+ end
312
+ end
313
+
314
+ it 'raises an error if called before finalize_line was called' do
315
+ expect do
316
+ arranger.line_width
317
+ end.to raise_error(Prawn::Text::Formatted::Arranger::NotFinalized)
318
+ end
319
+
320
+ it 'returns the width of the complete line' do
321
+ arranger.finalize_line
322
+ expect(arranger.line_width).to be > 0
323
+ end
324
+ end
325
+
326
+ describe '#line_width with character_spacing > 0' do
327
+ it 'returns a width greater than a line without a character_spacing' do
328
+ array = [
329
+ { text: 'hello ' },
330
+ { text: 'world', styles: [:bold] }
331
+ ]
332
+ arranger.format_array = array
333
+ while arranger.next_string
334
+ end
335
+ arranger.finalize_line
336
+
337
+ base_line_width = arranger.line_width
338
+
339
+ array = [
340
+ { text: 'hello ' },
341
+ { text: 'world', styles: [:bold], character_spacing: 7 }
342
+ ]
343
+ arranger.format_array = array
344
+ while arranger.next_string
345
+ end
346
+ arranger.finalize_line
347
+ expect(arranger.line_width).to be > base_line_width
348
+ end
349
+ end
350
+
351
+ describe '#line' do
352
+ before do
353
+ array = [
354
+ { text: 'hello ' },
355
+ { text: 'world', styles: [:bold] }
356
+ ]
357
+ arranger.format_array = array
358
+ while arranger.next_string
359
+ end
360
+ end
361
+
362
+ it 'raises an error if called before finalize_line was called' do
363
+ expect do
364
+ arranger.line
365
+ end.to raise_error(Prawn::Text::Formatted::Arranger::NotFinalized)
366
+ end
367
+
368
+ it 'returns the complete line' do
369
+ arranger.finalize_line
370
+ expect(arranger.line).to eq('hello world')
371
+ end
372
+ end
373
+
374
+ describe '#unconsumed' do
375
+ it 'returns the original array if nothing was consumed' do
376
+ array = [
377
+ { text: 'hello ' },
378
+ { text: 'world how ', styles: [:bold] },
379
+ { text: 'are', styles: %i[bold italic] },
380
+ { text: ' you now?' }
381
+ ]
382
+ arranger.format_array = array
383
+ expect(arranger.unconsumed).to eq(array)
384
+ end
385
+
386
+ it 'returns an empty array if everything was consumed' do
387
+ array = [
388
+ { text: 'hello ' },
389
+ { text: 'world how ', styles: [:bold] },
390
+ { text: 'are', styles: %i[bold italic] },
391
+ { text: ' you now?' }
392
+ ]
393
+ arranger.format_array = array
394
+ while arranger.next_string
395
+ end
396
+ expect(arranger.unconsumed).to eq([])
397
+ end
398
+ end
399
+
400
+ describe '#finished' do
401
+ it 'be_falses if anything was not printed' do
402
+ array = [
403
+ { text: 'hello ' },
404
+ { text: 'world how ', styles: [:bold] },
405
+ { text: 'are', styles: %i[bold italic] },
406
+ { text: ' you now?' }
407
+ ]
408
+ arranger.format_array = array
409
+ while arranger.next_string
410
+ end
411
+ arranger.update_last_string(' you', 'now?', nil)
412
+ expect(arranger).to_not be_finished
413
+ end
414
+
415
+ it 'be_falses if everything was printed' do
416
+ array = [
417
+ { text: 'hello ' },
418
+ { text: 'world how ', styles: [:bold] },
419
+ { text: 'are', styles: %i[bold italic] },
420
+ { text: ' you now?' }
421
+ ]
422
+ arranger.format_array = array
423
+ while arranger.next_string
424
+ end
425
+ expect(arranger).to be_finished
426
+ end
427
+ end
428
+
429
+ describe '#max_line_height' do
430
+ it 'is the height of the maximum consumed fragment' do
431
+ array = [
432
+ { text: 'hello ' },
433
+ { text: 'world how ', styles: [:bold] },
434
+ { text: 'are', styles: %i[bold italic], size: 28 },
435
+ { text: ' you now?' }
436
+ ]
437
+ arranger.format_array = array
438
+ while arranger.next_string
439
+ end
440
+ arranger.finalize_line
441
+ expect(arranger.max_line_height).to be_within(0.0001).of(33.32)
442
+ end
443
+ end
444
+
445
+ describe '#repack_unretrieved' do
446
+ it 'restores part of the original string' do
447
+ array = [
448
+ { text: 'hello ' },
449
+ { text: 'world how ', styles: [:bold] },
450
+ { text: 'are', styles: %i[bold italic] },
451
+ { text: ' you now?' }
452
+ ]
453
+ arranger.format_array = array
454
+ while arranger.next_string
455
+ end
456
+ arranger.finalize_line
457
+ arranger.retrieve_fragment
458
+ arranger.retrieve_fragment
459
+ arranger.repack_unretrieved
460
+ expect(arranger.unconsumed).to eq([
461
+ { text: 'are', styles: %i[bold italic] },
462
+ { text: ' you now?' }
463
+ ])
464
+ end
465
+ end
466
+ end