prawn 1.1.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 (309) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +1 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +9 -40
  7. data/lib/prawn/document/bounding_box.rb +54 -40
  8. data/lib/prawn/document/column_box.rb +8 -10
  9. data/lib/prawn/document/internals.rb +39 -146
  10. data/lib/prawn/document/span.rb +23 -17
  11. data/lib/prawn/document.rb +217 -182
  12. data/lib/prawn/encoding.rb +69 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +124 -104
  15. data/lib/prawn/font_metric_cache.rb +23 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +5 -12
  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 +140 -88
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +5 -5
  23. data/lib/prawn/graphics/color.rb +46 -44
  24. data/lib/prawn/graphics/dash.rb +27 -11
  25. data/lib/prawn/graphics/join_style.rb +11 -6
  26. data/lib/prawn/graphics/patterns.rb +220 -78
  27. data/lib/prawn/graphics/transformation.rb +20 -12
  28. data/lib/prawn/graphics/transparency.rb +20 -18
  29. data/lib/prawn/graphics.rb +153 -115
  30. data/lib/prawn/grid.rb +93 -50
  31. data/lib/prawn/image_handler.rb +4 -4
  32. data/lib/prawn/images/image.rb +3 -2
  33. data/lib/prawn/images/jpg.rb +31 -24
  34. data/lib/prawn/images/png.rb +101 -68
  35. data/lib/prawn/images.rb +64 -56
  36. data/lib/prawn/measurement_extensions.rb +10 -9
  37. data/lib/prawn/measurements.rb +20 -23
  38. data/lib/prawn/outline.rb +96 -75
  39. data/lib/prawn/repeater.rb +16 -16
  40. data/lib/prawn/security/arcfour.rb +2 -2
  41. data/lib/prawn/security.rb +100 -85
  42. data/lib/prawn/soft_mask.rb +37 -38
  43. data/lib/prawn/stamp.rb +28 -13
  44. data/lib/prawn/text/box.rb +24 -29
  45. data/lib/prawn/text/formatted/arranger.rb +108 -63
  46. data/lib/prawn/text/formatted/box.rb +187 -124
  47. data/lib/prawn/text/formatted/fragment.rb +24 -20
  48. data/lib/prawn/text/formatted/line_wrap.rb +133 -73
  49. data/lib/prawn/text/formatted/parser.rb +147 -127
  50. data/lib/prawn/text/formatted/wrap.rb +48 -35
  51. data/lib/prawn/text/formatted.rb +5 -5
  52. data/lib/prawn/text.rb +103 -68
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +10 -22
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +39 -54
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +34 -25
  60. data/manual/basic_concepts/creation.rb +10 -11
  61. data/manual/basic_concepts/cursor.rb +4 -5
  62. data/manual/basic_concepts/measurement.rb +8 -9
  63. data/manual/basic_concepts/origin.rb +5 -6
  64. data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
  65. data/manual/basic_concepts/view.rb +48 -0
  66. data/manual/bounding_box/bounding_box.rb +30 -28
  67. data/manual/bounding_box/bounds.rb +12 -13
  68. data/manual/bounding_box/canvas.rb +7 -8
  69. data/manual/bounding_box/creation.rb +6 -7
  70. data/manual/bounding_box/indentation.rb +14 -15
  71. data/manual/bounding_box/nesting.rb +25 -18
  72. data/manual/bounding_box/russian_boxes.rb +18 -18
  73. data/manual/bounding_box/stretchy.rb +12 -14
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -32
  76. data/manual/document_and_page_options/background.rb +15 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +24 -22
  78. data/manual/document_and_page_options/metadata.rb +20 -18
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -13
  81. data/manual/document_and_page_options/print_scaling.rb +18 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +52 -0
  84. data/manual/graphics/circle_and_ellipse.rb +4 -5
  85. data/manual/graphics/color.rb +7 -9
  86. data/manual/graphics/common_lines.rb +7 -8
  87. data/manual/graphics/fill_and_stroke.rb +5 -6
  88. data/manual/graphics/fill_rules.rb +12 -11
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +46 -40
  91. data/manual/graphics/helper.rb +19 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +8 -9
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -9
  97. data/manual/graphics/scale.rb +14 -13
  98. data/manual/graphics/soft_masks.rb +4 -6
  99. data/manual/graphics/stroke_cap.rb +7 -8
  100. data/manual/graphics/stroke_dash.rb +15 -16
  101. data/manual/graphics/stroke_join.rb +6 -7
  102. data/manual/graphics/translate.rb +10 -10
  103. data/manual/graphics/transparency.rb +7 -9
  104. data/manual/how_to_read_this_manual.rb +8 -9
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +10 -11
  108. data/manual/images/images.rb +28 -27
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +16 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +10 -11
  114. data/manual/layout/content.rb +9 -10
  115. data/manual/layout/layout.rb +17 -18
  116. data/manual/layout/simple_grid.rb +6 -7
  117. data/manual/outline/add_subsection_to.rb +20 -21
  118. data/manual/outline/insert_section_after.rb +15 -16
  119. data/manual/outline/outline.rb +22 -21
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +27 -23
  124. data/manual/repeatable_content/repeater.rb +15 -16
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +8 -11
  127. data/manual/security/permissions.rb +20 -15
  128. data/manual/security/security.rb +18 -18
  129. data/manual/table.rb +16 -0
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -12
  132. data/manual/text/column_box.rb +9 -11
  133. data/manual/text/fallback_fonts.rb +25 -21
  134. data/manual/text/font.rb +11 -12
  135. data/manual/text/font_size.rb +13 -14
  136. data/manual/text/font_style.rb +10 -8
  137. data/manual/text/formatted_callbacks.rb +33 -23
  138. data/manual/text/formatted_text.rb +36 -25
  139. data/manual/text/free_flowing_text.rb +22 -23
  140. data/manual/text/inline.rb +18 -19
  141. data/manual/text/kerning_and_character_spacing.rb +14 -15
  142. data/manual/text/leading.rb +7 -8
  143. data/manual/text/line_wrapping.rb +37 -18
  144. data/manual/text/paragraph_indentation.rb +15 -10
  145. data/manual/text/positioned_text.rb +16 -17
  146. data/manual/text/registering_families.rb +27 -24
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +30 -19
  149. data/manual/text/rotation.rb +33 -24
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +56 -54
  152. data/manual/text/text_box_excess.rb +20 -17
  153. data/manual/text/text_box_extensions.rb +18 -15
  154. data/manual/text/text_box_overflow.rb +24 -17
  155. data/manual/text/utf8.rb +12 -13
  156. data/manual/text/win_ansi_charset.rb +28 -25
  157. data/prawn.gemspec +45 -50
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  160. data/spec/prawn/document/column_box_spec.rb +75 -0
  161. data/spec/prawn/document/security_spec.rb +176 -0
  162. data/spec/prawn/document_annotations_spec.rb +76 -0
  163. data/spec/prawn/document_destinations_spec.rb +15 -0
  164. data/spec/prawn/document_grid_spec.rb +99 -0
  165. data/spec/prawn/document_reference_spec.rb +27 -0
  166. data/spec/prawn/document_span_spec.rb +44 -0
  167. data/spec/prawn/document_spec.rb +805 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +544 -0
  170. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  171. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  172. data/spec/prawn/graphics_spec.rb +872 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/prawn/image_handler_spec.rb +53 -0
  175. data/spec/prawn/images/jpg_spec.rb +20 -0
  176. data/spec/prawn/images/png_spec.rb +283 -0
  177. data/spec/prawn/images_spec.rb +229 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +512 -0
  180. data/spec/prawn/repeater_spec.rb +166 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +173 -0
  183. data/spec/prawn/text/box_spec.rb +1110 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +150 -0
  190. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  191. data/spec/prawn/text_spacing_spec.rb +95 -0
  192. data/spec/prawn/text_spec.rb +603 -0
  193. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  194. data/spec/prawn/transformation_stack_spec.rb +66 -0
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +19 -25
  198. data.tar.gz.sig +0 -0
  199. metadata +113 -276
  200. metadata.gz.sig +0 -0
  201. data/data/encodings/win_ansi.txt +0 -29
  202. data/data/images/16bit.alpha +0 -0
  203. data/data/images/16bit.color +0 -0
  204. data/data/images/16bit.png +0 -0
  205. data/data/images/arrow.png +0 -0
  206. data/data/images/arrow2.png +0 -0
  207. data/data/images/dice.alpha +0 -0
  208. data/data/images/dice.color +0 -0
  209. data/data/images/dice.png +0 -0
  210. data/data/images/dice_interlaced.png +0 -0
  211. data/data/images/fractal.jpg +0 -0
  212. data/data/images/indexed_color.dat +0 -0
  213. data/data/images/indexed_color.png +0 -0
  214. data/data/images/letterhead.jpg +0 -0
  215. data/data/images/license.md +0 -8
  216. data/data/images/page_white_text.alpha +0 -0
  217. data/data/images/page_white_text.color +0 -0
  218. data/data/images/page_white_text.png +0 -0
  219. data/data/images/pigs.jpg +0 -0
  220. data/data/images/prawn.png +0 -0
  221. data/data/images/ruport.png +0 -0
  222. data/data/images/ruport_data.dat +0 -0
  223. data/data/images/ruport_transparent.png +0 -0
  224. data/data/images/ruport_type0.png +0 -0
  225. data/data/images/stef.jpg +0 -0
  226. data/data/images/tru256.bmp +0 -0
  227. data/data/images/web-links.dat +0 -1
  228. data/data/images/web-links.png +0 -0
  229. data/data/pdfs/complex_template.pdf +0 -0
  230. data/data/pdfs/contains_ttf_font.pdf +0 -0
  231. data/data/pdfs/encrypted.pdf +0 -0
  232. data/data/pdfs/form.pdf +1 -819
  233. data/data/pdfs/hexagon.pdf +0 -61
  234. data/data/pdfs/indirect_reference.pdf +0 -86
  235. data/data/pdfs/multipage_template.pdf +0 -127
  236. data/data/pdfs/nested_pages.pdf +0 -118
  237. data/data/pdfs/page_without_mediabox.pdf +0 -193
  238. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  239. data/data/pdfs/two_hexagons.pdf +0 -90
  240. data/data/pdfs/version_1_6.pdf +0 -61
  241. data/data/shift_jis_text.txt +0 -1
  242. data/lib/prawn/document/graphics_state.rb +0 -73
  243. data/lib/prawn/font/afm.rb +0 -247
  244. data/lib/prawn/table/cell/image.rb +0 -69
  245. data/lib/prawn/table/cell/in_table.rb +0 -33
  246. data/lib/prawn/table/cell/span_dummy.rb +0 -93
  247. data/lib/prawn/table/cell/subtable.rb +0 -66
  248. data/lib/prawn/table/cell/text.rb +0 -154
  249. data/lib/prawn/table/cell.rb +0 -772
  250. data/lib/prawn/table/cells.rb +0 -255
  251. data/lib/prawn/table/column_width_calculator.rb +0 -182
  252. data/lib/prawn/table.rb +0 -644
  253. data/manual/table/basic_block.rb +0 -53
  254. data/manual/table/before_rendering_page.rb +0 -26
  255. data/manual/table/cell_border_lines.rb +0 -24
  256. data/manual/table/cell_borders_and_bg.rb +0 -31
  257. data/manual/table/cell_dimensions.rb +0 -30
  258. data/manual/table/cell_text.rb +0 -38
  259. data/manual/table/column_widths.rb +0 -30
  260. data/manual/table/content_and_subtables.rb +0 -39
  261. data/manual/table/creation.rb +0 -27
  262. data/manual/table/filtering.rb +0 -36
  263. data/manual/table/flow_and_header.rb +0 -17
  264. data/manual/table/image_cells.rb +0 -33
  265. data/manual/table/position.rb +0 -29
  266. data/manual/table/row_colors.rb +0 -20
  267. data/manual/table/span.rb +0 -30
  268. data/manual/table/style.rb +0 -22
  269. data/manual/table/table.rb +0 -52
  270. data/manual/table/width.rb +0 -27
  271. data/spec/acceptance/png.rb +0 -25
  272. data/spec/annotations_spec.rb +0 -74
  273. data/spec/bounding_box_spec.rb +0 -510
  274. data/spec/cell_spec.rb +0 -629
  275. data/spec/column_box_spec.rb +0 -65
  276. data/spec/destinations_spec.rb +0 -15
  277. data/spec/document_spec.rb +0 -730
  278. data/spec/extensions/mocha.rb +0 -46
  279. data/spec/font_metric_cache_spec.rb +0 -52
  280. data/spec/font_spec.rb +0 -449
  281. data/spec/formatted_text_arranger_spec.rb +0 -421
  282. data/spec/formatted_text_box_spec.rb +0 -639
  283. data/spec/formatted_text_fragment_spec.rb +0 -298
  284. data/spec/graphics_spec.rb +0 -669
  285. data/spec/grid_spec.rb +0 -96
  286. data/spec/image_handler_spec.rb +0 -54
  287. data/spec/images_spec.rb +0 -153
  288. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  289. data/spec/jpg_spec.rb +0 -25
  290. data/spec/line_wrap_spec.rb +0 -344
  291. data/spec/measurement_units_spec.rb +0 -25
  292. data/spec/outline_spec.rb +0 -430
  293. data/spec/png_spec.rb +0 -237
  294. data/spec/reference_spec.rb +0 -25
  295. data/spec/repeater_spec.rb +0 -160
  296. data/spec/security_spec.rb +0 -158
  297. data/spec/soft_mask_spec.rb +0 -79
  298. data/spec/span_spec.rb +0 -44
  299. data/spec/stamp_spec.rb +0 -160
  300. data/spec/stroke_styles_spec.rb +0 -211
  301. data/spec/table/span_dummy_spec.rb +0 -17
  302. data/spec/table_spec.rb +0 -1527
  303. data/spec/text_at_spec.rb +0 -115
  304. data/spec/text_box_spec.rb +0 -1034
  305. data/spec/text_rendering_mode_spec.rb +0 -45
  306. data/spec/text_spacing_spec.rb +0 -93
  307. data/spec/text_spec.rb +0 -437
  308. data/spec/text_with_inline_formatting_spec.rb +0 -35
  309. data/spec/transparency_spec.rb +0 -91
