blob: 0aa595063fb6bf9a8c92220692aad3b642fe4f2c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.fop.render.pdf.pdfbox;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSInteger;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSObject;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
public class PageParentTreeFinder {
private PDPage srcPage;
public PageParentTreeFinder(PDPage srcPage) {
this.srcPage = srcPage;
}
public COSArray getPageParentTreeArray(PDDocument srcDoc) throws IOException {
int position = srcPage.getCOSObject().getInt(COSName.STRUCT_PARENTS);
if (position == -1) {
position = findXObjectStructParent();
}
if (position != -1) {
PDNumberTreeNode srcNumberTreeNode = srcDoc.getDocumentCatalog().getStructureTreeRoot().getParentTree();
return traverseParentTree(srcNumberTreeNode.getCOSObject(), position);
}
return new COSArray();
}
//TODO handle structural hierarchy in xboject stream
private int findXObjectStructParent() throws IOException {
int position = -1;
Iterable<COSName> mapXObject = srcPage.getResources().getXObjectNames();
for (COSName n : mapXObject) {
PDXObject t = srcPage.getResources().getXObject(n);
COSDictionary xObjectDict = t.getCOSObject();
position = xObjectDict.getInt(COSName.STRUCT_PARENTS);
if (position != -1) {
return position;
}
}
return position;
}
private COSArray traverseParentTree(COSDictionary numberTreeNodeDict, int position) {
COSArray numberTree;
COSArray parentTree;
List<COSArray> nums = new ArrayList<COSArray>();
if (numberTreeNodeDict.containsKey(COSName.NUMS)) {
numberTree = (COSArray)numberTreeNodeDict.getItem(COSName.NUMS);
return extractMarkedContentParents(numberTree, position);
} else {
parentTree = (COSArray) numberTreeNodeDict.getDictionaryObject(COSName.KIDS);
traverseKids(parentTree, position, nums);
}
if (nums.isEmpty()) {
return new COSArray();
}
return nums.get(0);
}
private void traverseKids(COSBase kids, int position, List<COSArray> numList) {
if (!numList.isEmpty()) {
return;
}
if (kids instanceof COSArray) {
COSArray kidsArray = (COSArray)kids;
for (COSBase kid : kidsArray) {
COSObject kidCOSObj = (COSObject) kid;
traverseKids(kidCOSObj, position, numList);
}
} else if (kids instanceof COSObject) {
COSObject kidCOSObj = (COSObject) kids;
if (kidCOSObj.getDictionaryObject(COSName.NUMS) == null) {
traverseKids(kidCOSObj.getDictionaryObject(COSName.KIDS), position, numList);
} else {
if (kidCOSObj.getDictionaryObject(COSName.LIMITS) != null) {
COSArray kidCOSArray = (COSArray) kidCOSObj.getDictionaryObject(COSName.LIMITS);
int lowerLimit = ((COSInteger) kidCOSArray.get(0)).intValue();
int upperLimit = ((COSInteger) kidCOSArray.get(1)).intValue();
if (lowerLimit <= position && position <= upperLimit) {
COSArray nums = (COSArray) kidCOSObj.getDictionaryObject(COSName.NUMS);
numList.add(extractMarkedContentParents(nums, position));
}
} else {
COSArray nums = (COSArray) kidCOSObj.getDictionaryObject(COSName.NUMS);
numList.add(extractMarkedContentParents(nums, position));
}
}
}
}
private COSArray extractMarkedContentParents(COSArray numberTree, int position) {
COSBase tempObject;
boolean keyFlag = false;
for (COSBase kid : numberTree) {
if (keyFlag) {
if (kid instanceof COSObject) {
tempObject = ((COSObject)kid).getObject();
return (COSArray)tempObject;
} else if (kid instanceof COSArray) {
return (COSArray)kid;
}
}
if (kid instanceof COSInteger) {
int temp = ((COSInteger)kid).intValue();
if (temp == position) {
keyFlag = true;
}
}
}
return new COSArray();
}
}