hexapdf 0.6.0 → 0.7.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 +5 -5
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTERS +1 -1
- data/LICENSE +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/hexapdf +1 -1
- data/examples/text_layouter_styling.rb +1 -2
- data/lib/hexapdf.rb +2 -2
- data/lib/hexapdf/cli.rb +3 -3
- data/lib/hexapdf/cli/batch.rb +5 -5
- data/lib/hexapdf/cli/command.rb +15 -17
- data/lib/hexapdf/cli/files.rb +3 -3
- data/lib/hexapdf/cli/images.rb +3 -4
- data/lib/hexapdf/cli/info.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +6 -6
- data/lib/hexapdf/cli/merge.rb +6 -6
- data/lib/hexapdf/cli/modify.rb +4 -4
- data/lib/hexapdf/cli/optimize.rb +3 -3
- data/lib/hexapdf/configuration.rb +4 -5
- data/lib/hexapdf/content.rb +2 -2
- data/lib/hexapdf/content/canvas.rb +35 -36
- data/lib/hexapdf/content/color_space.rb +9 -14
- data/lib/hexapdf/content/graphic_object.rb +2 -2
- data/lib/hexapdf/content/graphic_object/arc.rb +3 -3
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +4 -8
- data/lib/hexapdf/content/graphics_state.rb +4 -13
- data/lib/hexapdf/content/operator.rb +33 -35
- data/lib/hexapdf/content/parser.rb +28 -18
- data/lib/hexapdf/content/processor.rb +4 -5
- data/lib/hexapdf/content/transformation_matrix.rb +2 -2
- data/lib/hexapdf/data_dir.rb +2 -2
- data/lib/hexapdf/dictionary.rb +8 -9
- data/lib/hexapdf/dictionary_fields.rb +7 -10
- data/lib/hexapdf/document.rb +18 -18
- data/lib/hexapdf/document/files.rb +12 -10
- data/lib/hexapdf/document/fonts.rb +2 -2
- data/lib/hexapdf/document/images.rb +3 -3
- data/lib/hexapdf/document/pages.rb +4 -4
- data/lib/hexapdf/encryption.rb +2 -2
- data/lib/hexapdf/encryption/aes.rb +2 -2
- data/lib/hexapdf/encryption/arc4.rb +4 -4
- data/lib/hexapdf/encryption/fast_aes.rb +2 -2
- data/lib/hexapdf/encryption/fast_arc4.rb +4 -4
- data/lib/hexapdf/encryption/identity.rb +5 -4
- data/lib/hexapdf/encryption/ruby_aes.rb +147 -139
- data/lib/hexapdf/encryption/ruby_arc4.rb +4 -4
- data/lib/hexapdf/encryption/security_handler.rb +11 -12
- data/lib/hexapdf/encryption/standard_security_handler.rb +6 -9
- data/lib/hexapdf/error.rb +7 -9
- data/lib/hexapdf/filter.rb +2 -3
- data/lib/hexapdf/filter/ascii85_decode.rb +3 -3
- data/lib/hexapdf/filter/ascii_hex_decode.rb +2 -2
- data/lib/hexapdf/filter/dct_decode.rb +2 -2
- data/lib/hexapdf/filter/encryption.rb +2 -2
- data/lib/hexapdf/filter/flate_decode.rb +16 -33
- data/lib/hexapdf/filter/jpx_decode.rb +2 -2
- data/lib/hexapdf/filter/lzw_decode.rb +4 -4
- data/lib/hexapdf/filter/predictor.rb +2 -6
- data/lib/hexapdf/filter/run_length_decode.rb +2 -2
- data/lib/hexapdf/font/cmap.rb +2 -3
- data/lib/hexapdf/font/cmap/parser.rb +11 -11
- data/lib/hexapdf/font/cmap/writer.rb +25 -25
- data/lib/hexapdf/font/encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/base.rb +2 -2
- data/lib/hexapdf/font/encoding/difference_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/glyph_list.rb +6 -6
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/standard_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +2 -2
- data/lib/hexapdf/font/invalid_glyph.rb +7 -7
- data/lib/hexapdf/font/true_type.rb +2 -2
- data/lib/hexapdf/font/true_type/builder.rb +13 -7
- data/lib/hexapdf/font/true_type/font.rb +2 -3
- data/lib/hexapdf/font/true_type/optimizer.rb +2 -2
- data/lib/hexapdf/font/true_type/subsetter.rb +4 -4
- data/lib/hexapdf/font/true_type/table.rb +3 -5
- data/lib/hexapdf/font/true_type/table/cmap.rb +2 -2
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +9 -16
- data/lib/hexapdf/font/true_type/table/directory.rb +4 -4
- data/lib/hexapdf/font/true_type/table/glyf.rb +2 -2
- data/lib/hexapdf/font/true_type/table/head.rb +3 -2
- data/lib/hexapdf/font/true_type/table/hhea.rb +2 -2
- data/lib/hexapdf/font/true_type/table/hmtx.rb +2 -2
- data/lib/hexapdf/font/true_type/table/kern.rb +3 -3
- data/lib/hexapdf/font/true_type/table/loca.rb +3 -3
- data/lib/hexapdf/font/true_type/table/maxp.rb +2 -2
- data/lib/hexapdf/font/true_type/table/name.rb +3 -5
- data/lib/hexapdf/font/true_type/table/os2.rb +4 -3
- data/lib/hexapdf/font/true_type/table/post.rb +3 -7
- data/lib/hexapdf/font/true_type_wrapper.rb +20 -22
- data/lib/hexapdf/font/type1.rb +2 -2
- data/lib/hexapdf/font/type1/afm_parser.rb +7 -7
- data/lib/hexapdf/font/type1/character_metrics.rb +2 -2
- data/lib/hexapdf/font/type1/font.rb +3 -3
- data/lib/hexapdf/font/type1/font_metrics.rb +2 -4
- data/lib/hexapdf/font/type1/pfb_parser.rb +2 -2
- data/lib/hexapdf/font/type1_wrapper.rb +8 -9
- data/lib/hexapdf/font_loader.rb +2 -2
- data/lib/hexapdf/font_loader/from_configuration.rb +2 -2
- data/lib/hexapdf/font_loader/from_file.rb +2 -2
- data/lib/hexapdf/font_loader/standard14.rb +2 -2
- data/lib/hexapdf/image_loader.rb +2 -2
- data/lib/hexapdf/image_loader/jpeg.rb +6 -4
- data/lib/hexapdf/image_loader/pdf.rb +2 -2
- data/lib/hexapdf/image_loader/png.rb +6 -6
- data/lib/hexapdf/importer.rb +6 -4
- data/lib/hexapdf/layout.rb +2 -2
- data/lib/hexapdf/layout/box.rb +4 -4
- data/lib/hexapdf/layout/inline_box.rb +2 -2
- data/lib/hexapdf/layout/line.rb +6 -6
- data/lib/hexapdf/layout/numeric_refinements.rb +2 -2
- data/lib/hexapdf/layout/style.rb +17 -8
- data/lib/hexapdf/layout/text_fragment.rb +86 -48
- data/lib/hexapdf/layout/text_layouter.rb +40 -21
- data/lib/hexapdf/layout/text_shaper.rb +2 -2
- data/lib/hexapdf/name_tree_node.rb +2 -2
- data/lib/hexapdf/number_tree_node.rb +2 -2
- data/lib/hexapdf/object.rb +6 -8
- data/lib/hexapdf/parser.rb +10 -10
- data/lib/hexapdf/rectangle.rb +4 -4
- data/lib/hexapdf/reference.rb +2 -2
- data/lib/hexapdf/revision.rb +4 -4
- data/lib/hexapdf/revisions.rb +5 -5
- data/lib/hexapdf/serializer.rb +27 -24
- data/lib/hexapdf/stream.rb +4 -4
- data/lib/hexapdf/task.rb +2 -2
- data/lib/hexapdf/task/dereference.rb +4 -4
- data/lib/hexapdf/task/optimize.rb +5 -4
- data/lib/hexapdf/tokenizer.rb +12 -14
- data/lib/hexapdf/type.rb +2 -2
- data/lib/hexapdf/type/action.rb +3 -3
- data/lib/hexapdf/type/actions.rb +2 -2
- data/lib/hexapdf/type/actions/go_to.rb +2 -2
- data/lib/hexapdf/type/actions/go_to_r.rb +2 -2
- data/lib/hexapdf/type/actions/launch.rb +2 -2
- data/lib/hexapdf/type/actions/uri.rb +3 -3
- data/lib/hexapdf/type/annotation.rb +3 -3
- data/lib/hexapdf/type/annotations.rb +2 -2
- data/lib/hexapdf/type/annotations/link.rb +2 -2
- data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -2
- data/lib/hexapdf/type/annotations/text.rb +2 -2
- data/lib/hexapdf/type/catalog.rb +4 -4
- data/lib/hexapdf/type/cid_font.rb +4 -5
- data/lib/hexapdf/type/embedded_file.rb +3 -3
- data/lib/hexapdf/type/file_specification.rb +6 -7
- data/lib/hexapdf/type/font.rb +4 -4
- data/lib/hexapdf/type/font_descriptor.rb +3 -4
- data/lib/hexapdf/type/font_simple.rb +12 -16
- data/lib/hexapdf/type/font_true_type.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +5 -5
- data/lib/hexapdf/type/font_type1.rb +4 -4
- data/lib/hexapdf/type/form.rb +3 -3
- data/lib/hexapdf/type/graphics_state_parameter.rb +3 -3
- data/lib/hexapdf/type/image.rb +13 -14
- data/lib/hexapdf/type/info.rb +2 -2
- data/lib/hexapdf/type/names.rb +2 -2
- data/lib/hexapdf/type/object_stream.rb +5 -5
- data/lib/hexapdf/type/page.rb +9 -10
- data/lib/hexapdf/type/page_tree_node.rb +5 -6
- data/lib/hexapdf/type/resources.rb +11 -11
- data/lib/hexapdf/type/trailer.rb +3 -3
- data/lib/hexapdf/type/viewer_preferences.rb +2 -2
- data/lib/hexapdf/type/xref_stream.rb +8 -4
- data/lib/hexapdf/utils/bit_field.rb +4 -4
- data/lib/hexapdf/utils/bit_stream.rb +4 -4
- data/lib/hexapdf/utils/graphics_helpers.rb +2 -2
- data/lib/hexapdf/utils/lru_cache.rb +2 -2
- data/lib/hexapdf/utils/math_helpers.rb +2 -2
- data/lib/hexapdf/utils/object_hash.rb +3 -3
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +3 -3
- data/lib/hexapdf/utils/sorted_tree_node.rb +12 -11
- data/lib/hexapdf/version.rb +3 -3
- data/lib/hexapdf/writer.rb +8 -8
- data/lib/hexapdf/xref_section.rb +3 -3
- data/test/hexapdf/common_tokenizer_tests.rb +6 -7
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +0 -1
- data/test/hexapdf/content/test_canvas.rb +28 -36
- data/test/hexapdf/content/test_color_space.rb +4 -0
- data/test/hexapdf/content/test_graphics_state.rb +2 -0
- data/test/hexapdf/content/test_operator.rb +6 -7
- data/test/hexapdf/content/test_parser.rb +2 -2
- data/test/hexapdf/content/test_processor.rb +1 -1
- data/test/hexapdf/document/test_files.rb +1 -0
- data/test/hexapdf/document/test_images.rb +1 -1
- data/test/hexapdf/encryption/common.rb +3 -3
- data/test/hexapdf/encryption/test_aes.rb +10 -4
- data/test/hexapdf/encryption/test_identity.rb +1 -1
- data/test/hexapdf/encryption/test_security_handler.rb +13 -17
- data/test/hexapdf/encryption/test_standard_security_handler.rb +12 -12
- data/test/hexapdf/filter/test_ascii85_decode.rb +2 -3
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +6 -1
- data/test/hexapdf/filter/test_flate_decode.rb +2 -2
- data/test/hexapdf/filter/test_lzw_decode.rb +10 -10
- data/test/hexapdf/filter/test_predictor.rb +10 -2
- data/test/hexapdf/filter/test_run_length_decode.rb +1 -1
- data/test/hexapdf/font/cmap/test_parser.rb +40 -40
- data/test/hexapdf/font/cmap/test_writer.rb +29 -29
- data/test/hexapdf/font/test_true_type_wrapper.rb +3 -2
- data/test/hexapdf/font/true_type/common.rb +2 -0
- data/test/hexapdf/font/true_type/table/test_cmap.rb +1 -1
- data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +5 -4
- data/test/hexapdf/font/true_type/table/test_glyf.rb +2 -2
- data/test/hexapdf/font/true_type/table/test_head.rb +2 -2
- data/test/hexapdf/font/true_type/table/test_name.rb +9 -6
- data/test/hexapdf/font/true_type/test_builder.rb +8 -3
- data/test/hexapdf/font/true_type/test_optimizer.rb +1 -2
- data/test/hexapdf/font/type1/test_afm_parser.rb +2 -2
- data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
- data/test/hexapdf/image_loader/test_pdf.rb +1 -1
- data/test/hexapdf/image_loader/test_png.rb +3 -3
- data/test/hexapdf/layout/test_inline_box.rb +10 -1
- data/test/hexapdf/layout/test_line.rb +4 -4
- data/test/hexapdf/layout/test_style.rb +19 -7
- data/test/hexapdf/layout/test_text_fragment.rb +73 -27
- data/test/hexapdf/layout/test_text_layouter.rb +84 -68
- data/test/hexapdf/layout/test_text_shaper.rb +4 -6
- data/test/hexapdf/task/test_dereference.rb +2 -2
- data/test/hexapdf/task/test_optimize.rb +16 -7
- data/test/hexapdf/test_configuration.rb +1 -1
- data/test/hexapdf/test_data_dir.rb +2 -2
- data/test/hexapdf/test_dictionary.rb +6 -3
- data/test/hexapdf/test_dictionary_fields.rb +15 -14
- data/test/hexapdf/test_document.rb +47 -48
- data/test/hexapdf/test_filter.rb +30 -26
- data/test/hexapdf/test_importer.rb +14 -0
- data/test/hexapdf/test_object.rb +16 -4
- data/test/hexapdf/test_parser.rb +36 -36
- data/test/hexapdf/test_reference.rb +7 -5
- data/test/hexapdf/test_revision.rb +1 -1
- data/test/hexapdf/test_revisions.rb +90 -90
- data/test/hexapdf/test_serializer.rb +3 -2
- data/test/hexapdf/test_stream.rb +2 -4
- data/test/hexapdf/test_tokenizer.rb +2 -2
- data/test/hexapdf/test_writer.rb +80 -80
- data/test/hexapdf/test_xref_section.rb +1 -1
- data/test/hexapdf/type/annotations/test_link.rb +1 -1
- data/test/hexapdf/type/annotations/test_text.rb +3 -3
- data/test/hexapdf/type/test_font_descriptor.rb +1 -1
- data/test/hexapdf/type/test_font_simple.rb +2 -2
- data/test/hexapdf/type/test_font_type0.rb +0 -1
- data/test/hexapdf/type/test_image.rb +0 -3
- data/test/hexapdf/type/test_object_stream.rb +2 -1
- data/test/hexapdf/type/test_page.rb +5 -1
- data/test/hexapdf/type/test_page_tree_node.rb +4 -4
- data/test/hexapdf/type/test_trailer.rb +1 -1
- data/test/hexapdf/type/test_xref_stream.rb +4 -0
- data/test/hexapdf/utils/test_bit_field.rb +2 -0
- data/test/hexapdf/utils/test_bit_stream.rb +1 -1
- data/test/hexapdf/utils/test_lru_cache.rb +1 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -4
- data/test/test_helper.rb +3 -6
- metadata +3 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
|
@@ -41,7 +41,14 @@ module HexaPDF
|
|
|
41
41
|
# More efficient tokenizer for content streams. This tokenizer class works directly on a
|
|
42
42
|
# string and not on an IO.
|
|
43
43
|
#
|
|
44
|
-
#
|
|
44
|
+
# Changes:
|
|
45
|
+
#
|
|
46
|
+
# * Since a content stream is normally parsed front to back, a StopIteration error can be raised
|
|
47
|
+
# instead of returning +NO_MORE_TOKENS+ once the end of the string is reached to avoid costly
|
|
48
|
+
# checks in each iteration. If this behaviour is wanted, pass "raise_on_eos: true" in the
|
|
49
|
+
# constructor.
|
|
50
|
+
#
|
|
51
|
+
# * Indirect object references are *not* supported by this tokenizer!
|
|
45
52
|
#
|
|
46
53
|
# See: PDF1.7 s7.2
|
|
47
54
|
class Tokenizer < HexaPDF::Tokenizer #:nodoc:
|
|
@@ -50,9 +57,10 @@ module HexaPDF
|
|
|
50
57
|
attr_reader :string
|
|
51
58
|
|
|
52
59
|
# Creates a new tokenizer.
|
|
53
|
-
def initialize(string)
|
|
60
|
+
def initialize(string, raise_on_eos: false)
|
|
54
61
|
@ss = StringScanner.new(string)
|
|
55
62
|
@string = string
|
|
63
|
+
@raise_on_eos = raise_on_eos
|
|
56
64
|
end
|
|
57
65
|
|
|
58
66
|
# See: HexaPDF::Tokenizer#pos
|
|
@@ -104,10 +112,12 @@ module HexaPDF
|
|
|
104
112
|
elsif byte == 123 || byte == 125 # { }
|
|
105
113
|
Token.new(@ss.get_byte)
|
|
106
114
|
elsif byte == 37 # %
|
|
107
|
-
|
|
115
|
+
unless @ss.skip_until(/(?=[\r\n])/)
|
|
116
|
+
(@raise_on_eos ? (raise StopIteration) : (return NO_MORE_TOKENS))
|
|
117
|
+
end
|
|
108
118
|
next_token
|
|
109
119
|
elsif byte == -1
|
|
110
|
-
NO_MORE_TOKENS
|
|
120
|
+
@raise_on_eos ? raise(StopIteration) : NO_MORE_TOKENS
|
|
111
121
|
else
|
|
112
122
|
parse_keyword
|
|
113
123
|
end
|
|
@@ -117,11 +127,11 @@ module HexaPDF
|
|
|
117
127
|
|
|
118
128
|
# See: HexaPDF::Tokenizer#parse_number
|
|
119
129
|
def parse_number
|
|
120
|
-
if (val = @ss.scan(/[+-]
|
|
121
|
-
val.
|
|
122
|
-
elsif (val = @ss.scan(/[+-]?(?:\d+\.\d*|\.\d+)/))
|
|
123
|
-
val << '0'.freeze if val.getbyte(-1) == 46 # dot '.'
|
|
130
|
+
if (val = @ss.scan(/[+-]?(?:\d+\.\d*|\.\d+)/))
|
|
131
|
+
val << '0' if val.getbyte(-1) == 46 # dot '.'
|
|
124
132
|
Float(val)
|
|
133
|
+
elsif (val = @ss.scan(/[+-]?\d++/))
|
|
134
|
+
val.to_i
|
|
125
135
|
else
|
|
126
136
|
parse_keyword
|
|
127
137
|
end
|
|
@@ -133,7 +143,6 @@ module HexaPDF
|
|
|
133
143
|
|
|
134
144
|
end
|
|
135
145
|
|
|
136
|
-
|
|
137
146
|
# This class knows how to correctly parse a content stream.
|
|
138
147
|
#
|
|
139
148
|
# == Overview
|
|
@@ -156,11 +165,12 @@ module HexaPDF
|
|
|
156
165
|
|
|
157
166
|
# Parses the contents and calls the processor object for each parsed operator.
|
|
158
167
|
def parse(contents, processor)
|
|
159
|
-
tokenizer = Tokenizer.new(contents)
|
|
168
|
+
tokenizer = Tokenizer.new(contents, raise_on_eos: true)
|
|
160
169
|
params = []
|
|
161
|
-
|
|
170
|
+
loop do
|
|
171
|
+
obj = tokenizer.next_object(allow_keyword: true)
|
|
162
172
|
if obj.kind_of?(Tokenizer::Token)
|
|
163
|
-
if obj == 'BI'
|
|
173
|
+
if obj == 'BI'
|
|
164
174
|
params = parse_inline_image(tokenizer)
|
|
165
175
|
end
|
|
166
176
|
processor.process(obj.to_sym, params)
|
|
@@ -179,15 +189,15 @@ module HexaPDF
|
|
|
179
189
|
def parse_inline_image(tokenizer)
|
|
180
190
|
# BI has already been read, so read the image dictionary
|
|
181
191
|
dict = {}
|
|
182
|
-
while (key = tokenizer.next_object(allow_keyword: true))
|
|
183
|
-
if key == 'ID'
|
|
192
|
+
while (key = tokenizer.next_object(allow_keyword: true) rescue Tokenizer::NO_MORE_TOKENS)
|
|
193
|
+
if key == 'ID'
|
|
184
194
|
break
|
|
185
195
|
elsif key == Tokenizer::NO_MORE_TOKENS
|
|
186
196
|
raise HexaPDF::Error, "EOS while trying to read dictionary key for inline image"
|
|
187
197
|
elsif !key.kind_of?(Symbol)
|
|
188
198
|
raise HexaPDF::Error, "Inline image dictionary keys must be PDF name objects"
|
|
189
199
|
end
|
|
190
|
-
value = tokenizer.next_object
|
|
200
|
+
value = tokenizer.next_object rescue Tokenizer::NO_MORE_TOKENS
|
|
191
201
|
if value == Tokenizer::NO_MORE_TOKENS
|
|
192
202
|
raise HexaPDF::Error, "EOS while trying to read dictionary value for inline image"
|
|
193
203
|
end
|
|
@@ -213,7 +223,7 @@ module HexaPDF
|
|
|
213
223
|
# Check if we found EI inside of the image data
|
|
214
224
|
count = 0
|
|
215
225
|
while count < MAX_TOKEN_CHECK
|
|
216
|
-
token = tokenizer.next_object(allow_keyword: true) rescue
|
|
226
|
+
token = tokenizer.next_object(allow_keyword: true) rescue Tokenizer::NO_MORE_TOKENS
|
|
217
227
|
if token == Tokenizer::NO_MORE_TOKENS
|
|
218
228
|
count += MAX_TOKEN_CHECK
|
|
219
229
|
elsif token.kind_of?(Tokenizer::Token) &&
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
|
@@ -145,7 +145,6 @@ module HexaPDF
|
|
|
145
145
|
|
|
146
146
|
end
|
|
147
147
|
|
|
148
|
-
|
|
149
148
|
# Represents a box composed of GlyphBox objects.
|
|
150
149
|
#
|
|
151
150
|
# The bounding box methods #lower_left, #lower_right, #upper_left, #upper_right are computed
|
|
@@ -387,10 +386,10 @@ module HexaPDF
|
|
|
387
386
|
# text strings together with positioning information (+TJ+ operator).
|
|
388
387
|
def decode_text(data)
|
|
389
388
|
if data.kind_of?(Array)
|
|
390
|
-
data = data.each_with_object(''.b) {|obj, result| result << obj if obj.kind_of?(String)}
|
|
389
|
+
data = data.each_with_object(''.b) {|obj, result| result << obj if obj.kind_of?(String) }
|
|
391
390
|
end
|
|
392
391
|
font = graphics_state.font
|
|
393
|
-
font.decode(data).map {|code_point| font.to_utf8(code_point)}.join('')
|
|
392
|
+
font.decode(data).map {|code_point| font.to_utf8(code_point) }.join('')
|
|
394
393
|
end
|
|
395
394
|
|
|
396
395
|
# Decodes the given text object and returns it as a CompositeBox object.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
data/lib/hexapdf/data_dir.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
data/lib/hexapdf/dictionary.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
|
@@ -130,7 +130,6 @@ module HexaPDF
|
|
|
130
130
|
defined?(@type) && @type
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
-
|
|
134
133
|
# Returns the value for the given dictionary entry.
|
|
135
134
|
#
|
|
136
135
|
# This method should be used instead of direct access to the value because it provides
|
|
@@ -150,14 +149,14 @@ module HexaPDF
|
|
|
150
149
|
field = self.class.field(name)
|
|
151
150
|
data = if key?(name)
|
|
152
151
|
value[name]
|
|
153
|
-
elsif field
|
|
152
|
+
elsif field&.default?
|
|
154
153
|
value[name] = field.default
|
|
155
154
|
end
|
|
156
155
|
value[name] = data = document.deref(data) if data.kind_of?(HexaPDF::Reference)
|
|
157
156
|
if data.class == HexaPDF::Object || (data.kind_of?(HexaPDF::Object) && data.value.nil?)
|
|
158
157
|
data = data.value
|
|
159
158
|
end
|
|
160
|
-
self[name] = data = field.convert(data, document) if field
|
|
159
|
+
self[name] = data = field.convert(data, document) if field&.convert?(data)
|
|
161
160
|
data
|
|
162
161
|
end
|
|
163
162
|
|
|
@@ -199,7 +198,7 @@ module HexaPDF
|
|
|
199
198
|
# Note that the yielded value is already preprocessed like in #[].
|
|
200
199
|
def each
|
|
201
200
|
return to_enum(__method__) unless block_given?
|
|
202
|
-
value.each_key {|name| yield(name, self[name])}
|
|
201
|
+
value.each_key {|name| yield(name, self[name]) }
|
|
203
202
|
self
|
|
204
203
|
end
|
|
205
204
|
|
|
@@ -244,7 +243,7 @@ module HexaPDF
|
|
|
244
243
|
|
|
245
244
|
# Iterates over all currently set fields and those that are required.
|
|
246
245
|
def each_set_key_or_required_field #:yields: name, field
|
|
247
|
-
value.each_key {|name| yield(name, self.class.field(name))}
|
|
246
|
+
value.each_key {|name| yield(name, self.class.field(name)) }
|
|
248
247
|
self.class.each_field do |name, field|
|
|
249
248
|
yield(name, field) if field.required? && !value.key?(name)
|
|
250
249
|
end
|
|
@@ -287,11 +286,11 @@ module HexaPDF
|
|
|
287
286
|
obj = value[name] # we need the unwrapped object!
|
|
288
287
|
if field.indirect && (!obj.kind_of?(HexaPDF::Object) || !obj.indirect?)
|
|
289
288
|
yield("Field #{name} needs to be an indirect object", true)
|
|
290
|
-
value[name] =
|
|
289
|
+
value[name] = document.add(obj)
|
|
291
290
|
elsif !field.indirect && obj.kind_of?(HexaPDF::Object) && obj.indirect?
|
|
292
291
|
yield("Field #{name} needs to be a direct object", true)
|
|
293
292
|
document.delete(obj)
|
|
294
|
-
value[name] = obj
|
|
293
|
+
value[name] = obj.value
|
|
295
294
|
end
|
|
296
295
|
end
|
|
297
296
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
|
@@ -94,10 +94,9 @@ module HexaPDF
|
|
|
94
94
|
# two converters could potentially be used for the same type, the one that appears earlier
|
|
95
95
|
# is used.
|
|
96
96
|
def self.converter_for(type)
|
|
97
|
-
@converters.find {|converter| converter.usable_for?(type)}
|
|
97
|
+
@converters.find {|converter| converter.usable_for?(type) }
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
|
|
101
100
|
# Returns +true+ if the value for this field needs to be an indirect object, +false+ if it
|
|
102
101
|
# needs to be a direct object or +nil+ if it can be either.
|
|
103
102
|
attr_reader :indirect
|
|
@@ -123,7 +122,7 @@ module HexaPDF
|
|
|
123
122
|
@type.concat(Array(@converter.additional_types))
|
|
124
123
|
@type.map! do |type|
|
|
125
124
|
if type.kind_of?(Symbol)
|
|
126
|
-
HexaPDF::GlobalConfiguration.constantize('object.type_map'
|
|
125
|
+
HexaPDF::GlobalConfiguration.constantize('object.type_map', type)
|
|
127
126
|
else
|
|
128
127
|
type
|
|
129
128
|
end
|
|
@@ -158,8 +157,8 @@ module HexaPDF
|
|
|
158
157
|
|
|
159
158
|
# Returns +true+ if the given object is valid for this field.
|
|
160
159
|
def valid_object?(obj)
|
|
161
|
-
type.any? {|t| obj.kind_of?(t)} ||
|
|
162
|
-
(obj.kind_of?(HexaPDF::Object) && type.any? {|t| obj.value.kind_of?(t)})
|
|
160
|
+
type.any? {|t| obj.kind_of?(t) } ||
|
|
161
|
+
(obj.kind_of?(HexaPDF::Object) && type.any? {|t| obj.value.kind_of?(t) })
|
|
163
162
|
end
|
|
164
163
|
|
|
165
164
|
# If a converter was defined, it is used. Otherwise +false+ is returned.
|
|
@@ -307,7 +306,7 @@ module HexaPDF
|
|
|
307
306
|
|
|
308
307
|
# Returns +true+ if the given data should be converted to a Time object.
|
|
309
308
|
def self.convert?(data, _type)
|
|
310
|
-
data.kind_of?(String) && data
|
|
309
|
+
data.kind_of?(String) && data.match?(DATE_RE)
|
|
311
310
|
end
|
|
312
311
|
|
|
313
312
|
# Converts the string into a Time object.
|
|
@@ -320,7 +319,6 @@ module HexaPDF
|
|
|
320
319
|
|
|
321
320
|
end
|
|
322
321
|
|
|
323
|
-
|
|
324
322
|
# Converter module for file specification fields. A file specification in string format is
|
|
325
323
|
# converted to the corresponding file specification dictionary.
|
|
326
324
|
module FileSpecificationConverter
|
|
@@ -349,7 +347,6 @@ module HexaPDF
|
|
|
349
347
|
|
|
350
348
|
end
|
|
351
349
|
|
|
352
|
-
|
|
353
350
|
# Converter module for fields of type Rectangle.
|
|
354
351
|
module RectangleConverter
|
|
355
352
|
|
data/lib/hexapdf/document.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
|
@@ -129,11 +129,11 @@ module HexaPDF
|
|
|
129
129
|
@version = '1.2'
|
|
130
130
|
|
|
131
131
|
@revisions = Revisions.from_io(self, io)
|
|
132
|
-
if encrypted? && @config['document.auto_decrypt']
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
@security_handler = if encrypted? && @config['document.auto_decrypt']
|
|
133
|
+
Encryption::SecurityHandler.set_up_decryption(self, decryption_opts)
|
|
134
|
+
else
|
|
135
|
+
nil
|
|
136
|
+
end
|
|
137
137
|
|
|
138
138
|
@listeners = {}
|
|
139
139
|
@cache = Hash.new {|h, k| h[k] = {} }
|
|
@@ -178,7 +178,7 @@ module HexaPDF
|
|
|
178
178
|
# because this method takes *all* revisions into account. Also see the discussion on #each for
|
|
179
179
|
# more information.
|
|
180
180
|
def object?(ref)
|
|
181
|
-
@revisions.any? {|rev| rev.object?(ref)}
|
|
181
|
+
@revisions.any? {|rev| rev.object?(ref) }
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
# :call-seq:
|
|
@@ -241,7 +241,7 @@ module HexaPDF
|
|
|
241
241
|
when :current
|
|
242
242
|
@revisions.current.delete(ref, mark_as_free: mark_as_free)
|
|
243
243
|
when :all
|
|
244
|
-
@revisions.each {|rev| rev.delete(ref, mark_as_free: mark_as_free)}
|
|
244
|
+
@revisions.each {|rev| rev.delete(ref, mark_as_free: mark_as_free) }
|
|
245
245
|
else
|
|
246
246
|
raise ArgumentError, "Unsupported option revision: #{revision}"
|
|
247
247
|
end
|
|
@@ -318,14 +318,14 @@ module HexaPDF
|
|
|
318
318
|
type = (klass <= HexaPDF::Dictionary ? klass.type : nil)
|
|
319
319
|
else
|
|
320
320
|
type ||= deref(data.value[:Type]) if data.value.kind_of?(Hash)
|
|
321
|
-
klass = GlobalConfiguration.constantize('object.type_map'
|
|
321
|
+
klass = GlobalConfiguration.constantize('object.type_map', type) { nil } if type
|
|
322
322
|
end
|
|
323
323
|
|
|
324
324
|
if data.value.kind_of?(Hash)
|
|
325
325
|
subtype ||= deref(data.value[:Subtype]) || deref(data.value[:S])
|
|
326
326
|
end
|
|
327
327
|
if subtype
|
|
328
|
-
klass = GlobalConfiguration.constantize('object.subtype_map'
|
|
328
|
+
klass = GlobalConfiguration.constantize('object.subtype_map', type, subtype) { klass }
|
|
329
329
|
end
|
|
330
330
|
|
|
331
331
|
klass ||= if data.stream
|
|
@@ -354,10 +354,10 @@ module HexaPDF
|
|
|
354
354
|
case object
|
|
355
355
|
when Hash
|
|
356
356
|
seen[object] = true
|
|
357
|
-
object.each_with_object({}) {|(key, val), memo| memo[key] = unwrap(val, seen.dup)}
|
|
357
|
+
object.each_with_object({}) {|(key, val), memo| memo[key] = unwrap(val, seen.dup) }
|
|
358
358
|
when Array
|
|
359
359
|
seen[object] = true
|
|
360
|
-
object.map {|inner_o| unwrap(inner_o, seen.dup)}
|
|
360
|
+
object.map {|inner_o| unwrap(inner_o, seen.dup) }
|
|
361
361
|
when HexaPDF::PDFData
|
|
362
362
|
seen[object] = true
|
|
363
363
|
unwrap(object.value, seen.dup)
|
|
@@ -415,7 +415,7 @@ module HexaPDF
|
|
|
415
415
|
|
|
416
416
|
# Dispatches the message +name+ with the given arguments to all registered listeners.
|
|
417
417
|
def dispatch_message(name, *args)
|
|
418
|
-
@listeners[name]
|
|
418
|
+
@listeners[name]&.each {|obj| obj.call(*args) }
|
|
419
419
|
end
|
|
420
420
|
|
|
421
421
|
# Caches the value or the return value of the given block using the given Object::PDFData and
|
|
@@ -477,7 +477,7 @@ module HexaPDF
|
|
|
477
477
|
#
|
|
478
478
|
# See Task for more information.
|
|
479
479
|
def task(name, **opts, &block)
|
|
480
|
-
task = config.constantize('task.map'
|
|
480
|
+
task = config.constantize('task.map', name) do
|
|
481
481
|
raise HexaPDF::Error, "No task named '#{name}' is available"
|
|
482
482
|
end
|
|
483
483
|
task.call(self, **opts, &block)
|
|
@@ -501,14 +501,14 @@ module HexaPDF
|
|
|
501
501
|
#
|
|
502
502
|
# See: PDF1.7 s7.2.2
|
|
503
503
|
def version
|
|
504
|
-
catalog_version = (catalog[:Version] || '1.0'
|
|
504
|
+
catalog_version = (catalog[:Version] || '1.0').to_s
|
|
505
505
|
(@version < catalog_version ? catalog_version : @version)
|
|
506
506
|
end
|
|
507
507
|
|
|
508
508
|
# Sets the version of the PDF document. The argument must be a string in the format 'M.N'
|
|
509
509
|
# where M is the major version and N the minor version (e.g. '1.4' or '2.0').
|
|
510
510
|
def version=(value)
|
|
511
|
-
raise ArgumentError, "PDF version must follow format M.N" unless value.to_s
|
|
511
|
+
raise ArgumentError, "PDF version must follow format M.N" unless value.to_s.match?(/\A\d\.\d\z/)
|
|
512
512
|
@version = value.to_s
|
|
513
513
|
end
|
|
514
514
|
|
|
@@ -615,7 +615,7 @@ module HexaPDF
|
|
|
615
615
|
dispatch_message(:before_write)
|
|
616
616
|
|
|
617
617
|
if file_or_io.kind_of?(String)
|
|
618
|
-
File.open(file_or_io, 'w+') {|file| Writer.write(self, file)}
|
|
618
|
+
File.open(file_or_io, 'w+') {|file| Writer.write(self, file) }
|
|
619
619
|
else
|
|
620
620
|
Writer.write(self, file_or_io)
|
|
621
621
|
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
2
|
#
|
|
3
3
|
#--
|
|
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-2018 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
|
|
@@ -49,8 +49,8 @@ module HexaPDF
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# :call-seq:
|
|
52
|
-
# files.add(filename, name:
|
|
53
|
-
# files.add(io, name:, description: nil)
|
|
52
|
+
# files.add(filename, name: nil, description: nil, embed: true) -> file_spec
|
|
53
|
+
# files.add(io, name:, description: nil) -> file_spec
|
|
54
54
|
#
|
|
55
55
|
# Adds the file or IO to the PDF document and returns the corresponding file specification
|
|
56
56
|
# object.
|
|
@@ -58,8 +58,11 @@ module HexaPDF
|
|
|
58
58
|
# Options:
|
|
59
59
|
#
|
|
60
60
|
# name::
|
|
61
|
-
# The name that should be used for the file path. This name is also for registering
|
|
62
|
-
# file in the EmbeddedFiles name tree.
|
|
61
|
+
# The name that should be used for the file path. This name is also used for registering
|
|
62
|
+
# the file in the EmbeddedFiles name tree.
|
|
63
|
+
#
|
|
64
|
+
# When a filename is given, the basename of the file is used by default for +name+ if it
|
|
65
|
+
# is not specified.
|
|
63
66
|
#
|
|
64
67
|
# description::
|
|
65
68
|
# A description of the file.
|
|
@@ -104,14 +107,13 @@ module HexaPDF
|
|
|
104
107
|
else
|
|
105
108
|
seen = {}
|
|
106
109
|
tree = @document.catalog[:Names] && @document.catalog[:Names][:EmbeddedFiles]
|
|
107
|
-
tree
|
|
110
|
+
tree&.each_entry do |_, spec|
|
|
108
111
|
seen[spec] = true
|
|
109
112
|
yield(spec)
|
|
110
|
-
end
|
|
113
|
+
end
|
|
111
114
|
|
|
112
115
|
@document.pages.each do |page|
|
|
113
|
-
|
|
114
|
-
page[:Annots].each do |annot|
|
|
116
|
+
page[:Annots]&.each do |annot|
|
|
115
117
|
annot = @document.deref(annot)
|
|
116
118
|
next unless annot[:Subtype] == :FileAttachment
|
|
117
119
|
spec = @document.deref(annot[:FS])
|