prawn 2.4.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 +213 -141
- data/lib/prawn/document/column_box.rb +61 -26
- data/lib/prawn/document/internals.rb +25 -16
- data/lib/prawn/document/span.rb +20 -18
- data/lib/prawn/document.rb +257 -171
- data/lib/prawn/encoding.rb +2 -5
- data/lib/prawn/errors.rb +23 -34
- data/lib/prawn/font.rb +248 -135
- data/lib/prawn/font_metric_cache.rb +11 -10
- data/lib/prawn/fonts/afm.rb +85 -45
- 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 +305 -93
- 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 +57 -34
- data/lib/prawn/graphics/dash.rb +45 -42
- data/lib/prawn/graphics/join_style.rb +17 -11
- data/lib/prawn/graphics/patterns.rb +190 -69
- data/lib/prawn/graphics/transformation.rb +48 -41
- data/lib/prawn/graphics/transparency.rb +16 -40
- data/lib/prawn/graphics.rb +363 -253
- data/lib/prawn/grid.rb +184 -57
- data/lib/prawn/image_handler.rb +27 -10
- data/lib/prawn/images/image.rb +8 -10
- data/lib/prawn/images/jpg.rb +42 -19
- data/lib/prawn/images/png.rb +92 -41
- data/lib/prawn/images.rb +44 -57
- data/lib/prawn/measurement_extensions.rb +39 -8
- data/lib/prawn/measurements.rb +60 -5
- data/lib/prawn/outline.rb +114 -108
- data/lib/prawn/repeater.rb +51 -35
- data/lib/prawn/security/arcfour.rb +4 -4
- data/lib/prawn/security.rb +75 -70
- data/lib/prawn/soft_mask.rb +42 -30
- data/lib/prawn/stamp.rb +38 -42
- data/lib/prawn/text/box.rb +146 -96
- data/lib/prawn/text/formatted/arranger.rb +87 -26
- data/lib/prawn/text/formatted/box.rb +221 -150
- data/lib/prawn/text/formatted/fragment.rb +130 -14
- data/lib/prawn/text/formatted/line_wrap.rb +33 -24
- data/lib/prawn/text/formatted/parser.rb +112 -72
- data/lib/prawn/text/formatted/wrap.rb +12 -17
- data/lib/prawn/text/formatted.rb +75 -0
- data/lib/prawn/text.rb +441 -196
- 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 +68 -53
- data/lib/prawn.rb +23 -18
- data.tar.gz.sig +0 -0
- metadata +54 -177
- metadata.gz.sig +0 -0
- data/.yardopts +0 -10
- data/Gemfile +0 -5
- data/Rakefile +0 -25
- 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 -29
- 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 -23
- 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 -38
- data/manual/graphics/gradients.rb +0 -43
- data/manual/graphics/graphics.rb +0 -64
- data/manual/graphics/helper.rb +0 -34
- 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 -29
- 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 -30
- 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 -43
- 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 -25
- data/manual/text/formatted_callbacks.rb +0 -70
- data/manual/text/formatted_text.rb +0 -61
- 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 -31
- 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 -52
- 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 -51
- data/manual/text/utf8.rb +0 -27
- data/manual/text/win_ansi_charset.rb +0 -62
- data/prawn.gemspec +0 -51
- data/spec/data/curves.pdf +0 -66
- data/spec/extensions/encoding_helpers.rb +0 -11
- data/spec/prawn/document/bounding_box_spec.rb +0 -550
- 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 -44
- data/spec/prawn/document_spec.rb +0 -805
- data/spec/prawn/font_metric_cache_spec.rb +0 -54
- data/spec/prawn/font_spec.rb +0 -544
- 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 -872
- 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 -229
- data/spec/prawn/measurements_extensions_spec.rb +0 -24
- data/spec/prawn/outline_spec.rb +0 -512
- data/spec/prawn/repeater_spec.rb +0 -166
- data/spec/prawn/soft_mask_spec.rb +0 -74
- data/spec/prawn/stamp_spec.rb +0 -173
- data/spec/prawn/text/box_spec.rb +0 -1110
- data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
- data/spec/prawn/text/formatted/box_spec.rb +0 -849
- data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
- data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -495
- data/spec/prawn/text/formatted/parser_spec.rb +0 -697
- data/spec/prawn/text_draw_text_spec.rb +0 -150
- 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/font.rb
CHANGED
@@ -1,51 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# font.rb : The Prawn font class
|
4
|
-
#
|
5
|
-
# Copyright May 2008, Gregory Brown / James Healy. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
#
|
9
3
|
require_relative 'font_metric_cache'
|
10
4
|
|
11
5
|
module Prawn
|
12
|
-
class Document
|
6
|
+
class Document # rubocop: disable Style/Documentation
|
13
7
|
# @group Stable API
|
14
8
|
|
15
|
-
#
|
16
|
-
|
9
|
+
# Default empty options.
|
10
|
+
DEFAULT_OPTS = {}.freeze
|
11
|
+
|
12
|
+
# Without arguments, this returns the currently selected font. Otherwise, it
|
13
|
+
# sets the current font. When a block is used, the font is applied
|
17
14
|
# transactionally and is rolled back when the block exits.
|
18
15
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# font "Times-Roman"
|
23
|
-
# text "Now using Times-Roman"
|
16
|
+
# ```ruby
|
17
|
+
# Prawn::Document.generate("font.pdf") do
|
18
|
+
# text "Default font is Helvetica"
|
24
19
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# font "Courier", :style => :bold
|
28
|
-
# text "You see this in bold Courier"
|
29
|
-
# end
|
20
|
+
# font "Times-Roman"
|
21
|
+
# text "Now using Times-Roman"
|
30
22
|
#
|
31
|
-
#
|
23
|
+
# font("DejaVuSans.ttf") do
|
24
|
+
# text "Using TTF font from file DejaVuSans.ttf"
|
25
|
+
# font "Courier", style: :bold
|
26
|
+
# text "You see this in bold Courier"
|
32
27
|
# end
|
33
28
|
#
|
34
|
-
#
|
29
|
+
# text "Times-Roman, again"
|
30
|
+
# end
|
31
|
+
# ```
|
32
|
+
#
|
33
|
+
# The `name` parameter must be a string. It can be one of the 14 built-in
|
35
34
|
# fonts supported by PDF, or the location of a TTF file. The
|
36
|
-
# Fonts::AFM::BUILT_INS array specifies the valid built in font
|
35
|
+
# {Fonts::AFM::BUILT_INS} array specifies the valid built in font names.
|
37
36
|
#
|
38
|
-
# If a
|
39
|
-
# will be embedded in the rendered PDF. This should be your
|
40
|
-
# in most cases. It will increase the size of the resulting
|
41
|
-
# make it more portable.
|
37
|
+
# If a TTF/OTF font is specified, the glyphs necessary to render your
|
38
|
+
# document will be embedded in the rendered PDF. This should be your
|
39
|
+
# preferred option in most cases. It will increase the size of the resulting
|
40
|
+
# file, but also make it more portable.
|
42
41
|
#
|
43
42
|
# The options parameter is an optional hash providing size and style. To use
|
44
43
|
# the :style option you need to map those font styles to their respective
|
45
44
|
# font files.
|
46
|
-
# See font_families for more information.
|
47
45
|
#
|
48
|
-
|
46
|
+
# @param name [String] font name. It can be:
|
47
|
+
# - One of 14 PDF built-in fonts.
|
48
|
+
# - A font file path.
|
49
|
+
# - A font name defined in {font_families}
|
50
|
+
# @param options [Hash{Symbol => any}]
|
51
|
+
# @option options :style [Symbol] font style
|
52
|
+
# @yield
|
53
|
+
# @return [Font]
|
54
|
+
# @see #font_families
|
55
|
+
# @see Font::AFM::BUILT_INS
|
56
|
+
def font(name = nil, options = DEFAULT_OPTS)
|
49
57
|
return((defined?(@font) && @font) || font('Helvetica')) if name.nil?
|
50
58
|
|
51
59
|
if state.pages.empty? && !state.page.in_stamp_stream?
|
@@ -66,32 +74,35 @@ module Prawn
|
|
66
74
|
@font
|
67
75
|
end
|
68
76
|
|
69
|
-
# @method font_size(points=nil)
|
70
|
-
#
|
71
77
|
# When called with no argument, returns the current font size.
|
72
78
|
#
|
73
79
|
# When called with a single argument but no block, sets the current font
|
74
|
-
# size.
|
75
|
-
# is rolled back when the block exits.
|
80
|
+
# size. When a block is used, the font size is applied transactionally and
|
81
|
+
# is rolled back when the block exits. You may still change the font size
|
76
82
|
# within a transactional block for individual text segments, or nested calls
|
77
|
-
# to font_size
|
83
|
+
# to `font_size`.
|
78
84
|
#
|
85
|
+
# @example
|
79
86
|
# Prawn::Document.generate("font_size.pdf") do
|
80
87
|
# font_size 16
|
81
88
|
# text "At size 16"
|
82
89
|
#
|
83
90
|
# font_size(10) do
|
84
91
|
# text "At size 10"
|
85
|
-
# text "At size 6", :
|
92
|
+
# text "At size 6", size: 6
|
86
93
|
# text "At size 10"
|
87
94
|
# end
|
88
95
|
#
|
89
96
|
# text "At size 16"
|
90
97
|
# end
|
91
98
|
#
|
92
|
-
#
|
93
|
-
# size
|
94
|
-
#
|
99
|
+
# @overload font_size()
|
100
|
+
# @return [Number] vurrent font size
|
101
|
+
# @overload font_size(points)
|
102
|
+
# @param points [Number] new font size
|
103
|
+
# @yield if block is provided font size is set only for the duration of
|
104
|
+
# the block
|
105
|
+
# @return [void]
|
95
106
|
def font_size(points = nil)
|
96
107
|
return @font_size unless points
|
97
108
|
|
@@ -101,33 +112,43 @@ module Prawn
|
|
101
112
|
@font_size = size_before_yield
|
102
113
|
end
|
103
114
|
|
104
|
-
# Sets the font size
|
115
|
+
# Sets the font size.
|
116
|
+
#
|
117
|
+
# @param size [Number]
|
118
|
+
# @return [Number]
|
105
119
|
def font_size=(size)
|
106
120
|
font_size(size)
|
107
121
|
end
|
108
122
|
|
109
|
-
# Returns the width of the given string using the given font. If
|
123
|
+
# Returns the width of the given string using the given font. If `:size` is
|
110
124
|
# not specified as one of the options, the string is measured using the
|
111
|
-
# current font size. You can also pass
|
125
|
+
# current font size. You can also pass `:kerning` as an option to indicate
|
112
126
|
# whether kerning should be used when measuring the width (defaults to
|
113
|
-
#
|
127
|
+
# `false`).
|
114
128
|
#
|
115
129
|
# Note that the string _must_ be encoded properly for the font being used.
|
116
|
-
# For AFM fonts, this is WinAnsi. For TTF, make sure the font is encoded
|
117
|
-
# UTF-8. You can use the Font#normalize_encoding method to make sure
|
118
|
-
# are in an encoding appropriate for the current font.
|
119
|
-
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
|
130
|
+
# For AFM fonts, this is WinAnsi. For TTF/OTF, make sure the font is encoded
|
131
|
+
# as UTF-8. You can use the Font#normalize_encoding method to make sure
|
132
|
+
# strings are in an encoding appropriate for the current font.
|
133
|
+
#
|
134
|
+
# @devnote
|
135
|
+
# For the record, this method used to be a method of Font (and still
|
136
|
+
# delegates to width computations on Font). However, having the primary
|
137
|
+
# interface for calculating string widths exist on Font made it tricky to
|
138
|
+
# write extensions for Prawn in which widths are computed differently
|
139
|
+
# (e.g., taking formatting tags into account, or the like).
|
140
|
+
#
|
141
|
+
# By putting width_of here, on Document itself, extensions may easily
|
142
|
+
# override it and redefine the width calculation behavior.
|
143
|
+
#
|
144
|
+
# @param string [String]
|
145
|
+
# @param options [Hash{Symbol => any}]
|
146
|
+
# @option options :inline_format [Boolean] (false)
|
147
|
+
# @option options :kerning [Boolean] (false)
|
148
|
+
# @option options :style [Symbol]
|
149
|
+
# @return [Number]
|
129
150
|
def width_of(string, options = {})
|
130
|
-
if options.key?
|
151
|
+
if options.key?(:inline_format)
|
131
152
|
p = options[:inline_format]
|
132
153
|
p = [] unless p.is_a?(Array)
|
133
154
|
|
@@ -143,69 +164,94 @@ module Prawn
|
|
143
164
|
end
|
144
165
|
end
|
145
166
|
|
146
|
-
# Hash that maps font family names to their styled individual font
|
167
|
+
# Hash that maps font family names to their styled individual font
|
168
|
+
# definitions.
|
147
169
|
#
|
148
170
|
# To add support for another font family, append to this hash, e.g:
|
149
171
|
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
172
|
+
# ```ruby
|
173
|
+
# pdf.font_families.update(
|
174
|
+
# "MyTrueTypeFamily" => {
|
175
|
+
# bold: "foo-bold.ttf",
|
176
|
+
# italic: "foo-italic.ttf",
|
177
|
+
# bold_italic: "foo-bold-italic.ttf",
|
178
|
+
# normal: "foo.ttf",
|
179
|
+
# }
|
180
|
+
# )
|
181
|
+
# ```
|
155
182
|
#
|
156
183
|
# This will then allow you to use the fonts like so:
|
157
184
|
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
185
|
+
# ```ruby
|
186
|
+
# pdf.font("MyTrueTypeFamily", style: :bold)
|
187
|
+
# pdf.text "Some bold text"
|
188
|
+
# pdf.font("MyTrueTypeFamily")
|
189
|
+
# pdf.text "Some normal text"
|
190
|
+
# ```
|
162
191
|
#
|
163
|
-
# This assumes that you have appropriate TTF fonts for each style you
|
192
|
+
# This assumes that you have appropriate TTF/OTF fonts for each style you
|
164
193
|
# wish to support.
|
165
194
|
#
|
166
|
-
# By default the styles
|
167
|
-
# defined for fonts "Courier", "Times-Roman" and "Helvetica". When
|
168
|
-
# defining your own font families, you can map any or all of these
|
169
|
-
#
|
195
|
+
# By default the styles `:bold`, `:italic`, `:bold_italic`, and `:normal`
|
196
|
+
# are defined for fonts "Courier", "Times-Roman" and "Helvetica". When
|
197
|
+
# defining your own font families, you can map any or all of these styles to
|
198
|
+
# whatever font files you'd like.
|
199
|
+
#
|
200
|
+
# Font definition can be either a hash or just a string.
|
201
|
+
#
|
202
|
+
# A hash font definition can specify a number of options:
|
170
203
|
#
|
204
|
+
# - `:file` -- path to the font file (required)
|
205
|
+
# - `:subset` -- whether to subset the font (default false). Only
|
206
|
+
# applicable to TrueType and OpenType fonts (includnig DFont and TTC).
|
207
|
+
#
|
208
|
+
# A string font definition is equivalent to hash definition with only
|
209
|
+
# `:file` being specified.
|
210
|
+
#
|
211
|
+
# @return [Hash{String => Hash{Symbol => String, Hash{Symbol => String}}}]
|
171
212
|
def font_families
|
172
213
|
@font_families ||= {}.merge!(
|
173
214
|
'Courier' => {
|
174
215
|
bold: 'Courier-Bold',
|
175
216
|
italic: 'Courier-Oblique',
|
176
217
|
bold_italic: 'Courier-BoldOblique',
|
177
|
-
normal: 'Courier'
|
218
|
+
normal: 'Courier',
|
178
219
|
},
|
179
220
|
|
180
221
|
'Times-Roman' => {
|
181
222
|
bold: 'Times-Bold',
|
182
223
|
italic: 'Times-Italic',
|
183
224
|
bold_italic: 'Times-BoldItalic',
|
184
|
-
normal: 'Times-Roman'
|
225
|
+
normal: 'Times-Roman',
|
185
226
|
},
|
186
227
|
|
187
228
|
'Helvetica' => {
|
188
229
|
bold: 'Helvetica-Bold',
|
189
230
|
italic: 'Helvetica-Oblique',
|
190
231
|
bold_italic: 'Helvetica-BoldOblique',
|
191
|
-
normal: 'Helvetica'
|
192
|
-
}
|
232
|
+
normal: 'Helvetica',
|
233
|
+
},
|
193
234
|
)
|
194
235
|
end
|
195
236
|
|
196
237
|
# @group Experimental API
|
197
238
|
|
198
|
-
# Sets the font directly, given an actual Font object
|
199
|
-
# and size.
|
239
|
+
# Sets the font directly, given an actual {Font} object and size.
|
200
240
|
#
|
201
|
-
|
241
|
+
# @private
|
242
|
+
# @param font [Font]
|
243
|
+
# @param size [Number]
|
244
|
+
# @return [void]
|
245
|
+
def set_font(font, size = nil)
|
202
246
|
@font = font
|
203
247
|
@font_size = size if size
|
204
248
|
end
|
205
249
|
|
206
|
-
# Saves the current font, and then yields. When the block
|
207
|
-
#
|
250
|
+
# Saves the current font, and then yields. When the block finishes, the
|
251
|
+
# original font is restored.
|
208
252
|
#
|
253
|
+
# @yield
|
254
|
+
# @return [void]
|
209
255
|
def save_font
|
210
256
|
@font ||= find_font('Helvetica')
|
211
257
|
original_font = @font
|
@@ -219,22 +265,30 @@ module Prawn
|
|
219
265
|
# Looks up the given font using the given criteria. Once a font has been
|
220
266
|
# found by that matches the criteria, it will be cached to subsequent
|
221
267
|
# lookups for that font will return the same object.
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
234
|
-
#
|
268
|
+
#
|
269
|
+
# @devnote
|
270
|
+
# Challenges involved: the name alone is not sufficient to uniquely
|
271
|
+
# identify a font (think dfont suitcases that can hold multiple different
|
272
|
+
# fonts in a single file). Thus, the `:name` key is included in the cache
|
273
|
+
# key.
|
274
|
+
#
|
275
|
+
# It is further complicated, however, since fonts in some formats (like
|
276
|
+
# the dfont suitcases) can be identified either by numeric index, OR by
|
277
|
+
# their name within the suitcase, and both should hash to the same font
|
278
|
+
# object (to avoid the font being embedded multiple times). This is not
|
279
|
+
# yet implemented, which means if someone selects a font both by name, and
|
280
|
+
# by index, the font will be embedded twice. Since we do font subsetting,
|
281
|
+
# this double embedding won't be catastrophic, just annoying.
|
235
282
|
#
|
236
283
|
# @private
|
237
|
-
|
284
|
+
# @param name [String]
|
285
|
+
# @param options [Hash]
|
286
|
+
# @option options :style [Symbol]
|
287
|
+
# @option options :file [String]
|
288
|
+
# @option options :font [Integer, String] index or name of the font in
|
289
|
+
# a font suitcase/collection
|
290
|
+
# @return [Font]
|
291
|
+
def find_font(name, options = {}) # :nodoc:
|
238
292
|
if font_families.key?(name)
|
239
293
|
family = name
|
240
294
|
name = font_families[name][options[:style] || :normal]
|
@@ -243,9 +297,9 @@ module Prawn
|
|
243
297
|
name = options[:file]
|
244
298
|
end
|
245
299
|
end
|
246
|
-
key = "#{name}:#{options[:font] || 0}"
|
300
|
+
key = "#{family}:#{name}:#{options[:font] || 0}"
|
247
301
|
|
248
|
-
if name.is_a?
|
302
|
+
if name.is_a?(Prawn::Font)
|
249
303
|
font_registry[key] = name
|
250
304
|
else
|
251
305
|
font_registry[key] ||=
|
@@ -253,9 +307,11 @@ module Prawn
|
|
253
307
|
end
|
254
308
|
end
|
255
309
|
|
256
|
-
# Hash of Font objects keyed by names
|
310
|
+
# Hash of Font objects keyed by names.
|
257
311
|
#
|
258
|
-
|
312
|
+
# @private
|
313
|
+
# @return [Hash{String => Font}]
|
314
|
+
def font_registry
|
259
315
|
@font_registry ||= {}
|
260
316
|
end
|
261
317
|
|
@@ -278,32 +334,46 @@ module Prawn
|
|
278
334
|
|
279
335
|
# Provides font information and helper functions.
|
280
336
|
#
|
337
|
+
# @abstract
|
281
338
|
class Font
|
282
|
-
require_relative 'fonts
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
require_relative 'fonts/ttc'
|
339
|
+
require_relative 'fonts'
|
340
|
+
|
341
|
+
# @deprecated
|
342
|
+
AFM = Prawn::Fonts::AFM
|
287
343
|
|
288
344
|
# @deprecated
|
289
|
-
AFM = Fonts::AFM
|
290
345
|
TTF = Fonts::TTF
|
346
|
+
|
347
|
+
# @deprecated
|
291
348
|
DFont = Fonts::DFont
|
349
|
+
|
350
|
+
# @deprecated
|
292
351
|
TTC = Fonts::TTC
|
293
352
|
|
294
|
-
# The
|
353
|
+
# The font name.
|
354
|
+
# @return [String]
|
295
355
|
attr_reader :name
|
296
356
|
|
297
|
-
# The
|
357
|
+
# The font family.
|
358
|
+
# @return [String]
|
298
359
|
attr_reader :family
|
299
360
|
|
300
|
-
# The options hash used to initialize the font
|
361
|
+
# The options hash used to initialize the font.
|
362
|
+
# @return [Hash]
|
301
363
|
attr_reader :options
|
302
364
|
|
303
|
-
# Shortcut interface for constructing a font object.
|
304
|
-
#
|
305
|
-
# Fonts::
|
306
|
-
# Fonts::
|
365
|
+
# Shortcut interface for constructing a font object. Filenames of the form
|
366
|
+
# `*.ttf` will call {Fonts::TTF#initialize TTF.new}, `*.otf` calls
|
367
|
+
# {Fonts::OTF#initialize OTF.new}, `*.dfont` calls {Fonts::DFont#initialize
|
368
|
+
# DFont.new}, `*.ttc` goes to {Fonts::TTC#initialize TTC.new}, and anything
|
369
|
+
# else will be passed through to {Prawn::Fonts::AFM#initialize AFM.new}.
|
370
|
+
#
|
371
|
+
# @param document [Prawn::Document] owning document
|
372
|
+
# @param src [String] font file path
|
373
|
+
# @param options [Hash]
|
374
|
+
# @option options :family [String]
|
375
|
+
# @option options :style [Symbol]
|
376
|
+
# @return [Prawn::Fonts::Font]
|
307
377
|
def self.load(document, src, options = {})
|
308
378
|
case font_format(src, options)
|
309
379
|
when 'ttf' then TTF.new(document, src, options)
|
@@ -314,8 +384,15 @@ module Prawn
|
|
314
384
|
end
|
315
385
|
end
|
316
386
|
|
387
|
+
# Guesses font format.
|
388
|
+
#
|
389
|
+
# @private
|
390
|
+
# @param src [String, IO]
|
391
|
+
# @param options [Hash]
|
392
|
+
# @option options :format [String]
|
393
|
+
# @return [String]
|
317
394
|
def self.font_format(src, options)
|
318
|
-
return options.fetch(:format, 'ttf') if src.respond_to?
|
395
|
+
return options.fetch(:format, 'ttf') if src.respond_to?(:read)
|
319
396
|
|
320
397
|
case src.to_s
|
321
398
|
when /\.ttf$/i then 'ttf'
|
@@ -326,7 +403,13 @@ module Prawn
|
|
326
403
|
end
|
327
404
|
end
|
328
405
|
|
329
|
-
|
406
|
+
# @private
|
407
|
+
# @param document [Prawn::Document]
|
408
|
+
# @param name [String]
|
409
|
+
# @param options [Hash{Symbol => any}]
|
410
|
+
# @option options :family [String]
|
411
|
+
# @option options :subset [Boolean] (true)
|
412
|
+
def initialize(document, name, options = {})
|
330
413
|
@document = document
|
331
414
|
@name = name
|
332
415
|
@options = options
|
@@ -336,54 +419,70 @@ module Prawn
|
|
336
419
|
@identifier = generate_unique_id
|
337
420
|
|
338
421
|
@references = {}
|
422
|
+
@subset_name_cache = {}
|
423
|
+
|
424
|
+
@full_font_embedding = options.key?(:subset) && !options[:subset]
|
339
425
|
end
|
340
426
|
|
341
|
-
# The size of the font ascender in PDF points
|
427
|
+
# The size of the font ascender in PDF points.
|
342
428
|
#
|
429
|
+
# @return [Number]
|
343
430
|
def ascender
|
344
431
|
@ascender / 1000.0 * size
|
345
432
|
end
|
346
433
|
|
347
|
-
# The size of the font descender in PDF points
|
434
|
+
# The size of the font descender in PDF points.
|
348
435
|
#
|
436
|
+
# @return [Number]
|
349
437
|
def descender
|
350
438
|
-@descender / 1000.0 * size
|
351
439
|
end
|
352
440
|
|
353
441
|
# The size of the recommended gap between lines of text in PDF points
|
354
442
|
#
|
443
|
+
# @return [Number]
|
355
444
|
def line_gap
|
356
445
|
@line_gap / 1000.0 * size
|
357
446
|
end
|
358
447
|
|
359
448
|
# Normalizes the encoding of the string to an encoding supported by the
|
360
449
|
# font. The string is expected to be UTF-8 going in. It will be re-encoded
|
361
|
-
# and the new string will be returned.
|
362
|
-
#
|
450
|
+
# and the new string will be returned.
|
451
|
+
#
|
452
|
+
# @abstract
|
453
|
+
# @!parse def normalize_encoding(string); end
|
454
|
+
# @param string [String]
|
455
|
+
# @return [String]
|
363
456
|
def normalize_encoding(_string)
|
364
457
|
raise NotImplementedError,
|
365
458
|
'subclasses of Prawn::Font must implement #normalize_encoding'
|
366
459
|
end
|
367
460
|
|
368
|
-
# Destructive version of normalize_encoding; normalizes the encoding of a
|
461
|
+
# Destructive version of {normalize_encoding}; normalizes the encoding of a
|
369
462
|
# string in place.
|
370
463
|
#
|
464
|
+
# @note This method doesn't mutate its argument any more.
|
465
|
+
#
|
371
466
|
# @deprecated
|
467
|
+
# @param str [String]
|
468
|
+
# @return [String]
|
372
469
|
def normalize_encoding!(str)
|
373
|
-
warn
|
374
|
-
'Please use non-mutating version Font#normalize_encoding instead.'
|
470
|
+
warn('Font#normalize_encoding! is deprecated. Please use non-mutating version Font#normalize_encoding instead.')
|
375
471
|
str.dup.replace(normalize_encoding(str))
|
376
472
|
end
|
377
473
|
|
378
|
-
# Gets height of
|
474
|
+
# Gets height of font in PDF points at the given font size.
|
379
475
|
#
|
476
|
+
# @param size [Number]
|
477
|
+
# @return [Number]
|
380
478
|
def height_at(size)
|
381
479
|
@normalized_height ||= (@ascender - @descender + @line_gap) / 1000.0
|
382
480
|
@normalized_height * size
|
383
481
|
end
|
384
482
|
|
385
|
-
# Gets height of current font in PDF points at current font size
|
483
|
+
# Gets height of current font in PDF points at current font size.
|
386
484
|
#
|
485
|
+
# @return [Number]
|
387
486
|
def height
|
388
487
|
height_at(size)
|
389
488
|
end
|
@@ -392,39 +491,53 @@ module Prawn
|
|
392
491
|
# page. This is safe to call multiple times for a given font and subset,
|
393
492
|
# as it will only add the font the first time it is called.
|
394
493
|
#
|
494
|
+
# @param subset [Integer]
|
495
|
+
# @return [void]
|
395
496
|
def add_to_current_page(subset)
|
396
497
|
@references[subset] ||= register(subset)
|
397
|
-
@document.state.page.fonts
|
398
|
-
identifier_for(subset) => @references[subset]
|
399
|
-
)
|
498
|
+
@document.state.page.fonts[identifier_for(subset)] = @references[subset]
|
400
499
|
end
|
401
500
|
|
402
|
-
|
403
|
-
|
501
|
+
# @private
|
502
|
+
# @param subset [Integer]
|
503
|
+
# @return [Symbol]
|
504
|
+
def identifier_for(subset)
|
505
|
+
@subset_name_cache[subset] ||=
|
506
|
+
if full_font_embedding
|
507
|
+
@identifier.to_sym
|
508
|
+
else
|
509
|
+
:"#{@identifier}.#{subset}"
|
510
|
+
end
|
404
511
|
end
|
405
512
|
|
406
|
-
|
513
|
+
# Returns a string containing a human-readable representation of this font.
|
514
|
+
#
|
515
|
+
# @return [String]
|
516
|
+
def inspect
|
407
517
|
"#{self.class.name}< #{name}: #{size} >"
|
408
518
|
end
|
409
519
|
|
410
|
-
# Return a hash (as in Object#hash) for the font
|
411
|
-
#
|
412
|
-
# that cache certain values (See
|
413
|
-
# Prawn::Table::Text#styled_with_of_single_character)
|
520
|
+
# Return a hash (as in `Object#hash`) for the font. This is required since
|
521
|
+
# font objects are used as keys in hashes that cache certain values.
|
414
522
|
#
|
415
|
-
|
416
|
-
|
523
|
+
# @return [Integer]
|
524
|
+
def hash
|
525
|
+
[self.class, name, family].hash
|
417
526
|
end
|
418
527
|
|
419
|
-
# Compliments the #hash implementation
|
528
|
+
# Compliments the {#hash} implementation.
|
420
529
|
#
|
421
|
-
|
530
|
+
# @param other [Object]
|
531
|
+
# @return [Boolean]
|
532
|
+
def eql?(other)
|
422
533
|
self.class == other.class && name == other.name &&
|
423
534
|
family == other.family && size == other.size
|
424
535
|
end
|
425
536
|
|
426
537
|
private
|
427
538
|
|
539
|
+
attr_reader :full_font_embedding
|
540
|
+
|
428
541
|
# generate a font identifier that hasn't been used on the current page yet
|
429
542
|
#
|
430
543
|
def generate_unique_id
|
@@ -1,19 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# font_metric_cache.rb : The Prawn font class
|
4
|
-
#
|
5
|
-
# Copyright Dec 2012, Kenneth Kalmer. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
#
|
9
|
-
|
10
3
|
module Prawn
|
11
|
-
# Cache used internally by Prawn::Document instances to calculate the width
|
4
|
+
# Cache used internally by {Prawn::Document} instances to calculate the width
|
12
5
|
# of various strings for layout purposes.
|
13
6
|
#
|
14
7
|
# @private
|
15
8
|
class FontMetricCache
|
16
|
-
CacheEntry = Struct.new(:font, :options, :string)
|
9
|
+
CacheEntry = Struct.new(:font, :font_size, :options, :string)
|
17
10
|
|
18
11
|
def initialize(document)
|
19
12
|
@document = document
|
@@ -21,6 +14,14 @@ module Prawn
|
|
21
14
|
@cache = {}
|
22
15
|
end
|
23
16
|
|
17
|
+
# Get width of string.
|
18
|
+
#
|
19
|
+
# @param string [String]
|
20
|
+
# @param options [Hash{Symbol => any}]
|
21
|
+
# @option options :style [Symbol]
|
22
|
+
# @option options :size [Number]
|
23
|
+
# @option options :kerning [Boolean] (false)
|
24
|
+
# @return [Number]
|
24
25
|
def width_of(string, options)
|
25
26
|
f =
|
26
27
|
if options[:style]
|
@@ -32,7 +33,7 @@ module Prawn
|
|
32
33
|
|
33
34
|
encoded_string = f.normalize_encoding(string)
|
34
35
|
|
35
|
-
key = CacheEntry.new(f, options, encoded_string)
|
36
|
+
key = CacheEntry.new(f, @document.font_size, options, encoded_string)
|
36
37
|
|
37
38
|
@cache[key] ||= f.compute_width_of(encoded_string, options)
|
38
39
|
|