prawn 2.1.0 → 2.3.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 (280) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +20 -23
  7. data/lib/prawn.rb +36 -49
  8. data/lib/prawn/document.rb +180 -133
  9. data/lib/prawn/document/bounding_box.rb +41 -29
  10. data/lib/prawn/document/column_box.rb +7 -7
  11. data/lib/prawn/document/internals.rb +8 -6
  12. data/lib/prawn/document/span.rb +21 -16
  13. data/lib/prawn/encoding.rb +69 -68
  14. data/lib/prawn/errors.rb +12 -7
  15. data/lib/prawn/font.rb +102 -69
  16. data/lib/prawn/font_metric_cache.rb +14 -8
  17. data/lib/prawn/{font → fonts}/afm.rb +102 -68
  18. data/lib/prawn/{font → fonts}/dfont.rb +5 -11
  19. data/lib/prawn/fonts/otf.rb +11 -0
  20. data/lib/prawn/fonts/ttc.rb +36 -0
  21. data/lib/prawn/{font → fonts}/ttf.rb +87 -68
  22. data/lib/prawn/graphics.rb +119 -81
  23. data/lib/prawn/graphics/blend_mode.rb +9 -8
  24. data/lib/prawn/graphics/cap_style.rb +3 -3
  25. data/lib/prawn/graphics/color.rb +27 -25
  26. data/lib/prawn/graphics/dash.rb +23 -11
  27. data/lib/prawn/graphics/join_style.rb +9 -3
  28. data/lib/prawn/graphics/patterns.rb +190 -96
  29. data/lib/prawn/graphics/transformation.rb +15 -9
  30. data/lib/prawn/graphics/transparency.rb +17 -13
  31. data/lib/prawn/grid.rb +48 -47
  32. data/lib/prawn/image_handler.rb +5 -5
  33. data/lib/prawn/images.rb +39 -30
  34. data/lib/prawn/images/image.rb +2 -1
  35. data/lib/prawn/images/jpg.rb +28 -22
  36. data/lib/prawn/images/png.rb +65 -62
  37. data/lib/prawn/measurement_extensions.rb +10 -9
  38. data/lib/prawn/measurements.rb +19 -15
  39. data/lib/prawn/outline.rb +97 -77
  40. data/lib/prawn/repeater.rb +14 -10
  41. data/lib/prawn/security.rb +81 -61
  42. data/lib/prawn/security/arcfour.rb +2 -2
  43. data/lib/prawn/soft_mask.rb +26 -26
  44. data/lib/prawn/stamp.rb +20 -13
  45. data/lib/prawn/text.rb +68 -52
  46. data/lib/prawn/text/box.rb +11 -8
  47. data/lib/prawn/text/formatted.rb +5 -5
  48. data/lib/prawn/text/formatted/arranger.rb +53 -32
  49. data/lib/prawn/text/formatted/box.rb +134 -100
  50. data/lib/prawn/text/formatted/fragment.rb +11 -14
  51. data/lib/prawn/text/formatted/line_wrap.rb +122 -63
  52. data/lib/prawn/text/formatted/parser.rb +139 -117
  53. data/lib/prawn/text/formatted/wrap.rb +43 -31
  54. data/lib/prawn/transformation_stack.rb +7 -5
  55. data/lib/prawn/utilities.rb +7 -22
  56. data/lib/prawn/version.rb +2 -2
  57. data/lib/prawn/view.rb +17 -7
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +31 -22
  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 +6 -7
  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 +22 -16
  66. data/manual/bounding_box/bounding_box.rb +29 -24
  67. data/manual/bounding_box/bounds.rb +11 -12
  68. data/manual/bounding_box/canvas.rb +4 -5
  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 +24 -17
  72. data/manual/bounding_box/russian_boxes.rb +14 -13
  73. data/manual/bounding_box/stretchy.rb +12 -13
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -28
  76. data/manual/document_and_page_options/background.rb +11 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +25 -20
  78. data/manual/document_and_page_options/metadata.rb +18 -16
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -12
  81. data/manual/document_and_page_options/print_scaling.rb +17 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +12 -9
  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 +4 -5
  88. data/manual/graphics/fill_rules.rb +9 -10
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +48 -40
  91. data/manual/graphics/helper.rb +12 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +7 -8
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -7
  97. data/manual/graphics/scale.rb +14 -15
  98. data/manual/graphics/soft_masks.rb +3 -4
  99. data/manual/graphics/stroke_cap.rb +6 -7
  100. data/manual/graphics/stroke_dash.rb +11 -12
  101. data/manual/graphics/stroke_join.rb +5 -6
  102. data/manual/graphics/translate.rb +9 -10
  103. data/manual/graphics/transparency.rb +7 -8
  104. data/manual/how_to_read_this_manual.rb +6 -6
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +9 -10
  108. data/manual/images/images.rb +28 -24
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +13 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +5 -6
  114. data/manual/layout/content.rb +7 -8
  115. data/manual/layout/layout.rb +18 -16
  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 +21 -17
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +21 -17
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +25 -19
  124. data/manual/repeatable_content/repeater.rb +14 -15
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +9 -10
  127. data/manual/security/permissions.rb +19 -14
  128. data/manual/security/security.rb +19 -16
  129. data/manual/table.rb +3 -3
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -11
  132. data/manual/text/column_box.rb +9 -10
  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 +7 -8
  137. data/manual/text/formatted_callbacks.rb +25 -21
  138. data/manual/text/formatted_text.rb +33 -25
  139. data/manual/text/free_flowing_text.rb +20 -21
  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 +13 -14
  145. data/manual/text/positioned_text.rb +15 -16
  146. data/manual/text/registering_families.rb +20 -21
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +26 -19
  149. data/manual/text/rotation.rb +28 -23
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +57 -52
  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 +18 -19
  155. data/manual/text/utf8.rb +11 -12
  156. data/manual/text/win_ansi_charset.rb +21 -19
  157. data/prawn.gemspec +44 -31
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +546 -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 +36 -0
  167. data/spec/prawn/document_spec.rb +802 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +542 -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 +837 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/{image_handler_spec.rb → prawn/image_handler_spec.rb} +14 -14
  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 +224 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +412 -0
  180. data/spec/prawn/repeater_spec.rb +165 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +172 -0
  183. data/spec/prawn/text/box_spec.rb +1112 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +846 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +494 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +149 -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/{transformation_stack_spec.rb → prawn/transformation_stack_spec.rb} +22 -19
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +18 -19
  198. metadata +144 -180
  199. metadata.gz.sig +4 -0
  200. data/data/images/16bit.alpha +0 -0
  201. data/data/images/16bit.color +0 -0
  202. data/data/images/16bit.png +0 -0
  203. data/data/images/arrow.png +0 -0
  204. data/data/images/arrow2.png +0 -0
  205. data/data/images/blend_modes_bottom_layer.jpg +0 -0
  206. data/data/images/blend_modes_top_layer.jpg +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/indexed_transparency.png +0 -0
  215. data/data/images/indexed_transparency_alpha.dat +0 -0
  216. data/data/images/indexed_transparency_color.dat +0 -0
  217. data/data/images/letterhead.jpg +0 -0
  218. data/data/images/license.md +0 -8
  219. data/data/images/page_white_text.alpha +0 -0
  220. data/data/images/page_white_text.color +0 -0
  221. data/data/images/page_white_text.png +0 -0
  222. data/data/images/pigs.jpg +0 -0
  223. data/data/images/prawn.png +0 -0
  224. data/data/images/ruport.png +0 -0
  225. data/data/images/ruport_data.dat +0 -0
  226. data/data/images/ruport_transparent.png +0 -0
  227. data/data/images/ruport_type0.png +0 -0
  228. data/data/images/stef.jpg +0 -0
  229. data/data/images/tru256.bmp +0 -0
  230. data/data/images/web-links.dat +0 -1
  231. data/data/images/web-links.png +0 -0
  232. data/data/pdfs/complex_template.pdf +0 -0
  233. data/data/pdfs/contains_ttf_font.pdf +0 -0
  234. data/data/pdfs/encrypted.pdf +0 -0
  235. data/data/pdfs/form.pdf +1 -819
  236. data/data/pdfs/hexagon.pdf +0 -61
  237. data/data/pdfs/indirect_reference.pdf +0 -86
  238. data/data/pdfs/multipage_template.pdf +0 -127
  239. data/data/pdfs/nested_pages.pdf +0 -118
  240. data/data/pdfs/page_without_mediabox.pdf +0 -193
  241. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  242. data/data/pdfs/two_hexagons.pdf +0 -90
  243. data/data/pdfs/version_1_6.pdf +0 -61
  244. data/data/shift_jis_text.txt +0 -1
  245. data/spec/acceptance/png_spec.rb +0 -35
  246. data/spec/annotations_spec.rb +0 -67
  247. data/spec/blend_mode_spec.rb +0 -71
  248. data/spec/bounding_box_spec.rb +0 -501
  249. data/spec/column_box_spec.rb +0 -59
  250. data/spec/destinations_spec.rb +0 -13
  251. data/spec/document_spec.rb +0 -738
  252. data/spec/font_metric_cache_spec.rb +0 -52
  253. data/spec/font_spec.rb +0 -475
  254. data/spec/formatted_text_arranger_spec.rb +0 -452
  255. data/spec/formatted_text_box_spec.rb +0 -716
  256. data/spec/formatted_text_fragment_spec.rb +0 -299
  257. data/spec/graphics_spec.rb +0 -705
  258. data/spec/grid_spec.rb +0 -95
  259. data/spec/images_spec.rb +0 -167
  260. data/spec/inline_formatted_text_parser_spec.rb +0 -568
  261. data/spec/jpg_spec.rb +0 -23
  262. data/spec/line_wrap_spec.rb +0 -366
  263. data/spec/measurement_units_spec.rb +0 -22
  264. data/spec/outline_spec.rb +0 -409
  265. data/spec/png_spec.rb +0 -257
  266. data/spec/reference_spec.rb +0 -25
  267. data/spec/repeater_spec.rb +0 -154
  268. data/spec/security_spec.rb +0 -151
  269. data/spec/soft_mask_spec.rb +0 -78
  270. data/spec/span_spec.rb +0 -43
  271. data/spec/stamp_spec.rb +0 -179
  272. data/spec/stroke_styles_spec.rb +0 -208
  273. data/spec/text_at_spec.rb +0 -142
  274. data/spec/text_box_spec.rb +0 -1042
  275. data/spec/text_rendering_mode_spec.rb +0 -45
  276. data/spec/text_spacing_spec.rb +0 -93
  277. data/spec/text_spec.rb +0 -543
  278. data/spec/text_with_inline_formatting_spec.rb +0 -35
  279. data/spec/transparency_spec.rb +0 -91
  280. data/spec/view_spec.rb +0 -42
