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
data/lib/prawn/font.rb CHANGED
@@ -1,19 +1,17 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # font.rb : The Prawn font class
4
4
  #
5
5
  # Copyright May 2008, Gregory Brown / James Healy. All Rights Reserved.
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
  #
9
- require "prawn/font/afm"
10
- require "prawn/font/ttf"
11
- require "prawn/font/dfont"
12
- require "prawn/font_metric_cache"
9
+ require_relative 'font_metric_cache'
13
10
 
14
11
  module Prawn
15
-
16
12
  class Document
13
+ # @group Stable API
14
+
17
15
  # Without arguments, this returns the currently selected font. Otherwise,
18
16
  # it sets the current font. When a block is used, the font is applied
19
17
  # transactionally and is rolled back when the block exits.
@@ -24,8 +22,8 @@ module Prawn
24
22
  # font "Times-Roman"
25
23
  # text "Now using Times-Roman"
26
24
  #
27
- # font("Chalkboard.ttf") do
28
- # text "Using TTF font from file Chalkboard.ttf"
25
+ # font("DejaVuSans.ttf") do
26
+ # text "Using TTF font from file DejaVuSans.ttf"
29
27
  # font "Courier", :style => :bold
30
28
  # text "You see this in bold Courier"
31
29
  # end
@@ -34,8 +32,8 @@ module Prawn
34
32
  # end
35
33
  #
36
34
  # The :name parameter must be a string. It can be one of the 14 built-in
37
- # fonts supported by PDF, or the location of a TTF file. The Font::AFM::BUILT_INS
38
- # array specifies the valid built in font values.
35
+ # fonts supported by PDF, or the location of a TTF file. The
36
+ # Fonts::AFM::BUILT_INS array specifies the valid built in font values.
39
37
  #
40
38
  # If a ttf font is specified, the glyphs necessary to render your document
41
39
  # will be embedded in the rendered PDF. This should be your preferred option
@@ -43,11 +41,12 @@ module Prawn
43
41
  # make it more portable.
44
42
  #
45
43
  # The options parameter is an optional hash providing size and style. To use
46
- # the :style option you need to map those font styles to their respective font files.
44
+ # the :style option you need to map those font styles to their respective
45
+ # font files.
47
46
  # See font_families for more information.
48
47
  #
49
- def font(name=nil, options={})
50
- return((defined?(@font) && @font) || font("Helvetica")) if name.nil?
48
+ def font(name = nil, options = {})
49
+ return((defined?(@font) && @font) || font('Helvetica')) if name.nil?
51
50
 
52
51
  if state.pages.empty? && !state.page.in_stamp_stream?
53
52
  raise Prawn::Errors::NotOnPage
@@ -67,7 +66,10 @@ module Prawn
67
66
  @font
68
67
  end
69
68
 
69
+ # @method font_size(points=nil)
70
+ #
70
71
  # When called with no argument, returns the current font size.
72
+ #
71
73
  # When called with a single argument but no block, sets the current font
72
74
  # size. When a block is used, the font size is applied transactionally and
73
75
  # is rolled back when the block exits. You may still change the font size
@@ -90,18 +92,113 @@ module Prawn
90
92
  # When called without an argument, this method returns the current font
91
93
  # size.
92
94
  #
93
- def font_size(points=nil)
95
+ def font_size(points = nil)
94
96
  return @font_size unless points
97
+
95
98
  size_before_yield = @font_size
96
99
  @font_size = points
97
100
  block_given? ? yield : return
98
101
  @font_size = size_before_yield
99
102
  end
100
103
 
