pdfrb 0.8.3 → 0.8.5

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pdfrb/annotation/base.rb +2 -2
  3. data/lib/pdfrb/appearance/generator.rb +1 -1
  4. data/lib/pdfrb/cli/images.rb +1 -1
  5. data/lib/pdfrb/cli.rb +3 -3
  6. data/lib/pdfrb/color/default_profile.rb +1 -1
  7. data/lib/pdfrb/conformance/ltv.rb +1 -1
  8. data/lib/pdfrb/conformance/pades.rb +4 -4
  9. data/lib/pdfrb/conformance/pdf_2_af.rb +2 -2
  10. data/lib/pdfrb/conformance/pdf_a.rb +1 -1
  11. data/lib/pdfrb/conformance/pdf_x.rb +3 -3
  12. data/lib/pdfrb/conformance/tagged_pdf.rb +1 -1
  13. data/lib/pdfrb/content/canvas.rb +1 -1
  14. data/lib/pdfrb/content/hidden_text_detector.rb +1 -1
  15. data/lib/pdfrb/content/shading/base.rb +1 -1
  16. data/lib/pdfrb/content/tiling_pattern.rb +1 -1
  17. data/lib/pdfrb/digital_signature/signing.rb +2 -2
  18. data/lib/pdfrb/document/annotations.rb +10 -10
  19. data/lib/pdfrb/document/associated_files.rb +2 -2
  20. data/lib/pdfrb/document/colors.rb +1 -1
  21. data/lib/pdfrb/document/destinations.rb +4 -4
  22. data/lib/pdfrb/document/encryption.rb +1 -1
  23. data/lib/pdfrb/document/files.rb +5 -5
  24. data/lib/pdfrb/document/fonts/subsetting.rb +87 -0
  25. data/lib/pdfrb/document/fonts.rb +10 -80
  26. data/lib/pdfrb/document/form.rb +9 -9
  27. data/lib/pdfrb/document/form_xobject.rb +1 -1
  28. data/lib/pdfrb/document/graphics_state.rb +1 -1
  29. data/lib/pdfrb/document/images.rb +1 -6
  30. data/lib/pdfrb/document/info.rb +1 -1
  31. data/lib/pdfrb/document/layers.rb +1 -1
  32. data/lib/pdfrb/document/metadata.rb +1 -1
  33. data/lib/pdfrb/document/outline.rb +8 -8
  34. data/lib/pdfrb/document/output_intents.rb +3 -3
  35. data/lib/pdfrb/document/pages.rb +19 -8
  36. data/lib/pdfrb/document/pdf_a.rb +1 -1
  37. data/lib/pdfrb/document/portfolio.rb +3 -3
  38. data/lib/pdfrb/document/shadings.rb +2 -9
  39. data/lib/pdfrb/document/stamps.rb +2 -2
  40. data/lib/pdfrb/document/structure.rb +9 -9
  41. data/lib/pdfrb/document.rb +10 -3
  42. data/lib/pdfrb/encryption/security_handler.rb +1 -2
  43. data/lib/pdfrb/font/cff/subsetter.rb +0 -0
  44. data/lib/pdfrb/font/sfnt.rb +73 -0
  45. data/lib/pdfrb/font/true_type/subsetter.rb +1 -57
  46. data/lib/pdfrb/font/true_type/wrapper.rb +3 -3
  47. data/lib/pdfrb/font.rb +1 -0
  48. data/lib/pdfrb/font_loader/true_type.rb +2 -2
  49. data/lib/pdfrb/font_loader/type3.rb +1 -1
  50. data/lib/pdfrb/importer.rb +3 -3
  51. data/lib/pdfrb/linearization/writer.rb +1 -1
  52. data/lib/pdfrb/model/object.rb +7 -0
  53. data/lib/pdfrb/model/type/action_hide.rb +1 -1
  54. data/lib/pdfrb/model/type/action_sound.rb +2 -2
  55. data/lib/pdfrb/model/type/add_action_catalog.rb +1 -1
  56. data/lib/pdfrb/model/type/add_action_form_field.rb +1 -1
  57. data/lib/pdfrb/model/type/add_action_page_object.rb +1 -1
  58. data/lib/pdfrb/model/type/add_action_screen_annotation.rb +1 -1
  59. data/lib/pdfrb/model/type/add_action_widget_annotation.rb +1 -1
  60. data/lib/pdfrb/model/type/alternate_image.rb +2 -2
  61. data/lib/pdfrb/model/type/bead.rb +4 -4
  62. data/lib/pdfrb/model/type/catalog.rb +1 -1
  63. data/lib/pdfrb/model/type/color_space.rb +5 -31
  64. data/lib/pdfrb/model/type/crypt_filter.rb +6 -6
  65. data/lib/pdfrb/model/type/d_part.rb +4 -4
  66. data/lib/pdfrb/model/type/destination.rb +2 -18
  67. data/lib/pdfrb/model/type/document_security_store.rb +1 -1
  68. data/lib/pdfrb/model/type/dss.rb +1 -1
  69. data/lib/pdfrb/model/type/font_multiple_master.rb +3 -12
  70. data/lib/pdfrb/model/type/function_stitching.rb +1 -1
  71. data/lib/pdfrb/model/type/generic_appearance.rb +1 -1
  72. data/lib/pdfrb/model/type/misc_extras.rb +2 -7
  73. data/lib/pdfrb/model/type/name_map.rb +33 -0
  74. data/lib/pdfrb/model/type/opt_content_ext.rb +2 -2
  75. data/lib/pdfrb/model/type/optional_content_membership.rb +2 -2
  76. data/lib/pdfrb/model/type/page.rb +5 -7
  77. data/lib/pdfrb/model/type/page_tree_node.rb +2 -2
  78. data/lib/pdfrb/model/type/pattern.rb +2 -18
  79. data/lib/pdfrb/model/type/rich_media_configuration.rb +1 -1
  80. data/lib/pdfrb/model/type/shading.rb +2 -18
  81. data/lib/pdfrb/model/type/signature_extras.rb +6 -21
  82. data/lib/pdfrb/model/type/soft_mask.rb +1 -13
  83. data/lib/pdfrb/model/type/struct_elem.rb +2 -2
  84. data/lib/pdfrb/model/type/struct_tree_root.rb +2 -2
  85. data/lib/pdfrb/model/type/structure_attributes.rb +5 -18
  86. data/lib/pdfrb/model/type/thread.rb +3 -3
  87. data/lib/pdfrb/model/type/three_d_stream.rb +1 -1
  88. data/lib/pdfrb/model/type/viewport.rb +1 -1
  89. data/lib/pdfrb/model/type/vri.rb +1 -1
  90. data/lib/pdfrb/model/type/web_capture_command.rb +1 -1
  91. data/lib/pdfrb/model/type/web_capture_image_set.rb +1 -1
  92. data/lib/pdfrb/model/type/web_capture_page_set.rb +2 -2
  93. data/lib/pdfrb/model/type/xobject_form.rb +1 -13
  94. data/lib/pdfrb/model/type.rb +2 -0
  95. data/lib/pdfrb/task/extract_images.rb +1 -2
  96. data/lib/pdfrb/task/extract_text.rb +1 -1
  97. data/lib/pdfrb/task/merge.rb +3 -3
  98. data/lib/pdfrb/task/thumbnail.rb +1 -1
  99. data/lib/pdfrb/version.rb +1 -1
  100. data/lib/pdfrb/writer.rb +4 -5
  101. data/lib/pdfrb/xmp.rb +2 -2
  102. metadata +5 -2
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Font
5
+ # sfnt container (OpenType/TTF) table directory: the shared seam
6
+ # for reading and rebuilding the wrapper around font outlines.
7
+ # Both subsetters (TrueType glyf and CFF) rebuild the directory
8
+ # around their subset tables; this module owns that format so
9
+ # the two implementations cannot drift (they once disagreed even
10
+ # on whether checksums are computed).
11
+ module Sfnt
12
+ Entry = Struct.new(:tag, :offset, :byte_length)
13
+
14
+ module_function
15
+
16
+ # Parse the table directory of an sfnt byte string.
17
+ # Returns [sfnt_version, Array<Entry>].
18
+ def parse_directory(sfnt)
19
+ num_tables = (sfnt.getbyte(4) * 256) + sfnt.getbyte(5)
20
+ version = sfnt.byteslice(0, 4)
21
+ entries = (0...num_tables).map do |i|
22
+ base = 12 + (i * 16)
23
+ Entry.new(
24
+ sfnt.byteslice(base, 4),
25
+ sfnt.byteslice(base + 8, 4).unpack1("N"),
26
+ sfnt.byteslice(base + 12, 4).unpack1("N")
27
+ )
28
+ end
29
+ [version, entries]
30
+ end
31
+
32
+ # Raw bytes of +tag+'s table, or nil.
33
+ def table_bytes(sfnt, tag)
34
+ entry = parse_directory(sfnt)[1].find { |e| e.tag == tag }
35
+ entry && sfnt.byteslice(entry.offset, entry.byte_length)
36
+ end
37
+
38
+ # Rebuild an sfnt wrapper: +sfnt_version+ is the 4-byte magic
39
+ # (e.g. "\x00\x01\x00\x00" or "OTTO"), +tables+ an Array of
40
+ # [tag, data] pairs. Checksums are computed per the sfnt spec
41
+ # (sum of big-endian u32s over zero-padded data).
42
+ def rebuild(sfnt_version, tables)
43
+ num = tables.length
44
+ search_range = (2**Math.log2(num).floor) * 16
45
+ entry_selector = Math.log2(num).floor
46
+ range_shift = (num * 16) - search_range
47
+
48
+ out = +"".b
49
+ out << sfnt_version.b
50
+ out << [num, search_range, entry_selector, range_shift].pack("n4")
51
+
52
+ sorted = tables.sort_by { |tag, _| tag }
53
+ offset = 12 + (num * 16)
54
+ sorted.each do |tag, data|
55
+ out << tag.b << [checksum(data), offset, data.bytesize].pack("NNN")
56
+ offset += (data.bytesize + 3) & ~3
57
+ end
58
+ sorted.to_h.each_value do |data|
59
+ out << data.b
60
+ out << ("\x00".b * ((4 - (out.bytesize % 4)) % 4))
61
+ end
62
+ out
63
+ end
64
+
65
+ def checksum(data)
66
+ padded = data + ("\x00".b * ((4 - (data.bytesize % 4)) % 4))
67
+ sum = 0
68
+ padded.unpack("N*").each { |w| sum = (sum + w) & 0xFFFFFFFF }
69
+ sum
70
+ end
71
+ end
72
+ end
73
+ end
@@ -310,58 +310,7 @@ module Pdfrb
310
310
 