data/lib/prawn/text.rb CHANGED
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # text.rb : Implements PDF text primitives
4
4
  #
@@ -6,25 +6,22 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
- require "zlib"
9
+ require 'zlib'
10
10
 
11
- require "pdf/core/text"
12
-
13
- require_relative "text/formatted"
14
- require_relative "text/box"
11
+ require_relative 'text/formatted'
12
+ require_relative 'text/box'
15
13
 
16
14
  module Prawn
17
15
  module Text
18
-
19
16
  include PDF::Core::Text
20
17
  include Prawn::Text::Formatted
21
18
 
22
19
  # No-Break Space
23
- Prawn::Text::NBSP = " "
20
+ NBSP = "\u00A0"
24
21
  # Zero Width Space (indicate word boundaries without a space)
25
- Prawn::Text::ZWSP = [8203].pack("U")
22
+ ZWSP = "\u200B"
26
23
  # Soft Hyphen (invisible, except when causing a line break)
27
- Prawn::Text::SHY = "­"
24
+ SHY = "\u00AD"
28
25
 
29
26
  # @group Stable API
30
27
 
@@ -116,7 +113,7 @@ module Prawn
116
113
  # the current font familly. [current style]
117
114
  # <tt>:indent_paragraphs</tt>:: <tt>number</tt>. The amount to indent the