104
+ # Sets the font size
105
+ def font_size=(size)
106
+ font_size(size)
107
+ end
108
+
109
+ # Returns the width of the given string using the given font. If :size is
110
+ # not specified as one of the options, the string is measured using the
111
+ # current font size. You can also pass :kerning as an option to indicate
112
+ # whether kerning should be used when measuring the width (defaults to
113
+ # +false+).
114
+ #
115
+ # Note that the string _must_ be encoded properly for the font being used.
116
+ # For AFM fonts, this is WinAnsi. For TTF, make sure the font is encoded as
117
+ # UTF-8. You can use the Font#normalize_encoding method to make sure strings
118
+ # are in an encoding appropriate for the current font.
119
+ #--
120
+ # For the record, this method used to be a method of Font (and still
121
+ # delegates to width computations on Font). However, having the primary
122
+ # interface for calculating string widths exist on Font made it tricky to
123
+ # write extensions for Prawn in which widths are computed differently (e.g.,
124
+ # taking formatting tags into account, or the like).
125
+ #
126
+ # By putting width_of here, on Document itself, extensions may easily
127
+ # override it and redefine the width calculation behavior.
128
+ #++
129
+ def width_of(string, options = {})
130
+ if options.key? :inline_format
131
+ p = options[:inline_format]
132
+ p = [] unless p.is_a?(Array)
133
+
134
+ # Build up an Arranger with the entire string on one line, finalize it,
135
+ # and find its width.
136
+ arranger = Prawn::Text::Formatted::Arranger.new(self, options)
137
+ arranger.consumed = text_formatter.format(string, *p)
138
+ arranger.finalize_line
139
+
140
+ arranger.line_width
141
+ else
142
+ width_of_string(string, options)
143
+ end
144
+ end
145
+
146
+ # Hash that maps font family names to their styled individual font names.
147
+ #
148
+ # To add support for another font family, append to this hash, e.g:
149
+ #
150
+ # pdf.font_families.update(
151
+ # "MyTrueTypeFamily" => { :bold => "foo-bold.ttf",
152
+ # :italic => "foo-italic.ttf",
153
+ # :bold_italic => "foo-bold-italic.ttf",
154
+ # :normal => "foo.ttf" })
155
+ #
156
+ # This will then allow you to use the fonts like so:
157
+ #
158
+ # pdf.font("MyTrueTypeFamily", :style => :bold)
159
+ # pdf.text "Some bold text"
160
+ # pdf.font("MyTrueTypeFamily")
161
+ # pdf.text "Some normal text"
162
+ #
163
+ # This assumes that you have appropriate TTF fonts for each style you
164
+ # wish to support.
165
+ #
166
+ # By default the styles :bold, :italic, :bold_italic, and :normal are
167
+ # defined for fonts "Courier", "Times-Roman" and "Helvetica". When
168
+ # defining your own font families, you can map any or all of these
169
+ # styles to whatever font files you'd like.
170
+ #
171
+ def font_families
172
+ @font_families ||= {}.merge!(
173
+ 'Courier' => {
174
+ bold: 'Courier-Bold',
175
+ italic: 'Courier-Oblique',
176
+ bold_italic: 'Courier-BoldOblique',
177
+ normal: 'Courier'
178
+ },
179
+
180
+ 'Times-Roman' => {
181
+ bold: 'Times-Bold',
182
+ italic: 'Times-Italic',
183
+ bold_italic: 'Times-BoldItalic',
184
+ normal: 'Times-Roman'
185
+ },
186
+
187
+ 'Helvetica' => {
188
+ bold: 'Helvetica-Bold',
189
+ italic: 'Helvetica-Oblique',
190
+ bold_italic: 'Helvetica-BoldOblique',
191
+ normal: 'Helvetica'
192
+ }
193
+ )
194
+ end
195
+
196
+ # @group Experimental API
197
+
101
198
  # Sets the font directly, given an actual Font object
102
199
  # and size.
103
200
  #
104
- def set_font(font, size=nil) # :nodoc:
201
+ def set_font(font, size = nil) # :nodoc:
105
202
  @font = font
106
203
  @font_size = size if size
107
204
  end
@@ -110,7 +207,7 @@ module Prawn
110
207
  # finishes, the original font is restored.
111
208
  #
112
209
  def save_font