311
311
  # rubocop:disable-next Metrics/MethodLength
312
312
  def assemble_ttf(tables)
313
- checksum_placeholder = [0].pack("N")
314
- num = tables.length
315
- search_range = power_of_2_floor(num) * 16
316
- entry_selector = Math.log2(search_range / 16).to_i
317
- range_shift = (num * 16) - search_range
318
-
319
- header_size = 12
320
- dir_size = num * 16
321
- data_offset = header_size + dir_size
322
-
323
- # Pad data_offset to 4 bytes
324
- data_offset = (data_offset + 3) & ~3
325
-
326
- out = +""
327
- out << SFNT_VERSION.pack("N") # sfnt version
328
- out << [num].pack("n")
329
- out << [search_range].pack("n")
330
- out << [entry_selector].pack("n")
331
- out << [range_shift].pack("n")
332
-
333
- # Sort tables by tag
334
- sorted = tables.sort_by { |tag, _| tag }
335
-
336
- # Calculate offsets
337
- current = data_offset
338
- offsets = {}
339
- sorted.each do |tag, data|
340
- offsets[tag] = current
341
- current += data.bytesize
342
- current = (current + 3) & ~3
343
-
344
- # Directory
345
- out << tag.to_s
346
- out << checksum_placeholder # checksum (skip)
347
- out << [offsets[tag]].pack("N")
348
- out << [data.bytesize].pack("N")
349
- end
350
-
351
- # Pad to data_offset
352
- while out.bytesize < data_offset
353
- out << "\x00"
354
- end
355
-
356
- # Table data
357
- sorted.each_value do |data|
358
- out << data
359
- while (out.bytesize % 4).nonzero?
360
- out << "\x00"
361
- end
362
- end
363
-
364
- out.force_encoding(::Encoding::BINARY)
313
+ Pdfrb::Font::Sfnt.rebuild(SFNT_VERSION.pack("N"), tables)
365
314
  end