118
115
  # first line of each paragraph. Omit this
119
- # option if you do not want indenting
116
+ # option if you do not want indenting.
120
117
  # <tt>:direction</tt>::
121
118
  # <tt>:ltr</tt>, <tt>:rtl</tt>, Direction of the text (left-to-right
122
119
  # or right-to-left) [value of document.text_direction]
@@ -140,9 +137,9 @@ module Prawn
140
137
  # each line is included below the last line;
141
138
  # otherwise, document.y is placed just below the
142
139
  # descender of the last line printed [true]
143
- # <tt>:mode</tt>:: The text rendering mode to use. Use this to specify if the
144
- # text should render with the fill color, stroke color or
145
- # both. See the comments to text_rendering_mode() to see
140
+ # <tt>:mode</tt>:: The text rendering mode to use. Use this to specify if
141
+ # the text should render with the fill color, stroke color
142
+ # or both. See the comments to text_rendering_mode() to see
146
143
  # a list of valid options. [0]
147
144
  #
148
145
  # == Exceptions
@@ -152,17 +149,19 @@ module Prawn
152
149
  # Raises <tt>Prawn::Errrors::CannotFit</tt> if not wide enough to print
153
150
  # any text
154
151
  #
155
- def text(string, options={})
152
+ def text(string, options = {})
156
153
  return false if string.nil?
