001/*
002 * $Id: PdfVersionImp.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 java.io.IOException;
047
048import com.itextpdf.text.DocWriter;
049import com.itextpdf.text.pdf.OutputStreamCounter;
050import com.itextpdf.text.pdf.PdfDeveloperExtension;
051import com.itextpdf.text.pdf.PdfDictionary;
052import com.itextpdf.text.pdf.PdfName;
053import com.itextpdf.text.pdf.PdfWriter;
054import com.itextpdf.text.pdf.interfaces.PdfVersion;
055
056/**
057 * Stores the PDF version information,
058 * knows how to write a PDF Header,
059 * and how to add the version to the catalog (if necessary).
060 */
061
062public class PdfVersionImp implements PdfVersion {
063    
064    /** Contains different strings that are part of the header. */
065    public static final byte[][] HEADER = {
066        DocWriter.getISOBytes("\n"),
067        DocWriter.getISOBytes("%PDF-"),
068        DocWriter.getISOBytes("\n%\u00e2\u00e3\u00cf\u00d3\n")
069    };
070    
071        /** Indicates if the header was already written. */
072        protected boolean headerWasWritten = false;
073        /** Indicates if we are working in append mode. */
074        protected boolean appendmode = false;
075        /** The version that was or will be written to the header. */
076        protected char header_version = PdfWriter.VERSION_1_4;
077        /** The version that will be written to the catalog. */
078        protected PdfName catalog_version = null;
079        /**
080         * The extensions dictionary.
081         * @since       2.1.6
082         */
083        protected PdfDictionary extensions = null;
084        
085        /**
086         * @see com.itextpdf.text.pdf.interfaces.PdfVersion#setPdfVersion(char)
087         */
088        public void setPdfVersion(char version) {
089                if (headerWasWritten || appendmode) {
090                        setPdfVersion(getVersionAsName(version));
091                }
092                else {
093                        this.header_version = version;
094                }
095        }
096        
097        /**
098         * @see com.itextpdf.text.pdf.interfaces.PdfVersion#setAtLeastPdfVersion(char)
099         */
100        public void setAtLeastPdfVersion(char version) {
101                if (version > header_version) {
102                        setPdfVersion(version);
103                }
104        }
105        
106        /**
107         * @see com.itextpdf.text.pdf.interfaces.PdfVersion#setPdfVersion(com.itextpdf.text.pdf.PdfName)
108         */
109        public void setPdfVersion(PdfName version) {
110                if (catalog_version == null || catalog_version.compareTo(version) < 0) {
111                        this.catalog_version = version;
112                }
113        }
114        
115        /**
116         * Sets the append mode.
117         */
118        public void setAppendmode(boolean appendmode) {
119                this.appendmode = appendmode;
120        }
121        
122        /**
123         * Writes the header to the OutputStreamCounter.
124         * @throws IOException 
125         */
126        public void writeHeader(OutputStreamCounter os) throws IOException {
127                if (appendmode) {
128                        os.write(HEADER[0]);
129                }
130                else {
131                        os.write(HEADER[1]);
132                        os.write(getVersionAsByteArray(header_version));
133                        os.write(HEADER[2]);
134                        headerWasWritten = true;
135                }
136        }
137        
138        /**
139         * Returns the PDF version as a name.
140         * @param version       the version character.
141         */
142        public PdfName getVersionAsName(char version) {
143                switch(version) {
144                case PdfWriter.VERSION_1_2:
145                        return PdfWriter.PDF_VERSION_1_2;
146                case PdfWriter.VERSION_1_3:
147                        return PdfWriter.PDF_VERSION_1_3;
148                case PdfWriter.VERSION_1_4:
149                        return PdfWriter.PDF_VERSION_1_4;
150                case PdfWriter.VERSION_1_5:
151                        return PdfWriter.PDF_VERSION_1_5;
152                case PdfWriter.VERSION_1_6:
153                        return PdfWriter.PDF_VERSION_1_6;
154                case PdfWriter.VERSION_1_7:
155                        return PdfWriter.PDF_VERSION_1_7;
156                default:
157                        return PdfWriter.PDF_VERSION_1_4;
158                }
159        }
160        
161        /**
162         * Returns the version as a byte[].
163         * @param version the version character
164         */
165        public byte[] getVersionAsByteArray(char version) {
166                return DocWriter.getISOBytes(getVersionAsName(version).toString().substring(1));
167        }
168
169        /** Adds the version to the Catalog dictionary. */
170        public void addToCatalog(PdfDictionary catalog) {
171                if(catalog_version != null) {
172                        catalog.put(PdfName.VERSION, catalog_version);
173                }
174                if (extensions != null) {
175                        catalog.put(PdfName.EXTENSIONS, extensions);
176                }
177        }
178
179        /**
180         * @see com.itextpdf.text.pdf.interfaces.PdfVersion#addDeveloperExtension(com.itextpdf.text.pdf.PdfDeveloperExtension)
181         * @since       2.1.6
182         */
183        public void addDeveloperExtension(PdfDeveloperExtension de) {
184                if (extensions == null) {
185                        extensions = new PdfDictionary();
186                }
187                else {
188                        PdfDictionary extension = extensions.getAsDict(de.getPrefix());
189                        if (extension != null) {
190                                int diff = de.getBaseversion().compareTo(extension.getAsName(PdfName.BASEVERSION));
191                                if (diff < 0)
192                                        return;
193                                diff = de.getExtensionLevel() - extension.getAsNumber(PdfName.EXTENSIONLEVEL).intValue();
194                                if (diff <= 0)
195                                        return;
196                        }
197                }
198                extensions.put(de.getPrefix(), de.getDeveloperExtensions());
199        }
200}