001: /*
002: * Copyright 2005 by Paulo Soares.
003: *
004: * The contents of this file are subject to the Mozilla Public License Version 1.1
005: * (the "License"); you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the License.
011: *
012: * The Original Code is 'iText, a free JAVA-PDF library'.
013: *
014: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
015: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
016: * All Rights Reserved.
017: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
018: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
019: *
020: * Contributor(s): all the names of the contributors are added in the source code
021: * where applicable.
022: *
023: * Alternatively, the contents of this file may be used under the terms of the
024: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
025: * provisions of LGPL are applicable instead of those above. If you wish to
026: * allow use of your version of this file only under the terms of the LGPL
027: * License and not to allow others to use your version of this file under
028: * the MPL, indicate your decision by deleting the provisions above and
029: * replace them with the notice and other provisions required by the LGPL.
030: * If you do not delete the provisions above, a recipient may use your version
031: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
032: *
033: * This library is free software; you can redistribute it and/or modify it
034: * under the terms of the MPL as stated above or under the terms of the GNU
035: * Library General Public License as published by the Free Software Foundation;
036: * either version 2 of the License, or any later version.
037: *
038: * This library is distributed in the hope that it will be useful, but WITHOUT
039: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
040: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
041: * details.
042: *
043: * If you didn't download this code from the following link, you should check if
044: * you aren't using an obsolete version:
045: * http://www.lowagie.com/iText/
046: */
047: package com.lowagie.text.pdf;
048:
049: import java.io.IOException;
050: import java.util.ArrayList;
051: import java.util.Arrays;
052: import java.util.HashMap;
053:
054: /**
055: * Creates a number tree.
056: * @author Paulo Soares (psoares@consiste.pt)
057: */
058: public class PdfNumberTree {
059:
060: private static final int leafSize = 64;
061:
062: /**
063: * Creates a number tree.
064: * @param items the item of the number tree. The key is an <CODE>Integer</CODE>
065: * and the value is a <CODE>PdfObject</CODE>.
066: * @param writer the writer
067: * @throws IOException on error
068: * @return the dictionary with the number tree.
069: */
070: public static PdfDictionary writeTree(HashMap items,
071: PdfWriter writer) throws IOException {
072: if (items.isEmpty())
073: return null;
074: Integer numbers[] = new Integer[items.size()];
075: numbers = (Integer[]) items.keySet().toArray(numbers);
076: Arrays.sort(numbers);
077: if (numbers.length <= leafSize) {
078: PdfDictionary dic = new PdfDictionary();
079: PdfArray ar = new PdfArray();
080: for (int k = 0; k < numbers.length; ++k) {
081: ar.add(new PdfNumber(numbers[k].intValue()));
082: ar.add((PdfObject) items.get(numbers[k]));
083: }
084: dic.put(PdfName.NUMS, ar);
085: return dic;
086: }
087: int skip = leafSize;
088: PdfIndirectReference kids[] = new PdfIndirectReference[(numbers.length
089: + leafSize - 1)
090: / leafSize];
091: for (int k = 0; k < kids.length; ++k) {
092: int offset = k * leafSize;
093: int end = Math.min(offset + leafSize, numbers.length);
094: PdfDictionary dic = new PdfDictionary();
095: PdfArray arr = new PdfArray();
096: arr.add(new PdfNumber(numbers[offset].intValue()));
097: arr.add(new PdfNumber(numbers[end - 1].intValue()));
098: dic.put(PdfName.LIMITS, arr);
099: arr = new PdfArray();
100: for (; offset < end; ++offset) {
101: arr.add(new PdfNumber(numbers[offset].intValue()));
102: arr.add((PdfObject) items.get(numbers[offset]));
103: }
104: dic.put(PdfName.NUMS, arr);
105: kids[k] = writer.addToBody(dic).getIndirectReference();
106: }
107: int top = kids.length;
108: while (true) {
109: if (top <= leafSize) {
110: PdfArray arr = new PdfArray();
111: for (int k = 0; k < top; ++k)
112: arr.add(kids[k]);
113: PdfDictionary dic = new PdfDictionary();
114: dic.put(PdfName.KIDS, arr);
115: return dic;
116: }
117: skip *= leafSize;
118: int tt = (numbers.length + skip - 1) / skip;
119: for (int k = 0; k < tt; ++k) {
120: int offset = k * leafSize;
121: int end = Math.min(offset + leafSize, top);
122: PdfDictionary dic = new PdfDictionary();
123: PdfArray arr = new PdfArray();
124: arr.add(new PdfNumber(numbers[k * skip].intValue()));
125: arr.add(new PdfNumber(numbers[Math.min((k + 1) * skip,
126: numbers.length) - 1].intValue()));
127: dic.put(PdfName.LIMITS, arr);
128: arr = new PdfArray();
129: for (; offset < end; ++offset) {
130: arr.add(kids[offset]);
131: }
132: dic.put(PdfName.KIDS, arr);
133: kids[k] = writer.addToBody(dic).getIndirectReference();
134: }
135: top = tt;
136: }
137: }
138:
139: private static void iterateItems(PdfDictionary dic, HashMap items) {
140: PdfArray nn = (PdfArray) PdfReader.getPdfObjectRelease(dic
141: .get(PdfName.NUMS));
142: if (nn != null) {
143: ArrayList arr = nn.getArrayList();
144: for (int k = 0; k < arr.size(); ++k) {
145: PdfNumber s = (PdfNumber) PdfReader
146: .getPdfObjectRelease((PdfObject) arr.get(k++));
147: items.put(new Integer(s.intValue()), arr.get(k));
148: }
149: } else if ((nn = (PdfArray) PdfReader.getPdfObjectRelease(dic
150: .get(PdfName.KIDS))) != null) {
151: ArrayList arr = nn.getArrayList();
152: for (int k = 0; k < arr.size(); ++k) {
153: PdfDictionary kid = (PdfDictionary) PdfReader
154: .getPdfObjectRelease((PdfObject) arr.get(k));
155: iterateItems(kid, items);
156: }
157: }
158: }
159:
160: public static HashMap readTree(PdfDictionary dic) {
161: HashMap items = new HashMap();
162: if (dic != null)
163: iterateItems(dic, items);
164: return items;
165: }
166: }
|