prawn 1.1.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
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)