@@ -1,15 +1,9 @@
1
- # encoding: utf-8
2
- #
3
- # font.rb : The Prawn font class
4
- #
5
- # Copyright November 2008, Jamis Buck. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
- #
1
+ # frozen_string_literal: true
2
+
9
3
  require_relative 'ttf'
10
4
 
11
5
  module Prawn
12
- class Font
6
+ module Fonts
13
7
  # @private
14
8
  class DFont < TTF
15
9
  # Returns a list of the names of all named fonts in the given dfont file.
@@ -20,7 +14,7 @@ module Prawn
20
14
  #
21
15
  def self.named_fonts(file)
22
16
  TTFunk::ResourceFile.open(file) do |f|
23
- return f.resources_for("sfnt")
17
+ return f.resources_for('sfnt')
24
18
  end
25
19
  end
26
20
 
@@ -28,7 +22,7 @@ module Prawn
28
22
  #
29
23
  def self.font_count(file)
30
24
  TTFunk::ResourceFile.open(file) do |f|
31
- return f.map["sfnt"][:list].length
25
+ return f.map['sfnt'][:list].length
32
26
  end
33
27
  end
34
28
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ttf'
4
+
5
+ module Prawn
6
+ module Fonts
7
+ # @private
8
+ class OTF < TTF
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ttf'
4
+
5
+ module Prawn
6
+ module Fonts
7
+ # @private
8
+ class TTC < TTF
9
+ # Returns a list of the names of all named fonts in the given ttc file.
10
+ # They are returned in order of their appearance in the file.
11
+ #
12
+ def self.font_names(file)
13
+ TTFunk::Collection.open(file) do |ttc|
14
+ ttc.map { |font| font.name.font_name.first }
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def read_ttf_file
21
+ TTFunk::File.from_ttc(
22
+ @name,
23
+ font_option_to_index(@name, @options[:font])
24
+ )
25
+ end
26
+
27
+ def font_option_to_index(file, option)
28
+ if option.is_a?(Numeric)
29
+ option
30
+ else
31
+ self.class.font_names(file).index { |n| n == option } || 0
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # prawn/font/ttf.rb : Implements AFM font support for Prawn
4
4
  #
