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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/GPLv2 +20 -21
- data/Gemfile +3 -9
- data/Rakefile +9 -41
- data/lib/prawn.rb +37 -49
- data/lib/prawn/document.rb +193 -141
- data/lib/prawn/document/bounding_box.rb +50 -30
- data/lib/prawn/document/column_box.rb +7 -7
- data/lib/prawn/document/internals.rb +8 -6
- data/lib/prawn/document/span.rb +22 -16
- data/lib/prawn/encoding.rb +69 -68
- data/lib/prawn/errors.rb +12 -7
- data/lib/prawn/font.rb +104 -69
- data/lib/prawn/font_metric_cache.rb +20 -13
- data/lib/prawn/{font → fonts}/afm.rb +108 -72
- data/lib/prawn/{font → fonts}/dfont.rb +5 -11
- data/lib/prawn/fonts/otf.rb +11 -0
- data/lib/prawn/fonts/ttc.rb +36 -0
- data/lib/prawn/{font → fonts}/ttf.rb +126 -81
- data/lib/prawn/graphics.rb +119 -81
- data/lib/prawn/graphics/blend_mode.rb +9 -8
- data/lib/prawn/graphics/cap_style.rb +3 -3
- data/lib/prawn/graphics/color.rb +43 -39
- data/lib/prawn/graphics/dash.rb +23 -11
- data/lib/prawn/graphics/join_style.rb +9 -3
- data/lib/prawn/graphics/patterns.rb +204 -102
- data/lib/prawn/graphics/transformation.rb +15 -9
- data/lib/prawn/graphics/transparency.rb +17 -13
- data/lib/prawn/grid.rb +84 -48
- data/lib/prawn/image_handler.rb +5 -5
- data/lib/prawn/images.rb +60 -49
- data/lib/prawn/images/image.rb +2 -1
- data/lib/prawn/images/jpg.rb +31 -22
- data/lib/prawn/images/png.rb +67 -63
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +19 -15
- data/lib/prawn/outline.rb +98 -77
- data/lib/prawn/repeater.rb +15 -11
- data/lib/prawn/security.rb +93 -70
- data/lib/prawn/security/arcfour.rb +2 -2
- data/lib/prawn/soft_mask.rb +26 -26
- data/lib/prawn/stamp.rb +20 -13
- data/lib/prawn/text.rb +76 -60
- data/lib/prawn/text/box.rb +18 -14
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text/formatted/arranger.rb +80 -40
- data/lib/prawn/text/formatted/box.rb +140 -101
- data/lib/prawn/text/formatted/fragment.rb +11 -14
- data/lib/prawn/text/formatted/line_wrap.rb +128 -67
- data/lib/prawn/text/formatted/parser.rb +147 -123
- data/lib/prawn/text/formatted/wrap.rb +48 -32
- data/lib/prawn/transformation_stack.rb +7 -5
- data/lib/prawn/utilities.rb +7 -22
- data/lib/prawn/version.rb +2 -2
- data/lib/prawn/view.rb +17 -7
- data/manual/basic_concepts/adding_pages.rb +6 -7
- data/manual/basic_concepts/basic_concepts.rb +31 -22
- data/manual/basic_concepts/creation.rb +10 -11
- data/manual/basic_concepts/cursor.rb +4 -5
- data/manual/basic_concepts/measurement.rb +7 -8
- data/manual/basic_concepts/origin.rb +5 -6
- data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
- data/manual/basic_concepts/view.rb +22 -16
- data/manual/bounding_box/bounding_box.rb +29 -24
- data/manual/bounding_box/bounds.rb +11 -12
- data/manual/bounding_box/canvas.rb +7 -8
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +25 -18
- data/manual/bounding_box/russian_boxes.rb +14 -13
- data/manual/bounding_box/stretchy.rb +12 -13
- data/manual/contents.rb +28 -22
- data/manual/cover.rb +33 -28
- data/manual/document_and_page_options/background.rb +15 -13
- data/manual/document_and_page_options/document_and_page_options.rb +25 -20
- data/manual/document_and_page_options/metadata.rb +18 -16
- data/manual/document_and_page_options/page_margins.rb +18 -20
- data/manual/document_and_page_options/page_size.rb +13 -12
- data/manual/document_and_page_options/print_scaling.rb +18 -15
- data/manual/example_helper.rb +5 -4
- data/manual/graphics/blend_mode.rb +12 -9
- data/manual/graphics/circle_and_ellipse.rb +4 -5
- data/manual/graphics/color.rb +7 -9
- data/manual/graphics/common_lines.rb +7 -8
- data/manual/graphics/fill_and_stroke.rb +5 -6
- data/manual/graphics/fill_rules.rb +10 -10
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +48 -40
- data/manual/graphics/helper.rb +19 -9
- data/manual/graphics/line_width.rb +8 -7
- data/manual/graphics/lines_and_curves.rb +7 -8
- data/manual/graphics/polygon.rb +6 -8
- data/manual/graphics/rectangle.rb +4 -5
- data/manual/graphics/rotate.rb +6 -7
- data/manual/graphics/scale.rb +14 -15
- data/manual/graphics/soft_masks.rb +3 -4
- data/manual/graphics/stroke_cap.rb +6 -7
- data/manual/graphics/stroke_dash.rb +15 -16
- data/manual/graphics/stroke_join.rb +5 -6
- data/manual/graphics/translate.rb +10 -10
- data/manual/graphics/transparency.rb +7 -8
- data/manual/how_to_read_this_manual.rb +6 -6
- data/manual/images/absolute_position.rb +6 -7
- data/manual/images/fit.rb +7 -8
- data/manual/images/horizontal.rb +10 -11
- data/manual/images/images.rb +28 -24
- data/manual/images/plain_image.rb +5 -6
- data/manual/images/scale.rb +9 -10
- data/manual/images/vertical.rb +16 -14
- data/manual/images/width_and_height.rb +10 -11
- data/manual/layout/boxes.rb +5 -6
- data/manual/layout/content.rb +7 -8
- data/manual/layout/layout.rb +18 -16
- data/manual/layout/simple_grid.rb +6 -7
- data/manual/outline/add_subsection_to.rb +20 -21
- data/manual/outline/insert_section_after.rb +15 -16
- data/manual/outline/outline.rb +21 -17
- data/manual/outline/sections_and_pages.rb +17 -18
- data/manual/repeatable_content/alternate_page_numbering.rb +21 -17
- data/manual/repeatable_content/page_numbering.rb +17 -16
- data/manual/repeatable_content/repeatable_content.rb +25 -19
- data/manual/repeatable_content/repeater.rb +14 -15
- data/manual/repeatable_content/stamp.rb +14 -15
- data/manual/security/encryption.rb +9 -10
- data/manual/security/permissions.rb +21 -14
- data/manual/security/security.rb +19 -16
- data/manual/table.rb +3 -3
- data/manual/text/alignment.rb +16 -17
- data/manual/text/color.rb +12 -11
- data/manual/text/column_box.rb +9 -10
- data/manual/text/fallback_fonts.rb +25 -21
- data/manual/text/font.rb +11 -12
- data/manual/text/font_size.rb +13 -14
- data/manual/text/font_style.rb +10 -8
- data/manual/text/formatted_callbacks.rb +33 -24
- data/manual/text/formatted_text.rb +36 -25
- data/manual/text/free_flowing_text.rb +22 -23
- data/manual/text/inline.rb +18 -19
- data/manual/text/kerning_and_character_spacing.rb +14 -15
- data/manual/text/leading.rb +7 -8
- data/manual/text/line_wrapping.rb +37 -18
- data/manual/text/paragraph_indentation.rb +12 -14
- data/manual/text/positioned_text.rb +15 -16
- data/manual/text/registering_families.rb +20 -21
- data/manual/text/rendering_and_color.rb +9 -10
- data/manual/text/right_to_left_text.rb +26 -19
- data/manual/text/rotation.rb +33 -23
- data/manual/text/single_usage.rb +8 -9
- data/manual/text/text.rb +57 -52
- data/manual/text/text_box_excess.rb +20 -17
- data/manual/text/text_box_extensions.rb +18 -15
- data/manual/text/text_box_overflow.rb +20 -19
- data/manual/text/utf8.rb +11 -12
- data/manual/text/win_ansi_charset.rb +27 -25
- data/prawn.gemspec +41 -34
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +550 -0
- data/spec/prawn/document/column_box_spec.rb +75 -0
- data/spec/prawn/document/security_spec.rb +176 -0
- data/spec/prawn/document_annotations_spec.rb +76 -0
- data/spec/prawn/document_destinations_spec.rb +15 -0
- data/spec/prawn/document_grid_spec.rb +99 -0
- data/spec/prawn/document_reference_spec.rb +27 -0
- data/spec/prawn/document_span_spec.rb +44 -0
- data/spec/prawn/document_spec.rb +805 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +544 -0
- data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
- data/spec/prawn/graphics/transparency_spec.rb +81 -0
- data/spec/prawn/graphics_spec.rb +872 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/{image_handler_spec.rb → prawn/image_handler_spec.rb} +14 -14
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +229 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +512 -0
- data/spec/prawn/repeater_spec.rb +166 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +173 -0
- data/spec/prawn/text/box_spec.rb +1110 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +849 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +150 -0
- data/spec/prawn/text_rendering_mode_spec.rb +48 -0
- data/spec/prawn/text_spacing_spec.rb +95 -0
- data/spec/prawn/text_spec.rb +603 -0
- data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
- data/spec/{transformation_stack_spec.rb → prawn/transformation_stack_spec.rb} +22 -19
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +18 -19
- metadata +102 -222
- metadata.gz.sig +0 -0
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/blend_modes_bottom_layer.jpg +0 -0
- data/data/images/blend_modes_top_layer.jpg +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/indexed_transparency.png +0 -0
- data/data/images/indexed_transparency_alpha.dat +0 -0
- data/data/images/indexed_transparency_color.dat +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/license.md +0 -8
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/prawn.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +0 -1
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/form.pdf +1 -819
- data/data/pdfs/hexagon.pdf +0 -61
- data/data/pdfs/indirect_reference.pdf +0 -86
- data/data/pdfs/multipage_template.pdf +0 -127
- data/data/pdfs/nested_pages.pdf +0 -118
- data/data/pdfs/page_without_mediabox.pdf +0 -193
- data/data/pdfs/resources_as_indirect_object.pdf +0 -83
- data/data/pdfs/two_hexagons.pdf +0 -90
- data/data/pdfs/version_1_6.pdf +0 -61
- data/data/shift_jis_text.txt +0 -1
- data/spec/acceptance/png_spec.rb +0 -35
- data/spec/annotations_spec.rb +0 -67
- data/spec/blend_mode_spec.rb +0 -71
- data/spec/bounding_box_spec.rb +0 -501
- data/spec/column_box_spec.rb +0 -59
- data/spec/destinations_spec.rb +0 -13
- data/spec/document_spec.rb +0 -738
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -475
- data/spec/formatted_text_arranger_spec.rb +0 -452
- data/spec/formatted_text_box_spec.rb +0 -716
- data/spec/formatted_text_fragment_spec.rb +0 -299
- data/spec/graphics_spec.rb +0 -705
- data/spec/grid_spec.rb +0 -95
- data/spec/images_spec.rb +0 -167
- data/spec/inline_formatted_text_parser_spec.rb +0 -568
- data/spec/jpg_spec.rb +0 -23
- data/spec/line_wrap_spec.rb +0 -366
- data/spec/measurement_units_spec.rb +0 -22
- data/spec/outline_spec.rb +0 -409
- data/spec/png_spec.rb +0 -257
- data/spec/reference_spec.rb +0 -25
- data/spec/repeater_spec.rb +0 -154
- data/spec/security_spec.rb +0 -151
- data/spec/soft_mask_spec.rb +0 -78
- data/spec/span_spec.rb +0 -43
- data/spec/stamp_spec.rb +0 -179
- data/spec/stroke_styles_spec.rb +0 -208
- data/spec/text_at_spec.rb +0 -142
- data/spec/text_box_spec.rb +0 -1042
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -543
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
- data/spec/view_spec.rb +0 -42
@@ -1,15 +1,9 @@
|
|
1
|
-
#
|
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
|
-
|
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(
|
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[
|
25
|
+
return f.map['sfnt'][:list].length
|
32
26
|
end
|
33
27
|
end
|
34
28
|
|
@@ -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
|
-
#
|
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
|
-
|
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
|
27
|
-
@subsets
|
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
|
35
|
-
@descender
|
36
|
-
@line_gap
|
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).
|
67
|
+
kern(string).reduce(0) do |s, r|
|
44
68
|
if r.is_a?(Numeric)
|
45
69
|
s - r
|
46
70
|
else
|
47
|
-
r.
|
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.
|
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).
|
108
|
+
kern(text).reduce([]) do |result, element|
|
82
109
|
if element.is_a?(Numeric)
|
83
|
-
|
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(
|
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
|
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
|
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 ||=
|
133
|
-
|
134
|
-
|
135
|
-
|
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
|
-
@
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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(
|
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]
|
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
|
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
|
-
@
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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
|
-
@
|
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.
|
251
|
-
ref = @document.ref!(:
|
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 { |
|
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].
|
301
|
+
basename = font.name.postscript_name[0, 33].delete("\0")
|
271
302
|
|
272
|
-
|
303
|
+
raise NoPostscriptName.new(font: font) if basename.nil?
|
273
304
|
|
274
|
-
fontfile = @document.ref!(:
|
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!(
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|
292
|
-
Integer(hmtx.widths[gid] * scale_factor)
|
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.
|
341
|
+
map.keys.sort.reduce('') do |_s, code|
|
308
342
|
ranges << [] if ranges.last.length >= 100
|
309
343
|
unicode = map[code]
|
310
|
-
ranges.last <<
|
344
|
+
ranges.last << format(
|
345
|
+
'<%<code>02x><%<unicode>04x>',
|
346
|
+
code: code,
|
347
|
+
unicode: unicode
|
348
|
+
)
|
311
349
|
end
|
312
350
|
|
313
|
-
range_blocks =
|
314
|
-
|
315
|
-
|
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(
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
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
|
data/lib/prawn/graphics.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
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
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
15
|
-
require_relative
|
16
|
-
require_relative
|
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]
|
70
|
-
|
71
|
-
|
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(
|
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
|
-
|
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
|
190
|
-
# as a complete subpath. The drawing point will be moved to
|
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>
|
200
|
-
# with the centre-point at <tt>point</tt> as a complete
|
201
|
-
# drawing point will be moved to the centre-point upon
|
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,
|
207
|
+
def ellipse(point, radius1, radius2 = radius1)
|
208
208
|
x, y = point
|
209
|
-
l1 =
|
210
|
-
l2 =
|
209
|
+
l1 = radius1 * KAPPA
|
210
|
+
l2 = radius2 * KAPPA
|
211
211
|
|
212
|
-
move_to(x +
|
212
|
+
move_to(x + radius1, y)
|
213
213
|
|
214
214
|
# Upper right hand corner
|
215
|
-
curve_to [x,
|
216
|
-
|
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 -
|
220
|
-
|
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 -
|
224
|
-
|
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 +
|
228
|
-
|
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
|
244
|
+
renderer.add_content 'h'
|
245
245
|
end
|
246
246
|
|
247
|
-
# Draws a rounded polygon from specified points using the radius to define
|
247
|
+
# Draws a rounded polygon from specified points using the radius to define
|
248
|
+
# bezier curves
|
248
249
|
#
|
249
|
-
#
|
250
|
-
# pdf.fill_and_stroke_rounded_polygon(
|
251
|
-
#
|
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
|
-
|
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
|
263
|
+
renderer.add_content 'h'
|
261
264
|
end
|
262
265
|
|
263
|
-
# Creates a rounded vertex for a line segment used for building a rounded
|
264
|
-
# requires a radius to define bezier curve and three points. The
|
265
|
-
# the line segment and the third point helps define
|
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
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
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
|
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
|
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
|
-
:
|
324
|
-
:
|
325
|
-
:
|
326
|
-
:
|
327
|
-
:
|
328
|
-
:
|
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(
|
332
|
-
|
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, :
|
339
|
-
stroke_horizontal_line(
|
340
|
-
|
341
|
-
|
342
|
-
|
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])
|
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(
|
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])
|
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(
|
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 ?
|
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 ?
|
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
|
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
|
598
|
-
shapes = %w
|
599
|
-
|
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
|
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
|
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)
|