hexapdf 0.9.3 → 0.10.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/CONTRIBUTERS +2 -1
  4. data/VERSION +1 -1
  5. data/lib/hexapdf/cli/command.rb +9 -5
  6. data/lib/hexapdf/cli/images.rb +68 -13
  7. data/lib/hexapdf/cli/inspect.rb +201 -71
  8. data/lib/hexapdf/content/canvas.rb +1 -1
  9. data/lib/hexapdf/dictionary.rb +15 -1
  10. data/lib/hexapdf/dictionary_fields.rb +5 -4
  11. data/lib/hexapdf/document.rb +15 -6
  12. data/lib/hexapdf/encryption/security_handler.rb +3 -2
  13. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +165 -165
  14. data/lib/hexapdf/font/true_type_wrapper.rb +2 -2
  15. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  16. data/lib/hexapdf/image_loader/jpeg.rb +13 -11
  17. data/lib/hexapdf/reference.rb +5 -0
  18. data/lib/hexapdf/revision.rb +14 -0
  19. data/lib/hexapdf/serializer.rb +6 -6
  20. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  21. data/lib/hexapdf/type/image.rb +3 -1
  22. data/lib/hexapdf/version.rb +1 -1
  23. data/lib/hexapdf/xref_section.rb +8 -0
  24. data/man/man1/hexapdf.1 +88 -20
  25. data/test/data/images/truecolour-alpha-8bit.png +0 -0
  26. data/test/data/images/ycck.jpg +0 -0
  27. data/test/hexapdf/content/test_canvas.rb +2 -2
  28. data/test/hexapdf/document/test_images.rb +7 -5
  29. data/test/hexapdf/encryption/test_security_handler.rb +13 -0
  30. data/test/hexapdf/image_loader/test_jpeg.rb +10 -0
  31. data/test/hexapdf/image_loader/test_png.rb +3 -2
  32. data/test/hexapdf/test_dictionary.rb +9 -0
  33. data/test/hexapdf/test_dictionary_fields.rb +15 -0
  34. data/test/hexapdf/test_document.rb +5 -2
  35. data/test/hexapdf/test_reference.rb +4 -0
  36. data/test/hexapdf/test_revision.rb +12 -0
  37. data/test/hexapdf/test_writer.rb +5 -5
  38. data/test/hexapdf/test_xref_section.rb +11 -0
  39. data/test/hexapdf/type/test_form.rb +1 -1
  40. data/test/hexapdf/type/test_image.rb +28 -19
  41. metadata +3 -2
@@ -1253,7 +1253,7 @@ module HexaPDF
1253
1253
  # end
1254
1254
  #
1255
1255
  # image = document.object(5) # Object with oid=5 is an image XObject in this example
1256
- # canvas.xobject(image, at: [100, 200], width: 200, heigth: 300)
1256
+ # canvas.xobject(image, at: [100, 200], width: 200, height: 300)
1257
1257
  #
1258
1258
  # See: PDF1.7 s8.8, s.8.10.1
1259
1259
  def xobject(obj, at:, width: nil, height: nil)
@@ -284,7 +284,16 @@ module HexaPDF
284
284
 
285
285
  # Check the type of the field
286
286
  unless field.valid_object?(obj)
287
- yield("Type of field #{name} is invalid: #{obj.class}", false)
287
+ msg = "Type of field #{name} is invalid: #{obj.class}"
288
+ if field.type.include?(String) && obj.kind_of?(Symbol)
289
+ yield(msg, true)
290
+ self[name] = obj.to_s
291
+ elsif field.type.include?(Symbol) && obj.kind_of?(String)
292
+ yield(msg, true)
293
+ self[name] = obj.intern
294
+ else
295
+ yield(msg, false)
296
+ end
288
297
  end
289
298
 
290
299
  # Check if field value needs to be (in)direct
@@ -304,4 +313,9 @@ module HexaPDF
304
313
 
305
314
  end
306
315
 
