From 5f10442af0ea4cc6d672a6d77f49f831e358058e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Sun, 26 Oct 2008 16:32:16 +0000 Subject: [PATCH] Bugzilla 45113: Added PDF /Launch action, which is used in case of references to URIs using the file:// protocol. Thanks to Alexander Stamenov (astamenov.AT.gmail.com) for the input! git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@708012 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFDocument.java | 35 ++++++---- src/java/org/apache/fop/pdf/PDFFactory.java | 35 ++++++++++ src/java/org/apache/fop/pdf/PDFLaunch.java | 68 ++++++++++++++++++++ status.xml | 5 ++ 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 src/java/org/apache/fop/pdf/PDFLaunch.java diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index 16ec81049..598fd433e 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -223,6 +223,11 @@ public class PDFDocument { */ protected List gotos = new java.util.ArrayList(); + /** + * List of PDFLaunch objects. + */ + protected List launches = new java.util.ArrayList(); + /** * The PDFDests object for the name dictionary. * Note: This object is not a list. @@ -486,6 +491,9 @@ public class PDFDocument { if (obj instanceof PDFPage) { this.pages.notifyKidRegistered((PDFPage)obj); } + if (obj instanceof PDFLaunch) { + this.launches.add(obj); + } if (obj instanceof PDFLink) { this.links.add(obj); } @@ -656,6 +664,15 @@ public class PDFDocument { return (PDFGoTo)findPDFObject(gotos, compare); } + /** + * Finds a launch. + * @param compare reference object to use as search template + * @return the launch if found, null otherwise + */ + protected PDFLaunch findLaunch(PDFLaunch compare) { + return (PDFLaunch) findPDFObject(launches, compare); + } + /** * Looks for an existing GState to use * @param wanted requested features @@ -703,7 +720,6 @@ public class PDFDocument { */ public void setColorSpace(int theColorspace) { this.colorspace.setColorSpace(theColorspace); - return; } /** @@ -1019,12 +1035,6 @@ public class PDFDocument { by the table's length */ this.position += outputXref(stream); - // Determine existance of encryption dictionary - String encryptEntry = ""; - if (this.encryption != null) { - encryptEntry = this.encryption.getTrailerEntry(); - } - /* construct the trailer */ String pdf = "trailer\n" @@ -1037,10 +1047,13 @@ public class PDFDocument { + "\n" + "/Info " + this.info.referencePDF() - + "\n" - + getIDEntry() - + "\n" - + encryptEntry + + "\n"; + if (this.encryption != null) { + pdf += this.encryption.getTrailerEntry(); + } else { + pdf += getIDEntry(); + } + pdf += "\n" + ">>\n" + "startxref\n" + this.xref diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index fc6e6b9fa..a5beb4ec7 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1011,6 +1011,10 @@ public class PDFFactory { // HTTP URL? if (targetLo.startsWith("http://")) { return new PDFUri(target); + // Non PDF files. Try to /Launch them. + } else if (targetLo.startsWith("file://")) { + target = target.substring("file://".length()); + return getLaunchAction(target); // Bare PDF file name? } else if (targetLo.endsWith(".pdf")) { return getGoToPDFAction(target, null, -1, newWindow); @@ -1104,6 +1108,37 @@ public class PDFFactory { return remote; } + /** + * Creates and returns a launch pdf document action using + * file to create a file spcifiaciton for + * the document/file to be opened with an external application. + * + * @param file the pdf file name + * @return the pdf launch object + */ + private PDFLaunch getLaunchAction(String file) { + getDocument().getProfile().verifyActionAllowed(); + + PDFFileSpec fileSpec = new PDFFileSpec(file); + PDFFileSpec oldSpec = getDocument().findFileSpec(fileSpec); + + if (oldSpec == null) { + getDocument().registerObject(fileSpec); + } else { + fileSpec = oldSpec; + } + PDFLaunch launch = new PDFLaunch(fileSpec); + PDFLaunch oldLaunch = getDocument().findLaunch(launch); + + if (oldLaunch == null) { + getDocument().registerObject(launch); + } else { + launch = oldLaunch; + } + + return launch; + } + /** * Make an outline object and add it to the given parent * diff --git a/src/java/org/apache/fop/pdf/PDFLaunch.java b/src/java/org/apache/fop/pdf/PDFLaunch.java new file mode 100644 index 000000000..d87fa2523 --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFLaunch.java @@ -0,0 +1,68 @@ +/* + * 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.pdf; + +/** + * This class represents the /Launch action. + */ +public class PDFLaunch extends PDFAction { + + private PDFFileSpec externalFileSpec; + + public PDFLaunch(PDFFileSpec fileSpec) { + this.externalFileSpec = fileSpec; + } + + public String getAction() { + return this.referencePDF(); + } + + public String toPDFString() { + StringBuffer sb = new StringBuffer(64); + sb.append(getObjectID()); + sb.append("<<\n/S /Launch\n/F "); + sb.append(externalFileSpec.referencePDF()); + sb.append(" \n>>\nendobj\n"); + + return sb.toString(); + } + + /** + * Check if this equals another object. + * + * @param obj the object to compare + * @return true if this equals other object + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || !(obj instanceof PDFLaunch)) { + return false; + } + + PDFLaunch launch = (PDFLaunch) obj; + + if (!launch.externalFileSpec.referencePDF().equals(externalFileSpec.referencePDF())) { + return false; + } + + return true; + } +} diff --git a/status.xml b/status.xml index 046416b59..85cd31935 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,11 @@ + + Added PDF /Launch action: references to URIs using the file:// protocol will now generate + a /Launch action as opposed to a more general /URI (which doesn't yield the expected result + for this protocol). + Fixed a problem where the BPD or a block area could be wrong if there is a nested, absolutely positioned area (for example a block-container). -- 2.39.5