154
+
157
155
  # we modify the options. don't change the user's hash
158
156
  options = options.dup
159
157
 
160
- if p = options[:inline_format]
158
+ p = options[:inline_format]
159
+ if p
161
160
  p = [] unless p.is_a?(Array)
162
161
  options.delete(:inline_format)
163
- array = self.text_formatter.format(string, *p)
162
+ array = text_formatter.format(string, *p)
164
163
  else
165
- array = [{ :text => string }]
164
+ array = [{ text: string }]
166
165
  end
167
166
 
168
167
  formatted_text(array, options)
@@ -188,37 +187,33 @@ module Prawn
188
187
  #
189
188
  # Same as for #text
190
189
  #
191
- def formatted_text(array, options={})
190
+ def formatted_text(array, options = {})
192
191
  options = inspect_options_for_text(options.dup)
193
192
 
194
- if color = options.delete(:color)
195
- array = array.map do |fragment|
196
- fragment[:color] ? fragment : fragment.merge(:color => color)
197
- end
193
+ color = options.delete(:color)
194
+ if color
195
+ array =
196
+ array.map do |fragment|
197
+ fragment[:color] ? fragment : fragment.merge(color: color)
198
+ end
198
199
  end
199
200
 
200
201
  if @indent_paragraphs
201
- self.text_formatter.array_paragraphs(array).each do |paragraph|
202
- options[:skip_encoding] = false
202
+ text_formatter.array_paragraphs(array).each do |paragraph|
203
203
  remaining_text = draw_indented_formatted_line(paragraph, options)
204
- options[:skip_encoding] = true
205
-
206
- if @no_text_printed
207
- # unless this paragraph was an empty line
208
- unless @all_text_printed
209
- @bounding_box.move_past_bottom
210
- options[:skip_encoding] = false
211
- remaining_text = draw_indented_formatted_line(paragraph, options)
212
- options[:skip_encoding] = true
213
- end
204
+
205
+ if @no_text_printed && !@all_text_printed
206
+ @bounding_box.move_past_bottom
207
+ remaining_text = draw_indented_formatted_line(paragraph, options)
214
208
  end
215
209
 
216
- remaining_text = fill_formatted_text_box(remaining_text, options)
217
- draw_remaining_formatted_text_on_new_pages(remaining_text, options)
210
+ unless @all_text_printed
211
+ remaining_text = fill_formatted_text_box(remaining_text, options)
212
+ draw_remaining_formatted_text_on_new_pages(remaining_text, options)
213
+ end
218
214
  end
219
215
  else