316
+ # :nodoc:
317
+ # Forward declaration of Stream to circumvent circular require problem
318
+ class Stream < Dictionary
319
+ end
320
+
307
321
  end
@@ -118,8 +118,7 @@ module HexaPDF
118
118
  # Returns the array with valid types for this field.
119
119
  def type
120
120
  return @type if @type_mapped
121
- @type_mapped = true
122
- @type.concat(@converters.map(&:additional_types).compact.flatten)
121
+ @type.concat(@converters.flat_map(&:additional_types).compact)
123
122
  @type.map! do |type|
124
123
  if type.kind_of?(Symbol)
125
124
  HexaPDF::GlobalConfiguration.constantize('object.type_map', type)
@@ -128,6 +127,7 @@ module HexaPDF
128
127
  end
129
128
  end
130
129
  @type.uniq!
130
+ @type_mapped = true
131
131
  @type
132
132
  end
133
133
 
@@ -191,8 +191,9 @@ module HexaPDF
191
191
  # Wraps the given data value in the PDF specific type class if it can be converted. Otherwise
192
192
  # returns +nil+.
193
193
  def self.convert(data, type, document)
194
- return if data.kind_of?(type.first) || !(data.kind_of?(Hash) ||
195
- data.kind_of?(HexaPDF::Dictionary))
194
+ return if data.kind_of?(type.first) ||
195
+ !(data.kind_of?(Hash) || data.kind_of?(HexaPDF::Dictionary)) ||
196
+ (type.first <= HexaPDF::Stream && (data.kind_of?(Hash) || data.data.stream.nil?))
196
197
  document.wrap(data, type: type.first)
197
198
  end
198
199
 
@@ -277,17 +277,22 @@ module HexaPDF
277
277
  # needed.
278
278
  #
279
279
  # The class of the returned object is always a subclass of HexaPDF::Object (or of
280
- # HexaPDF::Stream if a +stream+ is given). Which subclass is used, depends on the values
281
- # of the +type+ and +subtype+ options as well as on the 'object.type_map' and
282
- # 'object.subtype_map' global configuration options:
280
+ # HexaPDF::Stream if a +stream+ is given). Which subclass is used, depends on the values of the
281
+ # +type+ and +subtype+ options as well as on the 'object.type_map' and 'object.subtype_map'
282
+ # global configuration options:
283
283
  #
284
- # * First +type+ is used to try to determine the class. If it is already a Class object, it is
285
- # used, otherwise the type is looked up in 'object.type_map'.
284
+ # * First +type+ is used to try to determine the class. If it is not provided and if +obj+ is a
285
+ # hash with a :Type field, the value of this field is used instead. If the resulting object is
286
+ # already a Class object, it is used, otherwise the type is looked up in 'object.type_map'.
286
287
  #
287
288
  # * If +subtype+ is provided or can be determined because +obj+ is a hash with a :Subtype or :S
288
289
  # field, the type and subtype together are used to look up a special subtype class in
289
290
  # 'object.subtype_map'.
290
291
  #
292
+ # Additionally, if there is no +type+ but a +subtype+, all required fields of the subtype
293
+ # class need to have values; otherwise the subtype class is not used. This is done to better
294
+ # prevent invalid mappings when only partial knowledge (:Type key is missing) is available.
295
+ #
291
296
  # * If there is no valid class after the above steps, HexaPDF::Stream is used if a stream is
292
297
  # given, HexaPDF::Dictionary if the given objecct is a hash or else HexaPDF::Object is used.
293
298
  #
@@ -330,7 +335,11 @@ module HexaPDF
330
335
  subtype ||= deref(data.value[:Subtype]) || deref(data.value[:S])
331
336
  end
332
337
  if subtype
333
- klass = GlobalConfiguration.constantize('object.subtype_map', type, subtype) { klass }
338
+ sub_klass = GlobalConfiguration.constantize('object.subtype_map', type, subtype) { klass }
339
+ if type ||
340
+ sub_klass&.each_field&.none? {|name, field| field.required? && !data.value.key?(name) }
341
+ klass = sub_klass
342
+ end
334
343
  end
