prawn 2.3.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/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,19 +384,32 @@ 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
|
-
when /\.ttf$/i
|
322
|
-
when /\.otf$/i
|
398
|
+
when /\.ttf$/i then 'ttf'
|
399
|
+
when /\.otf$/i then 'otf'
|
323
400
|
when /\.dfont$/i then 'dfont'
|
324
|
-
when /\.ttc$/i
|
401
|
+
when /\.ttc$/i then 'ttc'
|
325
402
|
else 'afm'
|
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
|
-
family == other.family && size == other.
|
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
|
@@ -445,6 +558,8 @@ module Prawn
|
|
445
558
|
end
|
446
559
|
end
|
447
560
|
|
561
|
+
protected
|
562
|
+
|
448
563
|
def size
|
449
564
|
@document.font_size
|
450
565
|
end
|