366
315
 
367
316
  # rubocop:disable Naming/MethodName
@@ -382,11 +331,6 @@ module Pdfrb
382
331
  def pad_to_even(str); str << "\x00" if (str.bytesize % 2).nonzero?; end
383
332
 
384
333
  # rubocop:enable Naming/MethodName
385
- def power_of_2_floor(n)
386
- p = 1
387
- while p * 2 <= n; p *= 2; end
388
- p
389
- end
390
334
  end
391
335
  end
392
336
  end
@@ -16,7 +16,7 @@ module Pdfrb
16
16
  tu_stream = build_tounicode(document, ttf)
17
17
  font_file = embed_font_file(document, ttf_data)
18
18
 
19
- fd.value[:FontFile2] = Pdfrb::Model::Reference.new(font_file.oid, font_file.gen)
19
+ fd.value[:FontFile2] = font_file.ref
20
20
 
21
21
  document.add(
22
22
  {
@@ -26,8 +26,8 @@ module Pdfrb
26
26
  FirstChar: 0,
27
27
  LastChar: 255,
28
28
  Widths: widths,
29
- FontDescriptor: Pdfrb::Model::Reference.new(fd.oid, fd.gen),
30
- ToUnicode: Pdfrb::Model::Reference.new(tu_stream.oid, tu_stream.gen),
29
+ FontDescriptor: fd.ref,
30
+ ToUnicode: tu_stream.ref,
31
31
  Encoding: :WinAnsiEncoding,
32
32
  },
33
33
  type: Pdfrb::Model::Type::FontTrueType
data/lib/pdfrb/font.rb CHANGED
@@ -10,6 +10,7 @@ module Pdfrb
10
10
  autoload :CMap, "pdfrb/font/cmap"
11
11
  autoload :TrueType, "pdfrb/font/true_type"
12
12
  autoload :CFF, "pdfrb/font/cff"
13
+ autoload :Sfnt, "pdfrb/font/sfnt"
13
14
  autoload :Type1, "pdfrb/font/type1"
14
15
  autoload :Metrics, "pdfrb/font/metrics_helper"
15
16
  autoload :MetricsHelper, "pdfrb/font/metrics_helper"
@@ -45,12 +45,12 @@ module Pdfrb
45
45
  Descent: -200,
46
46
  CapHeight: 700,
47
47
  StemV: 80,
48
- FontFile2: Pdfrb::Model::Reference.new(font_stream.oid, 0)
48
+ FontFile2: font_stream.ref
49
49
  },