113
- @font ||= find_font("Helvetica")
210
+ @font ||= find_font('Helvetica')
114
211
  original_font = @font
115
212
  original_size = @font_size
116
213
 
@@ -120,31 +217,40 @@ module Prawn
120
217
  end
121
218
 
122
219
  # Looks up the given font using the given criteria. Once a font has been
123
- # found by that matches the criteria, it will be cached to subsequent lookups
124
- # for that font will return the same object.
125
- #--
220
+ # found by that matches the criteria, it will be cached to subsequent
221
+ # lookups for that font will return the same object.
222
+ # --
126
223
  # Challenges involved: the name alone is not sufficient to uniquely identify
127
224
  # a font (think dfont suitcases that can hold multiple different fonts in a
128
225
  # single file). Thus, the :name key is included in the cache key.
129
226
  #
130
227
  # It is further complicated, however, since fonts in some formats (like the
131
228
  # dfont suitcases) can be identified either by numeric index, OR by their
132
- # name within the suitcase, and both should hash to the same font object
133
- # (to avoid the font being embedded multiple times). This is not yet implemented,
134
- # which means if someone selects a font both by name, and by index, the
135
- # font will be embedded twice. Since we do font subsetting, this double
136
- # embedding won't be catastrophic, just annoying.
229
+ # name within the suitcase, and both should hash to the same font object (to
230
+ # avoid the font being embedded multiple times). This is not yet
231
+ # implemented, which means if someone selects a font both by name, and by
232
+ # index, the font will be embedded twice. Since we do font subsetting, this
233
+ # double embedding won't be catastrophic, just annoying.
137
234
  # ++
138
- def find_font(name, options={}) #:nodoc:
235
+ #
236
+ # @private
237
+ def find_font(name, options = {}) #:nodoc:
139
238
  if font_families.key?(name)
140
- family, name = name, font_families[name][options[:style] || :normal]
239
+ family = name
240
+ name = font_families[name][options[:style] || :normal]
141
241
  if name.is_a?(::Hash)
142
242
  options = options.merge(name)
143
243
  name = options[:file]
144
244
  end
145
245
  end
146
246
  key = "#{name}:#{options[:font] || 0}"
147
- font_registry[key] ||= Font.load(self, name, options.merge(:family => family))
247
+
248
+ if name.is_a? Prawn::Font
249
+ font_registry[key] = name
250
+ else
251
+ font_registry[key] ||=
252
+ Font.load(self, name, options.merge(family: family))
253
+ end
148
254
  end
149
255
 
150
256
  # Hash of Font objects keyed by names
@@ -153,89 +259,9 @@ module Prawn
153
259
  @font_registry ||= {}
154
260
  end
155
261
 
