prawn 2.3.0 → 2.5.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/prawn/document/bounding_box.rb +223 -143
- data/lib/prawn/document/column_box.rb +61 -26
- data/lib/prawn/document/internals.rb +25 -16
- data/lib/prawn/document/span.rb +21 -18
- data/lib/prawn/document.rb +273 -182
- data/lib/prawn/encoding.rb +2 -5
- data/lib/prawn/errors.rb +23 -34
- data/lib/prawn/font.rb +254 -139
- data/lib/prawn/font_metric_cache.rb +18 -16
- data/lib/prawn/fonts/afm.rb +99 -57
- data/lib/prawn/fonts/dfont.rb +7 -1
- data/lib/prawn/fonts/otf.rb +4 -1
- data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
- data/lib/prawn/fonts/ttc.rb +7 -2
- data/lib/prawn/fonts/ttf.rb +345 -107
- data/lib/prawn/fonts.rb +14 -0
- data/lib/prawn/graphics/blend_mode.rb +25 -28
- data/lib/prawn/graphics/cap_style.rb +9 -12
- data/lib/prawn/graphics/color.rb +75 -50
- data/lib/prawn/graphics/dash.rb +45 -42
- data/lib/prawn/graphics/join_style.rb +18 -12
- data/lib/prawn/graphics/patterns.rb +239 -110
- data/lib/prawn/graphics/transformation.rb +51 -44
- data/lib/prawn/graphics/transparency.rb +16 -40
- data/lib/prawn/graphics.rb +370 -260
- data/lib/prawn/grid.rb +219 -57
- data/lib/prawn/image_handler.rb +27 -10
- data/lib/prawn/images/image.rb +8 -10
- data/lib/prawn/images/jpg.rb +46 -20
- data/lib/prawn/images/png.rb +94 -42
- data/lib/prawn/images.rb +70 -81
- data/lib/prawn/measurement_extensions.rb +39 -8
- data/lib/prawn/measurements.rb +60 -5
- data/lib/prawn/outline.rb +120 -113
- data/lib/prawn/repeater.rb +52 -36
- data/lib/prawn/security/arcfour.rb +4 -4
- data/lib/prawn/security.rb +106 -98
- data/lib/prawn/soft_mask.rb +42 -30
- data/lib/prawn/stamp.rb +38 -42
- data/lib/prawn/text/box.rb +156 -105
- data/lib/prawn/text/formatted/arranger.rb +121 -41
- data/lib/prawn/text/formatted/box.rb +239 -163
- data/lib/prawn/text/formatted/fragment.rb +130 -14
- data/lib/prawn/text/formatted/line_wrap.rb +49 -38
- data/lib/prawn/text/formatted/parser.rb +116 -74
- data/lib/prawn/text/formatted/wrap.rb +25 -26
- data/lib/prawn/text/formatted.rb +75 -0
- data/lib/prawn/text.rb +456 -211
- data/lib/prawn/transformation_stack.rb +29 -10
- data/lib/prawn/utilities.rb +13 -13
- data/lib/prawn/version.rb +2 -1
- data/lib/prawn/view.rb +69 -54
- data/lib/prawn.rb +24 -18
- data.tar.gz.sig +0 -0
- metadata +55 -262
- metadata.gz.sig +3 -4
- data/.yardopts +0 -10
- data/Gemfile +0 -5
- data/Rakefile +0 -54
- data/manual/absolute_position.pdf +0 -0
- data/manual/basic_concepts/adding_pages.rb +0 -26
- data/manual/basic_concepts/basic_concepts.rb +0 -43
- data/manual/basic_concepts/creation.rb +0 -38
- data/manual/basic_concepts/cursor.rb +0 -32
- data/manual/basic_concepts/measurement.rb +0 -24
- data/manual/basic_concepts/origin.rb +0 -37
- data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
- data/manual/basic_concepts/view.rb +0 -48
- data/manual/bounding_box/bounding_box.rb +0 -41
- data/manual/bounding_box/bounds.rb +0 -48
- data/manual/bounding_box/canvas.rb +0 -23
- data/manual/bounding_box/creation.rb +0 -22
- data/manual/bounding_box/indentation.rb +0 -45
- data/manual/bounding_box/nesting.rb +0 -52
- data/manual/bounding_box/russian_boxes.rb +0 -40
- data/manual/bounding_box/stretchy.rb +0 -29
- data/manual/contents.rb +0 -35
- data/manual/cover.rb +0 -43
- data/manual/document_and_page_options/background.rb +0 -25
- data/manual/document_and_page_options/document_and_page_options.rb +0 -34
- data/manual/document_and_page_options/metadata.rb +0 -25
- data/manual/document_and_page_options/page_margins.rb +0 -36
- data/manual/document_and_page_options/page_size.rb +0 -34
- data/manual/document_and_page_options/print_scaling.rb +0 -22
- data/manual/example_helper.rb +0 -8
- data/manual/graphics/blend_mode.rb +0 -52
- data/manual/graphics/circle_and_ellipse.rb +0 -21
- data/manual/graphics/color.rb +0 -22
- data/manual/graphics/common_lines.rb +0 -29
- data/manual/graphics/fill_and_stroke.rb +0 -41
- data/manual/graphics/fill_rules.rb +0 -37
- data/manual/graphics/gradients.rb +0 -43
- data/manual/graphics/graphics.rb +0 -64
- data/manual/graphics/helper.rb +0 -27
- data/manual/graphics/line_width.rb +0 -36
- data/manual/graphics/lines_and_curves.rb +0 -40
- data/manual/graphics/polygon.rb +0 -27
- data/manual/graphics/rectangle.rb +0 -20
- data/manual/graphics/rotate.rb +0 -25
- data/manual/graphics/scale.rb +0 -42
- data/manual/graphics/soft_masks.rb +0 -44
- data/manual/graphics/stroke_cap.rb +0 -30
- data/manual/graphics/stroke_dash.rb +0 -47
- data/manual/graphics/stroke_join.rb +0 -29
- data/manual/graphics/translate.rb +0 -28
- data/manual/graphics/transparency.rb +0 -33
- data/manual/how_to_read_this_manual.rb +0 -39
- data/manual/images/absolute_position.rb +0 -22
- data/manual/images/fit.rb +0 -20
- data/manual/images/horizontal.rb +0 -24
- data/manual/images/images.rb +0 -41
- data/manual/images/plain_image.rb +0 -17
- data/manual/images/scale.rb +0 -21
- data/manual/images/vertical.rb +0 -27
- data/manual/images/width_and_height.rb +0 -24
- data/manual/layout/boxes.rb +0 -26
- data/manual/layout/content.rb +0 -24
- data/manual/layout/layout.rb +0 -27
- data/manual/layout/simple_grid.rb +0 -22
- data/manual/outline/add_subsection_to.rb +0 -60
- data/manual/outline/insert_section_after.rb +0 -46
- data/manual/outline/outline.rb +0 -33
- data/manual/outline/sections_and_pages.rb +0 -66
- data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
- data/manual/repeatable_content/page_numbering.rb +0 -55
- data/manual/repeatable_content/repeatable_content.rb +0 -35
- data/manual/repeatable_content/repeater.rb +0 -54
- data/manual/repeatable_content/stamp.rb +0 -40
- data/manual/security/encryption.rb +0 -28
- data/manual/security/permissions.rb +0 -41
- data/manual/security/security.rb +0 -28
- data/manual/table.rb +0 -16
- data/manual/text/alignment.rb +0 -43
- data/manual/text/color.rb +0 -24
- data/manual/text/column_box.rb +0 -30
- data/manual/text/fallback_fonts.rb +0 -41
- data/manual/text/font.rb +0 -40
- data/manual/text/font_size.rb +0 -44
- data/manual/text/font_style.rb +0 -22
- data/manual/text/formatted_callbacks.rb +0 -65
- data/manual/text/formatted_text.rb +0 -58
- data/manual/text/free_flowing_text.rb +0 -50
- data/manual/text/inline.rb +0 -40
- data/manual/text/kerning_and_character_spacing.rb +0 -38
- data/manual/text/leading.rb +0 -24
- data/manual/text/line_wrapping.rb +0 -60
- data/manual/text/paragraph_indentation.rb +0 -32
- data/manual/text/positioned_text.rb +0 -37
- data/manual/text/registering_families.rb +0 -51
- data/manual/text/rendering_and_color.rb +0 -36
- data/manual/text/right_to_left_text.rb +0 -54
- data/manual/text/rotation.rb +0 -47
- data/manual/text/single_usage.rb +0 -36
- data/manual/text/text.rb +0 -75
- data/manual/text/text_box_excess.rb +0 -35
- data/manual/text/text_box_extensions.rb +0 -48
- data/manual/text/text_box_overflow.rb +0 -49
- data/manual/text/utf8.rb +0 -27
- data/manual/text/win_ansi_charset.rb +0 -62
- data/prawn.gemspec +0 -57
- data/spec/data/curves.pdf +0 -66
- data/spec/extensions/encoding_helpers.rb +0 -11
- data/spec/prawn/document/bounding_box_spec.rb +0 -546
- data/spec/prawn/document/column_box_spec.rb +0 -75
- data/spec/prawn/document/security_spec.rb +0 -176
- data/spec/prawn/document_annotations_spec.rb +0 -76
- data/spec/prawn/document_destinations_spec.rb +0 -15
- data/spec/prawn/document_grid_spec.rb +0 -99
- data/spec/prawn/document_reference_spec.rb +0 -27
- data/spec/prawn/document_span_spec.rb +0 -36
- data/spec/prawn/document_spec.rb +0 -802
- data/spec/prawn/font_metric_cache_spec.rb +0 -54
- data/spec/prawn/font_spec.rb +0 -542
- data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
- data/spec/prawn/graphics/transparency_spec.rb +0 -81
- data/spec/prawn/graphics_spec.rb +0 -837
- data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
- data/spec/prawn/image_handler_spec.rb +0 -53
- data/spec/prawn/images/jpg_spec.rb +0 -20
- data/spec/prawn/images/png_spec.rb +0 -283
- data/spec/prawn/images_spec.rb +0 -224
- data/spec/prawn/measurements_extensions_spec.rb +0 -24
- data/spec/prawn/outline_spec.rb +0 -412
- data/spec/prawn/repeater_spec.rb +0 -165
- data/spec/prawn/soft_mask_spec.rb +0 -74
- data/spec/prawn/stamp_spec.rb +0 -172
- data/spec/prawn/text/box_spec.rb +0 -1112
- data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
- data/spec/prawn/text/formatted/box_spec.rb +0 -846
- data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
- data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
- data/spec/prawn/text/formatted/parser_spec.rb +0 -697
- data/spec/prawn/text_draw_text_spec.rb +0 -149
- data/spec/prawn/text_rendering_mode_spec.rb +0 -48
- data/spec/prawn/text_spacing_spec.rb +0 -95
- data/spec/prawn/text_spec.rb +0 -603
- data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
- data/spec/prawn/transformation_stack_spec.rb +0 -66
- data/spec/prawn/view_spec.rb +0 -63
- data/spec/prawn_manual_spec.rb +0 -35
- data/spec/spec_helper.rb +0 -48
data/lib/prawn/text/box.rb
CHANGED
@@ -1,140 +1,191 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# text/rectangle.rb : Implements text boxes
|
4
|
-
#
|
5
|
-
# Copyright November 2009, Daniel Nelson. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
#
|
9
|
-
|
10
3
|
require_relative 'formatted/box'
|
11
4
|
|
12
5
|
module Prawn
|
13
|
-
module Text
|
6
|
+
module Text # rubocop: disable Style/Documentation
|
14
7
|
# @group Stable API
|
15
8
|
|
16
|
-
# Draws the requested text into a box.
|
17
|
-
#
|
18
|
-
#
|
9
|
+
# Draws the requested text into a box.
|
10
|
+
#
|
11
|
+
# When the text overflows the rectangle, you shrink to fit, or truncate the
|
12
|
+
# text. Text boxes are independent of the document y position.
|
19
13
|
#
|
20
|
-
#
|
14
|
+
# #### Encoding
|
21
15
|
#
|
22
|
-
# Note that strings passed to this function should be encoded as UTF-8.
|
23
|
-
#
|
24
|
-
#
|
16
|
+
# Note that strings passed to this function should be encoded as UTF-8. If
|
17
|
+
# you get unexpected characters appearing in your rendered document, check
|
18
|
+
# this.
|
25
19
|
#
|
26
|
-
# If the current font is a built-in one, although the string must be
|
27
|
-
#
|
28
|
-
# are allowed.
|
20
|
+
# If the current font is a built-in one, although the string must be encoded
|
21
|
+
# as UTF-8, only characters that are available in WinAnsi are allowed.
|
29
22
|
#
|
30
23
|
# If an empty box is rendered to your PDF instead of the character you
|
31
24
|
# wanted it usually means the current font doesn't include that character.
|
32
25
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# or not to prevent mid-word breaks when text does not fit in box.
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
# <
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
# This controls the behavior when the amount of text
|
91
|
-
# exceeds the available space. [:truncate]
|
92
|
-
# <tt>:min_font_size</tt>::
|
93
|
-
# <tt>number</tt>. The minimum font size to use when :overflow is set to
|
94
|
-
# :shrink_to_fit (that is the font size will not be reduced to less than
|
95
|
-
# this value, even if it means that some text will be cut off). [5]
|
96
|
-
#
|
97
|
-
# == Returns
|
98
|
-
#
|
99
|
-
# Returns any text that did not print under the current settings.
|
100
|
-
#
|
101
|
-
# == Exceptions
|
102
|
-
#
|
103
|
-
# Raises <tt>Prawn::Errors::CannotFit</tt> if not wide enough to print
|
104
|
-
# any text
|
105
|
-
#
|
26
|
+
# @param string [String]
|
27
|
+
# @param options [Hash{Symbol => any}]
|
28
|
+
# @option options :kerning [Boolean] (value of document.default_kerning?)
|
29
|
+
# Whether or not to use kerning (if it is available with the current
|
30
|
+
# font).
|
31
|
+
# @option options :size [Number] (current font size)
|
32
|
+
# The font size to use.
|
33
|
+
# @option options :character_spacing [Number] (0)
|
34
|
+
# The amount of space to add to or remove from the default character
|
35
|
+
# spacing.
|
36
|
+
# @option options :disable_wrap_by_char [Boolean] (false)
|
37
|
+
# Whether or not to prevent mid-word breaks when text does not fit in box.
|
38
|
+
# @option options :mode [Symbol] (:fill)
|
39
|
+
# The text rendering mode. See documentation for
|
40
|
+
# {Prawn::Document#text_rendering_mode} for a list of valid options.
|
41
|
+
# @option option :style [Symbol] (current style)
|
42
|
+
# The style to use. The requested style must be part of the current font
|
43
|
+
# family.
|
44
|
+
# @option option :at [Array(Number, Number)] (bounds top left corner)
|
45
|
+
# The upper left corner of the box.
|
46
|
+
# @option options :width [Number] (bounds.right - at[0])
|
47
|
+
# The width of the box.
|
48
|
+
# @option options :height [Number] (default_height())
|
49
|
+
# The height of the box.
|
50
|
+
# @option options :direction [:ltr, :rtl] (value of document.text_direction)
|
51
|
+
# Direction of the text (left-to-right or right-to-left).
|
52
|
+
# @option options :fallback_fonts [Array<String>]
|
53
|
+
# An array of font names. Each name must be the name of an AFM font or the
|
54
|
+
# name that was used to register a family of external fonts (see
|
55
|
+
# {Prawn::Document#font_families}). If present, then each glyph will be
|
56
|
+
# rendered using the first font that includes the glyph, starting with the
|
57
|
+
# current font and then moving through `:fallback_fonts`.
|
58
|
+
# @option options :align [:left, :center, :right, :justify]
|
59
|
+
# (:left if direction is :ltr, :right if direction is :rtl)
|
60
|
+
# Alignment within the bounding box.
|
61
|
+
# @option options :valign [:top, :center, :bottom] (:top)
|
62
|
+
# Vertical alignment within the bounding box.
|
63
|
+
# @option options :rotate [Number]
|
64
|
+
# The angle to rotate the text.
|
65
|
+
# @option options :rotate_around
|
66
|
+
# [:center, :upper_left, :upper_right, :lower_right, :lower_left]
|
67
|
+
# (:upper_left)
|
68
|
+
# The point around which to rotate the text.
|
69
|
+
# @option options :leading [Number] (value of document.default_leading)
|
70
|
+
# Additional space between lines.
|
71
|
+
# @option options :single_line [Boolean] (false)
|
72
|
+
# If true, then only the first line will be drawn.
|
73
|
+
# @option options :overflow [:truncate, :shrink_to_fit, :expand] (:truncate)
|
74
|
+
# This controls the behavior when the amount of text exceeds the available
|
75
|
+
# space.
|
76
|
+
# @option options :min_font_size [Number] (5)
|
77
|
+
# The minimum font size to use when `:overflow` is set to `:shrink_to_fit`
|
78
|
+
# (that is the font size will not be reduced to less than this value, even
|
79
|
+
# if it means that some text will be cut off).
|
80
|
+
# @return [String] Any text that did not print under the current settings.
|
81
|
+
# @raise [Prawn::Errors::CannotFit]
|
82
|
+
# If not wide enough to print any text.
|
106
83
|
def text_box(string, options = {})
|
107
84
|
options = options.dup
|
108
85
|
options[:document] = self
|
109
86
|
|
110
|
-
box =
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
87
|
+
box =
|
88
|
+
if options[:inline_format]
|
89
|
+
p = options.delete(:inline_format)
|
90
|
+
p = [] unless p.is_a?(Array)
|
91
|
+
array = text_formatter.format(string, *p)
|
92
|
+
Text::Formatted::Box.new(array, options)
|
93
|
+
else
|
94
|
+
Text::Box.new(string, options)
|
95
|
+
end
|
118
96
|
|
119
97
|
box.render
|
120
98
|
end
|
121
99
|
|
122
100
|
# @group Experimental API
|
123
101
|
|
124
|
-
#
|
125
|
-
# method. However, using Text::Box.new in conjunction with
|
126
|
-
# #render(:dry_run=> true) enables one to do look-ahead calculations prior
|
127
|
-
# to placing text on the page, or to determine how much vertical space was
|
128
|
-
# consumed by the printed text
|
102
|
+
# Text box.
|
129
103
|
#
|
104
|
+
# Generally, one would use the {Prawn::Text#text_box} convenience method.
|
105
|
+
# However, using {Prawn::Text::Box#initialize Box.new} in conjunction with
|
106
|
+
# `render(dry_run: true)` enables one to do calculations prior to placing
|
107
|
+
# text on the page, or to determine how much vertical space was consumed by
|
108
|
+
# the printed text.
|
130
109
|
class Box < Prawn::Text::Formatted::Box
|
110
|
+
# @param string [String]
|
111
|
+
# @param options [Hash{Symbol => any}]
|
112
|
+
# @option options :document [Prawn::Document] Owning document.
|
113
|
+
# @option options :kerning [Boolean] (value of document.default_kerning?)
|
114
|
+
# Whether or not to use kerning (if it is available with the current
|
115
|
+
# font).
|
116
|
+
# @option options :size [Number] (current font size)
|
117
|
+
# The font size to use.
|
118
|
+
# @option options :character_spacing [Number] (0)
|
119
|
+
# The amount of space to add to or remove from the default character
|
120
|
+
# spacing.
|
121
|
+
# @option options :disable_wrap_by_char [Boolean] (false)
|
122
|
+
# Whether or not to prevent mid-word breaks when text does not fit in box.
|
123
|
+
# @option options :mode [Symbol] (:fill)
|
124
|
+
# The text rendering mode. See documentation for
|
125
|
+
# {Prawn::Document#text_rendering_mode} for a list of valid options.
|
126
|
+
# @option option :style [Symbol] (current style)
|
127
|
+
# The style to use. The requested style must be part of the current font
|
128
|
+
# family.
|
129
|
+
# @option option :at [Array(Number, Number)] (bounds top left corner)
|
130
|
+
# The upper left corner of the box.
|
131
|
+
# @option options :width [Number] (bounds.right - at[0])
|
132
|
+
# The width of the box.
|
133
|
+
# @option options :height [Number] (default_height())
|
134
|
+
# The height of the box.
|
135
|
+
# @option options :direction [:ltr, :rtl] (value of document.text_direction)
|
136
|
+
# Direction of the text (left-to-right or right-to-left).
|
137
|
+
# @option options :fallback_fonts [Array<String>]
|
138
|
+
# An array of font names. Each name must be the name of an AFM font or the
|
139
|
+
# name that was used to register a family of external fonts (see
|
140
|
+
# {Prawn::Document#font_families}). If present, then each glyph will be
|
141
|
+
# rendered using the first font that includes the glyph, starting with the
|
142
|
+
# current font and then moving through `:fallback_fonts`.
|
143
|
+
# @option options :align [:left, :center, :right, :justify]
|
144
|
+
# (:left if direction is :ltr, :right if direction is :rtl)
|
145
|
+
# Alignment within the bounding box.
|
146
|
+
# @option options :valign [:top, :center, :bottom] (:top)
|
147
|
+
# Vertical alignment within the bounding box.
|
148
|
+
# @option options :rotate [Number]
|
149
|
+
# The angle to rotate the text.
|
150
|
+
# @option options :rotate_around
|
151
|
+
# [:center, :upper_left, :upper_right, :lower_right, :lower_left]
|
152
|
+
# (:upper_left)
|
153
|
+
# The point around which to rotate the text.
|
154
|
+
# @option options :leading [Number] (value of document.default_leading)
|
155
|
+
# Additional space between lines.
|
156
|
+
# @option options :single_line [Boolean] (false)
|
157
|
+
# If true, then only the first line will be drawn.
|
158
|
+
# @option options :overflow [:truncate, :shrink_to_fit, :expand] (:truncate)
|
159
|
+
# This controls the behavior when the amount of text exceeds the available
|
160
|
+
# space.
|
161
|
+
# @option options :min_font_size [Number] (5)
|
162
|
+
# The minimum font size to use when `:overflow` is set to `:shrink_to_fit`
|
163
|
+
# (that is the font size will not be reduced to less than this value, even
|
164
|
+
# if it means that some text will be cut off).
|
131
165
|
def initialize(string, options = {})
|
132
166
|
super([{ text: string }], options)
|
133
167
|
end
|
134
168
|
|
169
|
+
# Render text to the document based on the settings defined in
|
170
|
+
# constructor.
|
171
|
+
#
|
172
|
+
# In order to facilitate look-ahead calculations, this method accepts
|
173
|
+
# a `dry_run: true` option. If provided, then everything is executed as if
|
174
|
+
# rendering, with the exception that nothing is drawn on the page. Useful
|
175
|
+
# for look-ahead computations of height, unprinted text, etc.
|
176
|
+
#
|
177
|
+
# @param flags [Hash{Symbol => any}]
|
178
|
+
# @option flags :dry_run [Boolean] (false)
|
179
|
+
# Do not draw the text. Everything else is done.
|
180
|
+
# @return [String]
|
181
|
+
# Any text that did not print under the current settings.
|
182
|
+
# @raise [Prawn::Text::Formatted::Arranger::BadFontFamily]
|
183
|
+
# If no font family is defined for the current font.
|
184
|
+
# @raise [Prawn::Errors::CannotFit]
|
185
|
+
# If not wide enough to print any text.
|
135
186
|
def render(flags = {})
|
136
187
|
leftover = super(flags)
|
137
|
-
leftover.
|
188
|
+
leftover.map { |hash| hash[:text] }.join
|
138
189
|
end
|
139
190
|
end
|
140
191
|
end
|
@@ -1,18 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# core/text/formatted/arranger.rb : Implements a data structure for 2-stage
|
4
|
-
# processing of lines of formatted text
|
5
|
-
#
|
6
|
-
# Copyright February 2010, Daniel Nelson. All Rights Reserved.
|
7
|
-
#
|
8
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
9
|
-
|
10
3
|
module Prawn
|
11
4
|
module Text
|
12
|
-
module Formatted
|
5
|
+
module Formatted
|
6
|
+
# D data structure for 2-stage processing of lines of formatted text.
|
13
7
|
# @private
|
8
|
+
class Arranger
|
9
|
+
# You're getting this because you're trying to get some information from
|
10
|
+
# the arranger before it finished processing text.
|
11
|
+
class NotFinalized < StandardError
|
12
|
+
# @private
|
13
|
+
DEFAULT_MESSAGE = 'Lines must be finalized'
|
14
|
+
|
15
|
+
# @private
|
16
|
+
MESSAGE_WITH_METHOD = 'Lines must be finalized before calling #%<method>s'
|
17
|
+
|
18
|
+
def initialize(message = DEFAULT_MESSAGE, method: nil)
|
19
|
+
if method && message == DEFAULT_MESSAGE
|
20
|
+
super(format(MESSAGE_WITH_METHOD, method: method))
|
21
|
+
else
|
22
|
+
super(message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# You're getting this because a font doesn't have a family name.
|
28
|
+
class BadFontFamily < StandardError
|
29
|
+
def initialize(message = 'Bad font family')
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
14
33
|
|
15
|
-
class Arranger #:nodoc:
|
16
34
|
attr_reader :max_line_height
|
17
35
|
attr_reader :max_descender
|
18
36
|
attr_reader :max_ascender
|
@@ -31,39 +49,55 @@ module Prawn
|
|
31
49
|
@kerning = options[:kerning]
|
32
50
|
end
|
33
51
|
|
52
|
+
# Number of spaces in the text.
|
53
|
+
#
|
54
|
+
# @return [Integer]
|
55
|
+
# @raise [NotFinalized]
|
34
56
|
def space_count
|
35
57
|
unless finalized
|
36
|
-
raise '
|
58
|
+
raise NotFinalized.new(method: 'space_count')
|
37
59
|
end
|
38
60
|
|
39
|
-
@fragments.
|
61
|
+
@fragments.reduce(0) do |sum, fragment|
|
40
62
|
sum + fragment.space_count
|
41
63
|
end
|
42
64
|
end
|
43
65
|
|
66
|
+
# Line width.
|
67
|
+
#
|
68
|
+
# @return [Number]
|
69
|
+
# @raise [NotFinalized]
|
44
70
|
def line_width
|
45
71
|
unless finalized
|
46
|
-
raise
|
72
|
+
raise raise NotFinalized.new(method: 'line_width')
|
47
73
|
end
|
48
74
|
|
49
|
-
@fragments.
|
75
|
+
@fragments.reduce(0) do |sum, fragment|
|
50
76
|
sum + fragment.width
|
51
77
|
end
|
52
78
|
end
|
53
79
|
|
80
|
+
# Line text.
|
81
|
+
#
|
82
|
+
# @return [String]
|
83
|
+
# @raise [NotFinalized]
|
54
84
|
def line
|
55
85
|
unless finalized
|
56
|
-
raise '
|
86
|
+
raise NotFinalized.new(method: 'line')
|
57
87
|
end
|
58
88
|
|
59
|
-
@fragments.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
89
|
+
@fragments.map { |fragment|
|
90
|
+
begin
|
91
|
+
fragment.text.dup.encode(::Encoding::UTF_8)
|
92
|
+
rescue ::Encoding::InvalidByteSequenceError, ::Encoding::UndefinedConversionError
|
93
|
+
fragment.text.dup.force_encoding(::Encoding::UTF_8)
|
94
|
+
end
|
95
|
+
}.join
|
65
96
|
end
|
66
97
|
|
98
|
+
# Finish laying out current line.
|
99
|
+
#
|
100
|
+
# @return [void]
|
67
101
|
def finalize_line
|
68
102
|
@finalized = true
|
69
103
|
|
@@ -76,7 +110,7 @@ module Prawn
|
|
76
110
|
fragment = Prawn::Text::Formatted::Fragment.new(
|
77
111
|
text,
|
78
112
|
format_state,
|
79
|
-
@document
|
113
|
+
@document,
|
80
114
|
)
|
81
115
|
@fragments << fragment
|
82
116
|
self.fragment_measurements = fragment
|
@@ -84,6 +118,10 @@ module Prawn
|
|
84
118
|
end
|
85
119
|
end
|
86
120
|
|
121
|
+
# Set new fragment array.
|
122
|
+
#
|
123
|
+
# @param array [Array<Hash>]
|
124
|
+
# @return [void]
|
87
125
|
def format_array=(array)
|
88
126
|
initialize_line
|
89
127
|
@unconsumed = []
|
@@ -94,6 +132,9 @@ module Prawn
|
|
94
132
|
end
|
95
133
|
end
|
96
134
|
|
135
|
+
# Prepare for new line layout.
|
136
|
+
#
|
137
|
+
# @return [void]
|
97
138
|
def initialize_line
|
98
139
|
@finalized = false
|
99
140
|
@max_line_height = 0
|
@@ -104,13 +145,20 @@ module Prawn
|
|
104
145
|
@fragments = []
|
105
146
|
end
|
106
147
|
|
148
|
+
# Were all fragments processed?
|
149
|
+
#
|
150
|
+
# @return [Boolean]
|
107
151
|
def finished?
|
108
152
|
@unconsumed.empty?
|
109
153
|
end
|
110
154
|
|
155
|
+
# Get the next unprocessed string.
|
156
|
+
#
|
157
|
+
# @return [String, nil]
|
158
|
+
# @raise [NotFinalized]
|
111
159
|
def next_string
|
112
160
|
if finalized
|
113
|
-
raise '
|
161
|
+
raise NotFinalized.new(method: 'next_string')
|
114
162
|
end
|
115
163
|
|
116
164
|
next_unconsumed_hash = @unconsumed.shift
|
@@ -124,6 +172,9 @@ module Prawn
|
|
124
172
|
end
|
125
173
|
end
|
126
174
|
|
175
|
+
# Get the next unprocessed string keeping it in the queue.
|
176
|
+
#
|
177
|
+
# @return [String, nil]
|
127
178
|
def preview_next_string
|
128
179
|
next_unconsumed_hash = @unconsumed.first
|
129
180
|
|
@@ -132,6 +183,11 @@ module Prawn
|
|
132
183
|
end
|
133
184
|
end
|
134
185
|
|
186
|
+
# Apply color and font settings.
|
187
|
+
#
|
188
|
+
# @param fragment [Prawn::Text::Formatted::Fragment]
|
189
|
+
# @yield
|
190
|
+
# @return [void]
|
135
191
|
def apply_color_and_font_settings(fragment, &block)
|
136
192
|
if fragment.color
|
137
193
|
original_fill_color = @document.fill_color
|
@@ -146,6 +202,11 @@ module Prawn
|
|
146
202
|
end
|
147
203
|
end
|
148
204
|
|
205
|
+
# Apply font settings.
|
206
|
+
#
|
207
|
+
# @param fragment [Prawn::Text::Formatted::Fragment]
|
208
|
+
# @yield
|
209
|
+
# @return [void]
|
149
210
|
def apply_font_settings(fragment = nil, &block)
|
150
211
|
if fragment.nil?
|
151
212
|
font = current_format_state[:font]
|
@@ -163,10 +224,10 @@ module Prawn
|
|
163
224
|
|
164
225
|
@document.character_spacing(character_spacing) do
|
165
226
|
if font || font_style != :normal
|
166
|
-
raise
|
227
|
+
raise BadFontFamily unless @document.font.family
|
167
228
|
|
168
229
|
@document.font(
|
169
|
-
font || @document.font.family, style: font_style
|
230
|
+
font || @document.font.family, style: font_style,
|
170
231
|
) do
|
171
232
|
apply_font_size(size, styles, &block)
|
172
233
|
end
|
@@ -176,6 +237,12 @@ module Prawn
|
|
176
237
|
end
|
177
238
|
end
|
178
239
|
|
240
|
+
# Update last fragment's text.
|
241
|
+
#
|
242
|
+
# @param printed [String]
|
243
|
+
# @param unprinted [String]
|
244
|
+
# @param normalized_soft_hyphen [Boolean]
|
245
|
+
# @return [void]
|
179
246
|
def update_last_string(printed, unprinted, normalized_soft_hyphen = nil)
|
180
247
|
return if printed.nil?
|
181
248
|
|
@@ -195,14 +262,21 @@ module Prawn
|
|
195
262
|
load_previous_format_state if printed.empty?
|
196
263
|
end
|
197
264
|
|
265
|
+
# Get the next fragment.
|
266
|
+
#
|
267
|
+
# @return [Prawn::Text::Formatted::Fragment]
|
268
|
+
# @raise [NotFinalized]
|
198
269
|
def retrieve_fragment
|
199
270
|
unless finalized
|
200
|
-
raise 'Lines must be finalized before fragments can be retrieved'
|
271
|
+
raise NotFinalized, 'Lines must be finalized before fragments can be retrieved'
|
201
272
|
end
|
202
273
|
|
203
274
|
@fragments.shift
|
204
275
|
end
|
205
276
|
|
277
|
+
# Repack remaining fragments.
|
278
|
+
#
|
279
|
+
# @return [void]
|
206
280
|
def repack_unretrieved
|
207
281
|
new_unconsumed = []
|
208
282
|
# rubocop: disable Lint/AssignmentInCondition
|
@@ -214,10 +288,13 @@ module Prawn
|
|
214
288
|
@unconsumed = new_unconsumed.concat(@unconsumed)
|
215
289
|
end
|
216
290
|
|
291
|
+
# Get font variant from fragment styles.
|
292
|
+
#
|
293
|
+
# @param styles [Array<Symbol>]
|
294
|
+
# @return [Symbol]
|
217
295
|
def font_style(styles)
|
218
|
-
|
219
|
-
|
220
|
-
elsif styles.include?(:bold) && styles.include?(:italic)
|
296
|
+
styles = Array(styles)
|
297
|
+
if styles.include?(:bold) && styles.include?(:italic)
|
221
298
|
:bold_italic
|
222
299
|
elsif styles.include?(:bold)
|
223
300
|
:bold
|
@@ -240,31 +317,34 @@ module Prawn
|
|
240
317
|
end
|
241
318
|
end
|
242
319
|
|
243
|
-
def apply_font_size(size, styles)
|
320
|
+
def apply_font_size(size, styles, &block)
|
244
321
|
if subscript?(styles) || superscript?(styles)
|
245
322
|
relative_size = 0.583
|
246
|
-
size =
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
323
|
+
size =
|
324
|
+
if size.nil?
|
325
|
+
@document.font_size * relative_size
|
326
|
+
else
|
327
|
+
size * relative_size
|
328
|
+
end
|
251
329
|
end
|
252
330
|
if size.nil?
|
253
331
|
yield
|
254
332
|
else
|
255
|
-
@document.font_size(size)
|
333
|
+
@document.font_size(size, &block)
|
256
334
|
end
|
257
335
|
end
|
258
336
|
|
259
337
|
def subscript?(styles)
|
260
338
|
if styles.nil? then false
|
261
|
-
else
|
339
|
+
else
|
340
|
+
styles.include?(:subscript)
|
262
341
|
end
|
263
342
|
end
|
264
343
|
|
265
344
|
def superscript?(styles)
|
266
345
|
if styles.nil? then false
|
267
|
-
else
|
346
|
+
else
|
347
|
+
styles.include?(:superscript)
|
268
348
|
end
|
269
349
|
end
|
270
350
|
|
@@ -288,7 +368,7 @@ module Prawn
|
|
288
368
|
apply_font_settings(fragment) do
|
289
369
|
fragment.width = @document.width_of(
|
290
370
|
fragment.text,
|
291
|
-
kerning: @kerning
|
371
|
+
kerning: @kerning,
|
292
372
|
)
|
293
373
|
fragment.line_height = @document.font.height
|
294
374
|
fragment.descender = @document.font.descender
|
@@ -299,15 +379,15 @@ module Prawn
|
|
299
379
|
def line_measurement_maximums=(fragment)
|
300
380
|
@max_line_height = [
|
301
381
|
defined?(@max_line_height) && @max_line_height,
|
302
|
-
fragment.line_height
|
382
|
+
fragment.line_height,
|
303
383
|
].compact.max
|
304
384
|
@max_descender = [
|
305
385
|
defined?(@max_descender) && @max_descender,
|
306
|
-
fragment.descender
|
386
|
+
fragment.descender,
|
307
387
|
].compact.max
|
308
388
|
@max_ascender = [
|
309
389
|
defined?(@max_ascender) && @max_ascender,
|
310
|
-
fragment.ascender
|
390
|
+
fragment.ascender,
|
311
391
|
].compact.max
|
312
392
|
end
|
313
393
|
end
|