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/font.rb CHANGED
@@ -1,18 +1,14 @@
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_relative "font/afm"
10
- require_relative "font/ttf"
11
- require_relative "font/dfont"
12
- require_relative "font_metric_cache"
9
+ require_relative 'font_metric_cache'
13
10
 
14
11
  module Prawn
15
-
16
12
  class Document
17
13
  # @group Stable API
18
14
 
@@ -36,8 +32,8 @@ module Prawn
36
32
  # end
37
33
  #
38
34
  # The :name parameter must be a string. It can be one of the 14 built-in
39
- # fonts supported by PDF, or the location of a TTF file. The Font::AFM::BUILT_INS
40
- # 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.
41
37
  #
42
38
  # If a ttf font is specified, the glyphs necessary to render your document
43
39
  # will be embedded in the rendered PDF. This should be your preferred option
@@ -45,11 +41,12 @@ module Prawn
45
41
  # make it more portable.
46
42
  #
47
43
  # The options parameter is an optional hash providing size and style. To use
48
- # 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.
49
46
  # See font_families for more information.
50
47
  #
51
- def font(name=nil, options={})
52
- 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?
53
50
 
54
51
  if state.pages.empty? && !state.page.in_stamp_stream?
55
52
  raise Prawn::Errors::NotOnPage
@@ -95,8 +92,9 @@ module Prawn
95
92
  # When called without an argument, this method returns the current font
96
93
  # size.
97
94
  #
98
- def font_size(points=nil)
95
+ def font_size(points = nil)
99
96
  return @font_size unless points
97
+
100
98
  size_before_yield = @font_size
101
99
  @font_size = points
102
100
  block_given? ? yield : return
@@ -108,33 +106,35 @@ module Prawn
108
106
  font_size(size)
109
107
  end
110
108
 
111
- # Returns the width of the given string using the given font. If :size is not
112
- # specified as one of the options, the string is measured using the current
113
- # font size. You can also pass :kerning as an option to indicate whether
114
- # kerning should be used when measuring the width (defaults to +false+).
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+).
115
114
  #
116
115
  # Note that the string _must_ be encoded properly for the font being used.
117
116
  # For AFM fonts, this is WinAnsi. For TTF, make sure the font is encoded as
118
117
  # UTF-8. You can use the Font#normalize_encoding method to make sure strings
119
118
  # are in an encoding appropriate for the current font.
120
119
  #--
121
- # For the record, this method used to be a method of Font (and still delegates
122
- # to width computations on Font). However, having the primary interface for
123
- # calculating string widths exist on Font made it tricky to write extensions
124
- # for Prawn in which widths are computed differently (e.g., taking formatting
125
- # tags into account, or the like).
126
- #
127
- # By putting width_of here, on Document itself, extensions may easily override
128
- # it and redefine the width calculation behavior.
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.
129
128
  #++
130
- def width_of(string, options={})
131
- if p = options[:inline_format]
129
+ def width_of(string, options = {})
130
+ if options.key? :inline_format
131
+ p = options[:inline_format]
132
132
  p = [] unless p.is_a?(Array)
133
133
 
134
134
  # Build up an Arranger with the entire string on one line, finalize it,
135
135
  # and find its width.
136
136
  arranger = Prawn::Text::Formatted::Arranger.new(self, options)
137
- arranger.consumed = self.text_formatter.format(string, *p)
137
+ arranger.consumed = text_formatter.format(string, *p)
138
138
  arranger.finalize_line
139
139
 
140
140
  arranger.line_width
@@ -170,21 +170,27 @@ module Prawn
170
170
  #
171
171
  def font_families
172
172
  @font_families ||= {}.merge!(
173
- { "Courier" => { :bold => "Courier-Bold",
174
- :italic => "Courier-Oblique",
175
- :bold_italic => "Courier-BoldOblique",
176
- :normal => "Courier" },
177
-
178
- "Times-Roman" => { :bold => "Times-Bold",
179
- :italic => "Times-Italic",
180
- :bold_italic => "Times-BoldItalic",
181
- :normal => "Times-Roman" },
182
-
183
- "Helvetica" => { :bold => "Helvetica-Bold",
184
- :italic => "Helvetica-Oblique",
185
- :bold_italic => "Helvetica-BoldOblique",
186
- :normal => "Helvetica" }
187
- })
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
+ )
188
194
  end
189
195
 
190
196
  # @group Experimental API
@@ -192,7 +198,7 @@ module Prawn
192
198
  # Sets the font directly, given an actual Font object
