]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
changes to support named destinations
authorJay Bryant <jbryant@apache.org>
Sun, 1 Apr 2007 14:50:36 +0000 (14:50 +0000)
committerJay Bryant <jbryant@apache.org>
Sun, 1 Apr 2007 14:50:36 +0000 (14:50 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@524606 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/pdf/PDFDestination.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/PDFDests.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/PDFDocument.java
src/java/org/apache/fop/pdf/PDFFactory.java
src/java/org/apache/fop/pdf/PDFLimits.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/PDFRoot.java

diff --git a/src/java/org/apache/fop/pdf/PDFDestination.java b/src/java/org/apache/fop/pdf/PDFDestination.java
new file mode 100644 (file)
index 0000000..e8228ac
--- /dev/null
@@ -0,0 +1,140 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id: PDFLink.java 426576 2006-07-28 15:44:37Z jeremias $ */\r
+\r
+package org.apache.fop.pdf;\r
+\r
+import org.apache.fop.area.DestinationData;\r
+import org.apache.fop.area.PageViewport;\r
+\r
+/**\r
+ * class representing a named destination\r
+ */\r
+public class PDFDestination extends PDFObject {\r
+\r
+    /**\r
+     * PDFReference (object reference) for this destination\r
+     */\r
+     private String goToReference;\r
+\r
+    /**\r
+     * ID Reference for this destination\r
+     */\r
+    private String idRef;\r
+\r
+    /**\r
+     * PageViewport to which the idRef item refers\r
+     */\r
+    private PageViewport pageViewport = null;\r
+\r
+    /**\r
+     * create a named destination\r
+     */\r
+    public PDFDestination(DestinationData destinationData) {\r
+        /* generic creation of PDF object */\r
+        super();\r
+        this.goToReference = destinationData.getGoToReference();\r
+        this.idRef = destinationData.getIDRef();\r
+        this.pageViewport = destinationData.getPageViewport();\r
+    }\r
+\r
+    /**\r
+     * @see org.apache.fop.pdf.PDFObject#toPDFString()\r
+     */\r
+    public String toPDFString() {\r
+        String s = getObjectID()\r
+                   + "<<"\r
+                   + "/Limits [(" + idRef + ") (" + idRef + ")]\n"\r
+                   + "/Names [(" + idRef + ") " + goToReference + "]"\r
+                   + "\n>>\nendobj\n";\r
+        return s;\r
+    }\r
+\r
+    /*\r
+     * example:\r
+     *\r
+     * 249 0 obj\r
+     * <<\r
+     * /Limits [(drivervariables) (drivervariables)]\r
+     * /Names [(drivervariables) 73 0 R]\r
+     * >>\r
+     * endobj\r
+     */\r
+\r
+    /**\r
+     * Sets the GoToReference in the associated DestinationData object.\r
+     *\r
+     * @param the GoToReference to set in the associated DestinationData object.\r
+     */\r
+    public void setGoToReference(String goToReference) {\r
+        this.goToReference = goToReference;\r
+    }\r
+\r
+    /**\r
+     * Returns the GoToReference from the associated DestinationData object.\r
+     *\r
+     * @return the GoToReference from the associated DestinationData object.\r
+     */\r
+    public String getGoToReference()\r
+    {\r
+        return this.goToReference;\r
+    }\r
+\r
+    /**\r
+     * Get the PageViewport object that this destination refers to\r
+     *\r
+     * @return the PageViewport that this destination points to\r
+     */\r
+    public PageViewport getPageViewport() {\r
+        return this.pageViewport;\r
+    }\r
+\r
+    /**\r
+     * Returns the RefID from the associated DestinationData object.\r
+     *\r
+     * @return the RefID from the associated DestinationData object.\r
+     */\r
+    public String getIDRef()\r
+    {\r
+        return this.idRef;\r
+    }\r
+\r
+    /**\r
+     * Check if this equals another object.\r
+     *\r
+     * @param obj the object to compare\r
+     * @return true if this equals other object\r
+     */\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+\r
+        if (obj == null || !(obj instanceof PDFDestination)) {\r
+            return false;\r
+        }\r
+\r
+        PDFDestination dest = (PDFDestination)obj;\r
+        if (dest.getIDRef() == this.getIDRef()) {\r
+            return true;\r
+        }\r
+        \r
+        return true;\r
+    }\r
+}\r
+\r
diff --git a/src/java/org/apache/fop/pdf/PDFDests.java b/src/java/org/apache/fop/pdf/PDFDests.java
new file mode 100644 (file)
index 0000000..3989b39
--- /dev/null
@@ -0,0 +1,79 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id: PDFLink.java 426576 2006-07-28 15:44:37Z jeremias $ */\r
+\r
+package org.apache.fop.pdf;\r
+\r
+import org.apache.fop.area.DestinationData;\r
+\r
+/**\r
+ * class representing an /Dests object (part of a name dictionary)\r
+ */\r
+public class PDFDests extends PDFObject {\r
+\r
+    private String limitsRef;\r
+\r
+    /**\r
+     * create a named destination\r
+     */\r
+    public PDFDests(String limitsRef) {\r
+        /* generic creation of PDF object */\r
+        super();\r
+        this.limitsRef = limitsRef;\r
+    }\r
+\r
+    /**\r
+     * @see org.apache.fop.pdf.PDFObject#toPDFString()\r
+     */\r
+    public String toPDFString() {\r
+        String s = getObjectID()\r
+                   + "<<\n"\r
+                   + "/Dests " + limitsRef\r
+                   + "\n>>\nendobj\n";\r
+        return s;\r
+    }\r
+\r
+    /*\r
+     * example:\r
+     *\r
+     * 262 0 obj\r
+     * <<\r
+     * /Dests 260 0 R\r
+     * >>\r
+     * endobj\r
+     */\r
+\r
+    /**\r
+     * Check if this equals another object.\r
+     *\r
+     * @param obj the object to compare\r
+     * @return true if this equals other object\r
+     */\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+\r
+        if (obj == null || !(obj instanceof PDFDests)) {\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+}\r
+\r
index 4ce82fab9b3795405342bcb8b5a35f43a01ee68e..042d3d00bd4443b00a5beb90bcc5dce4d43385bf 100644 (file)
@@ -32,6 +32,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Iterator;
+import java.util.ArrayList;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -85,7 +86,7 @@ public class PDFDocument {
     /**
      * the character position of each object
      */
-    protected List location = new java.util.ArrayList();
+    protected List location = new ArrayList();
 
     /** List of objects to write in the trailer */
     private List trailerObjects = new java.util.ArrayList();
@@ -201,6 +202,11 @@ public class PDFDocument {
      */
     protected List links = new java.util.ArrayList();
 
+    /**
+     * List of Destinations.
+     */
+    protected List destinations = new java.util.ArrayList();
+
     /**
      * List of FileSpecs.
      */
@@ -216,6 +222,25 @@ public class PDFDocument {
      */
     protected List gotos = new java.util.ArrayList();
 
+    /**
+     * The PDFDests object for the name dictionary.
+     * Note: This object is not a list.
+     */
+    private PDFDests dests;
+
+    /**
+     * The PDFLimits object for the name dictionary.
+     * Note: This object is not a list.
+     */
+    private PDFLimits limits;
+
+    /**
+     * Whether this PDFDocument has named destinations
+     * (and thus needs PDFDestinations, PDFLimits, and
+     * PDFDests)
+     */
+    private boolean hasDestinations = false;
+
     private PDFFactory factory;
 
     private boolean encodingOnTheFly = true;
@@ -460,6 +485,9 @@ public class PDFDocument {
         if (obj instanceof PDFLink) {
             this.links.add(obj);
         }
+        if (obj instanceof PDFDestination) {
+            this.destinations.add(obj);
+        }
         if (obj instanceof PDFFileSpec) {
             this.filespecs.add(obj);
         }
@@ -577,6 +605,15 @@ public class PDFDocument {
         return (PDFFont)fontMap.get(fontname);
     }
 
+    /**
+     * Finds a named destination.
+     * @param compare reference object to use as search template
+     * @return the link if found, null otherwise
+     */
+    protected PDFDestination findDestination(PDFDestination compare) {
+        return (PDFDestination)findPDFObject(destinations, compare);
+    }
+
     /**
      * Finds a link.
      * @param compare reference object to use as search template
@@ -701,6 +738,51 @@ public class PDFDocument {
         return xObject;
     }
 
+    /**
+     * Gets the PDFDests object (which represents the /Dests entry).
+     *
+     * @return the PDFDests object (which represents the /Dests entry).
+     */
+    public PDFDests getDests() {
+        return dests;
+    }
+
+    /**
+     * Gets the list of named destinations.
+     *
+     * @return the list of named destinations.
+     */
+    public ArrayList getDestinationList() {
+        return (ArrayList)destinations;
+    }
+
+    /**
+     * Sets whether the document has named destinations.
+     *
+     * @param whether the document has named destinations.
+     */
+    public void setHasDestinations(boolean hasDestinations) {
+        this.hasDestinations = hasDestinations;
+    }
+
+    /**
+     * Gets whether the document has named destinations.
+     *
+     * @return whether the document has named destinations.
+     */
+    public boolean getHasDestinations() {
+        return this.hasDestinations;
+    }
+
+    /**
+     * Gets the PDFLimits object (part of the name dictionary).
+     *
+     * @return the PDFLimits object (part of the name dictionary).
+     */
+    public PDFLimits getLimits() {
+        return limits;
+    }
+
     /**
      * Add an image to the PDF document.
      * This adds an image to the PDF objects.
@@ -893,6 +975,11 @@ public class PDFDocument {
      * @throws IOException if there is an exception writing to the output stream
      */
     public void outputTrailer(OutputStream stream) throws IOException {
+        if (hasDestinations) {
+            limits = getFactory().makeLimits((ArrayList)destinations);
+            dests = getFactory().makeDests(limits.referencePDF());
+            this.root.setNames(dests.referencePDF());
+        }
         output(stream);
         for (int count = 0; count < trailerObjects.size(); count++) {
             PDFObject o = (PDFObject)trailerObjects.get(count);
index 4ab6ebd7bfc2ce6df6932bfadcf1b2d6d15b9e79..3005f2018596351b614484bc20baeef0621b3895 100644 (file)
@@ -5,9 +5,9 @@
  * 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.
@@ -31,6 +31,7 @@ import java.util.List;
 import java.util.Map;
 import javax.xml.transform.Source;
 import javax.xml.transform.stream.StreamSource;
+import java.util.ArrayList;
 
 // Apache libs
 import org.apache.commons.io.IOUtils;
@@ -52,6 +53,8 @@ import org.apache.fop.fonts.truetype.TTFSubSetFile;
 import org.apache.fop.fonts.type1.PFBData;
 import org.apache.fop.fonts.type1.PFBParser;
 import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.DestinationData;
 
 /**
  * This class provides method to create and register PDF objects.
@@ -731,7 +734,7 @@ public class PDFFactory {
         PDFPattern myPattern;
         //PDFColorSpace theColorSpace;
         double interpolation = (double)1.000;
-        List theFunctions = new java.util.ArrayList();
+        List theFunctions = new ArrayList();
 
         int currentPosition;
         int lastPosition = theColors.size() - 1;
@@ -782,7 +785,7 @@ public class PDFFactory {
             } else {    // if the center x, center y, and radius specifiy
                 // the gradient, then assume the same center x, center y,
                 // and radius of zero for the other necessary component
-                List newCoords = new java.util.ArrayList();
+                List newCoords = new ArrayList();
                 newCoords.add(theCoords.get(0));
                 newCoords.add(theCoords.get(1));
                 newCoords.add(theCoords.get(2));
@@ -809,6 +812,56 @@ public class PDFFactory {
         return (myPattern);
     }
 
+    /* ============= named destinations and the name dictionary ============ */
+
+    /**
+     * Make a named destination.
+     *
+     * @param destinationData the DestinationData object that holds the info about this named destination
+     * @return the new PDF named destination object
+     */
+    public PDFDestination makeDestination(DestinationData destinationData) {
+        PageViewport pv = destinationData.getPageViewport();
+        if (pv == null) {
+            log.warn("Unresolved destination item received: " + destinationData.getIDRef());
+        }
+        PDFDestination destination = new PDFDestination(destinationData);
+
+        PDFDestination oldDestination = getDocument().findDestination(destination);
+        if (destination == oldDestination) {
+            destination = oldDestination;
+        } else {
+            getDocument().registerObject(destination);
+            getDocument().setHasDestinations(true);
+        }
+
+        return destination;
+    }
+
+    /**
+     * Make a the head object of the name dictionary (the /Dests object).
+     *
+     * @return the new PDFDests object
+     */
+    public PDFDests makeDests(String limitsRef) {
+        PDFDests dests = new PDFDests(limitsRef);
+        getDocument().registerObject(dests);
+
+        return dests;
+    }
+
+    /**
+     * Make a the limits object of the name dictionary (the /Limits object).
+     *
+     * @return the new PDFLimits object
+     */
+    public PDFLimits makeLimits(ArrayList destinationList) {
+        PDFLimits limits = new PDFLimits(destinationList);
+        getDocument().registerObject(limits);
+
+        return limits;
+    }
+
     /* ========================= links ===================================== */
 
     /**
@@ -888,7 +941,7 @@ public class PDFFactory {
         return link;
     }
 
-    private String getGoToReference(String destination, float yoffset) {
+    public String getGoToReference(String destination, float yoffset) {
         getDocument().getProfile().verifyActionAllowed();
         String goToReference = null;
         PDFGoTo gt = new PDFGoTo(destination);
@@ -1153,9 +1206,9 @@ public class PDFFactory {
         int value = 0;
         for (int i = 0, c = cidSubset.length(); i < c; i++) {
             int shift = i % 8;
-            boolean b = cidSubset.get(i); 
+            boolean b = cidSubset.get(i);
             if (b) {
-                value |= 1 << 7 - shift; 
+                value |= 1 << 7 - shift;
             }
             if (shift == 7) {
                 baout.write(value);
@@ -1335,7 +1388,7 @@ public class PDFFactory {
     public PDFICCBasedColorSpace makeICCBasedColorSpace(PDFResourceContext res,
             String explicitName, PDFICCStream iccStream) {
         PDFICCBasedColorSpace cs = new PDFICCBasedColorSpace(explicitName, iccStream);
-        
+
         getDocument().registerObject(cs);
 
         if (res != null) {
@@ -1343,7 +1396,7 @@ public class PDFFactory {
         } else {
             getDocument().getResources().addColorSpace(cs);
         }
-        
+
         return cs;
     }
 
diff --git a/src/java/org/apache/fop/pdf/PDFLimits.java b/src/java/org/apache/fop/pdf/PDFLimits.java
new file mode 100644 (file)
index 0000000..ece7a3d
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id: PDFLink.java 426576 2006-07-28 15:44:37Z jeremias $ */\r
+\r
+package org.apache.fop.pdf;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.apache.fop.pdf.PDFDestination;\r
+\r
+/**\r
+ * class representing a Limits object (part of the names dictionary for named destinations)\r
+ */\r
+public class PDFLimits extends PDFObject {\r
+\r
+    private ArrayList destinationList;\r
+\r
+    /**\r
+     * create a named destination\r
+     */\r
+    public PDFLimits(ArrayList destinationList) {\r
+        /* generic creation of PDF object */\r
+        super();\r
+        this.destinationList = destinationList;\r
+    }\r
+\r
+    /**\r
+     * @see org.apache.fop.pdf.PDFObject#toPDFString()\r
+     */\r
+    public String toPDFString() {\r
+        String[] idRefs = new String[destinationList.size()];\r
+        String kidsString = "";\r
+        for(int i = 0; i < destinationList.size(); i++) {\r
+            PDFDestination dest = (PDFDestination)destinationList.get(i);\r
+            idRefs[i] = dest.getIDRef();\r
+            kidsString += dest.referencePDF();\r
+            if (!(i == destinationList.size() - 1)) {\r
+                kidsString += " ";\r
+            }\r
+        }\r
+        String s = getObjectID()\r
+                   + "<<\n"\r
+                   + "/Limits [(" + idRefs[0] + ") (" + idRefs[destinationList.size() - 1] + ")]\n"\r
+                   + "/Kids [" + kidsString + "]"\r
+                   + "\n>>\nendobj\n";\r
+        return s;\r
+    }\r
+\r
+    /*\r
+     * example:\r
+     *\r
+     * 260 0 obj\r
+     * <<\r
+     * /Limits [(Annotate) (thumbnails)]\r
+     * /Kids [248 0 R 253 0 R 254 0 R 259 0 R]\r
+     * >>\r
+     * endobj\r
+     */\r
+\r
+    /**\r
+     * Check if this equals another object.\r
+     *\r
+     * @param obj the object to compare\r
+     * @return true if this equals other object\r
+     */\r
+    public boolean equals(Object obj) {\r
+        if (this == obj) {\r
+            return true;\r
+        }\r
+\r
+        if (obj == null || !(obj instanceof PDFLimits)) {\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+}\r
+\r
index ffe9611bad47fe503d1d2236f7de5d56a5613b7f..60fe6b39032a9e279315e5d1fc5a8dfbb35ca9c2 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.pdf;
 
 import java.util.List;
+import java.util.ArrayList;
 
 /**
  * class representing a Root (/Catalog) object
@@ -62,6 +63,12 @@ public class PDFRoot extends PDFObject {
     /** The array of OutputIntents */
     private List outputIntents;
     
+    /**
+     * The referencePDF value of the /Dests object,
+     * if this PDF has a Name Dictionary
+     */
+    private String namesReferencePDF = null;
+
     private int pageMode = PAGEMODE_USENONE;
 
     /**
@@ -125,6 +132,15 @@ public class PDFRoot extends PDFObject {
         return outline;
     }
     
+    /**
+     * Set the optional Metadata object.
+     * @param meta the Metadata object
+     * @since PDF 1.4
+     */
+    public void setNames(String referencePDF) {
+        this.namesReferencePDF = referencePDF;
+    }
+    
     /**
      * Set the optional Metadata object.
      * @param meta the Metadata object
@@ -181,6 +197,9 @@ public class PDFRoot extends PDFObject {
                 break;
             }
         }
+        if (getDocumentSafely().getHasDestinations() && namesReferencePDF != null) {
+            p.append(" /Names " + namesReferencePDF + "\n");
+        }
         if (getMetadata() != null 
                 && getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) {
             p.append("/Metadata " + getMetadata().referencePDF() + "\n");