220
216
  remaining_text = fill_formatted_text_box(array, options)
221
- options[:skip_encoding] = true
222
217
  draw_remaining_formatted_text_on_new_pages(remaining_text, options)
223
218
  end
224
219
  end
@@ -242,7 +237,8 @@ module Prawn
242
237
  # == Rotation
243
238
  #
244
239
  # Text can be rotated before it is placed on the canvas by specifying the
245
- # <tt>:rotate</tt> option with a given angle. Rotation occurs counter-clockwise.
240
+ # <tt>:rotate</tt> option with a given angle. Rotation occurs
241
+ # counter-clockwise.
246
242
  #
247
243
  # == Encoding
248
244
  #
@@ -259,7 +255,8 @@ module Prawn
259
255
  #
260
256
  # == Options (default values marked in [])
261
257
  #
262
- # <tt>:at</tt>:: <tt>[x, y]</tt>(required). The position at which to start the text
258
+ # <tt>:at</tt>:: <tt>[x, y]</tt>(required). The position at which to start
259
+ # the text
263
260
  # <tt>:kerning</tt>:: <tt>boolean</tt>. Whether or not to use kerning (if it
264
261
  # is available with the current font)
265
262
  # [value of default_kerning?]
@@ -283,11 +280,29 @@ module Prawn
283
280
  text = text.to_s.dup
284
281
  save_font do
285
282
  process_text_options(options)
286
- font.normalize_encoding!(text)
283
+ text = font.normalize_encoding(text)
287
284
  font_size(options[:size]) { draw_text!(text, options) }
288
285
  end
289
286
  end
290
287
 
288
+ # Low level text placement method. All font and size alterations
289
+ # should already be set
290
+ #
291
+ def draw_text!(text, options)
292
+ unless font.unicode? || font.class.hide_m17n_warning || text.ascii_only?
293
+ warn "PDF's built-in fonts have very limited support for " \
294
+ "internationalized text.\nIf you need full UTF-8 support, " \
295
+ "consider using an external font instead.\n\nTo disable this " \
296
+ "warning, add the following line to your code:\n" \
297
+ "Prawn::Fonts::AFM.hide_m17n_warning = true\n"
298
+
299
+ font.class.hide_m17n_warning = true
300
+ end
301
+
302
+ x, y = map_to_absolute(options[:at])
303
+ add_text_content(text, x, y, options)
304
+ end
305
+
291
306
  # Gets height of text in PDF points.
292
307
  # Same options as #text, except as noted.
293
308
  # Not compatible with :indent_paragraphs option
@@ -304,8 +319,8 @@ module Prawn
304
319
  # Raises <tt>Prawn::Errrors::CannotFit</tt> if not wide enough to print
305
320
  # any text
306
321
  #
307
- def height_of(string, options={})
308
- height_of_formatted([{ :text => string }], options)
322
+ def height_of(string, options = {})
323
+ height_of_formatted([{ text: string }], options)
309
324
  end
310
325
 
311
326
  # Gets height of formatted text in PDF points.
@@ -318,16 +333,17 @@ module Prawn
318
333
  # :size => 24,
319
334
  # :styles => [:bold, :italic] }])
320
335
  #
321
- def height_of_formatted(array, options={})
336
+ def height_of_formatted(array, options = {})
322
337
  if options[:indent_paragraphs]
323
- raise NotImplementedError, ":indent_paragraphs option not available" +
324
- "with height_of"
338
+ raise NotImplementedError,
339
+ ':indent_paragraphs option not available with height_of'
325
340
  end
326
341
  process_final_gap_option(options)
327
- box = Text::Formatted::Box.new(array,
328
- options.merge(:height => 100000000,
329
- :document => self))
330
- box.render(:dry_run => true)
342
+ box = Text::Formatted::Box.new(
343
+ array,
344
+ options.merge(height: 100_000_000, document: self)
345
+ )
346
+ box.render(dry_run: true)
331
347
 
332
348
  height = box.height
333
349
  height += box.line_gap + box.leading if @final_gap
@@ -337,7 +353,7 @@ module Prawn
337
353
  private
338
354
 
339
355
  def draw_remaining_formatted_text_on_new_pages(remaining_text, options)
340
- while remaining_text.length > 0
356
+ until remaining_text.empty?
341
357
  @bounding_box.move_past_bottom
342
358
  previous_remaining_text = remaining_text
343
359
  remaining_text = fill_formatted_text_box(remaining_text, options)
@@ -346,8 +362,15 @@ module Prawn
346
362
  end
347
363
 
348
364
  def draw_indented_formatted_line(string, options)
349
- indent(@indent_paragraphs) do
350
- fill_formatted_text_box(string, options.dup.merge(:single_line => true))
365
+ gap =
366
+ if options.fetch(:direction, text_direction) == :ltr
367
+ [@indent_paragraphs, 0]
368
+ else
369
+ [0, @indent_paragraphs]
370
+ end
371
+
372
+ indent(*gap) do
373
+ fill_formatted_text_box(string, options.dup.merge(single_line: true))
351
374
  end