50
50
  type: Pdfrb::Model::Type::FontDescriptor
51
51
  )
52
52
  font_dict.value[:FontDescriptor] =
53
- Pdfrb::Model::Reference.new(descriptor.oid, 0)
53
+ descriptor.ref
54
54
  end
55
55
 
56
56
  font_dict
@@ -40,7 +40,7 @@ module Pdfrb
40
40
  stream = document.add({ Length: glyph.procedure.bytesize },
41
41
  type: Pdfrb::Model::Cos::Stream)
42
42
  stream.stream = glyph.procedure
43
- char_procs[glyph.name.to_sym] = Pdfrb::Model::Reference.new(stream.oid, stream.gen)
43
+ char_procs[glyph.name.to_sym] = stream.ref
44
44
  widths[code] = glyph.width
45
45
  encoding[:Differences] << code << glyph.name.to_sym
46
46
  end
@@ -38,10 +38,10 @@ module Pdfrb
38
38
 
39
39
  def import_reference(ref, source_doc)
40
40
  cached = @mappings[ref.oid]
41
- return Pdfrb::Model::Reference.new(cached.oid, cached.gen) if cached
41
+ return cached.ref if cached
42
42
 
43
43
  in_progress = @in_progress[ref.oid]
44
- return Pdfrb::Model::Reference.new(in_progress.oid, in_progress.gen) if in_progress
44
+ return in_progress.ref if in_progress
45
45
 