@@ -11,7 +11,7 @@ require 'ttfunk'
11
11
  require 'ttfunk/subset_collection'
12
12
 
13
13
  module Prawn
14
- class Font
14
+ module Fonts
15
15
  # @private
16
16
  class TTF < Font
17
17
  attr_reader :ttf, :subsets
@@ -23,17 +23,18 @@ module Prawn
23
23
  def initialize(document, name, options = {})
24
24
  super
25
25
 
26
- @ttf = read_ttf_file
27
- @subsets = TTFunk::SubsetCollection.new(@ttf)
26
+ @ttf = read_ttf_file
27
+ @subsets = TTFunk::SubsetCollection.new(@ttf)
28
+ @italic_angle = nil
28
29
 
29
- @attributes = {}
30
- @bounding_boxes = {}
31
- @char_widths = {}
30
+ @attributes = {}
31
+ @bounding_boxes = {}
32
+ @char_widths = {}
32
33
  @has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
33
34
 
34
- @ascender = Integer(@ttf.ascent * scale_factor)
35
- @descender = Integer(@ttf.descent * scale_factor)
36
- @line_gap = Integer(@ttf.line_gap * scale_factor)
35
+ @ascender = Integer(@ttf.ascent * scale_factor)
36
+ @descender = Integer(@ttf.descent * scale_factor)
37
+ @line_gap = Integer(@ttf.line_gap * scale_factor)
37
38
  end
38
39
 
39
40
  # NOTE: +string+ must be UTF8-encoded.
@@ -44,7 +45,7 @@ module Prawn
44
45
  if r.is_a?(Numeric)
45
46
  s - r
46
47
  else
47
- r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
48
+ r.inject(s) { |a, e| a + character_width_by_code(e) }
48
49
  end
49
50
  end * scale
50
51
  else
@@ -61,9 +62,12 @@ module Prawn
61
62
  end
62
63
 
63
64
  # Returns true if the font has kerning data, false otherwise
65
+ #
66
+ # rubocop: disable Naming/PredicateName
64
67
  def has_kerning_data?
65
68
  @has_kerning_data
66
69
  end
70
+ # rubocop: enable Naming/PredicateName
67
71
 
68
72
  # Perform any changes to the string that need to happen