193
199
  # and size.
194
200
  #
195
- def set_font(font, size=nil) # :nodoc:
201
+ def set_font(font, size = nil) # :nodoc:
196
202
  @font = font
197
203
  @font_size = size if size
198
204
  end
@@ -201,7 +207,7 @@ module Prawn
201
207
  # finishes, the original font is restored.
202
208
  #
203
209
  def save_font
204
- @font ||= find_font("Helvetica")
210
+ @font ||= find_font('Helvetica')
205
211
  original_font = @font
206
212
  original_size = @font_size
207
213
 
@@ -211,26 +217,27 @@ module Prawn
211
217
  end
212
218
 
213
219
  # Looks up the given font using the given criteria. Once a font has been
214
- # found by that matches the criteria, it will be cached to subsequent lookups
215
- # for that font will return the same object.
216
- #--
220
+ # found by that matches the criteria, it will be cached to subsequent
221
+ # lookups for that font will return the same object.
222
+ # --
217
223
  # Challenges involved: the name alone is not sufficient to uniquely identify
218
224
  # a font (think dfont suitcases that can hold multiple different fonts in a
219
225
  # single file). Thus, the :name key is included in the cache key.
220
226
  #
221
227
  # It is further complicated, however, since fonts in some formats (like the
222
228
  # dfont suitcases) can be identified either by numeric index, OR by their
223
- # name within the suitcase, and both should hash to the same font object
224
- # (to avoid the font being embedded multiple times). This is not yet implemented,
225
- # which means if someone selects a font both by name, and by index, the
226
- # font will be embedded twice. Since we do font subsetting, this double
227
- # 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.
228
234
  # ++
229
235
  #
230
236
  # @private
231
- def find_font(name, options={}) #:nodoc:
237
+ def find_font(name, options = {}) #:nodoc:
232
238
  if font_families.key?(name)
233
- family, name = name, font_families[name][options[:style] || :normal]
239
+ family = name
240
+ name = font_families[name][options[:style] || :normal]
234
241
  if name.is_a?(::Hash)
235
242
  options = options.merge(name)
236
243
  name = options[:file]
@@ -241,10 +248,8 @@ module Prawn
241
248
  if name.is_a? Prawn::Font
242
249
  font_registry[key] = name
243
250
  else
244
- font_registry[key] ||= Font.load( self,
245
- name,
246
- options.merge(family: family)
247
- )
251
+ font_registry[key] ||=
252
+ Font.load(self, name, options.merge(family: family))
248
253
  end
249
254
  end
250
255
 
@@ -256,7 +261,7 @@ module Prawn
256
261
 
257
262
  private
258
263
 
259
- def width_of_inline_formatted_string(string, options={})
264
+ def width_of_inline_formatted_string(string, options = {})
260
265
  # Build up an Arranger with the entire string on one line, finalize it,
261
266
  # and find its width.
262
267
  arranger = Prawn::Text::Formatted::Arranger.new(self, options)
@@ -266,14 +271,25 @@ module Prawn
266
271
  arranger.line_width
267
272
  end
268
273
 
269
- def width_of_string(string, options={})
270
- font_metric_cache.width_of( string, options )
274
+ def width_of_string(string, options = {})
275
+ font_metric_cache.width_of(string, options)
271
276
  end
272
277
  end
273
278
 
274
279
  # Provides font information and helper functions.
275
280
  #
276
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
277
293
 
278
294
  # The current font name
279
295
  attr_reader :name
@@ -285,12 +301,15 @@ module Prawn
285
301
  attr_reader :options
286
302
 
287
303
  # Shortcut interface for constructing a font object. Filenames of the form
288
- # *.ttf will call Font::TTF.new, *.dfont Font::DFont.new, and anything else
289
- # will be passed through to Font::AFM.new()
290
- def self.load(document, src, 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 = {})
291
308
  case font_format(src, options)
292
- when 'ttf' then TTF.new(document, src, options)
309
+ when 'ttf' then TTF.new(document, src, options)
310
+ when 'otf' then Fonts::OTF.new(document, src, options)
293
311
  when 'dfont' then DFont.new(document, src, options)
312
+ when 'ttc' then TTC.new(document, src, options)
294
313
  else AFM.new(document, src, options)
295
314
  end
296
315
  end
@@ -299,18 +318,20 @@ module Prawn
299
318
  return options.fetch(:format, 'ttf') if src.respond_to? :read
300
319
 
301
320
  case src.to_s