46
46
  source_obj = source_doc.object(ref)
47
47
  return nil unless source_obj
@@ -58,7 +58,7 @@ module Pdfrb
58
58
  end
59
59
  @mappings[ref.oid] = stub
60
60
  @in_progress.delete(ref.oid)
61
- Pdfrb::Model::Reference.new(stub.oid, stub.gen)
61
+ stub.ref
62
62
  end
63
63
 
64
64
  def import_hash(hash, source_doc)
@@ -239,7 +239,7 @@ module Pdfrb
239
239
  def build_trailer(xref_offset)
240
240
  root = @document.catalog
241
241
  root_ref = if root.is_a?(Pdfrb::Model::Object) && root.indirect?
242
- Pdfrb::Model::Reference.new(root.oid, root.gen)
242
+ root.ref
243
243
  end
244
244
  size = [@document.next_oid || 1, 2].max
245
245
 
@@ -27,6 +27,13 @@ module Pdfrb
27
27
  @document = document
28
28
  end
29
29
 
30
+ # The indirect reference denoting this object. The single
31
+ # seam for "a reference to this" — callers never construct
32
+ # Reference.new(obj.oid, obj.gen) by hand.
33
+ def ref
34
+ Pdfrb::Model::Reference.new(oid, gen)
35
+ end
36
+
30
37
  # True when this object is referenced indirectly (oid > 0).
31
38
  def indirect?
32
39
  @oid > 0
@@ -17,7 +17,7 @@ module Pdfrb
17
17
 
18
18
  arr = targets.is_a?(Array) ? targets : [targets]
19
19
  arr.each do |ref|
20
- obj = ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
20
+ obj = document.resolve(ref)
21
21
  yield obj if obj
22
22
  end
23
23
  end
@@ -23,7 +23,7 @@ module Pdfrb
23
23
  ref = value[:Sound]
24
24
  return nil unless ref && document
25
25
 
26
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
26
+ document.resolve(ref)
27
27
  end
28
28
 
29
29
  # /Volume — optional, -1.0 to 1.0 (default 1.0).
@@ -52,7 +52,7 @@ module Pdfrb
52
52
  ref = value[:Next]
53
53
  return nil unless ref && document
54
54
 
55
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
55
+ document.resolve(ref)
56
56
  end
57
57
  end
58
58
  end
@@ -41,7 +41,7 @@ module Pdfrb
41
41
  ref = value[key]
42
42
  return nil unless ref && document
43
43
 
44
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
44
+ document.resolve(ref)
45
45
  end
46
46
  end
47
47
  end
@@ -34,7 +34,7 @@ module Pdfrb
34
34
  ref = value[key]
35
35
  return nil unless ref && document
36
36
 
37
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
37
+ document.resolve(ref)
38
38
  end
