@@ -57,6 +57,8 @@ namespace iText.Forms {
57
57
/// <remarks>
58
58
/// A sample implementation of the {#link IPdfPageExtraCopier} interface which
59
59
/// copies only AcroForm fields to a new page.
60
+ /// <p>
61
+ /// <p>
60
62
/// NOTE: While it's absolutely not necessary to use the same PdfPageFormCopier instance for copying operations,
61
63
/// it is still worth to know that PdfPageFormCopier uses some caching logic which can potentially improve performance
62
64
/// in case of the reusing of the same instance.
@@ -81,93 +83,110 @@ public virtual void Copy(PdfPage fromPage, PdfPage toPage) {
81
83
documentTo = toPage . GetDocument ( ) ;
82
84
formTo = PdfAcroForm . GetAcroForm ( documentTo , true ) ;
83
85
}
84
- if ( formFrom != null ) {
85
- //duplicate AcroForm dictionary
86
- IList < PdfName > excludedKeys = new List < PdfName > ( ) ;
87
- excludedKeys . Add ( PdfName . Fields ) ;
88
- excludedKeys . Add ( PdfName . DR ) ;
89
- PdfDictionary dict = formFrom . GetPdfObject ( ) . CopyTo ( documentTo , excludedKeys , false ) ;
90
- formTo . GetPdfObject ( ) . MergeDifferent ( dict ) ;
86
+ if ( formFrom == null ) {
87
+ return ;
91
88
}
92
- if ( formFrom != null ) {
93
- IDictionary < String , PdfFormField > fieldsFrom = formFrom . GetFormFields ( ) ;
94
- if ( fieldsFrom . Count > 0 ) {
95
- IDictionary < String , PdfFormField > fieldsTo = formTo . GetFormFields ( ) ;
96
- IList < PdfAnnotation > annots = toPage . GetAnnotations ( ) ;
97
- foreach ( PdfAnnotation annot in annots ) {
98
- if ( annot . GetSubtype ( ) . Equals ( PdfName . Widget ) ) {
99
- PdfDictionary parent = annot . GetPdfObject ( ) . GetAsDictionary ( PdfName . Parent ) ;
100
- if ( parent != null ) {
101
- PdfFormField parentField = GetParentField ( parent , documentTo ) ;
102
- PdfString parentName = parentField . GetFieldName ( ) ;
103
- if ( parentName == null ) {
104
- continue ;
105
- }
106
- if ( ! fieldsTo . ContainsKey ( parentName . ToUnicodeString ( ) ) ) {
107
- PdfFormField field = CreateParentFieldCopy ( annot . GetPdfObject ( ) , documentTo ) ;
108
- PdfArray kids = field . GetKids ( ) ;
109
- field . GetPdfObject ( ) . Remove ( PdfName . Kids ) ;
110
- formTo . AddField ( field , toPage ) ;
111
- field . GetPdfObject ( ) . Put ( PdfName . Kids , kids ) ;
112
- }
113
- else {
114
- PdfFormField field = PdfFormField . MakeFormField ( annot . GetPdfObject ( ) , documentTo ) ;
115
- PdfString fieldName = field . GetFieldName ( ) ;
116
- if ( fieldName != null ) {
117
- PdfFormField existingField = fieldsTo . Get ( fieldName . ToUnicodeString ( ) ) ;
118
- if ( existingField != null ) {
119
- PdfFormField clonedField = PdfFormField . MakeFormField ( field . GetPdfObject ( ) . Clone ( ) . MakeIndirect ( documentTo
120
- ) , documentTo ) ;
121
- toPage . GetPdfObject ( ) . GetAsArray ( PdfName . Annots ) . Add ( clonedField . GetPdfObject ( ) ) ;
122
- toPage . RemoveAnnotation ( annot ) ;
123
- MergeFieldsWithTheSameName ( clonedField ) ;
124
- }
125
- else {
126
- HashSet < String > existingFields = new HashSet < String > ( ) ;
127
- GetAllFieldNames ( formTo . GetFields ( ) , existingFields ) ;
128
- AddChildToExistingParent ( annot . GetPdfObject ( ) , existingFields ) ;
129
- }
130
- }
131
- else {
132
- if ( ! parentField . GetKids ( ) . Contains ( field . GetPdfObject ( ) ) ) {
133
- HashSet < String > existingFields = new HashSet < String > ( ) ;
134
- GetAllFieldNames ( formTo . GetFields ( ) , existingFields ) ;
135
- AddChildToExistingParent ( annot . GetPdfObject ( ) , existingFields ) ;
136
- }
137
- }
138
- }
139
- }
140
- else {
141
- PdfString annotName = annot . GetPdfObject ( ) . GetAsString ( PdfName . T ) ;
142
- String annotNameString = null ;
143
- if ( annotName != null ) {
144
- annotNameString = annotName . ToUnicodeString ( ) ;
145
- }
146
- if ( annotNameString != null && fieldsFrom . ContainsKey ( annotNameString ) ) {
147
- PdfFormField field = fieldsTo . Get ( annotNameString ) ;
148
- if ( field != null ) {
149
- PdfDictionary clonedAnnot = ( PdfDictionary ) annot . GetPdfObject ( ) . Clone ( ) . MakeIndirect ( documentTo ) ;
150
- toPage . GetPdfObject ( ) . GetAsArray ( PdfName . Annots ) . Add ( clonedAnnot ) ;
151
- toPage . RemoveAnnotation ( annot ) ;
152
- field = MergeFieldsWithTheSameName ( PdfFormField . MakeFormField ( clonedAnnot , toPage . GetDocument ( ) ) ) ;
153
- logger . Warn ( MessageFormatUtil . Format ( iText . IO . LogMessageConstant . DOCUMENT_ALREADY_HAS_FIELD , annotNameString
154
- ) ) ;
155
- PdfArray kids = field . GetKids ( ) ;
156
- if ( kids != null ) {
157
- field . GetPdfObject ( ) . Remove ( PdfName . Kids ) ;
158
- formTo . AddField ( field , toPage ) ;
159
- field . GetPdfObject ( ) . Put ( PdfName . Kids , kids ) ;
160
- }
161
- else {
162
- formTo . AddField ( field , toPage ) ;
163
- }
164
- }
165
- else {
166
- formTo . AddField ( PdfFormField . MakeFormField ( annot . GetPdfObject ( ) , documentTo ) , null ) ;
167
- }
168
- }
169
- }
170
- }
89
+ //duplicate AcroForm dictionary
90
+ IList < PdfName > excludedKeys = new List < PdfName > ( ) ;
91
+ excludedKeys . Add ( PdfName . Fields ) ;
92
+ excludedKeys . Add ( PdfName . DR ) ;
93
+ PdfDictionary dict = formFrom . GetPdfObject ( ) . CopyTo ( documentTo , excludedKeys , false ) ;
94
+ formTo . GetPdfObject ( ) . MergeDifferent ( dict ) ;
95
+ IDictionary < String , PdfFormField > fieldsFrom = formFrom . GetFormFields ( ) ;
96
+ if ( fieldsFrom . Count <= 0 ) {
97
+ return ;
98
+ }
99
+ IDictionary < String , PdfFormField > fieldsTo = formTo . GetFormFields ( ) ;
100
+ IList < PdfAnnotation > annots = toPage . GetAnnotations ( ) ;
101
+ foreach ( PdfAnnotation annot in annots ) {
102
+ if ( ! annot . GetSubtype ( ) . Equals ( PdfName . Widget ) ) {
103
+ continue ;
104
+ }
105
+ CopyField ( toPage , fieldsFrom , fieldsTo , annot ) ;
106
+ }
107
+ }
108
+
109
+ private void CopyField ( PdfPage toPage , IDictionary < String , PdfFormField > fieldsFrom , IDictionary < String , PdfFormField
110
+ > fieldsTo , PdfAnnotation currentAnnot ) {
111
+ PdfDictionary parent = currentAnnot . GetPdfObject ( ) . GetAsDictionary ( PdfName . Parent ) ;
112
+ if ( parent != null ) {
113
+ PdfFormField parentField = GetParentField ( parent , documentTo ) ;
114
+ PdfString parentName = parentField . GetFieldName ( ) ;
115
+ if ( parentName == null ) {
116
+ return ;
117
+ }
118
+ CopyParentFormField ( toPage , fieldsTo , currentAnnot , parentField ) ;
119
+ }
120
+ else {
121
+ PdfString annotName = currentAnnot . GetPdfObject ( ) . GetAsString ( PdfName . T ) ;
122
+ String annotNameString = null ;
123
+ if ( annotName != null ) {
124
+ annotNameString = annotName . ToUnicodeString ( ) ;
125
+ }
126
+ if ( annotNameString != null && fieldsFrom . ContainsKey ( annotNameString ) ) {
127
+ PdfFormField field = fieldsTo . Get ( annotNameString ) ;
128
+ if ( field == null ) {
129
+ formTo . AddField ( PdfFormField . MakeFormField ( currentAnnot . GetPdfObject ( ) , documentTo ) , null ) ;
130
+ }
131
+ else {
132
+ CopyExistingField ( toPage , currentAnnot , annotNameString ) ;
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ private void CopyExistingField ( PdfPage toPage , PdfAnnotation currentAnnot , String annotNameString ) {
139
+ PdfFormField field ;
140
+ PdfDictionary clonedAnnot = ( PdfDictionary ) currentAnnot . GetPdfObject ( ) . Clone ( ) . MakeIndirect ( documentTo ) ;
141
+ toPage . GetPdfObject ( ) . GetAsArray ( PdfName . Annots ) . Add ( clonedAnnot ) ;
142
+ toPage . RemoveAnnotation ( currentAnnot ) ;
143
+ field = MergeFieldsWithTheSameName ( PdfFormField . MakeFormField ( clonedAnnot , toPage . GetDocument ( ) ) ) ;
144
+ logger . Warn ( MessageFormatUtil . Format ( iText . IO . LogMessageConstant . DOCUMENT_ALREADY_HAS_FIELD , annotNameString
145
+ ) ) ;
146
+ PdfArray kids = field . GetKids ( ) ;
147
+ if ( kids != null ) {
148
+ field . GetPdfObject ( ) . Remove ( PdfName . Kids ) ;
149
+ formTo . AddField ( field , toPage ) ;
150
+ field . GetPdfObject ( ) . Put ( PdfName . Kids , kids ) ;
151
+ }
152
+ else {
153
+ formTo . AddField ( field , toPage ) ;
154
+ }
155
+ }
156
+
157
+ private void CopyParentFormField ( PdfPage toPage , IDictionary < String , PdfFormField > fieldsTo , PdfAnnotation
158
+ annot , PdfFormField parentField ) {
159
+ PdfString parentName = parentField . GetFieldName ( ) ;
160
+ if ( ! fieldsTo . ContainsKey ( parentName . ToUnicodeString ( ) ) ) {
161
+ PdfFormField field = CreateParentFieldCopy ( annot . GetPdfObject ( ) , documentTo ) ;
162
+ PdfArray kids = field . GetKids ( ) ;
163
+ field . GetPdfObject ( ) . Remove ( PdfName . Kids ) ;
164
+ formTo . AddField ( field , toPage ) ;
165
+ field . GetPdfObject ( ) . Put ( PdfName . Kids , kids ) ;
166
+ }
167
+ else {
168
+ PdfFormField field = PdfFormField . MakeFormField ( annot . GetPdfObject ( ) , documentTo ) ;
169
+ PdfString fieldName = field . GetFieldName ( ) ;
170
+ if ( fieldName != null ) {
171
+ PdfFormField existingField = fieldsTo . Get ( fieldName . ToUnicodeString ( ) ) ;
172
+ if ( existingField != null ) {
173
+ PdfFormField clonedField = PdfFormField . MakeFormField ( field . GetPdfObject ( ) . Clone ( ) . MakeIndirect ( documentTo
174
+ ) , documentTo ) ;
175
+ toPage . GetPdfObject ( ) . GetAsArray ( PdfName . Annots ) . Add ( clonedField . GetPdfObject ( ) ) ;
176
+ toPage . RemoveAnnotation ( annot ) ;
177
+ MergeFieldsWithTheSameName ( clonedField ) ;
178
+ }
179
+ else {
180
+ HashSet < String > existingFields = new HashSet < String > ( ) ;
181
+ GetAllFieldNames ( formTo . GetFields ( ) , existingFields ) ;
182
+ AddChildToExistingParent ( annot . GetPdfObject ( ) , existingFields , fieldsTo , toPage , annot ) ;
183
+ }
184
+ }
185
+ else {
186
+ if ( ! parentField . GetKids ( ) . Contains ( field . GetPdfObject ( ) ) ) {
187
+ HashSet < String > existingFields = new HashSet < String > ( ) ;
188
+ GetAllFieldNames ( formTo . GetFields ( ) , existingFields ) ;
189
+ AddChildToExistingParent ( annot . GetPdfObject ( ) , existingFields ) ;
171
190
}
172
191
}
173
192
}
@@ -233,18 +252,26 @@ private PdfFormField GetParentField(PdfDictionary parent, PdfDocument pdfDoc) {
233
252
}
234
253
235
254
private PdfFormField CreateParentFieldCopy ( PdfDictionary fieldDic , PdfDocument pdfDoc ) {
236
- fieldDic . Remove ( PdfName . Kids ) ;
237
255
PdfDictionary parent = fieldDic . GetAsDictionary ( PdfName . Parent ) ;
238
256
PdfFormField field = PdfFormField . MakeFormField ( fieldDic , pdfDoc ) ;
239
257
if ( parent != null ) {
240
258
field = CreateParentFieldCopy ( parent , pdfDoc ) ;
241
- parent . Put ( PdfName . Kids , new PdfArray ( fieldDic ) ) ;
259
+ PdfArray kids = ( PdfArray ) parent . Get ( PdfName . Kids ) ;
260
+ if ( kids == null ) {
261
+ parent . Put ( PdfName . Kids , new PdfArray ( fieldDic ) ) ;
262
+ }
263
+ else {
264
+ kids . Add ( fieldDic ) ;
265
+ }
242
266
}
243
267
return field ;
244
268
}
245
269
246
270
private void AddChildToExistingParent ( PdfDictionary fieldDic , ICollection < String > existingFields ) {
247
271
PdfDictionary parent = fieldDic . GetAsDictionary ( PdfName . Parent ) ;
272
+ if ( parent == null ) {
273
+ return ;
274
+ }
248
275
PdfString parentName = parent . GetAsString ( PdfName . T ) ;
249
276
if ( parentName != null ) {
250
277
String name = parentName . ToUnicodeString ( ) ;
@@ -259,6 +286,36 @@ private void AddChildToExistingParent(PdfDictionary fieldDic, ICollection<String
259
286
}
260
287
}
261
288
289
+ private void AddChildToExistingParent ( PdfDictionary fieldDic , ICollection < String > existingFields , IDictionary
290
+ < String , PdfFormField > fieldsTo , PdfPage toPage , PdfAnnotation annot ) {
291
+ PdfDictionary parent = fieldDic . GetAsDictionary ( PdfName . Parent ) ;
292
+ if ( parent == null ) {
293
+ return ;
294
+ }
295
+ PdfString parentName = parent . GetAsString ( PdfName . T ) ;
296
+ if ( parentName != null ) {
297
+ String name = parentName . ToUnicodeString ( ) ;
298
+ if ( existingFields . Contains ( name ) ) {
299
+ PdfArray kids = parent . GetAsArray ( PdfName . Kids ) ;
300
+ foreach ( PdfObject kid in kids ) {
301
+ if ( ( ( PdfDictionary ) kid ) . Get ( PdfName . T ) . Equals ( fieldDic . Get ( PdfName . T ) ) ) {
302
+ PdfFormField kidField = PdfFormField . MakeFormField ( kid , documentTo ) ;
303
+ fieldsTo . Put ( kidField . GetFieldName ( ) . ToUnicodeString ( ) , kidField ) ;
304
+ logger . Warn ( MessageFormatUtil . Format ( iText . IO . LogMessageConstant . DOCUMENT_ALREADY_HAS_FIELD , kidField . GetFieldName
305
+ ( ) . ToUnicodeString ( ) ) ) ;
306
+ MergeFieldsWithTheSameName ( PdfFormField . MakeFormField ( fieldDic , documentTo ) ) ;
307
+ return ;
308
+ }
309
+ }
310
+ kids . Add ( fieldDic ) ;
311
+ }
312
+ else {
313
+ parent . Put ( PdfName . Kids , new PdfArray ( fieldDic ) ) ;
314
+ AddChildToExistingParent ( parent , existingFields ) ;
315
+ }
316
+ }
317
+ }
318
+
262
319
private void GetAllFieldNames ( PdfArray fields , ICollection < String > existingFields ) {
263
320
foreach ( PdfObject field in fields ) {
264
321
if ( field . IsFlushed ( ) ) {
0 commit comments