69
73
  # before it is rendered to the canvas. Returns an array of
@@ -80,7 +84,9 @@ module Prawn
80
84
  last_subset = nil
81
85
  kern(text).inject([]) do |result, element|
82
86
  if element.is_a?(Numeric)
83
- result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
87
+ unless result.last[1].is_a?(Array)
88
+ result.last[1] = [result.last[1]]
89
+ end
84
90
  result.last[1] << element
85
91
  result
86
92
  else
@@ -100,7 +106,7 @@ module Prawn
100
106
  end
101
107
  end
102
108
  else
103
- @subsets.encode(text.unpack("U*"))
109
+ @subsets.encode(text.unpack('U*'))
104
110
  end
105
111
  end
106
112
 
@@ -109,7 +115,7 @@ module Prawn
109
115
  end
110
116
 
111
117
  # not sure how to compute this for true-type fonts...
112
- def stemV
118
+ def stem_v
113
119
  0
114
120
  end
115
121
 
@@ -118,7 +124,8 @@ module Prawn
118
124
 
119
125
  if @ttf.postscript.exists?
120
126
  raw = @ttf.postscript.italic_angle
121
- hi, low = raw >> 16, raw & 0xFF
127
+ hi = raw >> 16
128
+ low = raw & 0xFF
122
129
  hi = -((hi ^ 0xFFFF) + 1) if hi & 0x8000 != 0
123
130
  @italic_angle = "#{hi}.#{low}".to_f
124
131
  else
@@ -131,7 +138,7 @@ module Prawn
131
138
  def cap_height
132
139
  @cap_height ||= begin
133
140
  height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
134
- height == 0 ? @ascender : height
141
+ height.zero? ? @ascender : height
135
142
  end
136
143
  end
137
144
 
@@ -154,35 +161,34 @@ module Prawn
154
161
  end
155
162
 
156
163
  def pdf_flags
157
- @flags ||= begin
164
+ @pdf_flags ||= begin
158
165
  flags = 0
159
166
  flags |= 0x0001 if @ttf.postscript.fixed_pitch?
160
167
  flags |= 0x0002 if serif?
161
168
  flags |= 0x0008 if script?
162
169
  flags |= 0x0040 if italic_angle != 0
163
- flags |= 0x0004 # assume the font contains at least some non-latin characters
170
+ # Assume the font contains at least some non-latin characters
171
+ flags | 0x0004
164
172
  end
165
173
  end
166
174
 
167
175
  def normalize_encoding(text)
168
- begin
169
- text.encode(::Encoding::UTF_8)
170
- rescue => e
171
- puts e
172
- raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " \
173
- "#{text.encoding} can not be transparently converted to UTF-8. " \
174
- "Please ensure the encoding of the string you are attempting " \
175
- "to use is set correctly"
176
- end
176
+ text.encode(::Encoding::UTF_8)
177
+ rescue StandardError => e
178
+ puts e
179
+ raise Prawn::Errors::IncompatibleStringEncoding, 'Encoding ' \
180
+ "#{text.encoding} can not be transparently converted to UTF-8. " \
181
+ 'Please ensure the encoding of the string you are attempting ' \
182
+ 'to use is set correctly'
177
183
  end
178
184
 
179
185
  def to_utf8(text)
180
- text.encode("UTF-8")
186
+ text.encode('UTF-8')
181
187
  end
182
188
 
183
189
  def glyph_present?(char)
184
190
  code = char.codepoints.first
185
- cmap[code] > 0
191
+ cmap[code].positive?
186
192
  end
187
193
 
188
194
  # Returns the number of characters in +str+ (a UTF-8-encoded string).
@@ -194,7 +200,7 @@ module Prawn
194
200
  private
195
201
 
196
202
  def cmap
197
- @cmap ||= @ttf.cmap.unicode.first or fail("no unicode cmap for font")
203
+ (@cmap ||= @ttf.cmap.unicode.first) || raise('no unicode cmap for font')
198
204
  end
199
205
 
200
206
  # +string+ must be UTF8-encoded.
@@ -220,12 +226,12 @@ module Prawn
220
226
  end
221
227
 
222
228
  def kern_pairs_table
223
- @kerning_data ||= has_kerning_data? ? @ttf.kerning.tables.first.pairs : {}
224
- end
225
-
226
- def cid_to_gid_map
227
- max = cmap.code_map.keys.max
228
- (0..max).map { |cid| cmap[cid] }.pack("n*")
229
+ @kern_pairs_table ||=
230
+ if has_kerning_data?
231
+ @ttf.kerning.tables.first.pairs
232
+ else
233
+ {}
234
+ end
229
235
  end
230
236
 
231
237
  def hmtx
@@ -243,16 +249,16 @@ module Prawn
243
249
  end
244
250
 
245
251
  def scale_factor
246
- @scale ||= 1000.0 / @ttf.header.units_per_em
252
+ @scale_factor ||= 1000.0 / @ttf.header.units_per_em
247
253
  end
248
254
 
249
255
  def register(subset)
