com.sun.pdfview.NameTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pdf-renderer Show documentation
Show all versions of pdf-renderer Show documentation
PDF renderer implementation supporting the subset of PDF 1.4 specification.
The newest version!
/*
* $Id: NameTree.java,v 1.3 2009-01-16 16:26:09 tomoke Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.sun.pdfview;
import java.io.IOException;
/**
* A PDF name tree consists of three kinds of nodes:
*
* - The root node contains only a kids entry, pointing to many
* other objects
*
- An intermediate node contains the limits of all the children in
* its subtree, and a kids entry for each child
*
- A leaf node contains a set of name-to-object mappings in a dictionary,
* as well as the limits of the data contained in that child.
*
* A PDF name tree is sorted in accordance with the String.compareTo() method.
*/
public class NameTree {
/** the root object */
private PDFObject root;
/** Creates a new instance of NameTree */
public NameTree(PDFObject root) {
this.root = root;
}
/**
* Find the PDF object corresponding to the given String in a name tree
*
* @param key the key we are looking for in the name tree
* @return the object associated with str, if found, or null if not
*/
public PDFObject find(String key) throws IOException {
return find(root, key);
}
/**
* Recursively walk the name tree looking for a given value
*/
private PDFObject find(PDFObject root, String key)
throws IOException {
// first, look for a Names entry, meaning this is a leaf
PDFObject names = root.getDictRef("Names");
if (names != null) {
return findInArray(names.getArray(), key);
}
// no names given, look for kids
PDFObject kidsObj = root.getDictRef("Kids");
if (kidsObj != null) {
PDFObject[] kids = kidsObj.getArray();
for (int i = 0; i < kids.length; i++) {
// find the limits of this kid
PDFObject limitsObj = kids[i].getDictRef("Limits");
if (limitsObj != null) {
String lowerLimit = limitsObj.getAt(0).getStringValue();
String upperLimit = limitsObj.getAt(1).getStringValue();
// are we in range?
if ((key.compareTo(lowerLimit) >= 0) &&
(key.compareTo(upperLimit) <= 0)) {
// we are, so find in this child
return find(kids[i], key);
}
}
}
}
// no luck
return null;
}
/**
* Find an object in a (key,value) array. Do this by splitting in half
* repeatedly.
*/
private PDFObject findInArray(PDFObject[] array, String key)
throws IOException {
int start = 0;
int end = array.length / 2;
while (end >= start && start >= 0 && end < array.length) {
// find the key at the midpoint
int pos = start + ((end - start) / 2);
String posKey = array[pos * 2].getStringValue();
// compare the key to the key we are looking for
int comp = key.compareTo(posKey);
if (comp == 0) {
// they match. Return the value
return array[(pos * 2) + 1];
} else if (comp > 0) {
// too big, search the top half of the tree
start = pos + 1;
} else if (comp < 0) {
// too small, search the bottom half of the tree
end = pos - 1;
}
}
// not found
return null;
}
}