39
39
  end
40
40
  end
@@ -24,7 +24,7 @@ module Pdfrb
24
24
  ref = value[key]
25
25
  return nil unless ref && document
26
26
 
27
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
27
+ document.resolve(ref)
28
28
  end
29
29
  end
30
30
  end
@@ -54,7 +54,7 @@ module Pdfrb
54
54
  ref = value[key]
55
55
  return nil unless ref && document
56
56
 
57
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
57
+ document.resolve(ref)
58
58
  end
59
59
  end
60
60
  end
@@ -64,7 +64,7 @@ module Pdfrb
64
64
  ref = value[key]
65
65
  return nil unless ref && document
66
66
 
67
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
67
+ document.resolve(ref)
68
68
  end
69
69
  end
70
70
  end
@@ -16,7 +16,7 @@ module Pdfrb
16
16
  ref = value[:Image]
17
17
  return nil unless ref && document
18
18
 
19
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
19
+ document.resolve(ref)
20
20
  end
21
21
 
22
22
  # /DefaultForPrinting — optional, default false. When true,
@@ -31,7 +31,7 @@ module Pdfrb
31
31
  ref = value[:OC]
32
32
  return nil unless ref && document
33
33
 
34
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
34
+ document.resolve(ref)
35
35
  end
36
36
  end
37
37
  end
@@ -19,7 +19,7 @@ module Pdfrb
19
19
  ref = value[:T]
20
20
  return nil unless ref && document
21
21
 
22
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
22
+ document.resolve(ref)
23
23
  end
24
24
 
25
25
  # /N — required indirect next Bead.
@@ -27,7 +27,7 @@ module Pdfrb
27
27
  ref = value[:N]
28
28
  return nil unless ref && document
29
29
 
30
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
30
+ document.resolve(ref)
31
31
  end
32
32
 
33
33
  # /V — required indirect previous Bead.
@@ -35,7 +35,7 @@ module Pdfrb
35
35
  ref = value[:V]
36
36
  return nil unless ref && document
37
37
 
38
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
38
+ document.resolve(ref)
39
39
  end
40
40
 
41
41
  # /P — required indirect Page the bead sits on.
@@ -43,7 +43,7 @@ module Pdfrb
43
43
  ref = value[:P]
44
44
  return nil unless ref && document
45
45
 
46
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
46
+ document.resolve(ref)
47
47
  end
48
48
 
49
49
  # /R — required rectangle on the page.
@@ -123,7 +123,7 @@ module Pdfrb
123
123
  return unless arr.is_a?(Array) || arr.is_a?(Pdfrb::Model::PdfArray)
124
124
 
125
125
  arr.each do |entry|
126
- obj = entry.is_a?(Pdfrb::Model::Reference) ? document.object(entry) : entry
126
+ obj = document.resolve(entry)
127
127
  yield obj if obj
128
128
  end
129
129
  end
@@ -168,49 +168,23 @@ module Pdfrb
168
168
  # defaults /DefaultGray, /DefaultRGB, /DefaultCMYK.
169
169
  class ColorSpaceMap < Pdfrb::Model::Cos::Dictionary
170
170
  arlington_object "ColorSpaceMap"
171
-
172
- def [](name)
173
- value[name.to_sym] || value[name.to_s]
174
- end
175
-
176
- def add(name, color_space)
177
- value[name.to_sym] = color_space
178
- name.to_sym
179
- end
171
+ include NameMap
180
172
 
181
173
  def default_gray; self[:DefaultGray]; end
182
174
  def default_rgb; self[:DefaultRGB]; end
183
175
  def default_cmyk; self[:DefaultCMYK]; end
184
176
 
185
- def each_color_space(&)
186
- return enum_for(:each_color_space) unless block_given?
187
-
188
- value.each(&)
189
- end
190
-
191
- def names
192
- value.keys
193
- end
177
+ alias each_color_space each_entry
194
178
  end
