hexapdf 0.1.0 → 0.2.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 +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)
|