From 04221f3fcbbc549ac959b2ca5f35a35f88a748be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Co=C3=AAlho?= Date: Sun, 22 Oct 2023 18:34:46 +0000 Subject: [PATCH] Account unused object ids --- lib/rubrik/document.rb | 20 ++++++++++++++++-- lib/rubrik/document/increment.rb | 2 +- test/rubrik/document_test.rb | 2 +- .../without_interactive_form.expected.pdf | Bin 9334 -> 9398 bytes test/support/without_interactive_form.pdf | Bin 462 -> 520 bytes 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/rubrik/document.rb b/lib/rubrik/document.rb index f300bdb..e629bd1 100644 --- a/lib/rubrik/document.rb +++ b/lib/rubrik/document.rb @@ -17,19 +17,25 @@ class Document sig {returns(PDF::Reader::ObjectHash)} attr_accessor :objects + sig {returns(Integer)} + attr_accessor :first_free_object_id + sig {returns(T::Array[{id: PDF::Reader::Reference, value: T.untyped}])} attr_accessor :modified_objects sig {returns(Integer)} attr_accessor :last_object_id - private :io=, :objects=, :modified_objects=, :last_object_id= + private :io=, :objects=, :first_free_object_id=, :modified_objects=, :last_object_id= sig {params(input: T.any(File, Tempfile, StringIO)).void} def initialize(input) self.io = input self.objects = PDF::Reader::ObjectHash.new(input) - self.last_object_id = objects.size + + self.last_object_id = objects.trailer[:Size] - 1 + self.first_free_object_id = find_first_free_object_id + self.modified_objects = [] fetch_or_create_interactive_form! @@ -87,6 +93,16 @@ def interactive_form T.must(modified_objects.first).fetch(:value) end + sig{returns(Integer)} + def find_first_free_object_id + return 0 if last_object_id == objects.size + + xref = objects.send(:xref).instance_variable_get(:@xref) + missing_ids = (1..last_object_id).to_a - xref.keys + + T.must(missing_ids.min) + end + sig {void} def fetch_or_create_interactive_form! root_ref = objects.trailer[:Root] diff --git a/lib/rubrik/document/increment.rb b/lib/rubrik/document/increment.rb index 46ae112..10b9819 100644 --- a/lib/rubrik/document/increment.rb +++ b/lib/rubrik/document/increment.rb @@ -46,7 +46,7 @@ def call(document, io:) io << "#{starting_id} #{length}\n" if starting_id.zero? - io << "0000000000 65535 f \n" + io << "#{format("%010d", document.first_free_object_id)} 65535 f \n" subsection.shift end diff --git a/test/rubrik/document_test.rb b/test/rubrik/document_test.rb index f46d377..032886d 100644 --- a/test/rubrik/document_test.rb +++ b/test/rubrik/document_test.rb @@ -15,7 +15,7 @@ def test_initialize_document_without_interactive_form # Assert assert_equal(input, document.send(:io)) # FACT: the interactive form was created - assert_equal(5, document.last_object_id) + assert_equal(6, document.last_object_id) assert_kind_of(PDF::Reader::ObjectHash, document.objects) acro_form = document.modified_objects.find { |obj| obj.dig(:value, :Type) == :Catalog } diff --git a/test/support/without_interactive_form.expected.pdf b/test/support/without_interactive_form.expected.pdf index 22b5732f23e5c12c57dbb7cb9b068118ba5d42ad..2b1a42b89cc6173e3948386907d59fae37a0ef9b 100644 GIT binary patch delta 496 zcmZvZu}Z{16h(>UbhZ|9iELpZnaS)-=E1VqxF`rKQ7f@n$pj)x0!b9H@gwpJVq+r+ z{)nI8KiCN-yBiXsubATAnfKm3^L_kr^5#2F3LM$ZEt^cd3tN=%F4MchM$;*?Y19}G zxs4fzX1py0t&~)V(P@O0i?q{}{-X&Y2HKc&pZf!G-D-W-L&|)SEN$Mbc%D33=<3zk z*_FgbqoetZv3gD$VV2lsRN%@~U(V@vV}xB27Q7#B#W)BA!H|#`8+DC;s`tcHpYFaB zR6p*EW2)ypw+1#$uXHcHgxF9aPP_}IAzNC?A5!34OWECBgEkcOz_bv8mIA>Gv#dnj Z3n9F-+}=YOgh9f4kCCk5TL&(<9LZKlYGo?fUmk@(uN}DAQp?Bz9DD-jq z1f4rqP8_xIKZ!d|+;^Y1KR545uzxXn#W;v@e^5k{;N;U4IJ~g&5~;2vgy>2MPrOu{ zMY-07jYjc9xzixTv#P2SxD;mNG27M)QyCLk7nflm;EA*5S$a5m3Sz*5iu&-gyUPk>u*(`bsGW!(`_Ph&7|Ef!f7P8>- vuRcMZ*i$7vRXY%6u1|A*p}Y{Om(JORMt+1pvLl`v{R~Hawu1YBw=?_#PB~<} diff --git a/test/support/without_interactive_form.pdf b/test/support/without_interactive_form.pdf index 29e95d6a6a91f96a1dc93b5c422c88f759e7083e..544bfe21d1a6a26f83fd2b06a9b405720c4bfa1e 100644 GIT binary patch delta 202 zcmX@d+`+QJh_T*O!9XEDDT~X-Mn5FAxI{reG_SNcHO0=3D>W|#BvDb6n#N_IV8&$t z1EvaQrl!WG3TX-mF-rxotU?|_%+w4+%+SyfP0Yl=z{tP|O%P%fgalerQk0mPlUf9F ZVsK_vs)E_%)r?Y{#+F>Fs;>TSTmT@$E$jdQ delta 165 zcmeBRImf)gh_Sw+C^e1CK*5yD01gz)OihhV6@bDpV5tCRDdfS0OwG`R3=Iv@g^Uc0 z;6f!uiJ3X6MO-#E`oWo1sS2hF`a${mC9(=YT?#>Vc3j0JiA5z~*BBd^ajB}h`nz!f E0N!~e+yDRo