001/* 002 * $Id: PdfXConformanceImp.java 4784 2011-03-15 08:33:00Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.pdf.internal; 045 046import com.itextpdf.text.BaseColor; 047import com.itextpdf.text.error_messages.MessageLocalization; 048 049import com.itextpdf.text.pdf.BaseFont; 050import com.itextpdf.text.pdf.ExtendedColor; 051import com.itextpdf.text.pdf.PatternColor; 052import com.itextpdf.text.pdf.PdfArray; 053import com.itextpdf.text.pdf.PdfDictionary; 054import com.itextpdf.text.pdf.PdfGState; 055import com.itextpdf.text.pdf.PdfImage; 056import com.itextpdf.text.pdf.PdfName; 057import com.itextpdf.text.pdf.PdfNumber; 058import com.itextpdf.text.pdf.PdfObject; 059import com.itextpdf.text.pdf.PdfString; 060import com.itextpdf.text.pdf.PdfWriter; 061import com.itextpdf.text.pdf.PdfXConformanceException; 062import com.itextpdf.text.pdf.ShadingColor; 063import com.itextpdf.text.pdf.SpotColor; 064import com.itextpdf.text.pdf.interfaces.PdfXConformance; 065 066public class PdfXConformanceImp implements PdfXConformance { 067 068 /** A key for an aspect that can be checked for PDF/X Conformance. */ 069 public static final int PDFXKEY_COLOR = 1; 070 /** A key for an aspect that can be checked for PDF/X Conformance. */ 071 public static final int PDFXKEY_CMYK = 2; 072 /** A key for an aspect that can be checked for PDF/X Conformance. */ 073 public static final int PDFXKEY_RGB = 3; 074 /** A key for an aspect that can be checked for PDF/X Conformance. */ 075 public static final int PDFXKEY_FONT = 4; 076 /** A key for an aspect that can be checked for PDF/X Conformance. */ 077 public static final int PDFXKEY_IMAGE = 5; 078 /** A key for an aspect that can be checked for PDF/X Conformance. */ 079 public static final int PDFXKEY_GSTATE = 6; 080 /** A key for an aspect that can be checked for PDF/X Conformance. */ 081 public static final int PDFXKEY_LAYER = 7; 082 083 /** 084 * The value indicating if the PDF has to be in conformance with PDF/X. 085 */ 086 protected int pdfxConformance = PdfWriter.PDFXNONE; 087 088 /** 089 * @see com.itextpdf.text.pdf.interfaces.PdfXConformance#setPDFXConformance(int) 090 */ 091 public void setPDFXConformance(int pdfxConformance) { 092 this.pdfxConformance = pdfxConformance; 093 } 094 095 /** 096 * @see com.itextpdf.text.pdf.interfaces.PdfXConformance#getPDFXConformance() 097 */ 098 public int getPDFXConformance() { 099 return pdfxConformance; 100 } 101 102 /** 103 * Checks if the PDF/X Conformance is necessary. 104 * @return true if the PDF has to be in conformance with any of the PDF/X specifications 105 */ 106 public boolean isPdfX() { 107 return pdfxConformance != PdfWriter.PDFXNONE; 108 } 109 /** 110 * Checks if the PDF has to be in conformance with PDF/X-1a:2001 111 * @return true of the PDF has to be in conformance with PDF/X-1a:2001 112 */ 113 public boolean isPdfX1A2001() { 114 return pdfxConformance == PdfWriter.PDFX1A2001; 115 } 116 /** 117 * Checks if the PDF has to be in conformance with PDF/X-3:2002 118 * @return true of the PDF has to be in conformance with PDF/X-3:2002 119 */ 120 public boolean isPdfX32002() { 121 return pdfxConformance == PdfWriter.PDFX32002; 122 } 123 124 /** 125 * Checks if the PDF has to be in conformance with PDFA1 126 * @return true of the PDF has to be in conformance with PDFA1 127 */ 128 public boolean isPdfA1() { 129 return pdfxConformance == PdfWriter.PDFA1A || pdfxConformance == PdfWriter.PDFA1B; 130 } 131 132 /** 133 * Checks if the PDF has to be in conformance with PDFA1A 134 * @return true of the PDF has to be in conformance with PDFA1A 135 */ 136 public boolean isPdfA1A() { 137 return pdfxConformance == PdfWriter.PDFA1A; 138 } 139 140 public void completeInfoDictionary(PdfDictionary info) { 141 if (isPdfX() && !isPdfA1()) { 142 if (info.get(PdfName.GTS_PDFXVERSION) == null) { 143 if (isPdfX1A2001()) { 144 info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-1:2001")); 145 info.put(new PdfName("GTS_PDFXConformance"), new PdfString("PDF/X-1a:2001")); 146 } 147 else if (isPdfX32002()) 148 info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-3:2002")); 149 } 150 if (info.get(PdfName.TITLE) == null) { 151 info.put(PdfName.TITLE, new PdfString("Pdf document")); 152 } 153 if (info.get(PdfName.CREATOR) == null) { 154 info.put(PdfName.CREATOR, new PdfString("Unknown")); 155 } 156 if (info.get(PdfName.TRAPPED) == null) { 157 info.put(PdfName.TRAPPED, new PdfName("False")); 158 } 159 } 160 } 161 162 public void completeExtraCatalog(PdfDictionary extraCatalog) { 163 if (isPdfX() && !isPdfA1()) { 164 if (extraCatalog.get(PdfName.OUTPUTINTENTS) == null) { 165 PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT); 166 out.put(PdfName.OUTPUTCONDITION, new PdfString("SWOP CGATS TR 001-1995")); 167 out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString("CGATS TR 001")); 168 out.put(PdfName.REGISTRYNAME, new PdfString("http://www.color.org")); 169 out.put(PdfName.INFO, new PdfString("")); 170 out.put(PdfName.S, PdfName.GTS_PDFX); 171 extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out)); 172 } 173 } 174 } 175 176 /** 177 * Business logic that checks if a certain object is in conformance with PDF/X. 178 * @param writer the writer that is supposed to write the PDF/X file 179 * @param key the type of PDF/X conformance that has to be checked 180 * @param obj1 the object that is checked for conformance 181 */ 182 public static void checkPDFXConformance(PdfWriter writer, int key, Object obj1) { 183 if (writer == null || !writer.isPdfX()) 184 return; 185 int conf = writer.getPDFXConformance(); 186 switch (key) { 187 case PDFXKEY_COLOR: 188 switch (conf) { 189 case PdfWriter.PDFX1A2001: 190 if (obj1 instanceof ExtendedColor) { 191 ExtendedColor ec = (ExtendedColor)obj1; 192 switch (ec.getType()) { 193 case ExtendedColor.TYPE_CMYK: 194 case ExtendedColor.TYPE_GRAY: 195 return; 196 case ExtendedColor.TYPE_RGB: 197 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("colorspace.rgb.is.not.allowed")); 198 case ExtendedColor.TYPE_SEPARATION: 199 SpotColor sc = (SpotColor)ec; 200 checkPDFXConformance(writer, PDFXKEY_COLOR, sc.getPdfSpotColor().getAlternativeCS()); 201 break; 202 case ExtendedColor.TYPE_SHADING: 203 ShadingColor xc = (ShadingColor)ec; 204 checkPDFXConformance(writer, PDFXKEY_COLOR, xc.getPdfShadingPattern().getShading().getColorSpace()); 205 break; 206 case ExtendedColor.TYPE_PATTERN: 207 PatternColor pc = (PatternColor)ec; 208 checkPDFXConformance(writer, PDFXKEY_COLOR, pc.getPainter().getDefaultColor()); 209 break; 210 } 211 } 212 else if (obj1 instanceof BaseColor) 213 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("colorspace.rgb.is.not.allowed")); 214 break; 215 } 216 break; 217 case PDFXKEY_CMYK: 218 break; 219 case PDFXKEY_RGB: 220 if (conf == PdfWriter.PDFX1A2001) 221 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("colorspace.rgb.is.not.allowed")); 222 break; 223 case PDFXKEY_FONT: 224 if (!((BaseFont)obj1).isEmbedded()) 225 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("all.the.fonts.must.be.embedded.this.one.isn.t.1", ((BaseFont)obj1).getPostscriptFontName())); 226 break; 227 case PDFXKEY_IMAGE: 228 PdfImage image = (PdfImage)obj1; 229 if (image.get(PdfName.SMASK) != null) 230 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("the.smask.key.is.not.allowed.in.images")); 231 switch (conf) { 232 case PdfWriter.PDFX1A2001: 233 PdfObject cs = image.get(PdfName.COLORSPACE); 234 if (cs == null) 235 return; 236 if (cs.isName()) { 237 if (PdfName.DEVICERGB.equals(cs)) 238 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("colorspace.rgb.is.not.allowed")); 239 } 240 else if (cs.isArray()) { 241 if (PdfName.CALRGB.equals(((PdfArray)cs).getPdfObject(0))) 242 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("colorspace.calrgb.is.not.allowed")); 243 } 244 break; 245 } 246 break; 247 case PDFXKEY_GSTATE: 248 PdfDictionary gs = (PdfDictionary)obj1; 249 PdfObject obj = gs.get(PdfName.BM); 250 if (obj != null && !PdfGState.BM_NORMAL.equals(obj) && !PdfGState.BM_COMPATIBLE.equals(obj)) 251 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("blend.mode.1.not.allowed", obj.toString())); 252 obj = gs.get(PdfName.CA); 253 double v = 0.0; 254 if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0) 255 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("transparency.is.not.allowed.ca.eq.1", String.valueOf(v))); 256 obj = gs.get(PdfName.ca); 257 v = 0.0; 258 if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0) 259 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("transparency.is.not.allowed.ca.eq.1", String.valueOf(v))); 260 break; 261 case PDFXKEY_LAYER: 262 throw new PdfXConformanceException(MessageLocalization.getComposedMessage("layers.are.not.allowed")); 263 } 264 } 265}