352
375
  end
353
376
 
@@ -365,33 +388,41 @@ module Prawn
365
388
  end
366
389
 
367
390
  def merge_text_box_positioning_options(options)
368
- bottom = @bounding_box.stretchy? ? @margin_box.absolute_bottom :
369
- @bounding_box.absolute_bottom
391
+ bottom =
392
+ if @bounding_box.stretchy?
393
+ @margin_box.absolute_bottom
394
+ else
395
+ @bounding_box.absolute_bottom
396
+ end
370
397
 
371
398
  options[:height] = y - bottom
372
399
  options[:width] = bounds.width
373
- options[:at] = [@bounding_box.left_side - @bounding_box.absolute_left,
374
- y - @bounding_box.absolute_bottom]
400
+ options[:at] = [
401
+ @bounding_box.left_side - @bounding_box.absolute_left,
402
+ y - @bounding_box.absolute_bottom
403
+ ]
375
404
  end
376
405
 
377
406
  def inspect_options_for_draw_text(options)
378
407
  if options[:at].nil?
379
- raise ArgumentError, "The :at option is required for draw_text"
408
+ raise ArgumentError, 'The :at option is required for draw_text'
380
409
  elsif options[:align]
381
- raise ArgumentError, "The :align option does not work with draw_text"
410
+ raise ArgumentError, 'The :align option does not work with draw_text'
382
411
  end
383
- if options[:kerning].nil? then
412
+
413
+ if options[:kerning].nil?
384
414
  options[:kerning] = default_kerning?
385
415
  end
386
- valid_options = PDF::Core::Text::VALID_OPTIONS + [:at, :rotate]
416
+ valid_options = PDF::Core::Text::VALID_OPTIONS + %i[at rotate]
387
417
  Prawn.verify_options(valid_options, options)
388
418
  options
389
419
  end
390
420
 
391
421
  def inspect_options_for_text(options)
392
422
  if options[:at]
393
- raise ArgumentError, ":at is no longer a valid option with text." +
394
- "use draw_text or text_box instead"
423
+ raise ArgumentError,
424
+ ':at is no longer a valid option with text.' \
425
+ 'use draw_text or text_box instead'
395
426
  end
396
427
  process_final_gap_option(options)
397
428
  process_indent_paragraphs_option(options)
@@ -409,13 +440,17 @@ module Prawn
409
440
  options.delete(:indent_paragraphs)
410
441
  end
411
442
 
412
- def move_text_position(dy)
413
- bottom = @bounding_box.stretchy? ? @margin_box.absolute_bottom :
414
- @bounding_box.absolute_bottom
443
+ def move_text_position(amount)
444
+ bottom =
445
+ if @bounding_box.stretchy?
446
+ @margin_box.absolute_bottom
447
+ else
448
+ @bounding_box.absolute_bottom
449
+ end
415
450
 
416
- @bounding_box.move_past_bottom if (y - dy) < bottom
451
+ @bounding_box.move_past_bottom if (y - amount) < bottom
417
452
 
418
- self.y -= dy
453
+ self.y -= amount
419
454
  end
420
455
  end
421
456
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # transformation_stack.rb : Stores the transformations that have been applied to
4
+ # the document
5
+ #
6
+ # Copyright 2015, Roger Nesbitt. All Rights Reserved.
7
+ #
8
+ # This is free software. Please see the LICENSE and COPYING files for details.
9
+
10
+ require 'matrix'
11
+
12
+ # rubocop: disable Metrics/ParameterLists, Naming/MethodParameterName
13
+ module Prawn
14
+ module TransformationStack
15
+ def add_to_transformation_stack(a, b, c, d, e, f)
16
+ @transformation_stack ||= [[]]
17
+ @transformation_stack.last.push([a, b, c, d, e, f].map(&:to_f))
18
+ end
19
+
20
+ def save_transformation_stack
21
+ @transformation_stack ||= [[]]
22
+ @transformation_stack.push(@transformation_stack.last.dup)
23
+ end
24
+
25
+ def restore_transformation_stack
26
+ @transformation_stack&.pop
27
+ end
28
+
29
+ def current_transformation_matrix_with_translation(x = 0, y = 0)
30
+ transformations = (@transformation_stack || [[]]).last
31
+
32
+ matrix = Matrix.identity(3)
33
+
34
+ transformations.each do |a, b, c, d, e, f|
35
+ matrix *= Matrix[[a, c, e], [b, d, f], [0, 0, 1]]
36
+ end
37
+
38
+ matrix *= Matrix[[1, 0, x], [0, 1, y], [0, 0, 1]]
39
+
40
+ matrix.to_a[0..1].transpose.flatten
41
+ end
42
+ end
43
+ end
44
+ # rubocop: enable Metrics/ParameterLists, Naming/MethodParameterName
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # utilities.rb : General-purpose utility classes which don't fit anywhere else
4
4
  #
