hexapdf 0.1.0 → 0.2.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 +56 -0
- data/CONTRIBUTERS +1 -1
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/examples/arc.rb +1 -1
- data/examples/graphics.rb +1 -1
- data/examples/hello_world.rb +1 -1
- data/examples/merging.rb +1 -1
- data/examples/show_char_bboxes.rb +1 -1
- data/examples/standard_pdf_fonts.rb +1 -1
- data/examples/truetype.rb +1 -1
- data/lib/hexapdf/cli.rb +14 -7
- data/lib/hexapdf/cli/extract.rb +1 -1
- data/lib/hexapdf/cli/info.rb +2 -2
- data/lib/hexapdf/cli/inspect.rb +4 -4
- data/lib/hexapdf/cli/modify.rb +151 -51
- data/lib/hexapdf/configuration.rb +1 -1
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/dictionary.rb +6 -19
- data/lib/hexapdf/dictionary_fields.rb +1 -1
- data/lib/hexapdf/document.rb +23 -16
- data/lib/hexapdf/document/files.rb +130 -0
- data/lib/hexapdf/{font_utils.rb → document/fonts.rb} +40 -38
- data/lib/hexapdf/document/images.rb +117 -0
- data/lib/hexapdf/document/pages.rb +125 -0
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +10 -10
- data/lib/hexapdf/encryption/standard_security_handler.rb +11 -8
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -6
- data/lib/hexapdf/font/cmap/writer.rb +5 -7
- data/lib/hexapdf/font/true_type.rb +4 -1
- data/lib/hexapdf/font/true_type/font.rb +8 -16
- data/lib/hexapdf/font/true_type/table.rb +5 -16
- data/lib/hexapdf/font/true_type/table/cmap.rb +2 -7
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +2 -6
- data/lib/hexapdf/font/true_type/table/directory.rb +0 -5
- data/lib/hexapdf/font/true_type/table/glyf.rb +3 -11
- data/lib/hexapdf/font/true_type/table/head.rb +0 -12
- data/lib/hexapdf/font/true_type/table/hhea.rb +0 -7
- data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -5
- data/lib/hexapdf/font/true_type/table/loca.rb +0 -4
- data/lib/hexapdf/font/true_type/table/maxp.rb +0 -8
- data/lib/hexapdf/font/true_type/table/name.rb +3 -17
- data/lib/hexapdf/font/true_type/table/os2.rb +0 -14
- data/lib/hexapdf/font/true_type/table/post.rb +0 -8
- data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
- data/lib/hexapdf/font/type1.rb +2 -2
- data/lib/hexapdf/font/type1/font.rb +2 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +10 -1
- data/lib/hexapdf/font/type1_wrapper.rb +2 -1
- data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
- data/lib/hexapdf/font_loader/standard14.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 +2 -2
- data/lib/hexapdf/object.rb +18 -5
- data/lib/hexapdf/rectangle.rb +8 -1
- data/lib/hexapdf/revisions.rb +4 -2
- data/lib/hexapdf/serializer.rb +3 -3
- data/lib/hexapdf/stream.rb +3 -2
- data/lib/hexapdf/task/dereference.rb +4 -5
- data/lib/hexapdf/task/optimize.rb +6 -3
- data/lib/hexapdf/tokenizer.rb +3 -3
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/form.rb +19 -0
- data/lib/hexapdf/type/page.rb +21 -6
- data/lib/hexapdf/type/page_tree_node.rb +27 -34
- data/lib/hexapdf/utils/bit_stream.rb +1 -1
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/man/man1/hexapdf.1 +259 -187
- data/test/hexapdf/content/graphic_object/test_arc.rb +1 -1
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +1 -1
- data/test/hexapdf/content/graphic_object/test_solid_arc.rb +1 -1
- data/test/hexapdf/content/test_canvas.rb +1 -1
- data/test/hexapdf/document/test_files.rb +71 -0
- data/test/hexapdf/{test_font_utils.rb → document/test_fonts.rb} +1 -2
- data/test/hexapdf/document/test_images.rb +78 -0
- data/test/hexapdf/document/test_pages.rb +114 -0
- data/test/hexapdf/encryption/test_standard_security_handler.rb +26 -5
- data/test/hexapdf/font/test_true_type_wrapper.rb +1 -1
- data/test/hexapdf/font/true_type/common.rb +0 -4
- data/test/hexapdf/font/true_type/table/test_cmap.rb +0 -6
- data/test/hexapdf/font/true_type/table/test_directory.rb +0 -5
- data/test/hexapdf/font/true_type/table/test_glyf.rb +5 -8
- data/test/hexapdf/font/true_type/table/test_head.rb +0 -20
- data/test/hexapdf/font/true_type/table/test_hhea.rb +0 -7
- data/test/hexapdf/font/true_type/table/test_hmtx.rb +2 -7
- data/test/hexapdf/font/true_type/table/test_loca.rb +4 -8
- data/test/hexapdf/font/true_type/table/test_maxp.rb +0 -7
- data/test/hexapdf/font/true_type/table/test_name.rb +0 -19
- data/test/hexapdf/font/true_type/table/test_os2.rb +0 -8
- data/test/hexapdf/font/true_type/table/test_post.rb +0 -13
- data/test/hexapdf/font/true_type/test_font.rb +14 -38
- data/test/hexapdf/font/true_type/test_table.rb +0 -9
- data/test/hexapdf/font/type1/test_font_metrics.rb +22 -0
- data/test/hexapdf/task/test_dereference.rb +5 -1
- data/test/hexapdf/task/test_optimize.rb +1 -1
- data/test/hexapdf/test_dictionary.rb +4 -0
- data/test/hexapdf/test_document.rb +0 -7
- data/test/hexapdf/test_importer.rb +4 -4
- data/test/hexapdf/test_object.rb +31 -9
- data/test/hexapdf/test_rectangle.rb +18 -0
- data/test/hexapdf/test_revisions.rb +7 -0
- data/test/hexapdf/test_serializer.rb +6 -0
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/test_form.rb +12 -0
- data/test/hexapdf/type/test_page.rb +39 -20
- data/test/hexapdf/type/test_page_tree_node.rb +28 -21
- metadata +21 -9
- data/lib/hexapdf/document_utils.rb +0 -209
- data/test/hexapdf/test_document_utils.rb +0 -144
@@ -0,0 +1,125 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2016 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#++
|
33
|
+
|
34
|
+
module HexaPDF
|
35
|
+
class Document
|
36
|
+
|
37
|
+
# This class provides methods for managing the pages of a PDF file.
|
38
|
+
#
|
39
|
+
# It uses the methods of HexaPDF::Type::PageTreeNode underneath but provides a more convenient
|
40
|
+
# interface.
|
41
|
+
class Pages
|
42
|
+
|
43
|
+
include Enumerable
|
44
|
+
|
45
|
+
# Creates a new Pages object for the given PDF document.
|
46
|
+
def initialize(document)
|
47
|
+
@document = document
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the root of the page tree, a HexaPDF::Type::PageTreeNode object.
|
51
|
+
def root
|
52
|
+
@document.catalog.pages
|
53
|
+
end
|
54
|
+
|
55
|
+
# Adds the page or a new empty page at the end and returns it.
|
56
|
+
def add(page = nil)
|
57
|
+
@document.catalog.pages.add_page(page)
|
58
|
+
end
|
59
|
+
|
60
|
+
# :call-seq:
|
61
|
+
# pages << page -> pages
|
62
|
+
#
|
63
|
+
# Appends the given page at the end and returns the pages object itself to allow chaining.
|
64
|
+
def <<(page)
|
65
|
+
add(page)
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Inserts the page or a new empty page at the zero-based index and returns it.
|
70
|
+
#
|
71
|
+
# Negative indices count backwards from the end, i.e. -1 is the last page. When using
|
72
|
+
# negative indices, the page will be inserted after that element. So using an index of -1
|
73
|
+
# will insert the page after the last page.
|
74
|
+
def insert(index, page = nil)
|
75
|
+
@document.catalog.pages.insert_page(index, page)
|
76
|
+
end
|
77
|
+
|
78
|
+
# :call-seq:
|
79
|
+
# pages.delete(page) -> page or nil
|
80
|
+
#
|
81
|
+
# Deletes the given page object from the document's page tree (but *not* from the document).
|
82
|
+
#
|
83
|
+
# Returns the page object, or +nil+ if the page object was not in the page tree.
|
84
|
+
def delete(page)
|
85
|
+
@document.catalog.pages.delete_page(page)
|
86
|
+
end
|
87
|
+
|
88
|
+
# :call-seq:
|
89
|
+
# pages.delete_at(index) -> page or nil
|
90
|
+
#
|
91
|
+
# Deletes the page object at the given index from the document's page tree (but *not* from the
|
92
|
+
# document).
|
93
|
+
#
|
94
|
+
# Returns the page object, or +nil+ if the index was invalid.
|
95
|
+
def delete_at(index)
|
96
|
+
@document.catalog.pages.delete_page(index)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the page for the zero-based index, or +nil+ if no such page exists.
|
100
|
+
#
|
101
|
+
# Negative indices count backwards from the end, i.e. -1 is the last page.
|
102
|
+
def [](index)
|
103
|
+
@document.catalog.pages.page(index)
|
104
|
+
end
|
105
|
+
|
106
|
+
# :call-seq:
|
107
|
+
# pages.each {|page| block } -> pages
|
108
|
+
# pages.each -> Enumerator
|
109
|
+
#
|
110
|
+
# Iterates over all pages inorder.
|
111
|
+
def each(&block)
|
112
|
+
@document.catalog.pages.each_page(&block)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the number of pages in the PDF document. May be zero if the document has no pages.
|
116
|
+
def count
|
117
|
+
@document.catalog.pages.page_count
|
118
|
+
end
|
119
|
+
alias :size :count
|
120
|
+
alias :length :count
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
@@ -107,7 +107,7 @@ module HexaPDF
|
|
107
107
|
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
108
108
|
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
109
109
|
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
110
|
-
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]
|
110
|
+
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16].freeze
|
111
111
|
|
112
112
|
# :nodoc:
|
113
113
|
# Inverse of the Rijndael S-box
|
@@ -127,10 +127,10 @@ module HexaPDF
|
|
127
127
|
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
128
128
|
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
129
129
|
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
130
|
-
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]
|
130
|
+
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d].freeze
|
131
131
|
|
132
132
|
# :nodoc:
|
133
|
-
RCON = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c]
|
133
|
+
RCON = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c].freeze
|
134
134
|
|
135
135
|
# :nodoc:
|
136
136
|
# Precomputed Galois multiplication table for multiplication with 2 in GF(2^8)
|
@@ -150,7 +150,7 @@ module HexaPDF
|
|
150
150
|
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
|
151
151
|
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
|
152
152
|
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
|
153
|
-
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5]
|
153
|
+
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5].freeze
|
154
154
|
|
155
155
|
# :nodoc:
|
156
156
|
# Precomputed Galois multiplication table for multiplication with 3 in GF(2^8)
|
@@ -170,7 +170,7 @@ module HexaPDF
|
|
170
170
|
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
|
171
171
|
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
|
172
172
|
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
|
173
|
-
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a]
|
173
|
+
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a].freeze
|
174
174
|
|
175
175
|
# :nodoc:
|
176
176
|
# Precomputed Galois multiplication table for multiplication with 9 in GF(2^8)
|
@@ -190,7 +190,7 @@ module HexaPDF
|
|
190
190
|
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
|
191
191
|
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
|
192
192
|
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
|
193
|
-
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46]
|
193
|
+
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46].freeze
|
194
194
|
|
195
195
|
# :nodoc:
|
196
196
|
# Precomputed Galois multiplication table for multiplication with 11 in GF(2^8)
|
@@ -210,7 +210,7 @@ module HexaPDF
|
|
210
210
|
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
|
211
211
|
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
|
212
212
|
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
|
213
|
-
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3]
|
213
|
+
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3].freeze
|
214
214
|
|
215
215
|
# :nodoc:
|
216
216
|
# Precomputed Galois multiplication table for multiplication with 13 in GF(2^8)
|
@@ -230,7 +230,7 @@ module HexaPDF
|
|
230
230
|
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
|
231
231
|
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
|
232
232
|
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
|
233
|
-
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97]
|
233
|
+
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97].freeze
|
234
234
|
|
235
235
|
# :nodoc:
|
236
236
|
# Precomputed Galois multiplication table for multiplication with 14 in GF(2^8)
|
@@ -250,11 +250,11 @@ module HexaPDF
|
|
250
250
|
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
|
251
251
|
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
|
252
252
|
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
|
253
|
-
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d]
|
253
|
+
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d].freeze
|
254
254
|
|
255
255
|
# :nodoc:
|
256
256
|
# Number of rounds needed in various parts of the algorithm, depends on the key size
|
257
|
-
NUMBER_OF_ROUNDS = {16 => 10, 24 => 12, 32 => 14}
|
257
|
+
NUMBER_OF_ROUNDS = {16 => 10, 24 => 12, 32 => 14}.freeze
|
258
258
|
|
259
259
|
# KeyExpansion step
|
260
260
|
#
|
@@ -67,7 +67,7 @@ module HexaPDF
|
|
67
67
|
if !key?(:OE) || !key?(:UE) || !key?(:Perms)
|
68
68
|
yield("Value of /OE, /UE or /Perms is missing for dictionary revision 6", false)
|
69
69
|
end
|
70
|
-
if value[:U].length != 48 || value[:O].length != 48 || value[:UE].length
|
70
|
+
if value[:U].length != 48 || value[:O].length != 48 || value[:UE].length != 32 ||
|
71
71
|
value[:OE].length != 32 || value[:Perms].length != 16
|
72
72
|
yield("Invalid size for /U, /O, /UE, /OE or /Perms values for revisions 6", false)
|
73
73
|
end
|
@@ -140,7 +140,7 @@ module HexaPDF
|
|
140
140
|
EXTRACT_CONTENT | ASSEMBLE_DOCUMENT | HIGH_QUALITY_PRINT
|
141
141
|
|
142
142
|
# Reserved permission bits
|
143
|
-
RESERVED = 0xFFFFF000
|
143
|
+
RESERVED = 0xFFFFF000 | 0b11000000
|
144
144
|
|
145
145
|
# Maps permission symbols to their respective value
|
146
146
|
SYMBOL_TO_PERMISSION = {
|
@@ -152,7 +152,7 @@ module HexaPDF
|
|
152
152
|
extract_content: EXTRACT_CONTENT,
|
153
153
|
assemble_document: ASSEMBLE_DOCUMENT,
|
154
154
|
high_quality_print: HIGH_QUALITY_PRINT,
|
155
|
-
}
|
155
|
+
}.freeze
|
156
156
|
|
157
157
|
# Maps a permission value to its symbol
|
158
158
|
PERMISSION_TO_SYMBOL = {
|
@@ -164,7 +164,7 @@ module HexaPDF
|
|
164
164
|
EXTRACT_CONTENT => :extract_content,
|
165
165
|
ASSEMBLE_DOCUMENT => :assemble_document,
|
166
166
|
HIGH_QUALITY_PRINT => :high_quality_print,
|
167
|
-
}
|
167
|
+
}.freeze
|
168
168
|
|
169
169
|
end
|
170
170
|
|
@@ -198,6 +198,7 @@ module HexaPDF
|
|
198
198
|
fallback_pwd = data.delete(:password) { '' }
|
199
199
|
@user_password = data.delete(:user_password) { fallback_pwd }
|
200
200
|
@owner_password = data.delete(:owner_password) { fallback_pwd }
|
201
|
+
@owner_password = @user_password if @owner_password.to_s.empty?
|
201
202
|
@permissions = process_permissions(data.delete(:permissions) { Permissions::ALL })
|
202
203
|
@algorithm = data.delete(:algorithm) { :arc4 }
|
203
204
|
@encrypt_metadata = data.delete(:encrypt_metadata) { true }
|
@@ -209,13 +210,15 @@ module HexaPDF
|
|
209
210
|
private
|
210
211
|
|
211
212
|
# Maps the permissions to an integer for use by the standard security handler.
|
213
|
+
#
|
214
|
+
# See: PDF1.7 s7.6.3.2, ADB1.7 3.5.2 (table 3.20 and the paragraphs before)
|
212
215
|
def process_permissions(perms)
|
213
216
|
if perms.kind_of?(Array)
|
214
217
|
perms = perms.inject(0) do |result, perm|
|
215
218
|
result | Permissions::SYMBOL_TO_PERMISSION.fetch(perm, 0)
|
216
219
|
end
|
217
220
|
end
|
218
|
-
Permissions::RESERVED | perms
|
221
|
+
((Permissions::RESERVED | perms) & 0xFFFFFFFC) - 2**32
|
219
222
|
end
|
220
223
|
|
221
224
|
end
|
@@ -224,7 +227,7 @@ module HexaPDF
|
|
224
227
|
#
|
225
228
|
# See: SecurityHandler#encryption_key_valid?
|
226
229
|
def encryption_key_valid?
|
227
|
-
super && trailer_id_hash == @trailer_id_hash
|
230
|
+
super && (document.trailer[:Encrypt][:R] > 4 || trailer_id_hash == @trailer_id_hash)
|
228
231
|
end
|
229
232
|
|
230
233
|
# Returns the permissions of the managed dictionary as array of symbol values.
|
@@ -269,7 +272,7 @@ module HexaPDF
|
|
269
272
|
Length: key_length,
|
270
273
|
},
|
271
274
|
}
|
272
|
-
dict[:StmF] = dict[:StrF] =
|
275
|
+
dict[:StmF] = dict[:StrF] = :StdCF
|
273
276
|
end
|
274
277
|
|
275
278
|
if dict[:R] <= 4 && !document.trailer[:ID].kind_of?(Array)
|
@@ -567,7 +570,7 @@ module HexaPDF
|
|
567
570
|
while i < 64 || e.getbyte(-1) > i - 32
|
568
571
|
k1 = "#{password}#{k}#{user_key}" * 64
|
569
572
|
e = aes_algorithm.new(k[0, 16], k[16, 16], :encrypt).process(k1)
|
570
|
-
k = case e.unpack('C16').inject(&:+) % 3
|
573
|
+
k = case e.unpack('C16').inject(&:+) % 3 # 256 % 3 == 1 % 3 --> x*256 % 3 == x % 3
|
571
574
|
when 0 then Digest::SHA256.digest(e)
|
572
575
|
when 1 then Digest::SHA384.digest(e)
|
573
576
|
when 2 then Digest::SHA512.digest(e)
|
@@ -50,7 +50,7 @@ module HexaPDF
|
|
50
50
|
#
|
51
51
|
# Note that the returned CMap always uses a 16-bit input code space!
|
52
52
|
def create_to_unicode_cmap(mapping)
|
53
|
-
return to_unicode_template % '' if mapping.
|
53
|
+
return to_unicode_template % '' if mapping.empty?
|
54
54
|
|
55
55
|
chars, ranges = compute_section_entries(mapping)
|
56
56
|
|
@@ -93,13 +93,11 @@ module HexaPDF
|
|
93
93
|
if last_code + 1 == code && last_value + 1 == value && code % 256 != 0
|
94
94
|
ranges << last_code << nil << last_value unless is_range
|
95
95
|
is_range = true
|
96
|
+
elsif is_range
|
97
|
+
ranges[-2] = last_code
|
98
|
+
is_range = false
|
96
99
|
else
|
97
|
-
|
98
|
-
ranges[-2] = last_code
|
99
|
-
is_range = false
|
100
|
-
else
|
101
|
-
chars << last_code << last_value
|
102
|
-
end
|
100
|
+
chars << last_code << last_value
|
103
101
|
end
|
104
102
|
last_code = code
|
105
103
|
last_value = value
|
@@ -37,7 +37,10 @@ module HexaPDF
|
|
37
37
|
# This module provides classes for handling TrueType fonts.
|
38
38
|
#
|
39
39
|
# Note that currently not all parts of the file format are supported, only those needed for
|
40
|
-
# using the fonts with PDF.
|
40
|
+
# using the fonts with PDF. This means that the implementation is not a *complete* font handling
|
41
|
+
# library but is designed to allow reading font files and extracting information. Furthermore
|
42
|
+
# creating a font subset is also possible which is not the same as writing a complete font file
|
43
|
+
# from scratch.
|
41
44
|
module TrueType
|
42
45
|
|
43
46
|
autoload(:Font, 'hexapdf/font/true_type/font')
|
@@ -65,18 +65,16 @@ module HexaPDF
|
|
65
65
|
}
|
66
66
|
|
67
67
|
|
68
|
-
# The IO stream associated with this file.
|
69
|
-
# originally read from an IO stream.
|
68
|
+
# The IO stream associated with this file.
|
70
69
|
attr_reader :io
|
71
70
|
|
72
71
|
# The configuration for the TrueType font.
|
73
72
|
attr_reader :config
|
74
73
|
|
75
|
-
# Creates a new TrueType font file object
|
76
|
-
# is read from it.
|
74
|
+
# Creates a new TrueType font file object for the given IO object.
|
77
75
|
#
|
78
76
|
# The +config+ hash can contain configuration options.
|
79
|
-
def initialize(io
|
77
|
+
def initialize(io, config: {})
|
80
78
|
@io = io
|
81
79
|
@config = DEFAULT_CONFIG.merge(config)
|
82
80
|
@tables = {}
|
@@ -90,12 +88,6 @@ module HexaPDF
|
|
90
88
|
entry ? @tables[tag] = table_class(tag).new(self, entry) : nil
|
91
89
|
end
|
92
90
|
|
93
|
-
# Adds a new table instance for the given tag (a symbol) to the font if such a table
|
94
|
-
# instance doesn't already exist. Returns the table instance for the tag.
|
95
|
-
def add_table(tag)
|
96
|
-
@tables[tag] ||= table_class(tag).new(self)
|
97
|
-
end
|
98
|
-
|
99
91
|
# Returns the font directory.
|
100
92
|
def directory
|
101
93
|
@directory ||= Table::Directory.new(self, io ? Table::Directory::SELF_ENTRY : nil)
|
@@ -118,7 +110,7 @@ module HexaPDF
|
|
118
110
|
|
119
111
|
# Returns the weight of the font.
|
120
112
|
def weight
|
121
|
-
self[:"OS/2"]
|
113
|
+
self[:"OS/2"].weight_class || 0
|
122
114
|
end
|
123
115
|
|
124
116
|
# Returns the bounding of the font.
|
@@ -128,22 +120,22 @@ module HexaPDF
|
|
128
120
|
|
129
121
|
# Returns the cap height of the font.
|
130
122
|
def cap_height
|
131
|
-
self[:"OS/2"]
|
123
|
+
self[:"OS/2"].cap_height
|
132
124
|
end
|
133
125
|
|
134
126
|
# Returns the x-height of the font.
|
135
127
|
def x_height
|
136
|
-
self[:"OS/2"]
|
128
|
+
self[:"OS/2"].x_height
|
137
129
|
end
|
138
130
|
|
139
131
|
# Returns the ascender of the font.
|
140
132
|
def ascender
|
141
|
-
self[:"OS/2"]
|
133
|
+
self[:"OS/2"].typo_ascender || self[:hhea].ascent
|
142
134
|
end
|
143
135
|
|
144
136
|
# Returns the descender of the font.
|
145
137
|
def descender
|
146
|
-
self[:"OS/2"]
|
138
|
+
self[:"OS/2"].typo_descender || self[:hhea].descent
|
147
139
|
end
|
148
140
|
|
149
141
|
# Returns the italic angle of the font, in degrees counter-clockwise from the vertical.
|
@@ -67,14 +67,14 @@ module HexaPDF
|
|
67
67
|
# The TrueType font object associated with this table.
|
68
68
|
attr_reader :font
|
69
69
|
|
70
|
-
# Creates a new Table object for the given font and initializes it by
|
71
|
-
# data from the font's associated IO stream
|
70
|
+
# Creates a new Table object for the given font and initializes it by reading the
|
71
|
+
# data from the font's associated IO stream
|
72
72
|
#
|
73
|
-
# See: #parse_table
|
74
|
-
def initialize(font, entry
|
73
|
+
# See: #parse_table
|
74
|
+
def initialize(font, entry)
|
75
75
|
@font = font
|
76
76
|
@directory_entry = entry
|
77
|
-
|
77
|
+
load_from_io
|
78
78
|
end
|
79
79
|
|
80
80
|
# Returns the directory entry for this table.
|
@@ -87,10 +87,6 @@ module HexaPDF
|
|
87
87
|
# Returns +true+ if the checksum stored in the directory entry of the table matches the
|
88
88
|
# tables data.
|
89
89
|
def checksum_valid?
|
90
|
-
unless directory_entry
|
91
|
-
raise HexaPDF::Error, "Can't verify the checksum, no directory entry available"
|
92
|
-
end
|
93
|
-
|
94
90
|
data = with_io_pos(directory_entry.offset) { io.read(directory_entry.length) }
|
95
91
|
directory_entry.checksum == self.class.calculate_checksum(data)
|
96
92
|
end
|
@@ -120,13 +116,6 @@ module HexaPDF
|
|
120
116
|
# noop for unsupported tables
|
121
117
|
end
|
122
118
|
|
123
|
-
# Uses default values to populate the table.
|
124
|
-
#
|
125
|
-
# This method must be implemented by subclasses.
|
126
|
-
def load_default
|
127
|
-
# noop for unsupported tables
|
128
|
-
end
|
129
|
-
|
130
119
|
# Sets the IO cursor to the given position while yielding to the block and returns the
|
131
120
|
# block's return value.
|
132
121
|
def with_io_pos(pos)
|