@@ -155,19 +155,22 @@ public class PdfA2Checker extends PdfA1Checker {
155
155
PdfName .CCF ,
156
156
PdfName .DCT )));
157
157
158
+ protected Set <PdfObject > transparencyObjects = new HashSet <>();
159
+
158
160
static final int MAX_PAGE_SIZE = 14400 ;
159
161
static final int MIN_PAGE_SIZE = 3 ;
160
162
private static final int MAX_NUMBER_OF_DEVICEN_COLOR_COMPONENTS = 32 ;
161
163
162
164
private static final Logger logger = LoggerFactory .getLogger (PdfAChecker .class );
163
165
166
+ private static final String TRANSPARENCY_ERROR_MESSAGE =
167
+ PdfAConformanceException .THE_DOCUMENT_DOES_NOT_CONTAIN_A_PDFA_OUTPUTINTENT_BUT_PAGE_CONTAINS_TRANSPARENCY_AND_DOES_NOT_CONTAIN_BLENDING_COLOR_SPACE ;
168
+
164
169
private boolean currentFillCsIsIccBasedCMYK = false ;
165
170
private boolean currentStrokeCsIsIccBasedCMYK = false ;
166
171
167
172
private Map <PdfName , PdfArray > separationColorSpaces = new HashMap <>();
168
173
169
- private Set <PdfObject > transparencyObjects = new HashSet <>();
170
-
171
174
/**
172
175
* Creates a PdfA2Checker with the required conformance level
173
176
*
@@ -423,6 +426,9 @@ protected void checkPdfDictionary(PdfDictionary dictionary) {
423
426
// currently no validation for dictionaries is implemented for PDF/A 2
424
427
}
425
428
429
+ /**
430
+ * {@inheritDoc}
431
+ */
426
432
@ Override
427
433
protected void checkAnnotation (PdfDictionary annotDic ) {
428
434
PdfName subtype = annotDic .getAsName (PdfName .Subtype );
@@ -732,9 +738,6 @@ protected void checkPageTransparency(PdfDictionary pageDict, PdfDictionary pageR
732
738
if (pdfAOutputIntentColorSpace == null
733
739
&& transparencyObjects .size () > 0
734
740
&& (pageDict .getAsDictionary (PdfName .Group ) == null || pageDict .getAsDictionary (PdfName .Group ).get (PdfName .CS ) == null )) {
735
- if (transparencyObjects .contains (pageDict )) {
736
- throw new PdfAConformanceException (PdfAConformanceException .THE_DOCUMENT_DOES_NOT_CONTAIN_A_PDFA_OUTPUTINTENT_BUT_PAGE_CONTAINS_TRANSPARENCY_AND_DOES_NOT_CONTAIN_BLENDING_COLOR_SPACE );
737
- }
738
741
checkContentsForTransparency (pageDict );
739
742
checkAnnotationsForTransparency (pageDict .getAsArray (PdfName .Annots ));
740
743
checkResourcesForTransparency (pageResources , new HashSet <PdfObject >());
@@ -967,28 +970,52 @@ protected void checkFormXObject(PdfStream form, PdfStream contentStream) {
967
970
checkContentStream (form );
968
971
}
969
972
970
- private void checkContentsForTransparency (PdfDictionary pageDict ) {
973
+ /**
974
+ * Retrieve transparency error message valid for the pdf/a standard being used.
975
+ *
976
+ * @return error message.
977
+ */
978
+ protected String getTransparencyErrorMessage () {
979
+ return TRANSPARENCY_ERROR_MESSAGE ;
980
+ }
981
+
982
+ /**
983
+ * Check if blendMode is compatible with pdf/a standard being used.
984
+ *
985
+ * @param blendMode blend mode name to check.
986
+ */
987
+ protected void checkBlendMode (PdfName blendMode ) {
988
+ if (!allowedBlendModes .contains (blendMode )) {
989
+ throw new PdfAConformanceException (PdfAConformanceException .ONLY_STANDARD_BLEND_MODES_SHALL_BE_USED_FOR_THE_VALUE_OF_THE_BM_KEY_IN_AN_EXTENDED_GRAPHIC_STATE_DICTIONARY );
990
+ }
991
+ }
992
+
993
+ void checkContentsForTransparency (PdfDictionary pageDict ) {
971
994
PdfStream contentStream = pageDict .getAsStream (PdfName .Contents );
972
995
if (contentStream != null && transparencyObjects .contains (contentStream )) {
973
- throw new PdfAConformanceException (PdfAConformanceException . THE_DOCUMENT_DOES_NOT_CONTAIN_A_PDFA_OUTPUTINTENT_BUT_PAGE_CONTAINS_TRANSPARENCY_AND_DOES_NOT_CONTAIN_BLENDING_COLOR_SPACE );
996
+ throw new PdfAConformanceException (getTransparencyErrorMessage () );
974
997
} else {
975
998
PdfArray contentSteamArray = pageDict .getAsArray (PdfName .Contents );
976
999
if (contentSteamArray != null ) {
977
1000
for (int i = 0 ; i < contentSteamArray .size (); i ++) {
978
1001
if (transparencyObjects .contains (contentSteamArray .get (i ))) {
979
- throw new PdfAConformanceException (PdfAConformanceException . THE_DOCUMENT_DOES_NOT_CONTAIN_A_PDFA_OUTPUTINTENT_BUT_PAGE_CONTAINS_TRANSPARENCY_AND_DOES_NOT_CONTAIN_BLENDING_COLOR_SPACE );
1002
+ throw new PdfAConformanceException (getTransparencyErrorMessage () );
980
1003
}
981
1004
}
982
1005
}
983
1006
}
984
1007
}
985
1008
986
- private void checkAnnotationsForTransparency (PdfArray annotations ) {
1009
+ void checkAnnotationsForTransparency (PdfArray annotations ) {
987
1010
if (annotations == null ) {
988
1011
return ;
989
1012
}
990
1013
for (int i = 0 ; i < annotations .size (); ++i ) {
991
1014
PdfDictionary annot = annotations .getAsDictionary (i );
1015
+ if (this .transparencyObjects .contains (annot )) {
1016
+ throw new PdfAConformanceException (getTransparencyErrorMessage ());
1017
+ }
1018
+
992
1019
PdfDictionary ap = annot .getAsDictionary (PdfName .AP );
993
1020
if (ap != null ) {
994
1021
checkAppearanceStreamForTransparency (ap , new HashSet <PdfObject >());
@@ -1002,9 +1029,10 @@ private void checkAppearanceStreamForTransparency(PdfDictionary ap, Set<PdfObjec
1002
1029
} else {
1003
1030
checkedObjects .add (ap );
1004
1031
}
1032
+
1005
1033
for (final PdfObject val : ap .values ()) {
1006
1034
if (this .transparencyObjects .contains (val )) {
1007
- throw new PdfAConformanceException (PdfAConformanceException . THE_DOCUMENT_DOES_NOT_CONTAIN_A_PDFA_OUTPUTINTENT_BUT_PAGE_CONTAINS_TRANSPARENCY_AND_DOES_NOT_CONTAIN_BLENDING_COLOR_SPACE );
1035
+ throw new PdfAConformanceException (getTransparencyErrorMessage () );
1008
1036
} else if (val .isDictionary ()) {
1009
1037
checkAppearanceStreamForTransparency ((PdfDictionary ) val , checkedObjects );
1010
1038
} else if (val .isStream ()) {
@@ -1021,14 +1049,14 @@ private void checkObjectWithResourcesForTransparency(PdfObject objectWithResourc
1021
1049
}
1022
1050
1023
1051
if (this .transparencyObjects .contains (objectWithResources )) {
1024
- throw new PdfAConformanceException (PdfAConformanceException . THE_DOCUMENT_DOES_NOT_CONTAIN_A_PDFA_OUTPUTINTENT_BUT_PAGE_CONTAINS_TRANSPARENCY_AND_DOES_NOT_CONTAIN_BLENDING_COLOR_SPACE );
1052
+ throw new PdfAConformanceException (getTransparencyErrorMessage () );
1025
1053
}
1026
1054
if (objectWithResources instanceof PdfDictionary ) {
1027
1055
checkResourcesForTransparency (((PdfDictionary ) objectWithResources ).getAsDictionary (PdfName .Resources ), checkedObjects );
1028
1056
}
1029
1057
}
1030
1058
1031
- private void checkResourcesForTransparency (PdfDictionary resources , Set <PdfObject > checkedObjects ) {
1059
+ void checkResourcesForTransparency (PdfDictionary resources , Set <PdfObject > checkedObjects ) {
1032
1060
if (resources != null ) {
1033
1061
checkSingleResourceTypeForTransparency (resources .getAsDictionary (PdfName .XObject ), checkedObjects );
1034
1062
checkSingleResourceTypeForTransparency (resources .getAsDictionary (PdfName .Pattern ), checkedObjects );
@@ -1043,12 +1071,6 @@ private void checkSingleResourceTypeForTransparency(PdfDictionary singleResource
1043
1071
}
1044
1072
}
1045
1073
1046
- private void checkBlendMode (PdfName blendMode ) {
1047
- if (!allowedBlendModes .contains (blendMode )) {
1048
- throw new PdfAConformanceException (PdfAConformanceException .ONLY_STANDARD_BLEND_MODES_SHALL_BE_USED_FOR_THE_VALUE_OF_THE_BM_KEY_IN_AN_EXTENDED_GRAPHIC_STATE_DICTIONARY );
1049
- }
1050
- }
1051
-
1052
1074
private void checkSeparationInsideDeviceN (PdfArray separation , PdfObject deviceNColorSpace , PdfObject deviceNTintTransform ) {
1053
1075
if (!isAltCSIsTheSame (separation .get (2 ), deviceNColorSpace ) ||
1054
1076
!deviceNTintTransform .equals (separation .get (3 ))) {
@@ -1083,7 +1105,6 @@ private void checkSeparationCS(PdfArray separation) {
1083
1105
} else {
1084
1106
separationColorSpaces .put (separation .getAsName (0 ), separation );
1085
1107
}
1086
-
1087
1108
}
1088
1109
1089
1110
private boolean isAltCSIsTheSame (PdfObject cs1 , PdfObject cs2 ) {
0 commit comments