302
- when /\.ttf$/i then return 'ttf'
303
- when /\.dfont$/i then return 'dfont'
304
- else return 'afm'
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'
305
326
  end
306
327
  end
307
328
 
308
- def initialize(document,name,options={}) #:nodoc:
309
- @document = document
310
- @name = name
311
- @options = options
329
+ def initialize(document, name, options = {}) #:nodoc:
330
+ @document = document
331
+ @name = name
332
+ @options = options
312
333
 
313
- @family = options[:family]
334
+ @family = options[:family]
314
335
 
315
336
  @identifier = generate_unique_id
316
337
 
@@ -339,15 +360,19 @@ module Prawn
339
360
  # font. The string is expected to be UTF-8 going in. It will be re-encoded
340
361
  # and the new string will be returned. For an in-place (destructive)
341
362
  # version, see normalize_encoding!.
342
- def normalize_encoding(string)
343
- 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'
344
366
  end
345
367
 
346
368
  # Destructive version of normalize_encoding; normalizes the encoding of a
347
369
  # string in place.
348
370
  #
371
+ # @deprecated
349
372
  def normalize_encoding!(str)
350
- 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))
351
376
  end
352
377
 
353
378
  # Gets height of current font in PDF points at the given font size
@@ -369,11 +394,13 @@ module Prawn
369
394
  #
370
395
  def add_to_current_page(subset)
371
396
  @references[subset] ||= register(subset)
372
- @document.state.page.fonts.merge!(identifier_for(subset) => @references[subset])
397
+ @document.state.page.fonts.merge!(
398
+ identifier_for(subset) => @references[subset]
399
+ )
373
400
  end
374
401
 
375
402
  def identifier_for(subset) #:nodoc:
376
- "#{@identifier}.#{subset}"
403
+ "#{@identifier}.#{subset}".to_sym
377
404
  end
378
405
 
379
406
  def inspect #:nodoc:
@@ -386,49 +413,42 @@ module Prawn
386
413
  # Prawn::Table::Text#styled_with_of_single_character)
387
414
  #
388
415
  def hash #:nodoc:
389
- [ self.class, self.name, self.family, size ].hash
416
+ [self.class, name, family, size].hash
390
417
  end
391
418
 
392
419
  # Compliments the #hash implementation above
393
420
  #
394
- def eql?( other ) #:nodoc:
395
- self.class == other.class && self.name == other.name &&
396
- 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
397
424
  end
398
425
 
399
426
  private
400
427
 
401
- # 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
402
429
  #
403
430
  def generate_unique_id
404
- 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)
405
436
 
406
- while id.nil? || page_contains_font_id?(id)
407
- offset += 1
408
- id = :"F#{@document.font_registry.size + offset}"
437
+ font_count += 1
409
438
  end
410
-
411
- id
439
+ key
412
440
  end
413
441
 
414
- # Returns true if the provided font identifier already exists in the document.
415
- # This is used when adding new fonts to a document to ensure we don't step
416
- # on fonts imported from a template.
417
- #
418
- # page_contains_font_id?("F1")
419
- # => true
420
- #
421
- def page_contains_font_id?(id)
422
- id = id.to_s
423
- @document.state.page.fonts.keys.any? { |exist_id|
424
- exist_id.to_s[0,id.size] == id
425
- }
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
426
446
  end
427
447
 
448
+ protected
449
+
428
450
  def size
429
451
  @document.font_size
430
452
  end
431
-
432
453
  end
433
-
434
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,40 +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.
14
13
  #
15
14
  # @private
16
15
  class FontMetricCache
16
+ CacheEntry = Struct.new(:font, :options, :string)
17
17
 
18
- CacheEntry = Struct.new( :font, :options, :string )
19
-
20
- def initialize( document )
18
+ def initialize(document)
21
19
  @document = document
22
20
 
23
21
  @cache = {}
24
22
  end
25
23
 
26
- def width_of( string, options )
27
- f = if options[:style]
28
- # override style with :style => :bold
29
- @document.find_font(@document.font ? @document.font.name : 'Helvetica',
30
- :style => options[:style])
31
- else
32
- @document.font
33
- 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)
34
34
 
35
- key = CacheEntry.new( f, options, string )
35
+ key = CacheEntry.new(f, options, encoded_string)
36
36
 
37
- unless length = @cache[ key ]
38
- 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)
39
44
  end
40
45
 
41
- length +
42
- (@document.character_spacing * @document.font.character_count(string))
46
+ length
43
47
  end
44
-
45
48
  end
46
-
47
49
  end