001: /*
002: * $Id: PdfPages.java 2441 2006-10-27 17:24:01Z xlv $
003: * $Name$
004: *
005: * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.pdf;
052:
053: import java.io.IOException;
054: import java.util.ArrayList;
055:
056: import com.lowagie.text.DocumentException;
057: import com.lowagie.text.ExceptionConverter;
058:
059: /**
060: * <CODE>PdfPages</CODE> is the PDF Pages-object.
061: * <P>
062: * The Pages of a document are accessible through a tree of nodes known as the Pages tree.
063: * This tree defines the ordering of the pages in the document.<BR>
064: * This object is described in the 'Portable Document Format Reference Manual version 1.3'
065: * section 6.3 (page 71-73)
066: *
067: * @see PdfPage
068: */
069:
070: public class PdfPages {
071:
072: private ArrayList pages = new ArrayList();
073: private ArrayList parents = new ArrayList();
074: private int leafSize = 10;
075: private PdfWriter writer;
076: private PdfIndirectReference topParent;
077:
078: // constructors
079:
080: /**
081: * Constructs a <CODE>PdfPages</CODE>-object.
082: */
083:
084: PdfPages(PdfWriter writer) {
085: this .writer = writer;
086: }
087:
088: void addPage(PdfDictionary page) {
089: try {
090: if ((pages.size() % leafSize) == 0)
091: parents.add(writer.getPdfIndirectReference());
092: PdfIndirectReference parent = (PdfIndirectReference) parents
093: .get(parents.size() - 1);
094: page.put(PdfName.PARENT, parent);
095: PdfIndirectReference current = writer.getCurrentPage();
096: writer.addToBody(page, current);
097: pages.add(current);
098: } catch (Exception e) {
099: throw new ExceptionConverter(e);
100: }
101: }
102:
103: PdfIndirectReference addPageRef(PdfIndirectReference pageRef) {
104: try {
105: if ((pages.size() % leafSize) == 0)
106: parents.add(writer.getPdfIndirectReference());
107: pages.add(pageRef);
108: return (PdfIndirectReference) parents
109: .get(parents.size() - 1);
110: } catch (Exception e) {
111: throw new ExceptionConverter(e);
112: }
113: }
114:
115: // returns the top parent to include in the catalog
116: PdfIndirectReference writePageTree() throws IOException {
117: if (pages.isEmpty())
118: throw new IOException("The document has no pages.");
119: int leaf = 1;
120: ArrayList tParents = parents;
121: ArrayList tPages = pages;
122: ArrayList nextParents = new ArrayList();
123: while (true) {
124: leaf *= leafSize;
125: int stdCount = leafSize;
126: int rightCount = tPages.size() % leafSize;
127: if (rightCount == 0)
128: rightCount = leafSize;
129: for (int p = 0; p < tParents.size(); ++p) {
130: int count;
131: int this Leaf = leaf;
132: if (p == tParents.size() - 1) {
133: count = rightCount;
134: this Leaf = pages.size() % leaf;
135: if (this Leaf == 0)
136: this Leaf = leaf;
137: } else
138: count = stdCount;
139: PdfDictionary top = new PdfDictionary(PdfName.PAGES);
140: top.put(PdfName.COUNT, new PdfNumber(this Leaf));
141: PdfArray kids = new PdfArray();
142: ArrayList internal = kids.getArrayList();
143: internal.addAll(tPages.subList(p * stdCount, p
144: * stdCount + count));
145: top.put(PdfName.KIDS, kids);
146: if (tParents.size() > 1) {
147: if ((p % leafSize) == 0)
148: nextParents.add(writer
149: .getPdfIndirectReference());
150: top.put(PdfName.PARENT,
151: (PdfIndirectReference) nextParents.get(p
152: / leafSize));
153: }
154: writer.addToBody(top, (PdfIndirectReference) tParents
155: .get(p));
156: }
157: if (tParents.size() == 1) {
158: topParent = (PdfIndirectReference) tParents.get(0);
159: return topParent;
160: }
161: tPages = tParents;
162: tParents = nextParents;
163: nextParents = new ArrayList();
164: }
165: }
166:
167: PdfIndirectReference getTopParent() {
168: return topParent;
169: }
170:
171: void setLinearMode(PdfIndirectReference topParent) {
172: if (parents.size() > 1)
173: throw new RuntimeException(
174: "Linear page mode can only be called with a single parent.");
175: if (topParent != null) {
176: this .topParent = topParent;
177: parents.clear();
178: parents.add(topParent);
179: }
180: leafSize = 10000000;
181: }
182:
183: void addPage(PdfIndirectReference page) {
184: pages.add(page);
185: }
186:
187: int reorderPages(int order[]) throws DocumentException {
188: if (order == null)
189: return pages.size();
190: if (parents.size() > 1)
191: throw new DocumentException(
192: "Page reordering requires a single parent in the page tree. Call PdfWriter.setLinearMode() after open.");
193: if (order.length != pages.size())
194: throw new DocumentException(
195: "Page reordering requires an array with the same size as the number of pages.");
196: int max = pages.size();
197: boolean temp[] = new boolean[max];
198: for (int k = 0; k < max; ++k) {
199: int p = order[k];
200: if (p < 1 || p > max)
201: throw new DocumentException(
202: "Page reordering requires pages between 1 and "
203: + max + ". Found " + p + ".");
204: if (temp[p - 1])
205: throw new DocumentException(
206: "Page reordering requires no page repetition. Page "
207: + p + " is repeated.");
208: temp[p - 1] = true;
209: }
210: Object copy[] = pages.toArray();
211: for (int k = 0; k < max; ++k) {
212: pages.set(k, copy[order[k] - 1]);
213: }
214: return max;
215: }
216: }
|