1 /*
2  * $Id: PdfXConformanceImp.java 3829 2009-04-01 15:50:47Z blowagie $
3  *
4  * Copyright 2006 Bruno Lowagie (based on code by Paulo Soares)
5  *
6  * The contents of this file are subject to the Mozilla Public License Version 1.1
7  * (the "License"); you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the License.
13  *
14  * The Original Code is 'iText, a free JAVA-PDF library'.
15  *
16  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18  * All Rights Reserved.
19  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source code
23  * where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above.  If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the MPL as stated above or under the terms of the GNU
37  * Library General Public License as published by the Free Software Foundation;
38  * either version 2 of the License, or any later version.
39  *
40  * This library is distributed in the hope that it will be useful, but WITHOUT
41  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43  * details.
44  *
45  * If you didn't download this code from the following link, you should check if
46  * you aren't using an obsolete version:
47  * http://www.lowagie.com/iText/
48  */

49
50 package com.lowagie.text.pdf.internal;
51
52 import java.awt.Color;
53
54 import com.lowagie.text.pdf.BaseFont;
55 import com.lowagie.text.pdf.ExtendedColor;
56 import com.lowagie.text.pdf.PatternColor;
57 import com.lowagie.text.pdf.PdfArray;
58 import com.lowagie.text.pdf.PdfDictionary;
59 import com.lowagie.text.pdf.PdfGState;
60 import com.lowagie.text.pdf.PdfImage;
61 import com.lowagie.text.pdf.PdfName;
62 import com.lowagie.text.pdf.PdfNumber;
63 import com.lowagie.text.pdf.PdfObject;
64 import com.lowagie.text.pdf.PdfString;
65 import com.lowagie.text.pdf.PdfWriter;
66 import com.lowagie.text.pdf.PdfXConformanceException;
67 import com.lowagie.text.pdf.ShadingColor;
68 import com.lowagie.text.pdf.SpotColor;
69 import com.lowagie.text.pdf.interfaces.PdfXConformance;
70
71 public class PdfXConformanceImp implements PdfXConformance {
72
73     /** A key for an aspect that can be checked for PDF/X Conformance. */
74     public static final int PDFXKEY_COLOR = 1;
75     /** A key for an aspect that can be checked for PDF/X Conformance. */
76     public static final int PDFXKEY_CMYK = 2;
77     /** A key for an aspect that can be checked for PDF/X Conformance. */
78     public static final int PDFXKEY_RGB = 3;
79     /** A key for an aspect that can be checked for PDF/X Conformance. */
80     public static final int PDFXKEY_FONT = 4;
81     /** A key for an aspect that can be checked for PDF/X Conformance. */
82     public static final int PDFXKEY_IMAGE = 5;
83     /** A key for an aspect that can be checked for PDF/X Conformance. */
84     public static final int PDFXKEY_GSTATE = 6;
85     /** A key for an aspect that can be checked for PDF/X Conformance. */
86     public static final int PDFXKEY_LAYER = 7;
87     
88     /**
89      * The value indicating if the PDF has to be in conformance with PDF/X.
90      */

91     protected int pdfxConformance = PdfWriter.PDFXNONE;
92     
93     /**
94      * @see com.lowagie.text.pdf.interfaces.PdfXConformance#setPDFXConformance(int)
95      */

96     public void setPDFXConformance(int pdfxConformance) {
97         this.pdfxConformance = pdfxConformance;
98     }
99
100     /**
101      * @see com.lowagie.text.pdf.interfaces.PdfXConformance#getPDFXConformance()
102      */

103     public int getPDFXConformance() {
104         return pdfxConformance;
105     }
106     
107     /**
108      * Checks if the PDF/X Conformance is necessary.
109      * @return true if the PDF has to be in conformance with any of the PDF/X specifications
110      */

111     public boolean isPdfX() {
112         return pdfxConformance != PdfWriter.PDFXNONE;
113     }
114     /**
115      * Checks if the PDF has to be in conformance with PDF/X-1a:2001
116      * @return true of the PDF has to be in conformance with PDF/X-1a:2001
117      */

118     public boolean isPdfX1A2001() {
119         return pdfxConformance == PdfWriter.PDFX1A2001;
120     }
121     /**
122      * Checks if the PDF has to be in conformance with PDF/X-3:2002
123      * @return true of the PDF has to be in conformance with PDF/X-3:2002
124      */

125     public boolean isPdfX32002() {
126         return pdfxConformance == PdfWriter.PDFX32002;
127     }
128     
129     /**
130      * Checks if the PDF has to be in conformance with PDFA1
131      * @return true of the PDF has to be in conformance with PDFA1
132      */

133     public boolean isPdfA1() {
134         return pdfxConformance == PdfWriter.PDFA1A || pdfxConformance == PdfWriter.PDFA1B;
135     }
136     
137     /**
138      * Checks if the PDF has to be in conformance with PDFA1A
139      * @return true of the PDF has to be in conformance with PDFA1A
140      */

141     public boolean isPdfA1A() {
142         return pdfxConformance == PdfWriter.PDFA1A;
143     }
144     
145     public void completeInfoDictionary(PdfDictionary info) {
146         if (isPdfX() && !isPdfA1()) {
147             if (info.get(PdfName.GTS_PDFXVERSION) == null) {
148                 if (isPdfX1A2001()) {
149                     info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-1:2001"));
150                     info.put(new PdfName("GTS_PDFXConformance"), new PdfString("PDF/X-1a:2001"));
151                 }
152                 else if (isPdfX32002())
153                     info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-3:2002"));
154             }
155             if (info.get(PdfName.TITLE) == null) {
156                 info.put(PdfName.TITLE, new PdfString("Pdf document"));
157             }
158             if (info.get(PdfName.CREATOR) == null) {
159                 info.put(PdfName.CREATOR, new PdfString("Unknown"));
160             }
161             if (info.get(PdfName.TRAPPED) == null) {
162                 info.put(PdfName.TRAPPED, new PdfName("False"));
163             }
164         }
165     }
166     
167     public void completeExtraCatalog(PdfDictionary extraCatalog) {
168         if (isPdfX() && !isPdfA1()) {
169             if (extraCatalog.get(PdfName.OUTPUTINTENTS) == null) {
170                 PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
171                 out.put(PdfName.OUTPUTCONDITION, new PdfString("SWOP CGATS TR 001-1995"));
172                 out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString("CGATS TR 001"));
173                 out.put(PdfName.REGISTRYNAME, new PdfString("http://www.color.org"));
174                 out.put(PdfName.INFO, new PdfString(""));
175                 out.put(PdfName.S, PdfName.GTS_PDFX);
176                 extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
177             }
178         }
179     }
180     
181     /**
182      * Business logic that checks if a certain object is in conformance with PDF/X.
183      * @param writer    the writer that is supposed to write the PDF/X file
184      * @param key        the type of PDF/X conformance that has to be checked
185      * @param obj1        the object that is checked for conformance
186      */