250
- temp_name = @ttf.name.postscript_name.gsub("\0", "").to_sym
251
- ref = @document.ref!(:Type => :Font, :BaseFont => temp_name)
256
+ temp_name = @ttf.name.postscript_name.delete("\0").to_sym
257
+ ref = @document.ref!(Type: :Font, BaseFont: temp_name)
252
258
 
253
259
  # Embed the font metrics in the document after everything has been
254
260
  # drawn, just before the document is emitted.
255
- @document.renderer.before_render { |doc| embed(ref, subset) }
261
+ @document.renderer.before_render { |_doc| embed(ref, subset) }
256
262
 
257
263
  ref
258
264
  end
@@ -267,29 +273,32 @@ module Prawn
267
273
 
268
274
  # empirically, it looks like Adobe Reader will not display fonts
269
275
  # if their font name is more than 33 bytes long. Strange. But true.
270
- basename = font.name.postscript_name[0, 33].gsub("\0", "")
276
+ basename = font.name.postscript_name[0, 33].delete("\0")
271
277
 
272
- fail "Can't detect a postscript name for #{file}" if basename.nil?
278
+ raise "Can't detect a postscript name for #{file}" if basename.nil?
273
279
 
274
- fontfile = @document.ref!(:Length1 => font_content.size)
280
+ fontfile = @document.ref!(Length1: font_content.size)
275
281
  fontfile.stream << font_content
276
282
  fontfile.stream.compress!
277
283
 
278
- descriptor = @document.ref!(:Type => :FontDescriptor,
279
- :FontName => basename.to_sym,
280
- :FontFile2 => fontfile,
281
- :FontBBox => bbox,
282
- :Flags => pdf_flags,
283
- :StemV => stemV,
284
- :ItalicAngle => italic_angle,
285
- :Ascent => @ascender,
286
- :Descent => @descender,
287
- :CapHeight => cap_height,
288
- :XHeight => x_height)
284
+ descriptor = @document.ref!(
285
+ Type: :FontDescriptor,
286
+ FontName: basename.to_sym,
287
+ FontFile2: fontfile,
288
+ FontBBox: bbox,
289
+ Flags: pdf_flags,
290
+ StemV: stem_v,
291
+ ItalicAngle: italic_angle,
292
+ Ascent: @ascender,
293
+ Descent: @descender,
294
+ CapHeight: cap_height,
295
+ XHeight: x_height
296
+ )
289
297
 
290
298
  hmtx = font.horizontal_metrics
291
- widths = font.cmap.tables.first.code_map.map { |gid|
292
- Integer(hmtx.widths[gid] * scale_factor) }[32..-1]
299
+ widths = font.cmap.tables.first.code_map.map do |gid|
300
+ Integer(hmtx.widths[gid] * scale_factor)
301
+ end[32..-1]
293
302
 
294
303
  # It would be nice to have Encoding set for the macroman subsets,
295
304
  # and only do a ToUnicode cmap for non-encoded unicode subsets.
@@ -304,14 +313,22 @@ module Prawn
304
313
  map = @subsets[subset].to_unicode_map
305
314
 
306
315
  ranges = [[]]
307
- map.keys.sort.inject("") do |s, code|
316
+ map.keys.sort.inject('') do |_s, code|
308
317
  ranges << [] if ranges.last.length >= 100
309
318
  unicode = map[code]
310
- ranges.last << "<%02x><%04x>" % [code, unicode]
319
+ ranges.last << format(
320
+ '<%<code>02x><%<unicode>04x>',
321
+ code: code,
322
+ unicode: unicode
323
+ )
311
324
  end
312
325
 
313
- range_blocks = ranges.inject("") do |s, list|
314
- s << "%d beginbfchar\n%s\nendbfchar\n" % [list.length, list.join("\n")]
326
+ range_blocks = ranges.inject(+'') do |s, list|
327
+ s << format(
328
+ "%<lenght>d beginbfchar\n%<list>s\nendbfchar\n",
329
+ lenght: list.length,
330
+ list: list.join("\n")
331
+ )
315
332
  end
316
333
 
317
334
  to_unicode_cmap = UNICODE_CMAP_TEMPLATE % range_blocks.strip
@@ -320,16 +337,18 @@ module Prawn
320
337
  cmap << to_unicode_cmap
321
338
  cmap.stream.compress!
322
339
 
323
- reference.data.update(:Subtype => :TrueType,
324
- :BaseFont => basename.to_sym,
325
- :FontDescriptor => descriptor,
326
- :FirstChar => 32,
327
- :LastChar => 255,
328
- :Widths => @document.ref!(widths),
329
- :ToUnicode => cmap)
340
+ reference.data.update(
341
+ Subtype: :TrueType,
342
+ BaseFont: basename.to_sym,
343
+ FontDescriptor: descriptor,
344
+ FirstChar: 32,
345
+ LastChar: 255,
346
+ Widths: @document.ref!(widths),
347
+ ToUnicode: cmap
348
+ )
330
349
  end
331
350
 
332
- UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, "")
351
+ UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, '')
333
352
  /CIDInit /ProcSet findresource begin
334
353
  12 dict begin
335
354
  begincmap
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # graphics.rb : Implements PDF drawing primitives
4
4
  #
