hexapdf 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -0
  3. data/CONTRIBUTERS +1 -1
  4. data/Rakefile +3 -3
  5. data/VERSION +1 -1
  6. data/examples/arc.rb +1 -1
  7. data/examples/graphics.rb +1 -1
  8. data/examples/hello_world.rb +1 -1
  9. data/examples/merging.rb +1 -1
  10. data/examples/show_char_bboxes.rb +1 -1
  11. data/examples/standard_pdf_fonts.rb +1 -1
  12. data/examples/truetype.rb +1 -1
  13. data/lib/hexapdf/cli.rb +14 -7
  14. data/lib/hexapdf/cli/extract.rb +1 -1
  15. data/lib/hexapdf/cli/info.rb +2 -2
  16. data/lib/hexapdf/cli/inspect.rb +4 -4
  17. data/lib/hexapdf/cli/modify.rb +151 -51
  18. data/lib/hexapdf/configuration.rb +1 -1
  19. data/lib/hexapdf/content/canvas.rb +1 -1
  20. data/lib/hexapdf/content/processor.rb +1 -1
  21. data/lib/hexapdf/dictionary.rb +6 -19
  22. data/lib/hexapdf/dictionary_fields.rb +1 -1
  23. data/lib/hexapdf/document.rb +23 -16
  24. data/lib/hexapdf/document/files.rb +130 -0
  25. data/lib/hexapdf/{font_utils.rb → document/fonts.rb} +40 -38
  26. data/lib/hexapdf/document/images.rb +117 -0
  27. data/lib/hexapdf/document/pages.rb +125 -0
  28. data/lib/hexapdf/encryption/aes.rb +1 -1
  29. data/lib/hexapdf/encryption/ruby_aes.rb +10 -10
  30. data/lib/hexapdf/encryption/standard_security_handler.rb +11 -8
  31. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  32. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -6
  33. data/lib/hexapdf/font/cmap/writer.rb +5 -7
  34. data/lib/hexapdf/font/true_type.rb +4 -1
  35. data/lib/hexapdf/font/true_type/font.rb +8 -16
  36. data/lib/hexapdf/font/true_type/table.rb +5 -16
  37. data/lib/hexapdf/font/true_type/table/cmap.rb +2 -7
  38. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +2 -6
  39. data/lib/hexapdf/font/true_type/table/directory.rb +0 -5
  40. data/lib/hexapdf/font/true_type/table/glyf.rb +3 -11
  41. data/lib/hexapdf/font/true_type/table/head.rb +0 -12
  42. data/lib/hexapdf/font/true_type/table/hhea.rb +0 -7
  43. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -5
  44. data/lib/hexapdf/font/true_type/table/loca.rb +0 -4
  45. data/lib/hexapdf/font/true_type/table/maxp.rb +0 -8
  46. data/lib/hexapdf/font/true_type/table/name.rb +3 -17
  47. data/lib/hexapdf/font/true_type/table/os2.rb +0 -14
  48. data/lib/hexapdf/font/true_type/table/post.rb +0 -8
  49. data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
  50. data/lib/hexapdf/font/type1.rb +2 -2
  51. data/lib/hexapdf/font/type1/font.rb +2 -1
  52. data/lib/hexapdf/font/type1/font_metrics.rb +10 -1
  53. data/lib/hexapdf/font/type1_wrapper.rb +2 -1
  54. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  55. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  56. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  57. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  58. data/lib/hexapdf/image_loader/png.rb +2 -2
  59. data/lib/hexapdf/object.rb +18 -5
  60. data/lib/hexapdf/rectangle.rb +8 -1
  61. data/lib/hexapdf/revisions.rb +4 -2
  62. data/lib/hexapdf/serializer.rb +3 -3
  63. data/lib/hexapdf/stream.rb +3 -2
  64. data/lib/hexapdf/task/dereference.rb +4 -5
  65. data/lib/hexapdf/task/optimize.rb +6 -3
  66. data/lib/hexapdf/tokenizer.rb +3 -3
  67. data/lib/hexapdf/type/file_specification.rb +2 -2
  68. data/lib/hexapdf/type/form.rb +19 -0
  69. data/lib/hexapdf/type/page.rb +21 -6
  70. data/lib/hexapdf/type/page_tree_node.rb +27 -34
  71. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  72. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  73. data/lib/hexapdf/version.rb +1 -1
  74. data/man/man1/hexapdf.1 +259 -187
  75. data/test/hexapdf/content/graphic_object/test_arc.rb +1 -1
  76. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +1 -1
  77. data/test/hexapdf/content/graphic_object/test_solid_arc.rb +1 -1
  78. data/test/hexapdf/content/test_canvas.rb +1 -1
  79. data/test/hexapdf/document/test_files.rb +71 -0
  80. data/test/hexapdf/{test_font_utils.rb → document/test_fonts.rb} +1 -2
  81. data/test/hexapdf/document/test_images.rb +78 -0
  82. data/test/hexapdf/document/test_pages.rb +114 -0
  83. data/test/hexapdf/encryption/test_standard_security_handler.rb +26 -5
  84. data/test/hexapdf/font/test_true_type_wrapper.rb +1 -1
  85. data/test/hexapdf/font/true_type/common.rb +0 -4
  86. data/test/hexapdf/font/true_type/table/test_cmap.rb +0 -6
  87. data/test/hexapdf/font/true_type/table/test_directory.rb +0 -5
  88. data/test/hexapdf/font/true_type/table/test_glyf.rb +5 -8
  89. data/test/hexapdf/font/true_type/table/test_head.rb +0 -20
  90. data/test/hexapdf/font/true_type/table/test_hhea.rb +0 -7
  91. data/test/hexapdf/font/true_type/table/test_hmtx.rb +2 -7
  92. data/test/hexapdf/font/true_type/table/test_loca.rb +4 -8
  93. data/test/hexapdf/font/true_type/table/test_maxp.rb +0 -7
  94. data/test/hexapdf/font/true_type/table/test_name.rb +0 -19
  95. data/test/hexapdf/font/true_type/table/test_os2.rb +0 -8
  96. data/test/hexapdf/font/true_type/table/test_post.rb +0 -13
  97. data/test/hexapdf/font/true_type/test_font.rb +14 -38
  98. data/test/hexapdf/font/true_type/test_table.rb +0 -9
  99. data/test/hexapdf/font/type1/test_font_metrics.rb +22 -0
  100. data/test/hexapdf/task/test_dereference.rb +5 -1
  101. data/test/hexapdf/task/test_optimize.rb +1 -1
  102. data/test/hexapdf/test_dictionary.rb +4 -0
  103. data/test/hexapdf/test_document.rb +0 -7
  104. data/test/hexapdf/test_importer.rb +4 -4
  105. data/test/hexapdf/test_object.rb +31 -9
  106. data/test/hexapdf/test_rectangle.rb +18 -0
  107. data/test/hexapdf/test_revisions.rb +7 -0
  108. data/test/hexapdf/test_serializer.rb +6 -0
  109. data/test/hexapdf/test_writer.rb +2 -2
  110. data/test/hexapdf/type/test_form.rb +12 -0
  111. data/test/hexapdf/type/test_page.rb +39 -20
  112. data/test/hexapdf/type/test_page_tree_node.rb +28 -21
  113. metadata +21 -9
  114. data/lib/hexapdf/document_utils.rb +0 -209
  115. 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
