001/*
002 * $Id: PdfViewerPreferencesImp.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.pdf.PdfArray;
047import com.itextpdf.text.pdf.PdfBoolean;
048import com.itextpdf.text.pdf.PdfDictionary;
049import com.itextpdf.text.pdf.PdfName;
050import com.itextpdf.text.pdf.PdfNumber;
051import com.itextpdf.text.pdf.PdfObject;
052import com.itextpdf.text.pdf.PdfReader;
053import com.itextpdf.text.pdf.PdfWriter;
054import com.itextpdf.text.pdf.interfaces.PdfViewerPreferences;
055
056/**
057 * Stores the information concerning viewer preferences,
058 * and contains the business logic that allows you to set viewer preferences.
059 */
060
061public class PdfViewerPreferencesImp implements PdfViewerPreferences {
062        public static final PdfName[] VIEWER_PREFERENCES = {
063                        PdfName.HIDETOOLBAR,                    // 0
064                        PdfName.HIDEMENUBAR,            // 1
065                        PdfName.HIDEWINDOWUI,           // 2
066                        PdfName.FITWINDOW,              // 3
067                        PdfName.CENTERWINDOW,                   // 4
068                        PdfName.DISPLAYDOCTITLE,                // 5
069                        PdfName.NONFULLSCREENPAGEMODE,  // 6
070                        PdfName.DIRECTION,                              // 7
071                        PdfName.VIEWAREA,                               // 8
072                        PdfName.VIEWCLIP,                               // 9
073                        PdfName.PRINTAREA,                              // 10
074                        PdfName.PRINTCLIP,                              // 11
075                        PdfName.PRINTSCALING,                   // 12
076                        PdfName.DUPLEX,                                 // 13
077                        PdfName.PICKTRAYBYPDFSIZE,              // 14
078                        PdfName.PRINTPAGERANGE,                 // 15
079                        PdfName.NUMCOPIES                               // 16
080                };
081
082
083    /** A series of viewer preferences. */
084    public static final PdfName NONFULLSCREENPAGEMODE_PREFERENCES[] = {
085        PdfName.USENONE, PdfName.USEOUTLINES, PdfName.USETHUMBS, PdfName.USEOC
086    };
087    /** A series of viewer preferences. */
088    public static final PdfName DIRECTION_PREFERENCES[] = {
089        PdfName.L2R, PdfName.R2L
090    };
091        /** A series of viewer preferences. */
092        public static final PdfName PAGE_BOUNDARIES[] = {
093                PdfName.MEDIABOX, PdfName.CROPBOX, PdfName.BLEEDBOX, PdfName.TRIMBOX, PdfName.ARTBOX
094        };
095        /** A series of viewer preferences */
096        public static final PdfName PRINTSCALING_PREFERENCES[] = {
097                PdfName.APPDEFAULT, PdfName.NONE
098        };
099        /** A series of viewer preferences. */
100        public static final PdfName DUPLEX_PREFERENCES[] = {
101                PdfName.SIMPLEX, PdfName.DUPLEXFLIPSHORTEDGE, PdfName.DUPLEXFLIPLONGEDGE
102        };
103        
104        /** This value will hold the viewer preferences for the page layout and page mode. */
105        private int pageLayoutAndMode = 0;
106        
107        /** This dictionary holds the viewer preferences (other than page layout and page mode). */
108        private PdfDictionary viewerPreferences = new PdfDictionary();
109        
110        /** The mask to decide if a ViewerPreferences dictionary is needed */
111        private static final int viewerPreferencesMask = 0xfff000;
112
113        /**
114         * Returns the page layout and page mode value.
115         */
116        public int getPageLayoutAndMode() {
117                return pageLayoutAndMode;
118        }
119
120        /**
121         * Returns the viewer preferences.
122         */
123        public PdfDictionary getViewerPreferences() {
124                return viewerPreferences;
125        }
126        
127        /**
128         * Sets the viewer preferences as the sum of several constants.
129         * 
130         * @param preferences
131         *            the viewer preferences
132         * @see PdfViewerPreferences#setViewerPreferences
133         */
134        public void setViewerPreferences(int preferences) {
135                this.pageLayoutAndMode |= preferences;
136                // for backwards compatibility, it is also possible
137                // to set the following viewer preferences with this method:
138                if ((preferences & viewerPreferencesMask) != 0) {
139                        pageLayoutAndMode = ~viewerPreferencesMask & pageLayoutAndMode;
140                        if ((preferences & PdfWriter.HideToolbar) != 0)
141                                viewerPreferences.put(PdfName.HIDETOOLBAR, PdfBoolean.PDFTRUE);
142                        if ((preferences & PdfWriter.HideMenubar) != 0)
143                                viewerPreferences.put(PdfName.HIDEMENUBAR, PdfBoolean.PDFTRUE);
144                        if ((preferences & PdfWriter.HideWindowUI) != 0)
145                                viewerPreferences.put(PdfName.HIDEWINDOWUI, PdfBoolean.PDFTRUE);
146                        if ((preferences & PdfWriter.FitWindow) != 0)
147                                viewerPreferences.put(PdfName.FITWINDOW, PdfBoolean.PDFTRUE);
148                        if ((preferences & PdfWriter.CenterWindow) != 0)
149                                viewerPreferences.put(PdfName.CENTERWINDOW, PdfBoolean.PDFTRUE);
150                        if ((preferences & PdfWriter.DisplayDocTitle) != 0)
151                                viewerPreferences.put(PdfName.DISPLAYDOCTITLE, PdfBoolean.PDFTRUE);
152                        
153                        if ((preferences & PdfWriter.NonFullScreenPageModeUseNone) != 0)
154                                viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USENONE);
155                        else if ((preferences & PdfWriter.NonFullScreenPageModeUseOutlines) != 0)
156                                viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOUTLINES);
157                        else if ((preferences & PdfWriter.NonFullScreenPageModeUseThumbs) != 0)
158                                viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USETHUMBS);
159                        else if ((preferences & PdfWriter.NonFullScreenPageModeUseOC) != 0)
160                                viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOC);
161
162                        if ((preferences & PdfWriter.DirectionL2R) != 0)
163                                viewerPreferences.put(PdfName.DIRECTION, PdfName.L2R);
164                        else if ((preferences & PdfWriter.DirectionR2L) != 0)
165                                viewerPreferences.put(PdfName.DIRECTION, PdfName.R2L);
166
167                        if ((preferences & PdfWriter.PrintScalingNone) != 0)
168                                viewerPreferences.put(PdfName.PRINTSCALING, PdfName.NONE);                      
169                }
170        }
171        
172        /**
173         * Given a key for a viewer preference (a PdfName object),
174         * this method returns the index in the VIEWER_PREFERENCES array.
175         * @param key   a PdfName referring to a viewer preference
176         * @return      an index in the VIEWER_PREFERENCES array
177         */
178        private int getIndex(PdfName key) {
179                for (int i = 0; i < VIEWER_PREFERENCES.length; i++) {
180                        if (VIEWER_PREFERENCES[i].equals(key))
181                                return i;
182                }
183                return -1;
184        }
185        
186        /**
187         * Checks if some value is valid for a certain key.
188         */
189        private boolean isPossibleValue(PdfName value, PdfName[] accepted) {
190                for (int i = 0; i < accepted.length; i++) {
191                        if (accepted[i].equals(value)) {
192                                return true;
193                        }
194                }
195                return false;
196        }
197        
198        /**
199         * Sets the viewer preferences for printing.
200         */
201        public void addViewerPreference(PdfName key, PdfObject value) {
202                switch(getIndex(key)) {
203                case 0: // HIDETOOLBAR
204                case 1: // HIDEMENUBAR
205                case 2: // HIDEWINDOWUI
206                case 3: // FITWINDOW
207                case 4: // CENTERWINDOW
208                case 5: // DISPLAYDOCTITLE
209                case 14: // PICKTRAYBYPDFSIZE
210                        if (value instanceof PdfBoolean) {
211                                viewerPreferences.put(key, value);
212                        }
213                        break;
214                case 6: // NONFULLSCREENPAGEMODE
215                        if (value instanceof PdfName
216                                        && isPossibleValue((PdfName)value, NONFULLSCREENPAGEMODE_PREFERENCES)) {
217                                viewerPreferences.put(key, value);
218                        }
219                        break;
220                case 7: // DIRECTION
221                        if (value instanceof PdfName
222                                        && isPossibleValue((PdfName)value, DIRECTION_PREFERENCES)) {
223                                viewerPreferences.put(key, value);
224                        }
225                        break;
226                case 8:  // VIEWAREA
227                case 9:  // VIEWCLIP
228                case 10: // PRINTAREA
229                case 11: // PRINTCLIP
230                        if (value instanceof PdfName
231                                        && isPossibleValue((PdfName)value, PAGE_BOUNDARIES)) {
232                                viewerPreferences.put(key, value);
233                        }
234                        break;
235                case 12: // PRINTSCALING
236                        if (value instanceof PdfName
237                                        && isPossibleValue((PdfName)value, PRINTSCALING_PREFERENCES)) {
238                                viewerPreferences.put(key, value);
239                        }
240                        break;
241                case 13: // DUPLEX
242                        if (value instanceof PdfName
243                                        && isPossibleValue((PdfName)value, DUPLEX_PREFERENCES)) {
244                                viewerPreferences.put(key, value);
245                        }
246                        break;
247                case 15: // PRINTPAGERANGE
248                        if (value instanceof PdfArray) {
249                                viewerPreferences.put(key, value);
250                        }
251                        break;
252                case 16: // NUMCOPIES
253                        if (value instanceof PdfNumber)  {
254                                viewerPreferences.put(key, value);
255                        }
256                        break;
257                }
258        }
259
260        /**
261         * Adds the viewer preferences defined in the preferences parameter to a
262         * PdfDictionary (more specifically the root or catalog of a PDF file).
263         * 
264         * @param catalog
265         */
266        public void addToCatalog(PdfDictionary catalog) {
267                // Page Layout
268                catalog.remove(PdfName.PAGELAYOUT);
269                if ((pageLayoutAndMode & PdfWriter.PageLayoutSinglePage) != 0)
270                        catalog.put(PdfName.PAGELAYOUT, PdfName.SINGLEPAGE);
271                else if ((pageLayoutAndMode & PdfWriter.PageLayoutOneColumn) != 0)
272                        catalog.put(PdfName.PAGELAYOUT, PdfName.ONECOLUMN);
273                else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoColumnLeft) != 0)
274                        catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNLEFT);
275                else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoColumnRight) != 0)
276                        catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNRIGHT);
277                else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoPageLeft) != 0)
278                        catalog.put(PdfName.PAGELAYOUT, PdfName.TWOPAGELEFT);
279                else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoPageRight) != 0)
280                        catalog.put(PdfName.PAGELAYOUT, PdfName.TWOPAGERIGHT);
281
282                // Page Mode
283                catalog.remove(PdfName.PAGEMODE);
284                if ((pageLayoutAndMode & PdfWriter.PageModeUseNone) != 0)
285                        catalog.put(PdfName.PAGEMODE, PdfName.USENONE);
286                else if ((pageLayoutAndMode & PdfWriter.PageModeUseOutlines) != 0)
287                        catalog.put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
288                else if ((pageLayoutAndMode & PdfWriter.PageModeUseThumbs) != 0)
289                        catalog.put(PdfName.PAGEMODE, PdfName.USETHUMBS);
290                else if ((pageLayoutAndMode & PdfWriter.PageModeFullScreen) != 0)
291                        catalog.put(PdfName.PAGEMODE, PdfName.FULLSCREEN);
292                else if ((pageLayoutAndMode & PdfWriter.PageModeUseOC) != 0)
293                        catalog.put(PdfName.PAGEMODE, PdfName.USEOC);
294                else if ((pageLayoutAndMode & PdfWriter.PageModeUseAttachments) != 0)
295                        catalog.put(PdfName.PAGEMODE, PdfName.USEATTACHMENTS);
296
297                // viewer preferences (Table 8.1 of the PDF Reference)
298                catalog.remove(PdfName.VIEWERPREFERENCES);
299                if (viewerPreferences.size() > 0) {
300                        catalog.put(PdfName.VIEWERPREFERENCES, viewerPreferences);
301                }
302        }
303
304        public static PdfViewerPreferencesImp getViewerPreferences(PdfDictionary catalog) {
305                PdfViewerPreferencesImp preferences = new PdfViewerPreferencesImp();
306                int prefs = 0;
307                PdfName name = null;
308                // page layout
309                PdfObject obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.PAGELAYOUT));
310                if (obj != null && obj.isName()) {
311                        name = (PdfName) obj;
312                        if (name.equals(PdfName.SINGLEPAGE))
313                                prefs |= PdfWriter.PageLayoutSinglePage;
314                        else if (name.equals(PdfName.ONECOLUMN))
315                                prefs |= PdfWriter.PageLayoutOneColumn;
316                        else if (name.equals(PdfName.TWOCOLUMNLEFT))
317                                prefs |= PdfWriter.PageLayoutTwoColumnLeft;
318                        else if (name.equals(PdfName.TWOCOLUMNRIGHT))
319                                prefs |= PdfWriter.PageLayoutTwoColumnRight;
320                        else if (name.equals(PdfName.TWOPAGELEFT))
321                                prefs |= PdfWriter.PageLayoutTwoPageLeft;
322                        else if (name.equals(PdfName.TWOPAGERIGHT))
323                                prefs |= PdfWriter.PageLayoutTwoPageRight;
324                }
325                // page mode
326                obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.PAGEMODE));
327                if (obj != null && obj.isName()) {
328                        name = (PdfName) obj;
329                        if (name.equals(PdfName.USENONE))
330                                prefs |= PdfWriter.PageModeUseNone;
331                        else if (name.equals(PdfName.USEOUTLINES))
332                                prefs |= PdfWriter.PageModeUseOutlines;
333                        else if (name.equals(PdfName.USETHUMBS))
334                                prefs |= PdfWriter.PageModeUseThumbs;
335                        else if (name.equals(PdfName.FULLSCREEN))
336                                prefs |= PdfWriter.PageModeFullScreen;
337                        else if (name.equals(PdfName.USEOC))
338                                prefs |= PdfWriter.PageModeUseOC;
339                        else if (name.equals(PdfName.USEATTACHMENTS))
340                                prefs |= PdfWriter.PageModeUseAttachments;
341                }
342                // set page layout and page mode preferences
343                preferences.setViewerPreferences(prefs);
344                // other preferences
345                obj = PdfReader.getPdfObjectRelease(catalog
346                                .get(PdfName.VIEWERPREFERENCES));
347                if (obj != null && obj.isDictionary()) {
348                        PdfDictionary vp = (PdfDictionary) obj;
349                        for (int i = 0; i < VIEWER_PREFERENCES.length; i++) {
350                                obj = PdfReader.getPdfObjectRelease(vp.get(VIEWER_PREFERENCES[i]));
351                                preferences.addViewerPreference(VIEWER_PREFERENCES[i], obj);
352                        }
353                }
354                return preferences;
355        }
356}