hexapdf 0.11.9 → 0.12.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
- data/CHANGELOG.md +82 -0
- data/LICENSE +1 -1
- data/examples/001-hello_world.rb +1 -1
- data/examples/002-graphics.rb +1 -1
- data/examples/003-arcs.rb +1 -1
- data/examples/004-optimizing.rb +1 -1
- data/examples/005-merging.rb +1 -1
- data/examples/006-standard_pdf_fonts.rb +1 -1
- data/examples/007-truetype.rb +1 -1
- data/examples/008-show_char_bboxes.rb +1 -1
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +1 -1
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +1 -1
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +1 -1
- data/examples/016-frame_automatic_box_placement.rb +1 -1
- data/examples/017-frame_text_flow.rb +1 -1
- data/examples/018-composer.rb +1 -1
- data/examples/019-acro_form.rb +51 -0
- data/lib/hexapdf.rb +1 -1
- data/lib/hexapdf/cli.rb +3 -1
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +18 -9
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/form.rb +240 -0
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +1 -1
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +66 -11
- data/lib/hexapdf/content.rb +3 -1
- data/lib/hexapdf/content/canvas.rb +5 -18
- data/lib/hexapdf/content/color_space.rb +111 -32
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/content/graphics_state.rb +1 -1
- data/lib/hexapdf/content/operator.rb +9 -9
- data/lib/hexapdf/content/parser.rb +18 -5
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +1 -1
- data/lib/hexapdf/dictionary_fields.rb +1 -1
- data/lib/hexapdf/document.rb +14 -5
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/pages.rb +3 -14
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +1 -1
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +1 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
- data/lib/hexapdf/error.rb +1 -1
- data/lib/hexapdf/filter.rb +3 -3
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/encryption.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/{jpx_decode.rb → pass_through.rb} +5 -5
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +1 -1
- data/lib/hexapdf/font/encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/base.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +1 -1
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type/builder.rb +1 -1
- data/lib/hexapdf/font/true_type/font.rb +1 -1
- data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
- data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
- data/lib/hexapdf/font/true_type/table.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
- data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
- data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
- data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
- data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
- data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
- data/lib/hexapdf/font/true_type/table/name.rb +1 -1
- data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +54 -51
- data/lib/hexapdf/font/type1.rb +1 -1
- data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
- data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/font.rb +1 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
- data/lib/hexapdf/font/type1_wrapper.rb +67 -51
- data/lib/hexapdf/font_loader.rb +1 -1
- data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
- data/lib/hexapdf/font_loader/from_file.rb +1 -1
- data/lib/hexapdf/font_loader/standard14.rb +1 -1
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/image_loader/jpeg.rb +1 -1
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/importer.rb +2 -4
- data/lib/hexapdf/layout.rb +1 -1
- data/lib/hexapdf/layout/box.rb +1 -1
- data/lib/hexapdf/layout/frame.rb +1 -1
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/inline_box.rb +1 -1
- data/lib/hexapdf/layout/line.rb +1 -1
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +1 -1
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +1 -1
- data/lib/hexapdf/layout/text_shaper.rb +1 -1
- data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +2 -2
- data/lib/hexapdf/parser.rb +4 -3
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +31 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +2 -1
- data/lib/hexapdf/revisions.rb +1 -1
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +1 -1
- data/lib/hexapdf/tokenizer.rb +1 -1
- data/lib/hexapdf/type.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +7 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +401 -0
- data/lib/hexapdf/type/acro_form/button_field.rb +300 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
- data/lib/hexapdf/type/acro_form/field.rb +220 -17
- data/lib/hexapdf/type/acro_form/form.rb +157 -7
- data/lib/hexapdf/type/acro_form/text_field.rb +186 -0
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +122 -0
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +73 -3
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/annotations/link.rb +2 -2
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +239 -2
- data/lib/hexapdf/type/catalog.rb +21 -1
- data/lib/hexapdf/type/cid_font.rb +1 -1
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +1 -1
- data/lib/hexapdf/type/font.rb +18 -1
- data/lib/hexapdf/type/font_descriptor.rb +2 -2
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_true_type.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type1.rb +16 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +1 -1
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +3 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/names.rb +1 -1
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/page.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +8 -11
- data/lib/hexapdf/type/resources.rb +16 -3
- data/lib/hexapdf/type/trailer.rb +2 -3
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +1 -1
- data/lib/hexapdf/utils/bit_field.rb +38 -24
- data/lib/hexapdf/utils/bit_stream.rb +1 -1
- data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
- data/lib/hexapdf/utils/lru_cache.rb +1 -1
- data/lib/hexapdf/utils/math_helpers.rb +1 -1
- data/lib/hexapdf/utils/object_hash.rb +1 -1
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/test/hexapdf/content/common.rb +2 -2
- data/test/hexapdf/content/test_color_space.rb +71 -8
- data/test/hexapdf/content/test_operator.rb +22 -22
- data/test/hexapdf/content/test_parser.rb +14 -0
- data/test/hexapdf/document/test_fonts.rb +1 -1
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
- data/test/hexapdf/font/test_type1_wrapper.rb +32 -8
- data/test/hexapdf/test_document.rb +12 -0
- data/test/hexapdf/test_parser.rb +10 -0
- data/test/hexapdf/test_rectangle.rb +14 -0
- data/test/hexapdf/test_revision.rb +3 -0
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +515 -0
- data/test/hexapdf/type/acro_form/test_button_field.rb +276 -0
- data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
- data/test/hexapdf/type/acro_form/test_field.rb +124 -6
- data/test/hexapdf/type/acro_form/test_form.rb +189 -22
- data/test/hexapdf/type/acro_form/test_text_field.rb +119 -0
- data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
- data/test/hexapdf/type/annotations/test_text.rb +1 -1
- data/test/hexapdf/type/annotations/test_widget.rb +199 -0
- data/test/hexapdf/type/test_annotation.rb +45 -0
- data/test/hexapdf/type/test_catalog.rb +18 -0
- data/test/hexapdf/type/test_font.rb +5 -0
- data/test/hexapdf/type/test_font_type1.rb +8 -0
- data/test/hexapdf/type/test_image.rb +7 -0
- data/test/hexapdf/type/test_page_tree_node.rb +20 -12
- data/test/hexapdf/type/test_resources.rb +20 -0
- data/test/hexapdf/type/test_trailer.rb +4 -0
- data/test/hexapdf/utils/test_bit_field.rb +13 -1
- data/test/test_helper.rb +1 -1
- metadata +37 -18
- data/lib/hexapdf/filter/dct_decode.rb +0 -60
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -115,15 +115,19 @@ module HexaPDF
|
|
|
115
115
|
# Returns the wrapped TrueType font object.
|
|
116
116
|
attr_reader :wrapped_font
|
|
117
117
|
|
|
118
|
-
# Returns the PDF
|
|
119
|
-
attr_reader :
|
|
118
|
+
# Returns the PDF object associated with the wrapper.
|
|
119
|
+
attr_reader :pdf_object
|
|
120
120
|
|
|
121
121
|
# Creates a new object wrapping the TrueType font for the PDF document.
|
|
122
122
|
#
|
|
123
|
+
# The optional argument +pdf_object+ can be used to set the PDF font object that this wrapper
|
|
124
|
+
# should be associated with. If no object is set, a suitable one is automatically created.
|
|
125
|
+
#
|
|
123
126
|
# If +subset+ is true, the font is subset.
|
|
124
|
-
def initialize(document, font, subset: true)
|
|
125
|
-
@document = document
|
|
127
|
+
def initialize(document, font, pdf_object: nil, subset: true)
|
|
126
128
|
@wrapped_font = font
|
|
129
|
+
@missing_glyph_callable = document.config['font.on_missing_glyph']
|
|
130
|
+
|
|
127
131
|
@subsetter = (subset ? HexaPDF::Font::TrueType::Subsetter.new(font) : nil)
|
|
128
132
|
|
|
129
133
|
@cmap = font[:cmap].preferred_table
|
|
@@ -131,8 +135,7 @@ module HexaPDF
|
|
|
131
135
|
raise HexaPDF::Error, "No mapping table for Unicode characters found for TTF " \
|
|
132
136
|
"font #{font.full_name}"
|
|
133
137
|
end
|
|
134
|
-
@
|
|
135
|
-
@document.register_listener(:complete_objects, &method(:complete_font_dict))
|
|
138
|
+
@pdf_object = pdf_object || create_pdf_object(document)
|
|
136
139
|
|
|
137
140
|
@id_to_glyph = {}
|
|
138
141
|
@codepoint_to_glyph = {}
|
|
@@ -166,7 +169,7 @@ module HexaPDF
|
|
|
166
169
|
if id >= 0 && id < @wrapped_font[:maxp].num_glyphs
|
|
167
170
|
Glyph.new(@wrapped_font, id, str || (+'' << (@cmap.gid_to_code(id) || 0xFFFD)))
|
|
168
171
|
else
|
|
169
|
-
@
|
|
172
|
+
@missing_glyph_callable.call("\u{FFFD}", font_type, @wrapped_font)
|
|
170
173
|
end
|
|
171
174
|
end
|
|
172
175
|
end
|
|
@@ -179,7 +182,7 @@ module HexaPDF
|
|
|
179
182
|
if (gid = @cmap[c])
|
|
180
183
|
glyph(gid, +'' << c)
|
|
181
184
|
else
|
|
182
|
-
@
|
|
185
|
+
@missing_glyph_callable.call(+'' << c, font_type, @wrapped_font)
|
|
183
186
|
end
|
|
184
187
|
end
|
|
185
188
|
end
|
|
@@ -202,22 +205,21 @@ module HexaPDF
|
|
|
202
205
|
|
|
203
206
|
private
|
|
204
207
|
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
# The returned font object contains only information available at build time, so no
|
|
208
|
-
# information about glyph specific attributes like width.
|
|
208
|
+
# Creates a Type0 font object representing the TrueType font.
|
|
209
209
|
#
|
|
210
|
-
#
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
210
|
+
# The returned font object contains only information available at creation time, so no
|
|
211
|
+
# information about glyph specific attributes like width. The missing information is added
|
|
212
|
+
# before the PDF document gets written.
|
|
213
|
+
def create_pdf_object(document)
|
|
214
|
+
fd = document.add({Type: :FontDescriptor,
|
|
215
|
+
FontName: @wrapped_font.font_name.intern,
|
|
216
|
+
FontWeight: @wrapped_font.weight,
|
|
217
|
+
Flags: 0,
|
|
218
|
+
FontBBox: @wrapped_font.bounding_box.map {|m| m * scaling_factor },
|
|
219
|
+
ItalicAngle: @wrapped_font.italic_angle || 0,
|
|
220
|
+
Ascent: @wrapped_font.ascender * scaling_factor,
|
|
221
|
+
Descent: @wrapped_font.descender * scaling_factor,
|
|
222
|
+
StemV: @wrapped_font.dominant_vertical_stem_width})
|
|
221
223
|
if @wrapped_font[:'OS/2'].version >= 2
|
|
222
224
|
fd[:CapHeight] = @wrapped_font.cap_height * scaling_factor
|
|
223
225
|
fd[:XHeight] = @wrapped_font.x_height * scaling_factor
|
|
@@ -242,28 +244,29 @@ module HexaPDF
|
|
|
242
244
|
@wrapped_font[:'OS/2'].selection_include?(:oblique)
|
|
243
245
|
fd.flag(:symbolic)
|
|
244
246
|
|
|
245
|
-
cid_font =
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
247
|
+
cid_font = document.add({Type: :Font, Subtype: :CIDFontType2,
|
|
248
|
+
BaseFont: fd[:FontName], FontDescriptor: fd,
|
|
249
|
+
CIDSystemInfo: {Registry: "Adobe", Ordering: "Identity",
|
|
250
|
+
Supplement: 0},
|
|
251
|
+
CIDToGIDMap: :Identity})
|
|
252
|
+
dict = document.add({Type: :Font, Subtype: :Type0, BaseFont: cid_font[:BaseFont],
|
|
253
|
+
Encoding: :"Identity-H", DescendantFonts: [cid_font]})
|
|
254
|
+
dict.font_wrapper = self
|
|
255
|
+
|
|
256
|
+
document.register_listener(:complete_objects) do
|
|
257
|
+
update_font_name(dict)
|
|
258
|
+
embed_font(dict, document)
|
|
259
|
+
complete_width_information(dict)
|
|
260
|
+
create_to_unicode_cmap(dict, document)
|
|
261
|
+
end
|
|
253
262
|
|
|
254
|
-
|
|
255
|
-
# information.
|
|
256
|
-
def complete_font_dict
|
|
257
|
-
update_font_name
|
|
258
|
-
embed_font
|
|
259
|
-
complete_width_information
|
|
260
|
-
create_to_unicode_cmap
|
|
263
|
+
dict
|
|
261
264
|
end
|
|
262
265
|
|
|
263
266
|
UPPERCASE_LETTERS = ('A'..'Z').to_a.freeze #:nodoc:
|
|
264
267
|
|
|
265
268
|
# Updates the font name with a unique tag if the font is subset.
|
|
266
|
-
def update_font_name
|
|
269
|
+
def update_font_name(dict)
|
|
267
270
|
return unless @subsetter
|
|
268
271
|
|
|
269
272
|
tag = +''
|
|
@@ -275,13 +278,13 @@ module HexaPDF
|
|
|
275
278
|
end
|
|
276
279
|
|
|
277
280
|
name = (tag << "+" << @wrapped_font.font_name).intern
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
+
dict[:BaseFont] = name
|
|
282
|
+
dict[:DescendantFonts].first[:BaseFont] = name
|
|
283
|
+
dict[:DescendantFonts].first[:FontDescriptor][:FontName] = name
|
|
281
284
|
end
|
|
282
285
|
|
|
283
286
|
# Embeds the font.
|
|
284
|
-
def embed_font
|
|
287
|
+
def embed_font(dict, document)
|
|
285
288
|
if @subsetter
|
|
286
289
|
data = @subsetter.build_font
|
|
287
290
|
length = data.size
|
|
@@ -290,22 +293,22 @@ module HexaPDF
|
|
|
290
293
|
length = @wrapped_font.io.size
|
|
291
294
|
stream = HexaPDF::StreamData.new(@wrapped_font.io, length: length)
|
|
292
295
|
end
|
|
293
|
-
font =
|
|
294
|
-
|
|
296
|
+
font = document.add({Length1: length, Filter: :FlateDecode}, stream: stream)
|
|
297
|
+
dict[:DescendantFonts].first[:FontDescriptor][:FontFile2] = font
|
|
295
298
|
end
|
|
296
299
|
|
|
297
300
|
# Adds the /DW and /W fields to the CIDFont dictionary.
|
|
298
|
-
def complete_width_information
|
|
301
|
+
def complete_width_information(dict)
|
|
299
302
|
default_width = glyph(3, " ").width.to_i
|
|
300
303
|
widths = @encoded_glyphs.reject {|_, v| v[1].width == default_width }.map do |id, v|
|
|
301
304
|
[(@subsetter ? @subsetter.subset_glyph_id(id) : id), v[1].width]
|
|
302
305
|
end.sort!
|
|
303
|
-
|
|
306
|
+
dict[:DescendantFonts].first.set_widths(widths, default_width: default_width)
|
|
304
307
|
end
|
|
305
308
|
|
|
306
309
|
# Creates the /ToUnicode CMap and updates the font dictionary so that text extraction works
|
|
307
310
|
# correctly.
|
|
308
|
-
def create_to_unicode_cmap
|
|
311
|
+
def create_to_unicode_cmap(dict, document)
|
|
309
312
|
stream = HexaPDF::StreamData.new do
|
|
310
313
|
mapping = @encoded_glyphs.keys.map! do |id|
|
|
311
314
|
# Using 0xFFFD as mentioned in Adobe #5411, last line before section 1.5
|
|
@@ -313,9 +316,9 @@ module HexaPDF
|
|
|
313
316
|
end.sort_by!(&:first)
|
|
314
317
|
HexaPDF::Font::CMap.create_to_unicode_cmap(mapping)
|
|
315
318
|
end
|
|
316
|
-
stream_obj =
|
|
319
|
+
stream_obj = document.add({}, stream: stream)
|
|
317
320
|
stream_obj.set_filter(:FlateDecode)
|
|
318
|
-
|
|
321
|
+
dict[:ToUnicode] = stream_obj
|
|
319
322
|
end
|
|
320
323
|
|
|
321
324
|
end
|
data/lib/hexapdf/font/type1.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -104,23 +104,33 @@ module HexaPDF
|
|
|
104
104
|
# Returns the wrapped Type1 font object.
|
|
105
105
|
attr_reader :wrapped_font
|
|
106
106
|
|
|
107
|
-
#
|
|
108
|
-
attr_reader :
|
|
107
|
+
# Returns the PDF object associated with the wrapper.
|
|
108
|
+
attr_reader :pdf_object
|
|
109
109
|
|
|
110
|
-
# Creates a new object wrapping the Type1 font
|
|
110
|
+
# Creates a new Type1Wrapper object wrapping the Type1 font.
|
|
111
111
|
#
|
|
112
|
-
# The optional argument +
|
|
113
|
-
#
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
# The optional argument +pdf_object+ can be used to set the PDF font object that this wrapper
|
|
113
|
+
# should be associated with. If no object is set, a suitable one is automatically created.
|
|
114
|
+
#
|
|
115
|
+
# If +pdf_object+ is provided, the PDF object's encoding is used. Otherwise, the
|
|
116
|
+
# WinAnsiEncoding or, for 'Special' fonts, the font's internal encoding is used. The optional
|
|
117
|
+
# argument +custom_encoding+ can be set to +true+ so that a custom encoding is used (only
|
|
118
|
+
# respected if +pdf_object+ is not provided).
|
|
119
|
+
def initialize(document, font, pdf_object: nil, custom_encoding: false)
|
|
116
120
|
@wrapped_font = font
|
|
121
|
+
@pdf_object = pdf_object || create_pdf_object(document)
|
|
122
|
+
@missing_glyph_callable = document.config['font.on_missing_glyph']
|
|
117
123
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
124
|
+
if pdf_object
|
|
125
|
+
@encoding = pdf_object.encoding
|
|
126
|
+
@max_code = 255 # Encoding is not modified
|
|
127
|
+
elsif custom_encoding
|
|
121
128
|
@encoding = Encoding::Base.new
|
|
122
129
|
@encoding.code_to_name[32] = :space
|
|
123
130
|
@max_code = 32 # 32 = space
|
|
131
|
+
elsif @wrapped_font.metrics.character_set == 'Special'
|
|
132
|
+
@encoding = @wrapped_font.encoding
|
|
133
|
+
@max_code = 255 # Encoding is not modified
|
|
124
134
|
else
|
|
125
135
|
@encoding = Encoding.for_name(:WinAnsiEncoding)
|
|
126
136
|
@max_code = 255 # Encoding is not modified
|
|
@@ -150,17 +160,25 @@ module HexaPDF
|
|
|
150
160
|
if @wrapped_font.metrics.character_metrics.key?(name)
|
|
151
161
|
Glyph.new(@wrapped_font, name, str)
|
|
152
162
|
else
|
|
153
|
-
@
|
|
163
|
+
@missing_glyph_callable.call(str, font_type, @wrapped_font)
|
|
154
164
|
end
|
|
155
165
|
end
|
|
156
166
|
end
|
|
157
167
|
|
|
158
168
|
# Returns an array of glyph objects representing the characters in the UTF-8 encoded string.
|
|
169
|
+
#
|
|
170
|
+
# If a Unicode codepoint is not available as glyph object, it is tried to map the codepoint
|
|
171
|
+
# using the font's internal encoding. This is useful, for example, for the ZapfDingbats font
|
|
172
|
+
# to use ASCII characters for accessing the glyphs.
|
|
159
173
|
def decode_utf8(str)
|
|
160
174
|
str.codepoints.map! do |c|
|
|
161
175
|
@codepoint_to_glyph[c] ||=
|
|
162
176
|
begin
|
|
163
177
|
name = Encoding::GlyphList.unicode_to_name(+'' << c, **@zapf_dingbats_opt)
|
|
178
|
+
if @wrapped_font.metrics.character_set == 'Special' &&
|
|
179
|
+
(name == :'.notdef' || !@wrapped_font.metrics.character_metrics.key?(name))
|
|
180
|
+
name = @encoding.name(c)
|
|
181
|
+
end
|
|
164
182
|
name = +"u" << c.to_s(16).rjust(6, '0') if name == :'.notdef'
|
|
165
183
|
glyph(name)
|
|
166
184
|
end
|
|
@@ -189,49 +207,47 @@ module HexaPDF
|
|
|
189
207
|
|
|
190
208
|
private
|
|
191
209
|
|
|
192
|
-
# Builds a generic Type1 font dictionary for the wrapped font.
|
|
193
|
-
#
|
|
194
|
-
# Generic in the sense that no information regarding the encoding or widths is included.
|
|
195
|
-
def build_font_dict
|
|
196
|
-
unless defined?(@fd)
|
|
197
|
-
@fd = @document.wrap({Type: :FontDescriptor,
|
|
198
|
-
FontName: @wrapped_font.font_name.intern,
|
|
199
|
-
FontWeight: @wrapped_font.weight_class,
|
|
200
|
-
FontBBox: @wrapped_font.bounding_box,
|
|
201
|
-
ItalicAngle: @wrapped_font.italic_angle || 0,
|
|
202
|
-
Ascent: @wrapped_font.ascender || 0,
|
|
203
|
-
Descent: @wrapped_font.descender || 0,
|
|
204
|
-
CapHeight: @wrapped_font.cap_height,
|
|
205
|
-
XHeight: @wrapped_font.x_height,
|
|
206
|
-
StemH: @wrapped_font.dominant_horizontal_stem_width,
|
|
207
|
-
StemV: @wrapped_font.dominant_vertical_stem_width || 0})
|
|
208
|
-
@fd.flag(:fixed_pitch) if @wrapped_font.metrics.is_fixed_pitch
|
|
209
|
-
@fd.flag(@wrapped_font.metrics.character_set == 'Special' ? :symbolic : :nonsymbolic)
|
|
210
|
-
@fd.must_be_indirect = true
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
@document.wrap({Type: :Font, Subtype: :Type1,
|
|
214
|
-
BaseFont: @wrapped_font.font_name.intern, Encoding: :WinAnsiEncoding,
|
|
215
|
-
FontDescriptor: @fd})
|
|
216
|
-
end
|
|
217
|
-
|
|
218
210
|
# Array of valid encoding names in PDF
|
|
219
211
|
VALID_ENCODING_NAMES = [:WinAnsiEncoding, :MacRomanEncoding, :MacExpertEncoding].freeze
|
|
220
212
|
|
|
221
|
-
#
|
|
222
|
-
def
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
213
|
+
# Creates a PDF object representing the wrapped font for the given PDF document.
|
|
214
|
+
def create_pdf_object(document)
|
|
215
|
+
fd = document.wrap({Type: :FontDescriptor,
|
|
216
|
+
FontName: @wrapped_font.font_name.intern,
|
|
217
|
+
FontWeight: @wrapped_font.weight_class,
|
|
218
|
+
FontBBox: @wrapped_font.bounding_box,
|
|
219
|
+
ItalicAngle: @wrapped_font.italic_angle || 0,
|
|
220
|
+
Ascent: @wrapped_font.ascender || 0,
|
|
221
|
+
Descent: @wrapped_font.descender || 0,
|
|
222
|
+
CapHeight: @wrapped_font.cap_height,
|
|
223
|
+
XHeight: @wrapped_font.x_height,
|
|
224
|
+
StemH: @wrapped_font.dominant_horizontal_stem_width,
|
|
225
|
+
StemV: @wrapped_font.dominant_vertical_stem_width || 0})
|
|
226
|
+
fd.flag(:fixed_pitch) if @wrapped_font.metrics.is_fixed_pitch
|
|
227
|
+
fd.flag(@wrapped_font.metrics.character_set == 'Special' ? :symbolic : :nonsymbolic)
|
|
228
|
+
fd.must_be_indirect = true
|
|
229
|
+
|
|
230
|
+
dict = document.wrap({Type: :Font, Subtype: :Type1,
|
|
231
|
+
BaseFont: @wrapped_font.font_name.intern,
|
|
232
|
+
FontDescriptor: fd})
|
|
233
|
+
dict.font_wrapper = self
|
|
234
|
+
|
|
235
|
+
document.register_listener(:complete_objects) do
|
|
236
|
+
min, max = @encoding.code_to_name.keys.minmax
|
|
237
|
+
dict[:FirstChar] = min
|
|
238
|
+
dict[:LastChar] = max
|
|
239
|
+
dict[:Widths] = (min..max).map {|code| glyph(@encoding.name(code)).width }
|
|
240
|
+
|
|
241
|
+
if VALID_ENCODING_NAMES.include?(@encoding.encoding_name)
|
|
242
|
+
dict[:Encoding] = @encoding.encoding_name
|
|
243
|
+
elsif @encoding != @wrapped_font.encoding
|
|
244
|
+
differences = [min]
|
|
245
|
+
(min..max).each {|code| differences << @encoding.name(code) }
|
|
246
|
+
dict[:Encoding] = {Differences: differences}
|
|
247
|
+
end
|
|
234
248
|
end
|
|
249
|
+
|
|
250
|
+
dict
|
|
235
251
|
end
|
|
236
252
|
|
|
237
253
|
end
|
data/lib/hexapdf/font_loader.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|