@@ -6,41 +6,29 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
- require 'thread'
10
-
11
9
  module Prawn
12
-
13
- # Throughout the Prawn codebase, repeated calculations which can benefit from caching are made
14
- # In some cases, caching and reusing results can not only save CPU cycles but also greatly
15
- # reduce memory requirements
10
+ # Throughout the Prawn codebase, repeated calculations which can benefit from
11
+ # caching are made.
12
+ # In some cases, caching and reusing results can not only save CPU cycles but
13
+ # also greatly reduce memory requirements
16
14
  # But at the same time, we don't want to throw away thread safety
17
15
  # We have two interchangeable thread-safe cache implementations:
18
16
 
19
17
  # @private
20
18
  class SynchronizedCache
21
- # As an optimization, this could access the hash directly on VMs with a global interpreter lock (like MRI)
19
+ # As an optimization, this could access the hash directly on VMs with
20
+ # a global interpreter lock (like MRI)
22
21
  def initialize
23
22
  @cache = {}
24
23
  @mutex = Mutex.new
25
24
  end
25
+
26
26
  def [](key)
27
27
  @mutex.synchronize { @cache[key] }
28
28
  end
29
- def []=(key,value)
30
- @mutex.synchronize { @cache[key] = value }
31
- end
32
- end
33
29
 
34
- # @private
35
- class ThreadLocalCache
36
- def initialize
37
- @cache_id = "cache_#{self.object_id}".to_sym
38
- end
39
- def [](key)
40
- (Thread.current[@cache_id] ||= {})[key]
41
- end
42
- def []=(key,value)
43
- (Thread.current[@cache_id] ||= {})[key] = value
30
+ def []=(key, value)
31
+ @mutex.synchronize { @cache[key] = value }
44
32
  end
45
33
  end
46
34
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prawn
4
+ VERSION = '2.4.0'
5
+ end
data/lib/prawn/view.rb ADDED
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ # prawn/view.rb : Implements a mixin for Prawn's DSL
4
+ #
5
+ # This is free software. Please see the LICENSE and COPYING files for details.
6
+
7
+ module Prawn
8
+ # This mixin allows you to create modular Prawn code without the
9
+ # need to create subclasses of Prawn::Document.
10
+ #
11
+ # class Greeter
12
+ # include Prawn::View
13
+ #
14
+ # # Optional override: allows you to set document options or even use
15
+ # # a custom document class
16
+ # def document
17
+ # @document ||= Prawn::Document.new(page_size: 'A4')
18
+ # end
19
+ #
20
+ # def initialize(name)
21
+ # @name = name
22
+ # end
23
+ #
24
+ # def say_hello
25
+ # text "Hello, #{@name}!"
26
+ # end
27
+ #
28
+ # def say_goodbye
29
+ # font("Courier") do
30
+ # text "Goodbye, #{@name}!"
31
+ # end
32
+ # end
33
+ # end
34
+ #
35
+ # greeter = Greeter.new("Gregory")
36
+ #
37
+ # greeter.say_hello
38
+ # greeter.say_goodbye
39
+ #
40
+ # greeter.save_as("greetings.pdf")
41
+ #
42
+ # The short story about why you should use this mixin rather than
43
+ # creating subclasses of +Prawn::Document+ is that it helps
44
+ # prevent accidental conflicts between your code and Prawn's
45
+ # code.
46
+ #
47
+ # Here's the slightly longer story...
48
+ #
49
+ # By using composition rather than inheritance under the hood, this
50
+ # mixin allows you to keep your state separate from +Prawn::Document+'s
51
+ # state, and also will prevent unexpected method name collisions due
52
+ # to late binding effects.
53
+ #
54
+ # This mixin is mostly meant for extending Prawn's functionality
55
+ # with your own additions, but you can also use it to replace or
56
+ # wrap existing Prawn methods. Calling +super+ will still work
57
+ # as expected, and alternatively you can explictly call
58
+ # +document.some_method+ to delegate to Prawn where needed.
59
+ module View
60
+ # @group Experimental API
61
+
62
+ # Lazily instantiates a +Prawn::Document+ object.
63
+ #
64
+ # You can also redefine this method in your own classes to use
65
+ # a custom document class.
66
+ def document
67
+ @document ||= Prawn::Document.new
68
+ end
69
+
70
+ # Delegates all unhandled calls to object returned by +document+ method.
71
+ # (which is an instance of Prawn::Document by default)
72
+ def method_missing(method_name, *arguments, &block)
73
+ return super unless document.respond_to?(method_name)
74
+
75
+ document.public_send(method_name, *arguments, &block)
76
+ end
77
+
78
+ def respond_to_missing?(method_name, _include_all = false)
79
+ document.respond_to?(method_name) || super
80
+ end
81
+
82
+ # Syntactic sugar that uses +instance_eval+ under the hood to provide
83
+ # a block-based DSL.
84
+ #
85
+ # greeter.update do
86
+ # say_hello
87
+ # say_goodbye
88
+ # end
89
+ #
90
+ def update(&block)
91
+ instance_eval(&block)
92
+ end
93
+
94
+ # Syntatic sugar that calls +document.render_file+ under the hood.
95
+ #
96
+ # greeter.save_as("greetings.pdf")
97
+ def save_as(filename)
98
+ document.render_file(filename)
99
+ end
100
+ end
101
+ end
data/lib/prawn.rb CHANGED
@@ -1,21 +1,17 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # Welcome to Prawn, the best PDF Generation library ever.
4
4
  # This documentation covers user level functionality.
