hexapdf 0.11.9 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|