@@ -59,7 +59,7 @@ module HexaPDF
59
59
  module AES
60
60
 
61
61
  # Valid AES key lengths
62
- VALID_KEY_LENGTH = [16, 24, 32]
62
+ VALID_KEY_LENGTH = [16, 24, 32].freeze
63
63
 
64
64
  # The AES block size
65
65
  BLOCK_SIZE = 16
@@ -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 == 32 ||
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] = dict[:EFF] = :StdCF
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 # 256 % 3 == 1 % 3 --> x*256 % 3 == x % 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)
@@ -55,7 +55,7 @@ module HexaPDF
55
55
  POW85_3 = 85**3 #:nodoc:
56
56
  POW85_4 = 85**4 #:nodoc:
57
57
 
58
- MAX_VALUE = 0xffffffff #:nodoc:
58
+ MAX_VALUE = 0xffffffff #:nodoc:
59
59
  FIXED_SUBTRAHEND = 33 * (POW85_4 + POW85_3 + POW85_2 + POW85_1 + 1) #:nodoc:
60
60
 
61
61
  # See HexaPDF::Filter
@@ -58,12 +58,7 @@ module HexaPDF
58
58
  end
59
59
 
60
60
  data = rest << data if rest
61
-
62
- if data.size.odd?
63
- rest = data.slice!(-1, 1)
64
- else
65
- rest = nil
66
- end
61
+ rest = (data.size.odd? ? data.slice!(-1, 1) : nil)
67
62
 
68
63
  Fiber.yield([data].pack('H*'))
69
64
  end
@@ -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.length == 0
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
- if is_range
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. If this is +nil+ then the TrueType font wasn't
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. If an IO object is given, the TrueType font data
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: nil, config: {})
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"]&.weight_class || 0
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"]&.cap_height
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"]&.x_height
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"]&.typo_ascender || self[:hhea].ascent
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"]&.typo_descender || self[:hhea].descent
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 either reading the
71
- # data from the font's associated IO stream if +entry+ is given or by using default values.
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, #load_default
74
- def initialize(font, entry = nil)
73
+ # See: #parse_table
74
+ def initialize(font, entry)
75
75
  @font = font
76
76
  @directory_entry = entry
77
- entry ? load_from_io : load_default
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)