5
5
  #
6
- require "set"
6
+ require 'set'
7
7
 
8
8
  require 'ttfunk'
9
- require "pdf/core"
9
+ require 'pdf/core'
10
10
 
11
11
  module Prawn
12
- VERSION = "1.1.0"
13
-
14
- extend self
15
-
16
12
  file = __FILE__
17
13
  file = File.readlink(file) if File.symlink?(file)
18
- dir = File.dirname(file)
14
+ dir = File.dirname(file)
19
15
 
20
16
  # The base source directory for Prawn as installed on the system
21
17
  #
@@ -25,7 +21,7 @@ module Prawn
25
21
 
26
22
  FLOAT_PRECISION = 1.0e-9
27
23
 
28
- # Whe set to true, Prawn will verify hash options to ensure only valid keys
24
+ # When set to true, Prawn will verify hash options to ensure only valid keys
29
25
  # are used. Off by default.
30
26
  #
31
27
  # Example:
@@ -34,60 +30,49 @@ module Prawn
34
30
  # Detected unknown option(s): [:tomato]
35
31
  # Accepted options are: [:page_size, :page_layout, :left_margin, ...]
36
32
  #
37
- attr_accessor :debug # @private
33
+ # @private
34
+ attr_accessor :debug
35
+
36
+ module_function :debug, :debug=
37
+
38
+ module_function
38
39
 
39
- def verify_options(accepted, actual) # @private
40
+ # @private
41
+ def verify_options(accepted, actual)
40
42
  return unless debug || $DEBUG
41
- unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
43
+
44
+ unless (act = Set[*actual.keys]).subset?(acc = Set[*accepted])
42
45
  raise Prawn::Errors::UnknownOption,
43
- "\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
46
+ "\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" \
44
47
  "Accepted options are: #{accepted.inspect}"
45
48
  end
46
49
  yield if block_given?
47
50
  end
48
-
49
- module Configurable # @private
50
- def configuration(*args)
51
- @config ||= Marshal.load(Marshal.dump(default_configuration))
52
- if Hash === args[0]
53
- @config.update(args[0])
54
- elsif args.length > 1
55
- @config.values_at(*args)
56
- elsif args.length == 1
57
- @config[args[0]]
58
- else
59
- @config
60
- end
61
- end
62
-
63
- alias_method :C, :configuration
64
- end
65
51
  end
66
52
 
67
- require_relative "prawn/errors"
68
-
69
-
70
- require_relative "prawn/utilities"
71
- require_relative "prawn/text"
72
- require_relative "prawn/graphics"
73
- require_relative "prawn/images"
74
- require_relative "prawn/images/image"
75
- require_relative "prawn/images/jpg"
76
- require_relative "prawn/images/png"
77
- require_relative "prawn/stamp"
78
- require_relative "prawn/soft_mask"
79
- require_relative "prawn/security"
80
- require_relative "prawn/document"
81
- require_relative "prawn/font"
82
- require_relative "prawn/encoding"
83
- require_relative "prawn/measurements"
84
- require_relative "prawn/repeater"
85
- require_relative "prawn/outline"
86
- require_relative "prawn/grid"
87
-
88
- require_relative "prawn/image_handler"
89
-
90
-
53
+ require_relative 'prawn/version'
54
+
55
+ require_relative 'prawn/errors'
56
+
57
+ require_relative 'prawn/utilities'
58
+ require_relative 'prawn/text'
59
+ require_relative 'prawn/graphics'
60
+ require_relative 'prawn/images'
61
+ require_relative 'prawn/images/image'
62
+ require_relative 'prawn/images/jpg'
63
+ require_relative 'prawn/images/png'
64
+ require_relative 'prawn/stamp'
65
+ require_relative 'prawn/soft_mask'
66
+ require_relative 'prawn/security'
67
+ require_relative 'prawn/transformation_stack'
68
+ require_relative 'prawn/document'
69
+ require_relative 'prawn/font'
70
+ require_relative 'prawn/measurements'
71
+ require_relative 'prawn/repeater'
72
+ require_relative 'prawn/outline'
73
+ require_relative 'prawn/grid'
74
+ require_relative 'prawn/view'
75
+ require_relative 'prawn/image_handler'
91
76
 
92
77
  Prawn.image_handler.register(Prawn::Images::PNG)
93
78
  Prawn.image_handler.register(Prawn::Images::JPG)