156
- # Hash that maps font family names to their styled individual font names.
157
- #
158
- # To add support for another font family, append to this hash, e.g:
159
- #
160
- # pdf.font_families.update(
161
- # "MyTrueTypeFamily" => { :bold => "foo-bold.ttf",
162
- # :italic => "foo-italic.ttf",
163
- # :bold_italic => "foo-bold-italic.ttf",
164
- # :normal => "foo.ttf" })
165
- #
166
- # This will then allow you to use the fonts like so:
167
- #
168
- # pdf.font("MyTrueTypeFamily", :style => :bold)
169
- # pdf.text "Some bold text"
170
- # pdf.font("MyTrueTypeFamily")
171
- # pdf.text "Some normal text"
172
- #
173
- # This assumes that you have appropriate TTF fonts for each style you
174
- # wish to support.
175
- #
176
- # By default the styles :bold, :italic, :bold_italic, and :normal are
177
- # defined for fonts "Courier", "Times-Roman" and "Helvetica".
178
- #
179
- # You probably want to provide those four styles, but are free to define
180
- # custom ones, like :thin, and use them in font calls.
181
- #
182
- def font_families
183
- @font_families ||= {}.merge!(
184
- { "Courier" => { :bold => "Courier-Bold",
185
- :italic => "Courier-Oblique",
186
- :bold_italic => "Courier-BoldOblique",
187
- :normal => "Courier" },
188
-
189
- "Times-Roman" => { :bold => "Times-Bold",
190
- :italic => "Times-Italic",
191
- :bold_italic => "Times-BoldItalic",
192
- :normal => "Times-Roman" },
193
-
194
- "Helvetica" => { :bold => "Helvetica-Bold",
195
- :italic => "Helvetica-Oblique",
196
- :bold_italic => "Helvetica-BoldOblique",
197
- :normal => "Helvetica" }
198
- })
199
- end
200
-
201
- # Returns the width of the given string using the given font. If :size is not
202
- # specified as one of the options, the string is measured using the current
203
- # font size. You can also pass :kerning as an option to indicate whether
204
- # kerning should be used when measuring the width (defaults to +false+).
205
- #
206
- # Note that the string _must_ be encoded properly for the font being used.
207
- # For AFM fonts, this is WinAnsi. For TTF, make sure the font is encoded as
208
- # UTF-8. You can use the Font#normalize_encoding method to make sure strings
209
- # are in an encoding appropriate for the current font.
210
- #--
211
- # For the record, this method used to be a method of Font (and still delegates
212
- # to width computations on Font). However, having the primary interface for
213
- # calculating string widths exist on Font made it tricky to write extensions
214
- # for Prawn in which widths are computed differently (e.g., taking formatting
215
- # tags into account, or the like).
216
- #
217
- # By putting width_of here, on Document itself, extensions may easily override
218
- # it and redefine the width calculation behavior.
219
- #++
220
- def width_of(string, options={})
221
- if p = options[:inline_format]
222
- p = [] unless p.is_a?(Array)
223
-
224
- # Build up an Arranger with the entire string on one line, finalize it,
225
- # and find its width.
226
- arranger = Prawn::Text::Formatted::Arranger.new(self, options)
227
- arranger.consumed = self.text_formatter.format(string, *p)
228
- arranger.finalize_line
229
-
230
- arranger.line_width
231
- else
232
- width_of_string(string, options)
233
- end
234
- end
235
-
236
262
  private
237
263
 
238
- def width_of_inline_formatted_string(string, options={})
264
+ def width_of_inline_formatted_string(string, options = {})
239
265
  # Build up an Arranger with the entire string on one line, finalize it,
240
266
  # and find its width.
241
267
  arranger = Prawn::Text::Formatted::Arranger.new(self, options)
@@ -245,14 +271,25 @@ module Prawn
245
271
  arranger.line_width
246
272
  end
247
273
 
248
- def width_of_string(string, options={})
249
- font_metric_cache.width_of( string, options )
274
+ def width_of_string(string, options = {})
275
+ font_metric_cache.width_of(string, options)
250
276
  end
251
277
  end
252
278
 
253
279
  # Provides font information and helper functions.
254
280
  #
255
281
  class Font
282
+ require_relative 'fonts/afm'
283
+ require_relative 'fonts/ttf'
284
+ require_relative 'fonts/dfont'
285
+ require_relative 'fonts/otf'
286
+ require_relative 'fonts/ttc'
287
+
288
+ # @deprecated
289
+ AFM = Fonts::AFM
290
+ TTF = Fonts::TTF
291
+ DFont = Fonts::DFont
292
+ TTC = Fonts::TTC
256
293
 
257
294
  # The current font name
258
295
  attr_reader :name
@@ -264,24 +301,37 @@ module Prawn
264
301
  attr_reader :options
265
302
 
266
303
  # Shortcut interface for constructing a font object. Filenames of the form