@@ -6,14 +6,14 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
- require_relative "graphics/blend_mode"
10
- require_relative "graphics/color"
11
- require_relative "graphics/dash"
12
- require_relative "graphics/cap_style"
13
- require_relative "graphics/join_style"
14
- require_relative "graphics/transparency"
15
- require_relative "graphics/transformation"
16
- require_relative "graphics/patterns"
9
+ require_relative 'graphics/blend_mode'
10
+ require_relative 'graphics/color'
11
+ require_relative 'graphics/dash'
12
+ require_relative 'graphics/cap_style'
13
+ require_relative 'graphics/join_style'
14
+ require_relative 'graphics/transparency'
15
+ require_relative 'graphics/transformation'
16
+ require_relative 'graphics/patterns'
17
17
 
18
18
  module Prawn
19
19
  # Implements the drawing facilities for Prawn::Document.
@@ -66,9 +66,11 @@ module Prawn
66
66
  # pdf.curve_to [100,100], :bounds => [[90,90],[75,75]]
67
67
  #
68
68
  def curve_to(dest, options = {})
69
- options[:bounds] or fail Prawn::Errors::InvalidGraphicsPath,
70
- "Bounding points for bezier curve must be specified " \
71
- "as :bounds => [[x1,y1],[x2,y2]]"
69
+ options[:bounds] || raise(
70
+ Prawn::Errors::InvalidGraphicsPath,
71
+ 'Bounding points for bezier curve must be specified ' \
72
+ 'as :bounds => [[x1,y1],[x2,y2]]'
73
+ )
72
74
 
