@@ -44,8 +44,6 @@ This file is part of the iText (R) project.
44
44
package com .itextpdf .kernel .pdf ;
45
45
46
46
import com .itextpdf .io .source .ByteUtils ;
47
- import com .itextpdf .io .util .DecimalFormatUtil ;
48
- import com .itextpdf .kernel .PdfException ;
49
47
import com .itextpdf .kernel .Version ;
50
48
51
49
import java .io .IOException ;
@@ -68,7 +66,7 @@ class PdfXrefTable implements Serializable {
68
66
private PdfIndirectReference [] xref ;
69
67
private int count = 0 ;
70
68
71
- private final TreeSet <Integer > freeReferences ;
69
+ private final TreeSet <Integer > freeReferences ; // TODO not using this collection for now
72
70
73
71
public PdfXrefTable () {
74
72
this (INITIAL_CAPACITY );
@@ -116,20 +114,8 @@ public PdfIndirectReference get(int index) {
116
114
* @return created indirect reference.
117
115
*/
118
116
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 );
133
119
return reference .setState (PdfObject .MODIFIED );
134
120
}
135
121
@@ -141,19 +127,20 @@ PdfIndirectReference createNewIndirectReference(PdfDocument document) {
141
127
}
142
128
143
129
protected void freeReference (PdfIndirectReference reference ) {
130
+ freeReference (reference , false );
131
+ }
132
+
133
+ void freeReference (PdfIndirectReference reference , boolean readingFreeReference ) {
144
134
reference .setOffset (0 );
145
135
reference .setState (PdfObject .FREE );
146
136
if (!reference .checkState (PdfObject .FLUSHED )) {
147
137
if (reference .refersTo != null ) {
148
138
reference .refersTo .setIndirectReference (null ).setState (PdfObject .MUST_BE_INDIRECT );
149
139
reference .refersTo = null ;
150
140
}
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 ++;
157
144
}
158
145
}
159
146
@@ -170,18 +157,6 @@ protected void setCapacity(int capacity) {
170
157
*/
171
158
protected void writeXrefTableAndTrailer (PdfDocument document , PdfObject fileId , PdfObject crypto ) throws IOException {
172
159
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
-
185
160
186
161
for (int i = count ; i > 0 ; --i ) {
187
162
PdfIndirectReference lastRef = xref [i ];
@@ -195,19 +170,27 @@ protected void writeXrefTableAndTrailer(PdfDocument document, PdfObject fileId,
195
170
}
196
171
}
197
172
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
+
198
186
List <Integer > sections = new ArrayList <>();
199
187
int first = 0 ;
200
188
int len = 1 ;
201
- if (document .isAppendMode ()) {
202
- first = 1 ;
203
- len = 0 ;
204
- }
205
189
for (int i = 1 ; i < size (); i ++) {
206
190
PdfIndirectReference reference = xref [i ];
207
191
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 ()) {
211
194
reference = null ;
212
195
}
213
196
}
@@ -231,7 +214,8 @@ protected void writeXrefTableAndTrailer(PdfDocument document, PdfObject fileId,
231
214
sections .add (first );
232
215
sections .add (len );
233
216
}
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.
235
219
xref = null ;
236
220
return ;
237
221
}
@@ -273,7 +257,8 @@ protected void writeXrefTableAndTrailer(PdfDocument document, PdfObject fileId,
273
257
if (reference .isFree ()) {
274
258
xrefStream .getOutputStream ().write (0 );
275
259
//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 ()));
277
262
xrefStream .getOutputStream ().write (shortToBytes (reference .getGenNumber ()));
278
263
} else if (reference .getObjStreamNumber () == 0 ) {
279
264
xrefStream .getOutputStream ().write (1 );
0 commit comments