267
- # *.ttf will call Font::TTF.new, *.dfont Font::DFont.new, and anything else
268
- # will be passed through to Font::AFM.new()
269
- #
270
- def self.load(document,name,options={})
271
- case name.to_s
272
- when /\.ttf$/i then TTF.new(document, name, options)
273
- when /\.dfont$/i then DFont.new(document, name, options)
274
- when /\.afm$/i then AFM.new(document, name, options)
275
- else AFM.new(document, name, options)
304
+ # *.ttf will call Fonts::TTF.new, *.dfont Fonts::DFont.new, *.ttc goes to
305
+ # Fonts::TTC.new, and anything else will be passed through to
306
+ # Fonts::AFM.new()
307
+ def self.load(document, src, options = {})
308
+ case font_format(src, options)
309
+ when 'ttf' then TTF.new(document, src, options)
310
+ when 'otf' then Fonts::OTF.new(document, src, options)
311
+ when 'dfont' then DFont.new(document, src, options)
312
+ when 'ttc' then TTC.new(document, src, options)
313
+ else AFM.new(document, src, options)
314
+ end
315
+ end
316
+
317
+ def self.font_format(src, options)
318
+ return options.fetch(:format, 'ttf') if src.respond_to? :read
319
+
320
+ case src.to_s
321
+ when /\.ttf$/i then 'ttf'
322
+ when /\.otf$/i then 'otf'
323
+ when /\.dfont$/i then 'dfont'
324
+ when /\.ttc$/i then 'ttc'
325
+ else 'afm'
276
326
  end
277
327
  end
278
328
 
279
- def initialize(document,name,options={}) #:nodoc:
280
- @document = document
281
- @name = name
282
- @options = options
329
+ def initialize(document, name, options = {}) #:nodoc:
330
+ @document = document
331
+ @name = name
332
+ @options = options
283
333
 
284
- @family = options[:family]
334
+ @family = options[:family]
285
335
 
286
336
  @identifier = generate_unique_id
287
337
 
@@ -310,15 +360,19 @@ module Prawn
310
360
  # font. The string is expected to be UTF-8 going in. It will be re-encoded
311
361
  # and the new string will be returned. For an in-place (destructive)
312
362
  # version, see normalize_encoding!.
313
- def normalize_encoding(string)
314
- raise NotImplementedError, "subclasses of Prawn::Font must implement #normalize_encoding"
363
+ def normalize_encoding(_string)
364
+ raise NotImplementedError,
365
+ 'subclasses of Prawn::Font must implement #normalize_encoding'
315
366
  end
316
367
 
317
368
  # Destructive version of normalize_encoding; normalizes the encoding of a
318
369
  # string in place.
319
370
  #
371
+ # @deprecated
320
372
  def normalize_encoding!(str)
321
- str.replace(normalize_encoding(str))
373
+ warn 'Font#normalize_encoding! is deprecated. ' \
374
+ 'Please use non-mutating version Font#normalize_encoding instead.'
375
+ str.dup.replace(normalize_encoding(str))
322
376
  end
323
377
 
324
378
  # Gets height of current font in PDF points at the given font size
@@ -340,11 +394,13 @@ module Prawn
340
394
  #
341
395
  def add_to_current_page(subset)
342
396
  @references[subset] ||= register(subset)
343
- @document.state.page.fonts.merge!(identifier_for(subset) => @references[subset])
397
+ @document.state.page.fonts.merge!(
398
+ identifier_for(subset) => @references[subset]
399
+ )
344
400
  end
345
401
 
346
402
  def identifier_for(subset) #:nodoc:
347
- "#{@identifier}.#{subset}"
403
+ "#{@identifier}.#{subset}".to_sym
348
404
  end
349
405
 
350
406
  def inspect #:nodoc:
@@ -357,49 +413,42 @@ module Prawn
357
413
  # Prawn::Table::Text#styled_with_of_single_character)
358
414
  #
359
415
  def hash #:nodoc:
360
- [ self.class, self.name, self.family, size ].hash
416
+ [self.class, name, family, size].hash
361
417
  end
362
418
 
363
419
  # Compliments the #hash implementation above
364
420
  #