195
179
 
196
180
  # Colorants dictionary (s8.6.6.5, DeviceN /Colorants). Maps
197
181
  # individual colorant names to Separation spaces.
198
182
  class ColorantsDict < Pdfrb::Model::Cos::Dictionary
199
183
  arlington_object "ColorantsDict"
184
+ include NameMap
200
185
 
201
- def [](name)
202
- value[name.to_sym] || value[name.to_s]
203
- end
204
-
205
- def each_colorant(&)
206
- return enum_for(:each_colorant) unless block_given?
207
-
208
- value.each(&)
209
- end
210
-
211
- def colorant_names
212
- value.keys
213
- end
186
+ alias each_colorant each_entry
187
+ alias colorant_names names
214
188
  end
215
189
 
216
190
  # Box style dictionary (s7.11.4, BoxColorInfo entries). Guides
@@ -29,9 +29,9 @@ module Pdfrb
29
29
  # names to the default CryptFilter used.
30
30
  class CryptFilterMap < Pdfrb::Model::Cos::Dictionary
31
31
  arlington_object "CryptFilterMap"
32
- def filter_for(stream_name)
33
- value[stream_name.to_sym] || value[stream_name.to_s]
34
- end
32
+ include NameMap
33
+
34
+ alias filter_for []
35
35
 
36
36
  def each_filter(&)
37
37
  return enum_for(:each_filter) unless block_given?
@@ -53,9 +53,9 @@ module Pdfrb
53
53
  # public-key crypt filters.
54
54
  class CryptFilterPublicKeyMap < Pdfrb::Model::Cos::Dictionary
55
55
  arlington_object "CryptFilterPublicKeyMap"
56
- def filter_for(stream_name)
57
- value[stream_name.to_sym] || value[stream_name.to_s]
58
- end
56
+ include NameMap
57
+
58
+ alias filter_for []
59
59
  end
60
60
  end
61
61
  end
@@ -21,7 +21,7 @@ module Pdfrb
21
21
  ref = value[:DPartRootNode]
22
22
  return nil unless ref && document
23
23
 
24
- resolved = ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
24
+ resolved = document.resolve(ref)
25
25
  return nil unless resolved && resolved.value.is_a?(::Hash)
26
26
 
27
27
  DPart.new(resolved.value)
@@ -57,7 +57,7 @@ module Pdfrb
57
57
  ref = value[:Parent]
58
58
  return nil unless ref && document
59
59
 
60
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
60
+ document.resolve(ref)
61
61
  end
62
62
 
63
63
  # /DParts — array of arrays of child DParts. Mutually
@@ -71,7 +71,7 @@ module Pdfrb
71
71
  ref = value[:Start]
72
72
  return nil unless ref && document
73
73
 
74
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
74
+ document.resolve(ref)
75
75
  end
76
76
 
77
77
  # /End — indirect ref to the last Page in this part.
@@ -79,7 +79,7 @@ module Pdfrb
79
79
  ref = value[:End]
80
80
  return nil unless ref && document
81
81
 
82
- ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
82
+ document.resolve(ref)
83
83
  end
84
84
 
85
85
  def leaf?
@@ -111,25 +111,9 @@ module Pdfrb
111
111
  # map living on the (page or) catalog.
112
112
  class DestsMap < Pdfrb::Model::Cos::Dictionary
113
113
  arlington_object "DestsMap"
114
+ include NameMap
114
115
 
115
- def [](name)
116
- value[name.to_sym] || value[name.to_s]
117
- end
118
-
119
- def add(name, destination)
120
- value[name.to_sym] = destination
121
- name.to_sym
122
- end
123
-
124
- def each_destination(&)
125
- return enum_for(:each_destination) unless block_given?
126
-
127
- value.each(&)
128
- end
129
-
130
- def names
131
- value.keys
132
- end
116
+ alias each_destination each_entry
133
117
  end
134
118
  end
135
119
  end
