@@ -44,6 +44,8 @@ This file is part of the iText (R) project.
44
44
import com .itextpdf .kernel .pdf .xobject .PdfImageXObject ;
45
45
import com .itextpdf .kernel .utils .ICopyFilter ;
46
46
import com .itextpdf .kernel .utils .NullCopyFilter ;
47
+ import com .itextpdf .kernel .utils .checkers .PdfCheckersUtil ;
48
+ import com .itextpdf .kernel .validation .context .PdfAnnotationContext ;
47
49
import com .itextpdf .kernel .validation .context .PdfDestinationAdditionContext ;
48
50
import com .itextpdf .kernel .validation .context .PdfPageValidationContext ;
49
51
import com .itextpdf .kernel .xmp .XMPException ;
@@ -883,16 +885,7 @@ public PdfPage addAnnotation(PdfAnnotation annotation) {
883
885
public PdfPage addAnnotation (int index , PdfAnnotation annotation , boolean tagAnnotation ) {
884
886
if (getDocument ().isTagged ()) {
885
887
if (tagAnnotation ) {
886
- TagTreePointer tagPointer = getDocument ().getTagStructureContext ().getAutoTaggingPointer ();
887
- boolean tagAdded = addAnnotationTag (tagPointer , annotation );
888
- PdfPage prevPage = tagPointer .getCurrentPage ();
889
- tagPointer .setPageForTagging (this ).addAnnotationTag (annotation );
890
- if (prevPage != null ) {
891
- tagPointer .setPageForTagging (prevPage );
892
- }
893
- if (tagAdded ) {
894
- tagPointer .moveToParent ();
895
- }
888
+ tagAnnotation (annotation );
896
889
}
897
890
if (getTabOrder () == null ) {
898
891
setTabOrder (PdfName .S );
@@ -913,55 +906,11 @@ public PdfPage addAnnotation(int index, PdfAnnotation annotation, boolean tagAnn
913
906
//Annots are indirect so need to be marked as modified
914
907
annots .setModified ();
915
908
}
916
- checkIsoConformanceForDestinations (annotation );
909
+ checkIsoConformanceForAnnotation (annotation );
917
910
918
911
return this ;
919
912
}
920
913
921
- private void checkIsoConformanceForDestinations (PdfAnnotation annotation ) {
922
- if (annotation instanceof PdfLinkAnnotation ) {
923
- PdfLinkAnnotation linkAnnotation = (PdfLinkAnnotation ) annotation ;
924
- getDocument ().checkIsoConformance (new PdfDestinationAdditionContext (linkAnnotation .getDestinationObject ()));
925
- if (linkAnnotation .getAction () != null && PdfName .GoTo .equals (linkAnnotation .getAction ().get (PdfName .S ))) {
926
- // We only care about destinations, whose target lies within this document.
927
- // That's why GoToR and GoToE are ignored.
928
- getDocument ().checkIsoConformance (
929
- new PdfDestinationAdditionContext (new PdfAction (linkAnnotation .getAction ())));
930
- }
931
- }
932
- }
933
-
934
- private boolean addAnnotationTag (TagTreePointer tagPointer , PdfAnnotation annotation ) {
935
- if (annotation instanceof PdfLinkAnnotation ) {
936
- // "Link" tag was added starting from PDF 1.4
937
- if (PdfVersion .PDF_1_3 .compareTo (getDocument ().getPdfVersion ()) < 0 ) {
938
- if (!StandardRoles .LINK .equals (tagPointer .getRole ())) {
939
- tagPointer .addTag (StandardRoles .LINK );
940
- return true ;
941
- }
942
- }
943
- } else {
944
- if (!(annotation instanceof PdfWidgetAnnotation )
945
- && !(annotation instanceof PdfPrinterMarkAnnotation )) {
946
- // "Annot" tag was added starting from PDF 1.5
947
- if (PdfVersion .PDF_1_4 .compareTo (getDocument ().getPdfVersion ()) < 0 ) {
948
- if (!StandardRoles .ANNOT .equals (tagPointer .getRole ())) {
949
- tagPointer .addTag (StandardRoles .ANNOT );
950
- return true ;
951
- }
952
- }
953
- }
954
- if (annotation instanceof PdfPrinterMarkAnnotation &&
955
- PdfVersion .PDF_2_0 .compareTo (getDocument ().getPdfVersion ()) <= 0 ) {
956
- if (!StandardRoles .ARTIFACT .equals (tagPointer .getRole ())) {
957
- tagPointer .addTag (StandardRoles .ARTIFACT );
958
- return true ;
959
- }
960
- }
961
- }
962
- return false ;
963
- }
964
-
965
914
/**
966
915
* Removes an annotation from the page.
967
916
*
@@ -1327,6 +1276,103 @@ protected boolean isWrappedObjectMustBeIndirect() {
1327
1276
return true ;
1328
1277
}
1329
1278
1279
+ private static boolean isAnnotInvisible (PdfAnnotation annotation ) {
1280
+ PdfNumber f = annotation .getPdfObject ().getAsNumber (PdfName .F );
1281
+ if (f == null ) {
1282
+ return false ;
1283
+ }
1284
+ int flags = f .intValue ();
1285
+ return PdfCheckersUtil .checkFlag (flags , PdfAnnotation .INVISIBLE ) ||
1286
+ (PdfCheckersUtil .checkFlag (flags , PdfAnnotation .NO_VIEW ) &&
1287
+ !PdfCheckersUtil .checkFlag (flags , PdfAnnotation .TOGGLE_NO_VIEW ));
1288
+ }
1289
+
1290
+ private void tagAnnotation (PdfAnnotation annotation ) {
1291
+ boolean tagAdded = false ;
1292
+ boolean presentInTagStructure = true ;
1293
+ boolean isUA2 = isPdfUA2Document ();
1294
+ TagTreePointer tagPointer = getDocument ().getTagStructureContext ().getAutoTaggingPointer ();
1295
+ if (isUA2 && isAnnotInvisible (annotation )) {
1296
+ if (PdfVersion .PDF_2_0 .compareTo (getDocument ().getPdfVersion ()) <= 0 ) {
1297
+ if (!StandardRoles .ARTIFACT .equals (tagPointer .getRole ())) {
1298
+ tagPointer .addTag (StandardRoles .ARTIFACT );
1299
+ tagAdded = true ;
1300
+ }
1301
+ } else {
1302
+ presentInTagStructure = false ;
1303
+ }
1304
+ } else {
1305
+ tagAdded = addAnnotationTag (tagPointer , annotation );
1306
+ }
1307
+ if (presentInTagStructure ) {
1308
+ PdfPage prevPage = tagPointer .getCurrentPage ();
1309
+ tagPointer .setPageForTagging (this ).addAnnotationTag (annotation );
1310
+ if (prevPage != null ) {
1311
+ tagPointer .setPageForTagging (prevPage );
1312
+ }
1313
+ }
1314
+ if (tagAdded ) {
1315
+ tagPointer .moveToParent ();
1316
+ }
1317
+ }
1318
+
1319
+ private boolean isPdfUA2Document () {
1320
+ PdfUAConformance uaConformance = getDocument ().getConformance ().getUAConformance ();
1321
+ if (uaConformance == null ) {
1322
+ try {
1323
+ uaConformance = PdfConformance .getConformance (getDocument ().getXmpMetadata ()).getUAConformance ();
1324
+ } catch (XMPException e ) {
1325
+ return false ;
1326
+ }
1327
+ }
1328
+ return PdfUAConformance .PDF_UA_2 == uaConformance ;
1329
+ }
1330
+
1331
+ private void checkIsoConformanceForAnnotation (PdfAnnotation annotation ) {
1332
+ getDocument ().checkIsoConformance (new PdfAnnotationContext (annotation .getPdfObject ()));
1333
+ if (annotation instanceof PdfLinkAnnotation ) {
1334
+ PdfLinkAnnotation linkAnnotation = (PdfLinkAnnotation ) annotation ;
1335
+ getDocument ().checkIsoConformance (new PdfDestinationAdditionContext (linkAnnotation .getDestinationObject ()));
1336
+ if (linkAnnotation .getAction () != null && PdfName .GoTo .equals (linkAnnotation .getAction ().get (PdfName .S ))) {
1337
+ // We only care about destinations, whose target lies within this document.
1338
+ // That's why GoToR and GoToE are ignored.
1339
+ getDocument ().checkIsoConformance (
1340
+ new PdfDestinationAdditionContext (new PdfAction (linkAnnotation .getAction ())));
1341
+ }
1342
+ }
1343
+ }
1344
+
1345
+ private boolean addAnnotationTag (TagTreePointer tagPointer , PdfAnnotation annotation ) {
1346
+ if (annotation instanceof PdfLinkAnnotation ) {
1347
+ // "Link" tag was added starting from PDF 1.4
1348
+ if (PdfVersion .PDF_1_3 .compareTo (getDocument ().getPdfVersion ()) < 0 ) {
1349
+ if (!StandardRoles .LINK .equals (tagPointer .getRole ())) {
1350
+ tagPointer .addTag (StandardRoles .LINK );
1351
+ return true ;
1352
+ }
1353
+ }
1354
+ } else {
1355
+ if (!(annotation instanceof PdfWidgetAnnotation )
1356
+ && !(annotation instanceof PdfPrinterMarkAnnotation )) {
1357
+ // "Annot" tag was added starting from PDF 1.5
1358
+ if (PdfVersion .PDF_1_4 .compareTo (getDocument ().getPdfVersion ()) < 0 ) {
1359
+ if (!StandardRoles .ANNOT .equals (tagPointer .getRole ())) {
1360
+ tagPointer .addTag (StandardRoles .ANNOT );
1361
+ return true ;
1362
+ }
1363
+ }
1364
+ }
1365
+ if (annotation instanceof PdfPrinterMarkAnnotation &&
1366
+ PdfVersion .PDF_2_0 .compareTo (getDocument ().getPdfVersion ()) <= 0 ) {
1367
+ if (!StandardRoles .ARTIFACT .equals (tagPointer .getRole ())) {
1368
+ tagPointer .addTag (StandardRoles .ARTIFACT );
1369
+ return true ;
1370
+ }
1371
+ }
1372
+ }
1373
+ return false ;
1374
+ }
1375
+
1330
1376
private PdfPage copyTo (PdfPage page , PdfDocument toDocument , IPdfPageExtraCopier copier ) {
1331
1377
final ICopyFilter copyFilter = new DestinationResolverCopyFilter (this .getDocument (), toDocument );
1332
1378
copyInheritedProperties (page , toDocument , NullCopyFilter .getInstance ());
@@ -1540,6 +1586,4 @@ private void rebuildFormFieldParent(PdfDictionary field, PdfDictionary newField,
1540
1586
newField .put (PdfName .Parent , newParent );
1541
1587
}
1542
1588
}
1543
-
1544
-
1545
1589
}
0 commit comments