365
- def eql?( other ) #:nodoc:
366
- self.class == other.class && self.name == other.name &&
367
- self.family == other.family && size == other.send(:size)
421
+ def eql?(other) #:nodoc:
422
+ self.class == other.class && name == other.name &&
423
+ family == other.family && size == other.size
368
424
  end
369
425
 
370
426
  private
371
427
 
372
- # generate a font identifier that hasn't been used on the curretn page yet
428
+ # generate a font identifier that hasn't been used on the current page yet
373
429
  #
374
430
  def generate_unique_id
375
- offset, id = 0, nil
431
+ key = nil
432
+ font_count = @document.font_registry.size + 1
433
+ loop do
434
+ key = :"F#{font_count}"
435
+ break if key_is_unique?(key)
376
436
 
377
- while id.nil? || page_contains_font_id?(id)
378
- offset += 1
379
- id = :"F#{@document.font_registry.size + offset}"
437
+ font_count += 1
380
438
  end
381
-
382
- id
439
+ key
383
440
  end
384
441
 
385
- # Returns true if the provided font identifier already exists in the document.
386
- # This is used when adding new fonts to a document to ensure we don't step
387
- # on fonts imported from a template.
388
- #
389
- # page_contains_font_id?("F1")
390
- # => true
391
- #
392
- def page_contains_font_id?(id)
393
- id = id.to_s
394
- @document.state.page.fonts.keys.any? { |exist_id|
395
- exist_id.to_s[0,id.size] == id
396
- }
442
+ def key_is_unique?(test_key)
443
+ @document.state.page.fonts.keys.none? do |key|
444
+ key.to_s.start_with?("#{test_key}.")
445
+ end
397
446
  end
398
447
 
448
+ protected
449
+
399
450
  def size
400
451
  @document.font_size
401
452
  end
402
-
403
453
  end
404
-
405
454
  end
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # font_metric_cache.rb : The Prawn font class
4
4
  #
5
5
  # Copyright Dec 2012, Kenneth Kalmer. All Rights Reserved.
@@ -8,38 +8,42 @@
8
8
  #
9
9
 
10
10
  module Prawn
11
-
12
11
  # Cache used internally by Prawn::Document instances to calculate the width
13
12
  # of various strings for layout purposes.
13
+ #
14
+ # @private
14
15
  class FontMetricCache
16
+ CacheEntry = Struct.new(:font, :options, :string)
15
17
 
16
- CacheEntry = Struct.new( :font, :options, :string )
17
-
18
- def initialize( document )
18
+ def initialize(document)
19
19
  @document = document
20
20
 
21
21
  @cache = {}
22
22
  end
23
23
 
24
- def width_of( string, options )
25
- f = if options[:style]
26
- # override style with :style => :bold
27
- @document.find_font(@document.font ? @document.font.name : 'Helvetica',
28
- :style => options[:style])
29
- else
30
- @document.font
31
- end
24
+ def width_of(string, options)
25
+ f =
26
+ if options[:style]
27
+ # override style with :style => :bold
28
+ @document.find_font(@document.font.family, style: options[:style])
29
+ else
30
+ @document.font
31
+ end
32
+
33
+ encoded_string = f.normalize_encoding(string)
32
34
 
33
- key = CacheEntry.new( f, options, string )
35
+ key = CacheEntry.new(f, options, encoded_string)
34
36
 
35
- unless length = @cache[ key ]
36
- length = @cache[ key ] = f.compute_width_of(string, options)
37
+ @cache[key] ||= f.compute_width_of(encoded_string, options)
38
+
39
+ length = @cache[key]
40
+
41
+ character_count = @document.font.character_count(encoded_string)
42
+ if character_count.positive?
43
+ length += @document.character_spacing * (character_count - 1)
37
44
  end
38
45
 
39
- length +
40
- (@document.character_spacing * @document.font.character_count(string))
46
+ length
41
47
  end
42
-
43
48
  end
44
-
45
49
  end