@@ -44,8 +44,6 @@ This file is part of the iText (R) project.
4444package com .itextpdf .kernel .pdf ;
4545
4646import com .itextpdf .io .source .ByteUtils ;
47- import com .itextpdf .io .util .DecimalFormatUtil ;
48- import com .itextpdf .kernel .PdfException ;
4947import com .itextpdf .kernel .Version ;
5048
5149import java .io .IOException ;
@@ -68,7 +66,7 @@ class PdfXrefTable implements Serializable {
6866 private PdfIndirectReference [] xref ;
6967 private int count = 0 ;
7068
71- private final TreeSet <Integer > freeReferences ;
69+ private final TreeSet <Integer > freeReferences ; // TODO not using this collection for now
7270
7371 public PdfXrefTable () {
7472 this (INITIAL_CAPACITY );
@@ -116,20 +114,8 @@ public PdfIndirectReference get(int index) {
116114 * @return created indirect reference.
117115 */
118116 protected PdfIndirectReference createNextIndirectReference (PdfDocument document ) {
119- PdfIndirectReference reference ;
120- if (freeReferences .size () > 0 ) {
121- int num = (int ) freeReferences .pollFirst ();
122- reference = xref [num ];
123- if (reference == null ) {
124- reference = new PdfIndirectReference (document , num );
125- xref [num ] = reference ;
126- }
127- reference .setOffset (0 );
128- reference .clearState (PdfObject .FREE );
129- } else {
130- reference = new PdfIndirectReference (document , ++count );
131- add (reference );
132- }
117+ PdfIndirectReference reference = new PdfIndirectReference (document , ++count );
118+ add (reference );
133119 return reference .setState (PdfObject .MODIFIED );
134120 }
135121
@@ -141,19 +127,20 @@ PdfIndirectReference createNewIndirectReference(PdfDocument document) {
141127 }
142128
143129 protected void freeReference (PdfIndirectReference reference ) {
130+ freeReference (reference , false );
131+ }
132+
133+ void freeReference (PdfIndirectReference reference , boolean readingFreeReference ) {
144134 reference .setOffset (0 );
145135 reference .setState (PdfObject .FREE );
146136 if (!reference .checkState (PdfObject .FLUSHED )) {
147137 if (reference .refersTo != null ) {
148138 reference .refersTo .setIndirectReference (null ).setState (PdfObject .MUST_BE_INDIRECT );
149139 reference .refersTo = null ;
150140 }
151- if (reference .getGenNumber () < MAX_GENERATION ) {
152- freeReferences .add (reference .getObjNumber ());
153- ensureCount (Math .max (this .count , reference .getObjNumber ()));
154- xref [reference .getObjNumber ()] = null ;
155- }
156-
141+ }
142+ if (!readingFreeReference && reference .getGenNumber () < MAX_GENERATION ) {
143+ reference .genNr ++;
157144 }
158145 }
159146
@@ -170,18 +157,6 @@ protected void setCapacity(int capacity) {
170157 */
171158 protected void writeXrefTableAndTrailer (PdfDocument document , PdfObject fileId , PdfObject crypto ) throws IOException {
172159 PdfWriter writer = document .getWriter ();
173- if (document .isAppendMode ()) {
174- // Increment generation number for all freed references.
175- for (Integer objNr : freeReferences ) {
176- xref [(int ) objNr ].genNr ++;
177- }
178- } else {
179- for (Integer objNr : freeReferences ) {
180- xref [(int ) objNr ] = null ;
181- }
182- }
183- freeReferences .clear ();
184-
185160
186161 for (int i = count ; i > 0 ; --i ) {
187162 PdfIndirectReference lastRef = xref [i ];
@@ -195,19 +170,27 @@ protected void writeXrefTableAndTrailer(PdfDocument document, PdfObject fileId,
195170 }
196171 }
197172
173+ int lastFreeObjNr = 0 ;
174+ for (int i = count ; i >= 0 ; --i ) {
175+ PdfIndirectReference ref = xref [i ];
176+ if (ref == null ) {
177+ ref = new PdfIndirectReference (document , i , 0 ).setState (PdfObject .FREE );
178+ xref [i ] = ref ;
179+ }
180+ if (ref .isFree ()) {
181+ ref .setOffset (lastFreeObjNr );
182+ lastFreeObjNr = i ;
183+ }
184+ }
185+
198186 List <Integer > sections = new ArrayList <>();
199187 int first = 0 ;
200188 int len = 1 ;
201- if (document .isAppendMode ()) {
202- first = 1 ;
203- len = 0 ;
204- }
205189 for (int i = 1 ; i < size (); i ++) {
206190 PdfIndirectReference reference = xref [i ];
207191 if (reference != null ) {
208- if ((document .properties .appendMode && !reference .checkState (PdfObject .MODIFIED )) ||
209- (reference .isFree () && reference .getGenNumber () == 0 ) ||
210- (!reference .checkState (PdfObject .FLUSHED ))) {
192+ if (document .properties .appendMode && !reference .checkState (PdfObject .MODIFIED )
193+ && !reference .isFree ()) {
211194 reference = null ;
212195 }
213196 }
@@ -231,7 +214,8 @@ protected void writeXrefTableAndTrailer(PdfDocument document, PdfObject fileId,
231214 sections .add (first );
232215 sections .add (len );
233216 }
234- if (document .properties .appendMode && sections .size () == 0 ) { // no modifications.
217+ if (document .properties .appendMode && sections .size () == 2
218+ && sections .get (1 ) == 1 ) { // no modifications.
235219 xref = null ;
236220 return ;
237221 }
@@ -273,7 +257,8 @@ protected void writeXrefTableAndTrailer(PdfDocument document, PdfObject fileId,
273257 if (reference .isFree ()) {
274258 xrefStream .getOutputStream ().write (0 );
275259 //NOTE The object number of the next free object should be at this position due to spec.
276- xrefStream .getOutputStream ().write (intToBytes (0 ));
260+ assert reference .getOffset () < Integer .MAX_VALUE ;
261+ xrefStream .getOutputStream ().write (intToBytes ((int ) reference .getOffset ()));
277262 xrefStream .getOutputStream ().write (shortToBytes (reference .getGenNumber ()));
278263 } else if (reference .getObjStreamNumber () == 0 ) {
279264 xrefStream .getOutputStream ().write (1 );
0 commit comments