prawn 2.1.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +9 -41
  7. data/lib/prawn.rb +37 -49
  8. data/lib/prawn/document.rb +193 -141
  9. data/lib/prawn/document/bounding_box.rb +50 -30
  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 +22 -16
  13. data/lib/prawn/encoding.rb +69 -68
  14. data/lib/prawn/errors.rb +12 -7
  15. data/lib/prawn/font.rb +104 -69
  16. data/lib/prawn/font_metric_cache.rb +20 -13
  17. data/lib/prawn/{font → fonts}/afm.rb +108 -72
  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 +126 -81
  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 +43 -39
  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 +204 -102
  29. data/lib/prawn/graphics/transformation.rb +15 -9
  30. data/lib/prawn/graphics/transparency.rb +17 -13
  31. data/lib/prawn/grid.rb +84 -48
  32. data/lib/prawn/image_handler.rb +5 -5
  33. data/lib/prawn/images.rb +60 -49
  34. data/lib/prawn/images/image.rb +2 -1
  35. data/lib/prawn/images/jpg.rb +31 -22
  36. data/lib/prawn/images/png.rb +67 -63
  37. data/lib/prawn/measurement_extensions.rb +10 -9
  38. data/lib/prawn/measurements.rb +19 -15
  39. data/lib/prawn/outline.rb +98 -77
  40. data/lib/prawn/repeater.rb +15 -11
  41. data/lib/prawn/security.rb +93 -70
  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 +76 -60
  46. data/lib/prawn/text/box.rb +18 -14
  47. data/lib/prawn/text/formatted.rb +5 -5
  48. data/lib/prawn/text/formatted/arranger.rb +80 -40
  49. data/lib/prawn/text/formatted/box.rb +140 -101
  50. data/lib/prawn/text/formatted/fragment.rb +11 -14
  51. data/lib/prawn/text/formatted/line_wrap.rb +128 -67
  52. data/lib/prawn/text/formatted/parser.rb +147 -123
  53. data/lib/prawn/text/formatted/wrap.rb +48 -32
  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 +7 -8
  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 +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 +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 +15 -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 +18 -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 +5 -6
  88. data/manual/graphics/fill_rules.rb +10 -10
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +48 -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 +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 +15 -16
  101. data/manual/graphics/stroke_join.rb +5 -6
  102. data/manual/graphics/translate.rb +10 -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 +10 -11
  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 +16 -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 +21 -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 +10 -8
  137. data/manual/text/formatted_callbacks.rb +33 -24
  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 +12 -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 +33 -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 +20 -19
  155. data/manual/text/utf8.rb +11 -12
  156. data/manual/text/win_ansi_charset.rb +27 -25
  157. data/prawn.gemspec +41 -34
  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/{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 +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/{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 +102 -222
  199. metadata.gz.sig +0 -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,9 +11,32 @@ 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
+ class Error < StandardError
18
+ DEFAULT_MESSAGE = 'TTF font error'
19
+ MESSAGE_WITH_FONT = 'TTF font error in font %<font>s'
20
+
21
+ def initialize(message = DEFAULT_MESSAGE, font: nil)
22
+ if font && message == DEFAULT_MESSAGE
23
+ super format(MESSAGE_WITH_FONT, font: font)
24
+ else
25
+ super message
26
+ end
27
+ end
28
+ end
29
+
30
+ class NoUnicodeCMap < Error
31
+ DEFAULT_MESSAGE = 'No unicode cmap found in font'
32
+ MESSAGE_WITH_FONT = 'No unicode cmap found in font %<font>s'
33
+ end
34
+
35
+ class NoPostscriptName < Error
36
+ DEFAULT_MESSAGE = 'Can not detect a postscript name'
37
+ MESSAGE_WITH_FONT = 'Can not detect a postscript name in font %<font>s'
38
+ end
39
+
17
40
  attr_reader :ttf, :subsets
18
41
 
19
42
  def unicode?
@@ -23,32 +46,33 @@ module Prawn
23
46
  def initialize(document, name, options = {})
24
47
  super
25
48
 
26
- @ttf = read_ttf_file
27
- @subsets = TTFunk::SubsetCollection.new(@ttf)
49
+ @ttf = read_ttf_file
50
+ @subsets = TTFunk::SubsetCollection.new(@ttf)
51
+ @italic_angle = nil
28
52
 
29
- @attributes = {}
30
- @bounding_boxes = {}
31
- @char_widths = {}
53
+ @attributes = {}
54
+ @bounding_boxes = {}
55
+ @char_widths = {}
32
56
  @has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
33
57
 
34
- @ascender = Integer(@ttf.ascent * scale_factor)
35
- @descender = Integer(@ttf.descent * scale_factor)
36
- @line_gap = Integer(@ttf.line_gap * scale_factor)
58
+ @ascender = Integer(@ttf.ascent * scale_factor)
59
+ @descender = Integer(@ttf.descent * scale_factor)
60
+ @line_gap = Integer(@ttf.line_gap * scale_factor)
37
61
  end
38
62
 
39
63
  # NOTE: +string+ must be UTF8-encoded.
40
64
  def compute_width_of(string, options = {}) #:nodoc:
41
65
  scale = (options[:size] || size) / 1000.0
42
66
  if options[:kerning]
43
- kern(string).inject(0) do |s, r|
67
+ kern(string).reduce(0) do |s, r|
44
68
  if r.is_a?(Numeric)
45
69
  s - r
46
70
  else
47
- r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
71
+ r.reduce(s) { |a, e| a + character_width_by_code(e) }
48
72
  end
49
73
  end * scale
50
74
  else
51
- string.codepoints.inject(0) do |s, r|
75
+ string.codepoints.reduce(0) do |s, r|
52
76
  s + character_width_by_code(r)
53
77
  end * scale
54
78
  end
@@ -61,9 +85,12 @@ module Prawn
61
85
  end
62
86
 
63
87
  # Returns true if the font has kerning data, false otherwise
88
+ #
89
+ # rubocop: disable Naming/PredicateName
64
90
  def has_kerning_data?
65
91
  @has_kerning_data
66
92
  end
93
+ # rubocop: enable Naming/PredicateName
67
94
 
68
95
  # Perform any changes to the string that need to happen
69
96
  # before it is rendered to the canvas. Returns an array of
@@ -78,9 +105,11 @@ module Prawn
78
105
 
79
106
  if options[:kerning]
80
107
  last_subset = nil
81
- kern(text).inject([]) do |result, element|
108
+ kern(text).reduce([]) do |result, element|
82
109
  if element.is_a?(Numeric)
83
- result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
110
+ unless result.last[1].is_a?(Array)
111
+ result.last[1] = [result.last[1]]
112
+ end
84
113
  result.last[1] << element
85
114
  result
86
115
  else
@@ -100,7 +129,7 @@ module Prawn
100
129
  end
101
130
  end
102
131
  else
103
- @subsets.encode(text.unpack("U*"))
132
+ @subsets.encode(text.unpack('U*'))
104
133
  end
105
134
  end
106
135
 
@@ -109,7 +138,7 @@ module Prawn
109
138
  end
110
139
 
111
140
  # not sure how to compute this for true-type fonts...
112
- def stemV
141
+ def stem_v
113
142
  0
114
143
  end
115
144
 
@@ -118,7 +147,8 @@ module Prawn
118
147
 
119
148
  if @ttf.postscript.exists?
120
149
  raw = @ttf.postscript.italic_angle
121
- hi, low = raw >> 16, raw & 0xFF
150
+ hi = raw >> 16
151
+ low = raw & 0xFF
122
152
  hi = -((hi ^ 0xFFFF) + 1) if hi & 0x8000 != 0
123
153
  @italic_angle = "#{hi}.#{low}".to_f
124
154
  else
@@ -129,10 +159,11 @@ module Prawn
129
159
  end
130
160
 
131
161
  def cap_height
132
- @cap_height ||= begin
133
- height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
134
- height == 0 ? @ascender : height
135
- end
162
+ @cap_height ||=
163
+ begin
164
+ height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
165
+ height.zero? ? @ascender : height
166
+ end
136
167
  end
137
168
 
138
169
  def x_height
@@ -154,35 +185,35 @@ module Prawn
154
185
  end
155
186
 
156
187
  def pdf_flags
157
- @flags ||= begin
158
- flags = 0
159
- flags |= 0x0001 if @ttf.postscript.fixed_pitch?
160
- flags |= 0x0002 if serif?
161
- flags |= 0x0008 if script?
162
- flags |= 0x0040 if italic_angle != 0
163
- flags |= 0x0004 # assume the font contains at least some non-latin characters
164
- end
188
+ @pdf_flags ||=
189
+ begin
190
+ flags = 0
191
+ flags |= 0x0001 if @ttf.postscript.fixed_pitch?
192
+ flags |= 0x0002 if serif?
193
+ flags |= 0x0008 if script?
194
+ flags |= 0x0040 if italic_angle != 0
195
+ # Assume the font contains at least some non-latin characters
196
+ flags | 0x0004
197
+ end
165
198
  end
166
199
 
167
200
  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
201
+ text.encode(::Encoding::UTF_8)
202
+ rescue StandardError => e
203
+ puts e
204
+ raise Prawn::Errors::IncompatibleStringEncoding,
205
+ "Encoding #{text.encoding} can not be transparently converted to UTF-8. " \
206
+ 'Please ensure the encoding of the string you are attempting ' \
207
+ 'to use is set correctly'
177
208
  end
178
209
 
179
210
  def to_utf8(text)
180
- text.encode("UTF-8")
211
+ text.encode('UTF-8')
181
212
  end
182
213
 
183
214
  def glyph_present?(char)
184
215
  code = char.codepoints.first
185
- cmap[code] > 0
216
+ cmap[code].positive?
186
217
  end
187
218
 
188
219
  # Returns the number of characters in +str+ (a UTF-8-encoded string).
@@ -194,7 +225,7 @@ module Prawn
194
225
  private
195
226
 
196
227
  def cmap
197
- @cmap ||= @ttf.cmap.unicode.first or fail("no unicode cmap for font")
228
+ (@cmap ||= @ttf.cmap.unicode.first) || raise(NoUnicodeCMap.new(font: name))
198
229
  end
199
230
 
200
231
  # +string+ must be UTF8-encoded.
@@ -220,12 +251,12 @@ module Prawn
220
251
  end
221
252
 
222
253
  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*")
254
+ @kern_pairs_table ||=
255
+ if has_kerning_data?
256
+ @ttf.kerning.tables.first.pairs
257
+ else
258
+ {}
259
+ end
229
260
  end
230
261
 
231
262
  def hmtx
@@ -243,16 +274,16 @@ module Prawn
243
274
  end
244
275
 
245
276
  def scale_factor
246
- @scale ||= 1000.0 / @ttf.header.units_per_em
277
+ @scale_factor ||= 1000.0 / @ttf.header.units_per_em
247
278
  end
248
279
 
249
280
  def register(subset)
250
- temp_name = @ttf.name.postscript_name.gsub("\0", "").to_sym
251
- ref = @document.ref!(:Type => :Font, :BaseFont => temp_name)
281
+ temp_name = @ttf.name.postscript_name.delete("\0").to_sym
282
+ ref = @document.ref!(Type: :Font, BaseFont: temp_name)
252
283
 
253
284
  # Embed the font metrics in the document after everything has been
254
285
  # drawn, just before the document is emitted.
255
- @document.renderer.before_render { |doc| embed(ref, subset) }
286
+ @document.renderer.before_render { |_doc| embed(ref, subset) }
256
287
 
257
288
  ref
258
289
  end
@@ -267,29 +298,32 @@ module Prawn
267
298
 
268
299
  # empirically, it looks like Adobe Reader will not display fonts
269
300
  # if their font name is more than 33 bytes long. Strange. But true.
270
- basename = font.name.postscript_name[0, 33].gsub("\0", "")
301
+ basename = font.name.postscript_name[0, 33].delete("\0")
271
302
 
272
- fail "Can't detect a postscript name for #{file}" if basename.nil?
303
+ raise NoPostscriptName.new(font: font) if basename.nil?
273
304
 
274
- fontfile = @document.ref!(:Length1 => font_content.size)
305
+ fontfile = @document.ref!(Length1: font_content.size)
275
306
  fontfile.stream << font_content
276
307
  fontfile.stream.compress!
277
308
 
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)
309
+ descriptor = @document.ref!(
310
+ Type: :FontDescriptor,
311
+ FontName: basename.to_sym,
312
+ FontFile2: fontfile,
313
+ FontBBox: bbox,
314
+ Flags: pdf_flags,
315
+ StemV: stem_v,
316
+ ItalicAngle: italic_angle,
317
+ Ascent: @ascender,
318
+ Descent: @descender,
319
+ CapHeight: cap_height,
320
+ XHeight: x_height
321
+ )
289
322
 
290
323
  hmtx = font.horizontal_metrics
291
- widths = font.cmap.tables.first.code_map.map { |gid|
292
- Integer(hmtx.widths[gid] * scale_factor) }[32..-1]
324
+ widths = font.cmap.tables.first.code_map.map do |gid|
325
+ Integer(hmtx.widths[gid] * scale_factor)
326
+ end[32..-1]
293
327
 
294
328
  # It would be nice to have Encoding set for the macroman subsets,
295
329
  # and only do a ToUnicode cmap for non-encoded unicode subsets.
@@ -304,15 +338,24 @@ module Prawn
304
338
  map = @subsets[subset].to_unicode_map
305
339
 
306
340
  ranges = [[]]
307
- map.keys.sort.inject("") do |s, code|
341
+ map.keys.sort.reduce('') do |_s, code|
308
342
  ranges << [] if ranges.last.length >= 100
309
343
  unicode = map[code]
310
- ranges.last << "<%02x><%04x>" % [code, unicode]
344
+ ranges.last << format(
345
+ '<%<code>02x><%<unicode>04x>',
346
+ code: code,
347
+ unicode: unicode
348
+ )
311
349
  end
312
350
 
313
- range_blocks = ranges.inject("") do |s, list|
314
- s << "%d beginbfchar\n%s\nendbfchar\n" % [list.length, list.join("\n")]
315
- end
351
+ range_blocks =
352
+ ranges.reduce(+'') do |s, list|
353
+ s << format(
354
+ "%<lenght>d beginbfchar\n%<list>s\nendbfchar\n",
355
+ lenght: list.length,
356
+ list: list.join("\n")
357
+ )
358
+ end
316
359
 
317
360
  to_unicode_cmap = UNICODE_CMAP_TEMPLATE % range_blocks.strip
318
361
 
@@ -320,16 +363,18 @@ module Prawn
320
363
  cmap << to_unicode_cmap
321
364
  cmap.stream.compress!
322
365
 
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)
366
+ reference.data.update(
367
+ Subtype: :TrueType,
368
+ BaseFont: basename.to_sym,
369
+ FontDescriptor: descriptor,
370
+ FirstChar: 32,
371
+ LastChar: 255,
372
+ Widths: @document.ref!(widths),
373
+ ToUnicode: cmap
374
+ )
330
375
  end
331
376
 
332
- UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, "")
377
+ UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, '')
333
378
  /CIDInit /ProcSet findresource begin
334
379
  12 dict begin
335
380
  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[at width height step_length negative_axes_length color],
345
+ options
346
+ )
333
347
 
334
348
  save_graphics_state do
335
349
  fill_color(options[:color])
336
350
  stroke_color(options[:color])
337
351
 
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])
352
+ dash(1, space: 4)
353
+ stroke_horizontal_line(
354
+ options[:at][0] - options[:negative_axes_length],
355
+ options[:at][0] + options[:width],
356
+ at: options[:at][1]
357
+ )
358
+ stroke_vertical_line(
359
+ options[:at][1] - options[:negative_axes_length],
360
+ options[:at][1] + options[:height],
361
+ 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) # def fill_polygon(*args)
637
+ #{shape}(*args) # polygon(*args)
638
+ #{operation} # fill
639
+ end # 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)