@@ -45,7 +45,7 @@ module Pdfrb
45
45
 
46
46
  arr = certs.is_a?(Pdfrb::Model::PdfArray) ? certs.to_a : certs
47
47
  arr.each do |ref|
48
- obj = ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
48
+ obj = document.resolve(ref)
49
49
  yield obj if obj
50
50
  end
51
51
  end
@@ -73,7 +73,7 @@ module Pdfrb
73
73
 
74
74
  arr = refs.is_a?(Pdfrb::Model::PdfArray) ? refs.value : refs
75
75
  arr = [arr] unless arr.is_a?(::Array)
76
- arr.filter_map { |r| r.is_a?(Pdfrb::Model::Reference) ? document.object(r) : r }
76
+ arr.filter_map { |r| document.resolve(r) }
77
77
  end
78
78
  end
79
79
  end
@@ -39,19 +39,10 @@ module Pdfrb
39
39
  # Tiling pattern's Resources.
40
40
  class CharProcMap < Pdfrb::Model::Cos::Dictionary
41
41
  arlington_object "CharProcMap"
42
- def entries
43
- value.each
44
- end
45
-
46
- def each_procedure(&block)
47
- return enum_for(:each_procedure) unless block
42
+ include NameMap
48
43
 
49
- value.each(&block)
50
- end
51
-
52
- def procedure_for(char_name)
53
- value[char_name.to_sym] || value[char_name.to_s]
54
- end
44
+ alias each_procedure each_entry
45
+ alias procedure_for []
55
46
 
56
47
  def has_glyph?(char_name)
57
48
  !!procedure_for(char_name)
@@ -24,7 +24,7 @@ module Pdfrb
24
24
 
25
25
  arr = sub_functions.is_a?(Pdfrb::Model::PdfArray) ? sub_functions.to_a : sub_functions
26
26
  arr.each do |ref|
27
- obj = ref.is_a?(Pdfrb::Model::Reference) ? document.object(ref) : ref
27
+ obj = document.resolve(ref)
28
28
  yield obj if obj
29
29
  end
30
30
  end
@@ -31,7 +31,7 @@ module Pdfrb
31
31
  type: Pdfrb::Model::Cos::Stream
32
32
  )
33
33
  stream.stream = "q Q\n"
34
- annotation[:AP] = { N: Pdfrb::Model::Reference.new(stream.oid, stream.gen) }
34
+ annotation[:AP] = { N: stream.ref }
35
35
  stream
36
36
  end
37
37
  end
@@ -208,14 +208,9 @@ module Pdfrb
208
208
  # colorant name -> ink solidity percentage.
209
209
  class Solidities < Pdfrb::Model::Cos::Dictionary
210
210
  arlington_object "Solidities"
211
+ include NameMap
211
212
 
212
- def [](colorant)
213
- value[colorant.to_sym] || value[colorant.to_s]
214
- end
215
-
216
- def colorant_names
217
- value.keys
218
- end
213
+ alias colorant_names names
219
214
  end
220
215
 
221
216
  # Source information (s14.10.2, /SourceInfo): provenance for
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pdfrb
4
+ module Model
5
+ module Type
6
+ # Shared behaviour for name-keyed maps (Resources
7
+ # sub-dictionaries, role/class maps, VRI entries): lookup
8
+ # accepts Symbol or String, +add+ normalises the key to a
9
+ # Symbol, +names+ lists the keys.
10
+ module NameMap
11
+ def [](name)
12
+ key = name.to_sym
13
+ value.key?(key) ? value[key] : value[name.to_s]
14
+ end
15
+
16
+ def add(name, entry)
17
+ value[name.to_sym] = entry
18
+ name.to_sym
19
+ end
20
+
21
+ def names
22
+ value.keys
23
+ end
24
+
25
+ def each_entry(&)
26
+ return enum_for(:each_entry) unless block_given?
27
+
28
+ value.each(&)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end