335
344
 
336
345
  klass ||= if data.stream
@@ -257,7 +257,7 @@ module HexaPDF
257
257
 
258
258
  key = object_key(obj.oid, obj.gen, string_algorithm)
259
259
  each_string_in_object(obj.value) do |str|
260
- next if str.empty?
260
+ next if str.empty? || (obj.type == :Sig && obj[:Contents].equal?(str))
261
261
  str.replace(string_algorithm.decrypt(key, str))
262
262
  end
263
263
 
@@ -275,7 +275,8 @@ module HexaPDF
275
275
  #
276
276
  # See: PDF1.7 s7.6.2
277
277
  def encrypt_string(str, obj)
278
- return str if str.empty? || obj == document.trailer[:Encrypt] || obj.type == :XRef
278
+ return str if str.empty? || obj == document.trailer[:Encrypt] || obj.type == :XRef ||
279
+ (obj.type == :Sig && obj[:Contents].equal?(str))
279
280
 
280
281
  key = object_key(obj.oid, obj.gen, string_algorithm)
281
282
  string_algorithm.encrypt(key, str)
@@ -49,171 +49,171 @@ module HexaPDF
49
49
  super
50
50
  @encoding_name = :MacExpertEncoding
51
51
  @code_to_name = {
52
- 0276 => :AEsmall,
53
- 0207 => :Aacutesmall,
54
- 0211 => :Acircumflexsmall,
55
- 0047 => :Acutesmall,
56
- 0212 => :Adieresissmall,
57
- 0210 => :Agravesmall,
58
- 0214 => :Aringsmall,
59
- 0141 => :Asmall,
60
- 0213 => :Atildesmall,
61
- 0363 => :Brevesmall,
62
- 0142 => :Bsmall,
63
- 0256 => :Caronsmall,
64
- 0215 => :Ccedillasmall,
65
- 0311 => :Cedillasmall,
66
- 0136 => :Circumflexsmall,
67
- 0143 => :Csmall,
68
- 0254 => :Dieresissmall,
69
- 0372 => :Dotaccentsmall,
70
- 0144 => :Dsmall,
71
- 0216 => :Eacutesmall,
72
- 0220 => :Ecircumflexsmall,
73
- 0221 => :Edieresissmall,
74
- 0217 => :Egravesmall,
75
- 0145 => :Esmall,
76
- 0104 => :Ethsmall,
77
- 0146 => :Fsmall,
78
- 0140 => :Gravesmall,
79
- 0147 => :Gsmall,
80
- 0150 => :Hsmall,
81
- 0042 => :Hungarumlautsmall,
82
- 0222 => :Iacutesmall,
83
- 0224 => :Icircumflexsmall,
84
- 0225 => :Idieresissmall,
85
- 0223 => :Igravesmall,
86
- 0151 => :Ismall,
87
- 0152 => :Jsmall,
88
- 0153 => :Ksmall,
89
- 0302 => :Lslashsmall,
90
- 0154 => :Lsmall,
91
- 0364 => :Macronsmall,
92
- 0155 => :Msmall,
93
- 0156 => :Nsmall,
94
- 0226 => :Ntildesmall,
95
- 0317 => :OEsmall,
96
- 0227 => :Oacutesmall,
97
- 0231 => :Ocircumflexsmall,
98
- 0232 => :Odieresissmall,
99
- 0362 => :Ogoneksmall,
100
- 0230 => :Ogravesmall,
101
- 0277 => :Oslashsmall,
102
- 0157 => :Osmall,
103
- 0233 => :Otildesmall,
104
- 0160 => :Psmall,
105
- 0161 => :Qsmall,
106
- 0373 => :Ringsmall,
107
- 0162 => :Rsmall,
108
- 0247 => :Scaronsmall,
109
- 0163 => :Ssmall,
110
- 0271 => :Thornsmall,
111
- 0176 => :Tildesmall,
112
- 0164 => :Tsmall,
113
- 0234 => :Uacutesmall,
114
- 0236 => :Ucircumflexsmall,
115
- 0237 => :Udieresissmall,
116
- 0235 => :Ugravesmall,
117
- 0165 => :Usmall,
118
- 0166 => :Vsmall,
119
- 0167 => :Wsmall,
120
- 0170 => :Xsmall,
121
- 0264 => :Yacutesmall,
122
- 0330 => :Ydieresissmall,
123
- 0171 => :Ysmall,
124
- 0275 => :Zcaronsmall,
125
- 0172 => :Zsmall,
126
- 0046 => :ampersandsmall,
127
- 0201 => :asuperior,
128
- 0365 => :bsuperior,
129
- 0251 => :centinferior,
130
- 0043 => :centoldstyle,
131
- 0202 => :centsuperior,
132
- 0072 => :colon,
133
- 0173 => :colonmonetary,
134
- 0054 => :comma,
135
- 0262 => :commainferior,
136
- 0370 => :commasuperior,
137
- 0266 => :dollarinferior,
138
- 0044 => :dollaroldstyle,
139
- 0045 => :dollarsuperior,
140
- 0353 => :dsuperior,
141
- 0245 => :eightinferior,
142
- 0070 => :eightoldstyle,
143
- 0241 => :eightsuperior,
144
- 0344 => :esuperior,
145
- 0326 => :exclamdownsmall,
146
- 0041 => :exclamsmall,
147
- 0126 => :ff,
148
- 0131 => :ffi,
149
- 0132 => :ffl,
150
- 0127 => :fi,
151
- 0320 => :figuredash,
152
- 0114 => :fiveeighths,
153
- 0260 => :fiveinferior,
154
- 0065 => :fiveoldstyle,
155
- 0336 => :fivesuperior,
156
- 0130 => :fl,
157
- 0242 => :fourinferior,
158
- 0064 => :fouroldstyle,
159
- 0335 => :foursuperior,
160
- 0057 => :fraction,
161
- 0055 => :hyphen,
162
- 0137 => :hypheninferior,
163
- 0321 => :hyphensuperior,
164
- 0351 => :isuperior,
165
- 0361 => :lsuperior,
166
- 0367 => :msuperior,
167
- 0273 => :nineinferior,
168
- 0071 => :nineoldstyle,
169
- 0341 => :ninesuperior,
170
- 0366 => :nsuperior,
171
- 0053 => :onedotenleader,
172
- 0112 => :oneeighth,
173
- 0174 => :onefitted,
174
- 0110 => :onehalf,
175
- 0301 => :oneinferior,
176
- 0061 => :oneoldstyle,
177
- 0107 => :onequarter,
178
- 0332 => :onesuperior,
179
- 0116 => :onethird,
180
- 0257 => :osuperior,
181
- 0133 => :parenleftinferior,
182
- 0050 => :parenleftsuperior,
183
- 0135 => :parenrightinferior,
184
- 0051 => :parenrightsuperior,
185
- 0056 => :period,
186
- 0263 => :periodinferior,
187
- 0371 => :periodsuperior,
188
- 0300 => :questiondownsmall,
189
- 0077 => :questionsmall,
190
- 0345 => :rsuperior,
191
- 0175 => :rupiah,
192
- 0073 => :semicolon,
193
- 0115 => :seveneighths,
194
- 0246 => :seveninferior,
195
- 0067 => :sevenoldstyle,
196
- 0340 => :sevensuperior,
197
- 0244 => :sixinferior,
198
- 0066 => :sixoldstyle,
199
- 0337 => :sixsuperior,
200
- 0040 => :space,
201
- 0352 => :ssuperior,
202
- 0113 => :threeeighths,
203
- 0243 => :threeinferior,
204
- 0063 => :threeoldstyle,
205
- 0111 => :threequarters,
206
- 0075 => :threequartersemdash,
207
- 0334 => :threesuperior,
208
- 0346 => :tsuperior,
209
- 0052 => :twodotenleader,
210
- 0252 => :twoinferior,
211
- 0062 => :twooldstyle,
212
- 0333 => :twosuperior,
213
- 0117 => :twothirds,
214
- 0274 => :zeroinferior,
215
- 0060 => :zerooldstyle,
216
- 0342 => :zerosuperior,
52
+ 0276 => :AEsmall,
53
+ 0207 => :Aacutesmall,
54
+ 0211 => :Acircumflexsmall,
55
+ 0047 => :Acutesmall,
56
+ 0212 => :Adieresissmall,
57
+ 0210 => :Agravesmall,
58
+ 0214 => :Aringsmall,
59
+ 0141 => :Asmall,
60
+ 0213 => :Atildesmall,
61
+ 0363 => :Brevesmall,
62
+ 0142 => :Bsmall,
63
+ 0256 => :Caronsmall,
64
+ 0215 => :Ccedillasmall,
65
+ 0311 => :Cedillasmall,
66
+ 0136 => :Circumflexsmall,
67
+ 0143 => :Csmall,
68
+ 0254 => :Dieresissmall,
69
+ 0372 => :Dotaccentsmall,
70
+ 0144 => :Dsmall,
71
+ 0216 => :Eacutesmall,
72
+ 0220 => :Ecircumflexsmall,
73
+ 0221 => :Edieresissmall,
74
+ 0217 => :Egravesmall,
75
+ 0145 => :Esmall,
76
+ 0104 => :Ethsmall,
77
+ 0146 => :Fsmall,
78
+ 0140 => :Gravesmall,
79
+ 0147 => :Gsmall,
80
+ 0150 => :Hsmall,
81
+ 0042 => :Hungarumlautsmall,
82
+ 0222 => :Iacutesmall,
83
+ 0224 => :Icircumflexsmall,
84
+ 0225 => :Idieresissmall,
85
+ 0223 => :Igravesmall,
86
+ 0151 => :Ismall,
87
+ 0152 => :Jsmall,
88
+ 0153 => :Ksmall,
89
+ 0302 => :Lslashsmall,
90
+ 0154 => :Lsmall,
91
+ 0364 => :Macronsmall,
92
+ 0155 => :Msmall,
93
+ 0156 => :Nsmall,
94
+ 0226 => :Ntildesmall,
95
+ 0317 => :OEsmall,
96
+ 0227 => :Oacutesmall,
97
+ 0231 => :Ocircumflexsmall,
98
+ 0232 => :Odieresissmall,
99
+ 0362 => :Ogoneksmall,
100
+ 0230 => :Ogravesmall,
101
+ 0277 => :Oslashsmall,
102
+ 0157 => :Osmall,
103
+ 0233 => :Otildesmall,
104
+ 0160 => :Psmall,
105
+ 0161 => :Qsmall,
106
+ 0373 => :Ringsmall,
107
+ 0162 => :Rsmall,
108
+ 0247 => :Scaronsmall,
109
+ 0163 => :Ssmall,
110
+ 0271 => :Thornsmall,
111
+ 0176 => :Tildesmall,
112
+ 0164 => :Tsmall,
113
+ 0234 => :Uacutesmall,
114
+ 0236 => :Ucircumflexsmall,
115
+ 0237 => :Udieresissmall,
116
+ 0235 => :Ugravesmall,
117
+ 0165 => :Usmall,
118
+ 0166 => :Vsmall,
119
+ 0167 => :Wsmall,
120
+ 0170 => :Xsmall,
121
+ 0264 => :Yacutesmall,
122
+ 0330 => :Ydieresissmall,
123
+ 0171 => :Ysmall,
124
+ 0275 => :Zcaronsmall,
125
+ 0172 => :Zsmall,
126
+ 0046 => :ampersandsmall,
127
+ 0201 => :asuperior,
128
+ 0365 => :bsuperior,
129
+ 0251 => :centinferior,
130
+ 0043 => :centoldstyle,
131
+ 0202 => :centsuperior,
132
+ 0072 => :colon,
133
+ 0173 => :colonmonetary,
134
+ 0054 => :comma,
135
+ 0262 => :commainferior,
136
+ 0370 => :commasuperior,
137
+ 0266 => :dollarinferior,
138
+ 0044 => :dollaroldstyle,
139
+ 0045 => :dollarsuperior,
140
+ 0353 => :dsuperior,
141
+ 0245 => :eightinferior,
142
+ 0070 => :eightoldstyle,
143
+ 0241 => :eightsuperior,
144
+ 0344 => :esuperior,
145
+ 0326 => :exclamdownsmall,
146
+ 0041 => :exclamsmall,
147
+ 0126 => :ff,
148
+ 0131 => :ffi,
149
+ 0132 => :ffl,
150
+ 0127 => :fi,
151
+ 0320 => :figuredash,
152
+ 0114 => :fiveeighths,
153
+ 0260 => :fiveinferior,
154
+ 0065 => :fiveoldstyle,
155
+ 0336 => :fivesuperior,
156
+ 0130 => :fl,
157
+ 0242 => :fourinferior,
158
+ 0064 => :fouroldstyle,
159
+ 0335 => :foursuperior,
160
+ 0057 => :fraction,
161
+ 0055 => :hyphen,
162
+ 0137 => :hypheninferior,
163
+ 0321 => :hyphensuperior,
164
+ 0351 => :isuperior,
165
+ 0361 => :lsuperior,
166
+ 0367 => :msuperior,
167
+ 0273 => :nineinferior,
168
+ 0071 => :nineoldstyle,
169
+ 0341 => :ninesuperior,
170
+ 0366 => :nsuperior,
171
+ 0053 => :onedotenleader,
172
+ 0112 => :oneeighth,
173
+ 0174 => :onefitted,
174
+ 0110 => :onehalf,
175
+ 0301 => :oneinferior,
176
+ 0061 => :oneoldstyle,
177
+ 0107 => :onequarter,
178
+ 0332 => :onesuperior,
179
+ 0116 => :onethird,
180
+ 0257 => :osuperior,
181
+ 0133 => :parenleftinferior,
182
+ 0050 => :parenleftsuperior,
183
+ 0135 => :parenrightinferior,
184
+ 0051 => :parenrightsuperior,
185
+ 0056 => :period,
186
+ 0263 => :periodinferior,
187
+ 0371 => :periodsuperior,
188
+ 0300 => :questiondownsmall,
189
+ 0077 => :questionsmall,
190
+ 0345 => :rsuperior,
191
+ 0175 => :rupiah,
192
+ 0073 => :semicolon,
193
+ 0115 => :seveneighths,
194
+ 0246 => :seveninferior,
195
+ 0067 => :sevenoldstyle,
196
+ 0340 => :sevensuperior,
197
+ 0244 => :sixinferior,
198
+ 0066 => :sixoldstyle,
199
+ 0337 => :sixsuperior,
200
+ 0040 => :space,
201
+ 0352 => :ssuperior,
202
+ 0113 => :threeeighths,
203
+ 0243 => :threeinferior,
204
+ 0063 => :threeoldstyle,
205
+ 0111 => :threequarters,
206
+ 0075 => :threequartersemdash,
207
+ 0334 => :threesuperior,
208
+ 0346 => :tsuperior,
209
+ 0052 => :twodotenleader,
210
+ 0252 => :twoinferior,
211
+ 0062 => :twooldstyle,
212
+ 0333 => :twosuperior,
213
+ 0117 => :twothirds,
214
+ 0274 => :zeroinferior,
215
+ 0060 => :zerooldstyle,
216
+ 0342 => :zerosuperior,
217
217
  }
218
218
  end
219
219