187     public static void checkPDFXConformance(PdfWriter writer, int key, Object obj1) {
188         if (writer == null || !writer.isPdfX())
189             return;
190         int conf = writer.getPDFXConformance();
191         switch (key) {
192             case PDFXKEY_COLOR:
193                 switch (conf) {
194                     case PdfWriter.PDFX1A2001:
195                         if (obj1 instanceof ExtendedColor) {
196                             ExtendedColor ec = (ExtendedColor)obj1;
197                             switch (ec.getType()) {
198                                 case ExtendedColor.TYPE_CMYK:
199                                 case ExtendedColor.TYPE_GRAY:
200                                     return;
201                                 case ExtendedColor.TYPE_RGB:
202                                     throw new PdfXConformanceException("Colorspace RGB is not allowed.");
203                                 case ExtendedColor.TYPE_SEPARATION:
204                                     SpotColor sc = (SpotColor)ec;
205                                     checkPDFXConformance(writer, PDFXKEY_COLOR, sc.getPdfSpotColor().getAlternativeCS());
206                                     break;
207                                 case ExtendedColor.TYPE_SHADING:
208                                     ShadingColor xc = (ShadingColor)ec;
209                                     checkPDFXConformance(writer, PDFXKEY_COLOR, xc.getPdfShadingPattern().getShading().getColorSpace());
210                                     break;
211                                 case ExtendedColor.TYPE_PATTERN:
212                                     PatternColor pc = (PatternColor)ec;
213                                     checkPDFXConformance(writer, PDFXKEY_COLOR, pc.getPainter().getDefaultColor());
214                                     break;
215                             }
216                         }
217                         else if (obj1 instanceof Color)
218                             throw new PdfXConformanceException("Colorspace RGB is not allowed.");
219                         break;
220                 }
221                 break;
222             case PDFXKEY_CMYK:
223                 break;
224             case PDFXKEY_RGB:
225                 if (conf == PdfWriter.PDFX1A2001)
226                     throw new PdfXConformanceException("Colorspace RGB is not allowed.");
227                 break;
228             case PDFXKEY_FONT:
229                 if (!((BaseFont)obj1).isEmbedded())
230                     throw new PdfXConformanceException("All the fonts must be embedded. This one isn't: " + ((BaseFont)obj1).getPostscriptFontName());
231                 break;
232             case PDFXKEY_IMAGE:
233                 PdfImage image = (PdfImage)obj1;
234                 if (image.get(PdfName.SMASK) != null)
235                     throw new PdfXConformanceException("The /SMask key is not allowed in images.");
236                 switch (conf) {
237                     case PdfWriter.PDFX1A2001:
238                         PdfObject cs = image.get(PdfName.COLORSPACE);
239                         if (cs == null)
240                             return;
241                         if (cs.isName()) {
242                             if (PdfName.DEVICERGB.equals(cs))
243                                 throw new PdfXConformanceException("Colorspace RGB is not allowed.");
244                         }
245                         else if (cs.isArray()) {
246                             if (PdfName.CALRGB.equals(((PdfArray)cs).getPdfObject(0)))
247                                 throw new PdfXConformanceException("Colorspace CalRGB is not allowed.");
248                         }
249                         break;
250                 }
251                 break;
252             case PDFXKEY_GSTATE:
253                 PdfDictionary gs = (PdfDictionary)obj1;
254                 PdfObject obj = gs.get(PdfName.BM);
255                 if (obj != null && !PdfGState.BM_NORMAL.equals(obj) && !PdfGState.BM_COMPATIBLE.equals(obj))
256                     throw new PdfXConformanceException("Blend mode " + obj.toString() + " not allowed.");
257                 obj = gs.get(PdfName.CA);
258                 double v = 0.0;
259                 if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
260                     throw new PdfXConformanceException("Transparency is not allowed: /CA = " + v);
261                 obj = gs.get(PdfName.ca);
262                 v = 0.0;
263                 if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
264                     throw new PdfXConformanceException("Transparency is not allowed: /ca = " + v);
265                 break;
266             case PDFXKEY_LAYER:
267                 throw new PdfXConformanceException("Layers are not allowed.");
268         }
269     }
270 }
271