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/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