prawn 2.0.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +20 -23
- data/lib/prawn.rb +37 -49
- data/lib/prawn/document.rb +181 -133
- data/lib/prawn/document/bounding_box.rb +41 -29
- data/lib/prawn/document/column_box.rb +7 -7
- data/lib/prawn/document/internals.rb +18 -8
- data/lib/prawn/document/span.rb +21 -16
- data/lib/prawn/encoding.rb +69 -68
- data/lib/prawn/errors.rb +12 -7
- data/lib/prawn/font.rb +115 -69
- data/lib/prawn/font_metric_cache.rb +14 -8
- data/lib/prawn/{font → fonts}/afm.rb +102 -68
- 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 +87 -68
- data/lib/prawn/graphics.rb +120 -80
- data/lib/prawn/graphics/blend_mode.rb +65 -0
- data/lib/prawn/graphics/cap_style.rb +3 -3
- data/lib/prawn/graphics/color.rb +27 -25
- data/lib/prawn/graphics/dash.rb +23 -11
- data/lib/prawn/graphics/join_style.rb +9 -3
- data/lib/prawn/graphics/patterns.rb +197 -67
- data/lib/prawn/graphics/transformation.rb +17 -8
- data/lib/prawn/graphics/transparency.rb +17 -13
- data/lib/prawn/grid.rb +48 -47
- data/lib/prawn/image_handler.rb +5 -5
- data/lib/prawn/images.rb +39 -30
- data/lib/prawn/images/image.rb +2 -1
- data/lib/prawn/images/jpg.rb +28 -22
- data/lib/prawn/images/png.rb +107 -66
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +19 -15
- data/lib/prawn/outline.rb +97 -77
- data/lib/prawn/repeater.rb +14 -10
- data/lib/prawn/security.rb +81 -61
- 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 +68 -52
- data/lib/prawn/text/box.rb +11 -8
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text/formatted/arranger.rb +78 -49
- data/lib/prawn/text/formatted/box.rb +134 -100
- data/lib/prawn/text/formatted/fragment.rb +11 -14
- data/lib/prawn/text/formatted/line_wrap.rb +121 -63
- data/lib/prawn/text/formatted/parser.rb +139 -117
- data/lib/prawn/text/formatted/wrap.rb +43 -31
- data/lib/prawn/transformation_stack.rb +44 -0
- 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 +6 -7
- 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 +4 -5
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +24 -17
- 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 +11 -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 +17 -15
- data/manual/example_helper.rb +5 -4
- data/manual/graphics/blend_mode.rb +52 -0
- 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 +4 -5
- data/manual/graphics/fill_rules.rb +9 -10
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +48 -39
- data/manual/graphics/helper.rb +12 -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 +4 -5
- data/manual/graphics/stroke_cap.rb +6 -7
- data/manual/graphics/stroke_dash.rb +11 -12
- data/manual/graphics/stroke_join.rb +5 -6
- data/manual/graphics/translate.rb +9 -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 +9 -10
- 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 +13 -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 +19 -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 +7 -8
- data/manual/text/formatted_callbacks.rb +25 -21
- data/manual/text/formatted_text.rb +33 -25
- data/manual/text/free_flowing_text.rb +20 -21
- 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 +13 -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 +28 -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 +18 -19
- data/manual/text/utf8.rb +11 -12
- data/manual/text/win_ansi_charset.rb +21 -19
- data/prawn.gemspec +45 -33
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +546 -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 +36 -0
- data/spec/prawn/document_spec.rb +802 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +542 -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 +837 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/prawn/image_handler_spec.rb +53 -0
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +224 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +412 -0
- data/spec/prawn/repeater_spec.rb +165 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +172 -0
- data/spec/prawn/text/box_spec.rb +1112 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +846 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +494 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +149 -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/prawn/transformation_stack_spec.rb +66 -0
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +19 -23
- metadata +145 -185
- metadata.gz.sig +4 -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/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/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/pal_bk.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.rb +0 -24
- data/spec/annotations_spec.rb +0 -67
- 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 -742
- data/spec/extensions/mocha.rb +0 -45
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -475
- data/spec/formatted_text_arranger_spec.rb +0 -423
- data/spec/formatted_text_box_spec.rb +0 -716
- data/spec/formatted_text_fragment_spec.rb +0 -299
- data/spec/graphics_spec.rb +0 -666
- data/spec/grid_spec.rb +0 -95
- data/spec/image_handler_spec.rb +0 -53
- 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 -235
- 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 -1038
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -549
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
- data/spec/view_spec.rb +0 -42
data/lib/prawn/text/formatted.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'formatted/wrap'
|
4
4
|
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
5
|
+
require_relative 'formatted/box'
|
6
|
+
require_relative 'formatted/parser'
|
7
|
+
require_relative 'formatted/fragment'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# core/text/formatted/arranger.rb : Implements a data structure for 2-stage
|
4
4
|
# processing of lines of formatted text
|
@@ -16,6 +16,7 @@ module Prawn
|
|
16
16
|
attr_reader :max_line_height
|
17
17
|
attr_reader :max_descender
|
18
18
|
attr_reader :max_ascender
|
19
|
+
attr_reader :finalized
|
19
20
|
attr_accessor :consumed
|
20
21
|
|
21
22
|
# The following present only for testing purposes
|
@@ -31,46 +32,55 @@ module Prawn
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def space_count
|
34
|
-
|
35
|
-
|
35
|
+
unless finalized
|
36
|
+
raise 'Lines must be finalized before calling #space_count'
|
36
37
|
end
|
38
|
+
|
37
39
|
@fragments.inject(0) do |sum, fragment|
|
38
40
|
sum + fragment.space_count
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
44
|
def line_width
|
43
|
-
|
44
|
-
|
45
|
+
unless finalized
|
46
|
+
raise 'Lines must be finalized before calling #line_width'
|
45
47
|
end
|
48
|
+
|
46
49
|
@fragments.inject(0) do |sum, fragment|
|
47
50
|
sum + fragment.width
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
51
54
|
def line
|
52
|
-
|
53
|
-
|
55
|
+
unless finalized
|
56
|
+
raise 'Lines must be finalized before calling #line'
|
54
57
|
end
|
58
|
+
|
55
59
|
@fragments.collect do |fragment|
|
60
|
+
fragment.text.dup.encode(::Encoding::UTF_8)
|
61
|
+
rescue ::Encoding::InvalidByteSequenceError,
|
62
|
+
::Encoding::UndefinedConversionError
|
56
63
|
fragment.text.dup.force_encoding(::Encoding::UTF_8)
|
57
64
|
end.join
|
58
65
|
end
|
59
66
|
|
60
67
|
def finalize_line
|
61
|
-
@
|
68
|
+
@finalized = true
|
69
|
+
|
62
70
|
omit_trailing_whitespace_from_line_width
|
63
71
|
@fragments = []
|
64
72
|
@consumed.each do |hash|
|
65
73
|
text = hash[:text]
|
66
74
|
format_state = hash.dup
|
67
75
|
format_state.delete(:text)
|
68
|
-
fragment = Prawn::Text::Formatted::Fragment.new(
|
69
|
-
|
70
|
-
|
76
|
+
fragment = Prawn::Text::Formatted::Fragment.new(
|
77
|
+
text,
|
78
|
+
format_state,
|
79
|
+
@document
|
80
|
+
)
|
71
81
|
@fragments << fragment
|
72
|
-
|
73
|
-
|
82
|
+
self.fragment_measurements = fragment
|
83
|
+
self.line_measurement_maximums = fragment
|
74
84
|
end
|
75
85
|
end
|
76
86
|
|
@@ -79,13 +89,13 @@ module Prawn
|
|
79
89
|
@unconsumed = []
|
80
90
|
array.each do |hash|
|
81
91
|
hash[:text].scan(/[^\n]+|\n/) do |line|
|
82
|
-
@unconsumed << hash.merge(:
|
92
|
+
@unconsumed << hash.merge(text: line)
|
83
93
|
end
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
87
97
|
def initialize_line
|
88
|
-
@
|
98
|
+
@finalized = false
|
89
99
|
@max_line_height = 0
|
90
100
|
@max_descender = 0
|
91
101
|
@max_ascender = 0
|
@@ -95,28 +105,30 @@ module Prawn
|
|
95
105
|
end
|
96
106
|
|
97
107
|
def finished?
|
98
|
-
@unconsumed.
|
108
|
+
@unconsumed.empty?
|
99
109
|
end
|
100
110
|
|
101
111
|
def next_string
|
102
|
-
|
103
|
-
|
112
|
+
if finalized
|
113
|
+
raise 'Lines must not be finalized when calling #next_string'
|
104
114
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
@consumed <<
|
110
|
-
@current_format_state =
|
115
|
+
|
116
|
+
next_unconsumed_hash = @unconsumed.shift
|
117
|
+
|
118
|
+
if next_unconsumed_hash
|
119
|
+
@consumed << next_unconsumed_hash.dup
|
120
|
+
@current_format_state = next_unconsumed_hash.dup
|
111
121
|
@current_format_state.delete(:text)
|
112
|
-
|
122
|
+
|
123
|
+
next_unconsumed_hash[:text]
|
113
124
|
end
|
114
125
|
end
|
115
126
|
|
116
127
|
def preview_next_string
|
117
|
-
|
118
|
-
|
119
|
-
|
128
|
+
next_unconsumed_hash = @unconsumed.first
|
129
|
+
|
130
|
+
if next_unconsumed_hash
|
131
|
+
next_unconsumed_hash[:text]
|
120
132
|
end
|
121
133
|
end
|
122
134
|
|
@@ -139,21 +151,23 @@ module Prawn
|
|
139
151
|
font = current_format_state[:font]
|
140
152
|
size = current_format_state[:size]
|
141
153
|
character_spacing = current_format_state[:character_spacing] ||
|
142
|
-
|
154
|
+
@document.character_spacing
|
143
155
|
styles = current_format_state[:styles]
|
144
|
-
font_style = font_style(styles)
|
145
156
|
else
|
146
157
|
font = fragment.font
|
147
158
|
size = fragment.size
|
148
159
|
character_spacing = fragment.character_spacing
|
149
160
|
styles = fragment.styles
|
150
|
-
font_style = font_style(styles)
|
151
161
|
end
|
162
|
+
font_style = font_style(styles)
|
152
163
|
|
153
164
|
@document.character_spacing(character_spacing) do
|
154
165
|
if font || font_style != :normal
|
155
|
-
|
156
|
-
|
166
|
+
raise 'Bad font family' unless @document.font.family
|
167
|
+
|
168
|
+
@document.font(
|
169
|
+
font || @document.font.family, style: font_style
|
170
|
+
) do
|
157
171
|
apply_font_size(size, styles, &block)
|
158
172
|
end
|
159
173
|
else
|
@@ -164,6 +178,7 @@ module Prawn
|
|
164
178
|
|
165
179
|
def update_last_string(printed, unprinted, normalized_soft_hyphen = nil)
|
166
180
|
return if printed.nil?
|
181
|
+
|
167
182
|
if printed.empty?
|
168
183
|
@consumed.pop
|
169
184
|
else
|
@@ -174,24 +189,27 @@ module Prawn
|
|
174
189
|
end
|
175
190
|
|
176
191
|
unless unprinted.empty?
|
177
|
-
@unconsumed.unshift(@current_format_state.merge(:
|
192
|
+
@unconsumed.unshift(@current_format_state.merge(text: unprinted))
|
178
193
|
end
|
179
194
|
|
180
195
|
load_previous_format_state if printed.empty?
|
181
196
|
end
|
182
197
|
|
183
198
|
def retrieve_fragment
|
184
|
-
|
185
|
-
|
199
|
+
unless finalized
|
200
|
+
raise 'Lines must be finalized before fragments can be retrieved'
|
186
201
|
end
|
202
|
+
|
187
203
|
@fragments.shift
|
188
204
|
end
|
189
205
|
|
190
206
|
def repack_unretrieved
|
191
207
|
new_unconsumed = []
|
208
|
+
# rubocop: disable Lint/AssignmentInCondition
|
192
209
|
while fragment = retrieve_fragment
|
210
|
+
# rubocop: enable Lint/AssignmentInCondition
|
193
211
|
fragment.include_trailing_white_space!
|
194
|
-
new_unconsumed << fragment.format_state.merge(:
|
212
|
+
new_unconsumed << fragment.format_state.merge(text: fragment.text)
|
195
213
|
end
|
196
214
|
@unconsumed = new_unconsumed.concat(@unconsumed)
|
197
215
|
end
|
@@ -225,11 +243,11 @@ module Prawn
|
|
225
243
|
def apply_font_size(size, styles)
|
226
244
|
if subscript?(styles) || superscript?(styles)
|
227
245
|
relative_size = 0.583
|
228
|
-
if size.nil?
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
246
|
+
size = if size.nil?
|
247
|
+
@document.font_size * relative_size
|
248
|
+
else
|
249
|
+
size * relative_size
|
250
|
+
end
|
233
251
|
end
|
234
252
|
if size.nil?
|
235
253
|
yield
|
@@ -266,20 +284,31 @@ module Prawn
|
|
266
284
|
end
|
267
285
|
end
|
268
286
|
|
269
|
-
def
|
287
|
+
def fragment_measurements=(fragment)
|
270
288
|
apply_font_settings(fragment) do
|
271
|
-
fragment.width = @document.width_of(
|
272
|
-
|
289
|
+
fragment.width = @document.width_of(
|
290
|
+
fragment.text,
|
291
|
+
kerning: @kerning
|
292
|
+
)
|
273
293
|
fragment.line_height = @document.font.height
|
274
294
|
fragment.descender = @document.font.descender
|
275
295
|
fragment.ascender = @document.font.ascender
|
276
296
|
end
|
277
297
|
end
|
278
298
|
|
279
|
-
def
|
280
|
-
@max_line_height = [
|
281
|
-
|
282
|
-
|
299
|
+
def line_measurement_maximums=(fragment)
|
300
|
+
@max_line_height = [
|
301
|
+
defined?(@max_line_height) && @max_line_height,
|
302
|
+
fragment.line_height
|
303
|
+
].compact.max
|
304
|
+
@max_descender = [
|
305
|
+
defined?(@max_descender) && @max_descender,
|
306
|
+
fragment.descender
|
307
|
+
].compact.max
|
308
|
+
@max_ascender = [
|
309
|
+
defined?(@max_ascender) && @max_ascender,
|
310
|
+
fragment.ascender
|
311
|
+
].compact.max
|
283
312
|
end
|
284
313
|
end
|
285
314
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# text/formatted/rectangle.rb : Implements text boxes with formatted text
|
4
4
|
#
|
@@ -54,8 +54,8 @@ module Prawn
|
|
54
54
|
# a file or application to be opened locally. A clickable link will be
|
55
55
|
# created to the provided local file or application. If the file is
|
56
56
|
# another PDF, it will be opened in a new window. Note that you must
|
57
|
-
# explicitly underline and color using the appropriate tags if you
|
58
|
-
# to draw attention to the link
|
57
|
+
# explicitly underline and color using the appropriate tags if you
|
58
|
+
# which to draw attention to the link
|
59
59
|
# <tt>:draw_text_callback</tt>:
|
60
60
|
# if provided, this Proc will be called instead of #draw_text! once
|
61
61
|
# per fragment for every low-level addition of text to the page.
|
@@ -83,13 +83,14 @@ module Prawn
|
|
83
83
|
#
|
84
84
|
# == Exceptions
|
85
85
|
#
|
86
|
-
# Raises "Bad font family" if no font family is defined for the current
|
86
|
+
# Raises "Bad font family" if no font family is defined for the current
|
87
|
+
# font
|
87
88
|
#
|
88
89
|
# Raises <tt>Prawn::Errors::CannotFit</tt> if not wide enough to print
|
89
90
|
# any text
|
90
91
|
#
|
91
92
|
def formatted_text_box(array, options = {})
|
92
|
-
Text::Formatted::Box.new(array, options.merge(:
|
93
|
+
Text::Formatted::Box.new(array, options.merge(document: self)).render
|
93
94
|
end
|
94
95
|
|
95
96
|
# Generally, one would use the Prawn::Text::Formatted#formatted_text_box
|
@@ -137,37 +138,38 @@ module Prawn
|
|
137
138
|
# See Prawn::Text#text_box for valid options
|
138
139
|
#
|
139
140
|
def initialize(formatted_text, options = {})
|
140
|
-
@inked
|
141
|
+
@inked = false
|
141
142
|
Prawn.verify_options(valid_options, options)
|
142
|
-
options
|
143
|
+
options = options.dup
|
143
144
|
|
144
145
|
self.class.extensions.reverse_each { |e| extend e }
|
145
146
|
|
146
|
-
@overflow
|
147
|
+
@overflow = options[:overflow] || :truncate
|
147
148
|
@disable_wrap_by_char = options[:disable_wrap_by_char]
|
148
149
|
|
149
150
|
self.original_text = formatted_text
|
150
|
-
@text
|
151
|
-
|
152
|
-
@document
|
153
|
-
@direction
|
154
|
-
@fallback_fonts
|
155
|
-
|
156
|
-
@at
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
@
|
162
|
-
|
163
|
-
|
164
|
-
@
|
151
|
+
@text = nil
|
152
|
+
|
153
|
+
@document = options[:document]
|
154
|
+
@direction = options[:direction] || @document.text_direction
|
155
|
+
@fallback_fonts = options[:fallback_fonts] ||
|
156
|
+
@document.fallback_fonts
|
157
|
+
@at = (
|
158
|
+
options[:at] || [@document.bounds.left, @document.bounds.top]
|
159
|
+
).dup
|
160
|
+
@width = options[:width] ||
|
161
|
+
@document.bounds.right - @at[0]
|
162
|
+
@height = options[:height] || default_height
|
163
|
+
@align = options[:align] ||
|
164
|
+
(@direction == :rtl ? :right : :left)
|
165
|
+
@vertical_align = options[:valign] || :top
|
166
|
+
@leading = options[:leading] || @document.default_leading
|
165
167
|
@character_spacing = options[:character_spacing] ||
|
166
|
-
|
167
|
-
@mode
|
168
|
-
@rotate
|
169
|
-
@rotate_around
|
170
|
-
@single_line
|
168
|
+
@document.character_spacing
|
169
|
+
@mode = options[:mode] || @document.text_rendering_mode
|
170
|
+
@rotate = options[:rotate] || 0
|
171
|
+
@rotate_around = options[:rotate_around] || :upper_left
|
172
|
+
@single_line = options[:single_line]
|
171
173
|
@draw_text_callback = options[:draw_text_callback]
|
172
174
|
|
173
175
|
# if the text rendering mode is :unknown, force it back to :fill
|
@@ -183,25 +185,28 @@ module Prawn
|
|
183
185
|
@overflow = :truncate
|
184
186
|
end
|
185
187
|
@min_font_size = options[:min_font_size] || 5
|
186
|
-
if options[:kerning].nil?
|
188
|
+
if options[:kerning].nil?
|
187
189
|
options[:kerning] = @document.default_kerning?
|
188
190
|
end
|
189
|
-
@options = {
|
190
|
-
|
191
|
-
|
191
|
+
@options = {
|
192
|
+
kerning: options[:kerning],
|
193
|
+
size: options[:size],
|
194
|
+
style: options[:style]
|
195
|
+
}
|
192
196
|
|
193
197
|
super(formatted_text, options)
|
194
198
|
end
|
195
199
|
|
196
|
-
# Render text to the document based on the settings defined in
|
200
|
+
# Render text to the document based on the settings defined in
|
201
|
+
# initialize.
|
197
202
|
#
|
198
|
-
# In order to facilitate look-ahead calculations, <tt>render</tt>
|
199
|
-
# a <tt>:dry_run => true</tt> option. If provided, then
|
200
|
-
# executed as if rendering, with the exception that
|
201
|
-
# the page. Useful for look-ahead computations of
|
202
|
-
# etc.
|
203
|
+
# In order to facilitate look-ahead calculations, <tt>render</tt>
|
204
|
+
# accepts a <tt>:dry_run => true</tt> option. If provided, then
|
205
|
+
# everything is executed as if rendering, with the exception that
|
206
|
+
# nothing is drawn on the page. Useful for look-ahead computations of
|
207
|
+
# height, unprinted text, etc.
|
203
208
|
#
|
204
|
-
# Returns any text that did not print under the current settings
|
209
|
+
# Returns any text that did not print under the current settings.
|
205
210
|
#
|
206
211
|
def render(flags = {})
|
207
212
|
unprinted_text = []
|
@@ -217,11 +222,11 @@ module Prawn
|
|
217
222
|
shrink_to_fit(text) if @overflow == :shrink_to_fit
|
218
223
|
process_vertical_alignment(text)
|
219
224
|
@inked = true unless flags[:dry_run]
|
220
|
-
if @rotate != 0 && @inked
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
+
unprinted_text = if @rotate != 0 && @inked
|
226
|
+
render_rotated(text)
|
227
|
+
else
|
228
|
+
wrap(text)
|
229
|
+
end
|
225
230
|
@inked = false
|
226
231
|
end
|
227
232
|
end
|
@@ -229,7 +234,7 @@ module Prawn
|
|
229
234
|
end
|
230
235
|
|
231
236
|
unprinted_text.map do |e|
|
232
|
-
e.merge(:
|
237
|
+
e.merge(text: @document.font.to_utf8(e[:text]))
|
233
238
|
end
|
234
239
|
end
|
235
240
|
|
@@ -243,13 +248,16 @@ module Prawn
|
|
243
248
|
#
|
244
249
|
def height
|
245
250
|
return 0 if @baseline_y.nil? || @descender.nil?
|
251
|
+
|
246
252
|
(@baseline_y - @descender).abs
|
247
253
|
end
|
248
254
|
|
249
255
|
# <tt>fragment</tt> is a Prawn::Text::Formatted::Fragment object
|
250
256
|
#
|
251
|
-
def draw_fragment(
|
252
|
-
|
257
|
+
def draw_fragment(
|
258
|
+
fragment, accumulated_width = 0, line_width = 0, word_spacing = 0
|
259
|
+
) #:nodoc:
|
260
|
+
case @align
|
253
261
|
when :left
|
254
262
|
x = @at[0]
|
255
263
|
when :center
|
@@ -257,11 +265,14 @@ module Prawn
|
|
257
265
|
when :right
|
258
266
|
x = @at[0] + @width - line_width
|
259
267
|
when :justify
|
260
|
-
if @direction == :ltr
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
268
|
+
x = if @direction == :ltr
|
269
|
+
@at[0]
|
270
|
+
else
|
271
|
+
@at[0] + @width - line_width
|
272
|
+
end
|
273
|
+
else
|
274
|
+
raise ArgumentError,
|
275
|
+
'align must be one of :left, :right, :center or :justify symbols'
|
265
276
|
end
|
266
277
|
|
267
278
|
x += accumulated_width
|
@@ -276,15 +287,19 @@ module Prawn
|
|
276
287
|
if @inked
|
277
288
|
draw_fragment_underlays(fragment)
|
278
289
|
|
279
|
-
@document.word_spacing(word_spacing)
|
290
|
+
@document.word_spacing(word_spacing) do
|
280
291
|
if @draw_text_callback
|
281
|
-
@draw_text_callback.call(
|
282
|
-
|
292
|
+
@draw_text_callback.call(
|
293
|
+
fragment.text, at: [x, y],
|
294
|
+
kerning: @kerning
|
295
|
+
)
|
283
296
|
else
|
284
|
-
@document.draw_text!(
|
285
|
-
|
297
|
+
@document.draw_text!(
|
298
|
+
fragment.text, at: [x, y],
|
299
|
+
kerning: @kerning
|
300
|
+
)
|
286
301
|
end
|
287
|
-
|
302
|
+
end
|
288
303
|
|
289
304
|
draw_fragment_overlays(fragment)
|
290
305
|
end
|
@@ -329,19 +344,19 @@ module Prawn
|
|
329
344
|
end
|
330
345
|
|
331
346
|
def valid_options
|
332
|
-
PDF::Core::Text::VALID_OPTIONS + [
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
347
|
+
PDF::Core::Text::VALID_OPTIONS + %i[
|
348
|
+
at
|
349
|
+
height width
|
350
|
+
align valign
|
351
|
+
rotate rotate_around
|
352
|
+
overflow min_font_size
|
353
|
+
disable_wrap_by_char
|
354
|
+
leading character_spacing
|
355
|
+
mode single_line
|
356
|
+
document
|
357
|
+
direction
|
358
|
+
fallback_fonts
|
359
|
+
draw_text_callback
|
345
360
|
]
|
346
361
|
end
|
347
362
|
|
@@ -407,10 +422,14 @@ module Prawn
|
|
407
422
|
|
408
423
|
@document.save_font do
|
409
424
|
hash[:text].each_char do |char|
|
410
|
-
font_glyph_pairs << [
|
411
|
-
|
412
|
-
|
413
|
-
|
425
|
+
font_glyph_pairs << [
|
426
|
+
find_font_for_this_glyph(
|
427
|
+
char,
|
428
|
+
fragment_font,
|
429
|
+
fallback_fonts.dup
|
430
|
+
),
|
431
|
+
char
|
432
|
+
]
|
414
433
|
end
|
415
434
|
end
|
416
435
|
|
@@ -426,7 +445,7 @@ module Prawn
|
|
426
445
|
|
427
446
|
def find_font_for_this_glyph(char, current_font, fallback_fonts)
|
428
447
|
@document.font(current_font)
|
429
|
-
if fallback_fonts.
|
448
|
+
if fallback_fonts.empty? || @document.font.glyph_present?(char)
|
430
449
|
current_font
|
431
450
|
else
|
432
451
|
find_font_for_this_glyph(char, fallback_fonts.shift, fallback_fonts)
|
@@ -439,7 +458,7 @@ module Prawn
|
|
439
458
|
current_font = nil
|
440
459
|
|
441
460
|
font_glyph_pairs.each do |font, char|
|
442
|
-
if font != current_font || fragments.count
|
461
|
+
if font != current_font || fragments.count.zero?
|
443
462
|
current_font = font
|
444
463
|
fragment = hash.dup
|
445
464
|
fragment[:text] = char
|
@@ -454,8 +473,8 @@ module Prawn
|
|
454
473
|
end
|
455
474
|
|
456
475
|
def move_baseline_down
|
457
|
-
if @baseline_y
|
458
|
-
@baseline_y
|
476
|
+
if @baseline_y.zero?
|
477
|
+
@baseline_y = -@ascender
|
459
478
|
else
|
460
479
|
@baseline_y -= (@line_height + @leading)
|
461
480
|
end
|
@@ -479,7 +498,11 @@ module Prawn
|
|
479
498
|
# we need to wait until render() is called so that the fonts are set
|
480
499
|
# up properly for wrapping. So guard with a boolean to ensure this is
|
481
500
|
# only run once.
|
482
|
-
|
501
|
+
if defined?(@vertical_alignment_processed) &&
|
502
|
+
@vertical_alignment_processed
|
503
|
+
return
|
504
|
+
end
|
505
|
+
|
483
506
|
@vertical_alignment_processed = true
|
484
507
|
|
485
508
|
return if @vertical_align == :top
|
@@ -523,7 +546,7 @@ module Prawn
|
|
523
546
|
# document.process_text_options sets the font
|
524
547
|
@document.process_text_options(@options)
|
525
548
|
@font_size = @options[:size]
|
526
|
-
@kerning
|
549
|
+
@kerning = @options[:kerning]
|
527
550
|
end
|
528
551
|
|
529
552
|
def render_rotated(text)
|
@@ -547,7 +570,7 @@ module Prawn
|
|
547
570
|
y = @at[1]
|
548
571
|
end
|
549
572
|
|
550
|
-
@document.rotate(@rotate, :
|
573
|
+
@document.rotate(@rotate, origin: [x, y]) do
|
551
574
|
unprinted_text = wrap(text)
|
552
575
|
end
|
553
576
|
unprinted_text
|
@@ -571,41 +594,52 @@ module Prawn
|
|
571
594
|
|
572
595
|
def draw_fragment_overlay_link(fragment)
|
573
596
|
return unless fragment.link
|
597
|
+
|
574
598
|
box = fragment.absolute_bounding_box
|
575
|
-
@document.link_annotation(
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
599
|
+
@document.link_annotation(
|
600
|
+
box,
|
601
|
+
Border: [0, 0, 0],
|
602
|
+
A: {
|
603
|
+
Type: :Action,
|
604
|
+
S: :URI,
|
605
|
+
URI: PDF::Core::LiteralString.new(fragment.link)
|
606
|
+
}
|
607
|
+
)
|
580
608
|
end
|
581
609
|
|
582
610
|
def draw_fragment_overlay_anchor(fragment)
|
583
611
|
return unless fragment.anchor
|
612
|
+
|
584
613
|
box = fragment.absolute_bounding_box
|
585
|
-
@document.link_annotation(
|
586
|
-
|
587
|
-
|
614
|
+
@document.link_annotation(
|
615
|
+
box,
|
616
|
+
Border: [0, 0, 0],
|
617
|
+
Dest: fragment.anchor
|
618
|
+
)
|
588
619
|
end
|
589
620
|
|
590
621
|
def draw_fragment_overlay_local(fragment)
|
591
622
|
return unless fragment.local
|
623
|
+
|
592
624
|
box = fragment.absolute_bounding_box
|
593
|
-
@document.link_annotation(
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
625
|
+
@document.link_annotation(
|
626
|
+
box,
|
627
|
+
Border: [0, 0, 0],
|
628
|
+
A: {
|
629
|
+
Type: :Action,
|
630
|
+
S: :Launch,
|
631
|
+
F: PDF::Core::LiteralString.new(fragment.local),
|
632
|
+
NewWindow: true
|
633
|
+
}
|
634
|
+
)
|
599
635
|
end
|
600
636
|
|
601
637
|
def draw_fragment_overlay_styles(fragment)
|
602
|
-
|
603
|
-
if underline
|
638
|
+
if fragment.styles.include?(:underline)
|
604
639
|
@document.stroke_line(fragment.underline_points)
|
605
640
|
end
|
606
641
|
|
607
|
-
|
608
|
-
if strikethrough
|
642
|
+
if fragment.styles.include?(:strikethrough)
|
609
643
|
@document.stroke_line(fragment.strikethrough_points)
|
610
644
|
end
|
611
645
|
end
|