| /* |
| * 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. |
| */ |
| |
| /* $Id$ */ |
| package org.apache.fop.render.pdf.pdfbox; |
| |
| import java.awt.geom.AffineTransform; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.pdfbox.cos.COSBase; |
| import org.apache.pdfbox.cos.COSDictionary; |
| import org.apache.pdfbox.cos.COSName; |
| import org.apache.pdfbox.cos.COSObject; |
| import org.apache.pdfbox.cos.COSStream; |
| import org.apache.pdfbox.pdmodel.PDPage; |
| import org.apache.pdfbox.pdmodel.common.PDRectangle; |
| import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; |
| |
| import org.apache.fop.pdf.PDFArray; |
| import org.apache.fop.pdf.PDFDictionary; |
| |
| public final class PDFBoxAdapterUtil { |
| private PDFBoxAdapterUtil() { |
| } |
| |
| private static Integer getStreamHash(COSStream o) throws IOException { |
| for (COSBase x : o.getValues()) { |
| if (x instanceof COSObject || x instanceof COSDictionary) { |
| return null; |
| } |
| } |
| InputStream stream = o.getFilteredStream(); |
| byte[] b = IOUtils.toByteArray(stream); |
| return Arrays.deepHashCode(new Object[]{b, o.toString()}); |
| } |
| |
| private static String getDictionaryHash(COSBase base) throws IOException { |
| return getDictionaryHash(base, new ArrayList<COSBase>()); |
| } |
| |
| private static String getDictionaryHash(COSBase base, List<COSBase> objs) throws IOException { |
| if (base == null) { |
| return "null"; |
| } |
| if (objs.contains(base)) { |
| return String.valueOf(base.hashCode()); |
| } |
| objs.add(base); |
| if (base instanceof COSDictionary) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("COSDictionary{"); |
| for (Map.Entry<COSName, COSBase> x : ((COSDictionary) base).entrySet()) { |
| sb.append(x.getKey()); |
| sb.append(":"); |
| sb.append(getDictionaryHash(x.getValue(), objs)); |
| sb.append(";"); |
| } |
| sb.append("}"); |
| if (base instanceof COSStream) { |
| InputStream stream = ((COSStream)base).getFilteredStream(); |
| byte[] b = IOUtils.toByteArray(stream); |
| sb.append("COSStream{").append(Arrays.hashCode(b)).append("}"); |
| } |
| return sb.toString(); |
| } else if (base instanceof COSObject) { |
| COSObject obj = (COSObject) base; |
| return "COSObject{" + getDictionaryHash(obj.getObject(), objs) + "}"; |
| } else { |
| return base.toString(); |
| } |
| } |
| |
| protected static Object getBaseKey(Object base) throws IOException { |
| if (base instanceof COSObject) { |
| COSObject obj = (COSObject)base; |
| COSBase o = obj.getObject(); |
| if (o instanceof COSStream) { |
| Integer hash = PDFBoxAdapterUtil.getStreamHash((COSStream) o); |
| if (hash != null) { |
| return hash; |
| } |
| } |
| return obj.getObjectNumber() + " " + obj.getGenerationNumber(); |
| } |
| if (base instanceof COSDictionary) { |
| String dict = PDFBoxAdapterUtil.getDictionaryHash((COSBase) base); |
| return String.valueOf(dict.hashCode()); |
| } |
| return null; |
| } |
| |
| protected static void rotate(int rotation, PDRectangle viewBox, AffineTransform atdoc) { |
| float w = viewBox.getWidth(); |
| float h = viewBox.getHeight(); |
| float x = viewBox.getLowerLeftX(); |
| float y = viewBox.getLowerLeftY(); |
| switch (rotation) { |
| case 90: |
| atdoc.rotate(Math.toRadians(rotation + 180), x, y); |
| atdoc.translate(-h, 0); |
| break; |
| case 180: |
| atdoc.translate(w, h); |
| atdoc.rotate(Math.toRadians(rotation), x, y); |
| break; |
| case 270: |
| atdoc.rotate(Math.toRadians(rotation + 180), x, h + y); |
| atdoc.translate(-w, 0); |
| break; |
| default: |
| //no additional transformations necessary |
| break; |
| } |
| } |
| |
| protected static void updateAnnotationLink(PDFDictionary clonedAnnot) { |
| Object a = clonedAnnot.get("A"); |
| if (a instanceof PDFDictionary) { |
| PDFDictionary annot = (PDFDictionary) a; |
| Object oldarrayObj = annot.get("D"); |
| if (oldarrayObj instanceof PDFArray) { |
| PDFArray oldarray = (PDFArray) oldarrayObj; |
| Object newarrayObj = oldarray.get(0); |
| if (newarrayObj instanceof PDFArray) { |
| PDFArray newarray = (PDFArray) newarrayObj; |
| for (int i = 1; i < oldarray.length(); i++) { |
| newarray.add(oldarray.get(i)); |
| } |
| annot.put("D", oldarray.get(0)); |
| } |
| } |
| } |
| } |
| |
| protected static void moveAnnotations(PDPage page, List pageAnnotations, AffineTransform at) { |
| PDRectangle mediaBox = page.getMediaBox(); |
| PDRectangle cropBox = page.getCropBox(); |
| PDRectangle viewBox = cropBox != null ? cropBox : mediaBox; |
| for (Object obj : pageAnnotations) { |
| PDAnnotation annot = (PDAnnotation)obj; |
| PDRectangle rect = annot.getRectangle(); |
| float translateX = (float) (at.getTranslateX() - viewBox.getLowerLeftX()); |
| float translateY = (float) (at.getTranslateY() - viewBox.getLowerLeftY()); |
| if (rect != null) { |
| rect.setUpperRightX(rect.getUpperRightX() + translateX); |
| rect.setLowerLeftX(rect.getLowerLeftX() + translateX); |
| rect.setUpperRightY(rect.getUpperRightY() + translateY); |
| rect.setLowerLeftY(rect.getLowerLeftY() + translateY); |
| annot.setRectangle(rect); |
| } |
| // COSArray vertices = (COSArray) annot.getCOSObject().getDictionaryObject("Vertices"); |
| // if (vertices != null) { |
| // Iterator iter = vertices.iterator(); |
| // while (iter.hasNext()) { |
| // COSFloat x = (COSFloat) iter.next(); |
| // COSFloat y = (COSFloat) iter.next(); |
| // x.setValue(x.floatValue() + translateX); |
| // y.setValue(y.floatValue() + translateY); |
| // } |
| // } |
| } |
| } |
| } |