73
75
  curve_points = PDF::Core.real_params(
74
76
  (options[:bounds] << dest).flat_map { |e| map_to_absolute(e) }
@@ -97,7 +99,9 @@ module Prawn
97
99
  #
98
100
  def rounded_rectangle(point, width, height, radius)
99
101
  x, y = point
100
- rounded_polygon(radius, point, [x + width, y], [x + width, y - height], [x, y - height])
102
+ rounded_polygon(
103
+ radius, point, [x + width, y], [x + width, y - height], [x, y - height]
104
+ )
101
105
  end
102
106
 
103
107
  ###########################################################
@@ -146,11 +150,7 @@ module Prawn
146
150
  # horizontal_line 25, 100, :at => 75
147
151
  #
148
152
  def horizontal_line(x1, x2, options = {})
149
- if options[:at]
150
- y1 = options[:at]
151
- else
152
- y1 = y - bounds.absolute_bottom
153
- end
153
+ y1 = options[:at] || y - bounds.absolute_bottom
154
154
 
155
155
  line(x1, y1, x2, y1)
156
156
  end
@@ -186,9 +186,9 @@ module Prawn
186
186
  #
187
187
  KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
188
188
 
189
- # Draws a circle of radius <tt>radius</tt> with the centre-point at <tt>point</tt>
190
- # as a complete subpath. The drawing point will be moved to the
191
- # centre-point upon completion of the drawing the circle.
189
+ # Draws a circle of radius <tt>radius</tt> with the centre-point at
190
+ # <tt>point</tt> as a complete subpath. The drawing point will be moved to
191
+ # the centre-point upon completion of the drawing the circle.
192
192
  #
193
193
  # pdf.circle [100,100], 25
194
194
  #
@@ -196,36 +196,36 @@ module Prawn
196
196
  ellipse(center, radius, radius)
197
197
  end
198
198
 
199
- # Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
200
- # with the centre-point at <tt>point</tt> as a complete subpath. The
201
- # drawing point will be moved to the centre-point upon completion of the
202
- # drawing the ellipse.
199
+ # Draws an ellipse of +x+ radius <tt>radius1</tt> and +y+ radius
200
+ # <tt>radius2</tt> with the centre-point at <tt>point</tt> as a complete
201
+ # subpath. The drawing point will be moved to the centre-point upon
202
+ # completion of the drawing the ellipse.
203
203
  #
204
204
  # # draws an ellipse with x-radius 25 and y-radius 50
205
205
  # pdf.ellipse [100,100], 25, 50
206
206
  #
207
- def ellipse(point, r1, r2 = r1)
207
+ def ellipse(point, radius1, radius2 = radius1)
208
208
  x, y = point
209
- l1 = r1 * KAPPA
210
- l2 = r2 * KAPPA
209
+ l1 = radius1 * KAPPA
210
+ l2 = radius2 * KAPPA
211
211
 
212
- move_to(x + r1, y)
212
+ move_to(x + radius1, y)
213
213
 
214
214
  # Upper right hand corner
215
- curve_to [x, y + r2],
216
- :bounds => [[x + r1, y + l2], [x + l1, y + r2]]
215
+ curve_to [x, y + radius2],
216
+ bounds: [[x + radius1, y + l2], [x + l1, y + radius2]]
217
217
 
218
218
  # Upper left hand corner
219
- curve_to [x - r1, y],
220
- :bounds => [[x - l1, y + r2], [x - r1, y + l2]]
219
+ curve_to [x - radius1, y],
220
+ bounds: [[x - l1, y + radius2], [x - radius1, y + l2]]
221
221
 
222
222
  # Lower left hand corner
223
- curve_to [x, y - r2],
224
- :bounds => [[x - r1, y - l2], [x - l1, y - r2]]
223
+ curve_to [x, y - radius2],
224
+ bounds: [[x - radius1, y - l2], [x - l1, y - radius2]]
225
225
 
226
226
  # Lower right hand corner
227
- curve_to [x + r1, y],
228
- :bounds => [[x + l1, y - r2], [x + r1, y - l2]]
227
+ curve_to [x + radius1, y],
228
+ bounds: [[x + l1, y - radius2], [x + radius1, y - l2]]
229
229
 
230
230
  move_to(x, y)
231
231
  end
@@ -241,35 +241,47 @@ module Prawn
241
241
  line_to(*point)
242
242
  end
243
243
  # close the path
244
- renderer.add_content "h"
244
+ renderer.add_content 'h'
245
245
  end
246
246
 
247
- # Draws a rounded polygon from specified points using the radius to define bezier curves
247
+ # Draws a rounded polygon from specified points using the radius to define
248
+ # bezier curves
248
249
  #
249
- # # draws a rounded filled in polygon
250
- # pdf.fill_and_stroke_rounded_polygon(10, [100, 250], [200, 300], [300, 250],
251
- # [300, 150], [200, 100], [100, 150])
250
+ # # draws a rounded filled in polygon
251
+ # pdf.fill_and_stroke_rounded_polygon(
252
+ # 10, [100, 250], [200, 300], [300, 250], [300, 150], [200, 100],
253
+ # [100, 150]
254
+ # )
252
255
  def rounded_polygon(radius, *points)
253
256
  move_to point_on_line(radius, points[1], points[0])
254
257
  sides = points.size
255
258
  points << points[0] << points[1]
256
- (sides).times do |i|
259
+ sides.times do |i|
257
260
  rounded_vertex(radius, points[i], points[i + 1], points[i + 2])
258
261
  end
259
262
  # close the path
260
- renderer.add_content "h"
263
+ renderer.add_content 'h'
261
264
  end
262
265
 
263
- # Creates a rounded vertex for a line segment used for building a rounded polygon
264
- # requires a radius to define bezier curve and three points. The first two points define
265
- # the line segment and the third point helps define the curve for the vertex.
266
+ # Creates a rounded vertex for a line segment used for building a rounded
267
+ # polygon requires a radius to define bezier curve and three points. The
268
+ # first two points define the line segment and the third point helps define
269
+ # the curve for the vertex.
266
270
  def rounded_vertex(radius, *points)
267
- radial_point_1 = point_on_line(radius, points[0], points[1])
268
- bezier_point_1 = point_on_line((radius - radius * KAPPA), points[0], points[1])
269
- radial_point_2 = point_on_line(radius, points[2], points[1])
270
- bezier_point_2 = point_on_line((radius - radius * KAPPA), points[2], points[1])
271
- line_to(radial_point_1)
272
- curve_to(radial_point_2, :bounds => [bezier_point_1, bezier_point_2])
271
+ radial_point1 = point_on_line(radius, points[0], points[1])
272
+ bezier_point1 = point_on_line(
273
+ (radius - radius * KAPPA),
274
+ points[0],
275
+ points[1]
276
+ )
277
+ radial_point2 = point_on_line(radius, points[2], points[1])
278
+ bezier_point2 = point_on_line(
279
+ (radius - radius * KAPPA),
280
+ points[2],
281
+ points[1]
282
+ )
283
+ line_to(radial_point1)
284
+ curve_to(radial_point2, bounds: [bezier_point1, bezier_point2])
273
285
  end
274
286
 
275
287
  # Strokes the current path. If a block is provided, yields to the block
@@ -277,7 +289,7 @@ module Prawn
277
289
  #
278
290
  def stroke
279
291
  yield if block_given?
280
- renderer.add_content "S"
292
+ renderer.add_content 'S'
281
293
  end
282
294
 
283
295
  # Closes and strokes the current path. If a block is provided, yields to
@@ -285,7 +297,7 @@ module Prawn
285
297
  #
286
298
  def close_and_stroke
287
299
  yield if block_given?
288
- renderer.add_content "s"
300
+ renderer.add_content 's'
289
301
  end
290
302
 
291
303
  # Draws and strokes a rectangle represented by the current bounding box
@@ -320,38 +332,56 @@ module Prawn
320
332
  #
321
333
  def stroke_axis(options = {})
322
334
  options = {
323
- :at => [0, 0],
324
- :height => bounds.height.to_i - (options[:at] || [0, 0])[1],
325
- :width => bounds.width.to_i - (options[:at] || [0, 0])[0],
326
- :step_length => 100,
327
- :negative_axes_length => 20,
328
- :color => "000000"
335
+ at: [0, 0],
336
+ height: bounds.height.to_i - (options[:at] || [0, 0])[1],
337
+ width: bounds.width.to_i - (options[:at] || [0, 0])[0],
338
+ step_length: 100,
339
+ negative_axes_length: 20,
340
+ color: '000000'
329
341
  }.merge(options)
330
342
 
331
- Prawn.verify_options([:at, :width, :height, :step_length,
332
- :negative_axes_length, :color], options)
343
+ Prawn.verify_options(
344
+ %i[
345
+ at width height step_length
346
+ negative_axes_length color
347
+ ], options
348
+ )
333
349
 
334
350
  save_graphics_state do
335
351
  fill_color(options[:color])
336
352
  stroke_color(options[:color])
337
353
 
338
- dash(1, :space => 4)
339
- stroke_horizontal_line(options[:at][0] - options[:negative_axes_length],
340
- options[:at][0] + options[:width], :at => options[:at][1])
341
- stroke_vertical_line(options[:at][1] - options[:negative_axes_length],
342
- options[:at][1] + options[:height], :at => options[:at][0])
354
+ dash(1, space: 4)
355
+ stroke_horizontal_line(
356
+ options[:at][0] - options[:negative_axes_length],
357
+ options[:at][0] + options[:width], at: options[:at][1]
358
+ )
359
+ stroke_vertical_line(
360
+ options[:at][1] - options[:negative_axes_length],
361
+ options[:at][1] + options[:height], at: options[:at][0]
362
+ )
343
363
  undash
344
364
 
345
365
  fill_circle(options[:at], 1)
346
366
 
347
- (options[:step_length]..options[:width]).step(options[:step_length]) do |point|
367
+ (options[:step_length]..options[:width])
368
+ .step(options[:step_length]) do |point|
348
369
  fill_circle([options[:at][0] + point, options[:at][1]], 1)
349
- draw_text(point, :at => [options[:at][0] + point - 5, options[:at][1] - 10], :size => 7)
370
+ draw_text(
371
+ point,
372
+ at: [options[:at][0] + point - 5, options[:at][1] - 10],
373
+ size: 7
374
+ )
350
375
  end
351
376
 
352
- (options[:step_length]..options[:height]).step(options[:step_length]) do |point|
377
+ (options[:step_length]..options[:height])
378
+ .step(options[:step_length]) do |point|
353
379
  fill_circle([options[:at][0], options[:at][1] + point], 1)
354
- draw_text(point, :at => [options[:at][0] - 17, options[:at][1] + point - 2], :size => 7)
380
+ draw_text(
381
+ point,
382
+ at: [options[:at][0] - 17, options[:at][1] + point - 2],
383
+ size: 7
384
+ )
355
385
  end
356
386
  end
357
387
  end
@@ -365,7 +395,7 @@ module Prawn
365
395
  #
366
396
  def fill(options = {})
367
397
  yield if block_given?
368
- renderer.add_content(options[:fill_rule] == :even_odd ? "f*" : "f")
398
+ renderer.add_content(options[:fill_rule] == :even_odd ? 'f*' : 'f')
369
399
  end
370
400
 
371
401
  # Closes, fills, and strokes the current path. If a block is provided,
@@ -379,13 +409,13 @@ module Prawn
379
409
  #
380
410
  def fill_and_stroke(options = {})
381
411
  yield if block_given?
382
- renderer.add_content(options[:fill_rule] == :even_odd ? "b*" : "b")
412
+ renderer.add_content(options[:fill_rule] == :even_odd ? 'b*' : 'b')
383
413
  end
384
414
 
385
415
  # Closes the current path.
386
416
  #
387
417
  def close_path
388
- renderer.add_content "h"
418
+ renderer.add_content 'h'
389
419
  end
390
420
 
391
421
  ##
@@ -594,12 +624,20 @@ module Prawn
594
624
  # :call-seq:
595
625
  # fill_and_stroke_rounded_polygon(radius, *points)
596
626
 
597
- ops = %w{fill stroke fill_and_stroke}
598
- shapes = %w{line_to curve_to rectangle rounded_rectangle line horizontal_line horizontal_rule vertical_line
599
- curve circle_at circle ellipse_at ellipse polygon rounded_polygon rounded_vertex}
627
+ ops = %w[fill stroke fill_and_stroke]
628
+ shapes = %w[
629
+ line_to curve_to rectangle rounded_rectangle line horizontal_line
630
+ horizontal_rule vertical_line curve circle_at circle ellipse_at ellipse
631
+ polygon rounded_polygon rounded_vertex
632
+ ]
600
633
 
601
634
  ops.product(shapes).each do |operation, shape|
602
- class_eval "def #{operation}_#{shape}(*args); #{shape}(*args); #{operation}; end"
635
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
636
+ def #{operation}_#{shape}(*args)
637
+ #{shape}(*args)
638
+ #{operation}
639
+ end
640
+ METHOD
603
641
  end
604
642
 
605
643
  private
@@ -629,8 +667,8 @@ module Prawn
629
667
  angle * Math::PI / 180
630
668
  end
631
669
 
632
- # Returns the coordinates for a point on a line that is a given distance away from the second
633
- # point defining the line segement
670
+ # Returns the coordinates for a point on a line that is a given distance
671
+ # away from the second point defining the line segement
634
672
  def point_on_line(distance_from_end, *points)
635
673
  x0, y0, x1, y1 = points.flatten
636
674
  length = Math.sqrt((x1 - x0)**2 + (y1 - y0)**2)