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