--- test/layoutengine/standard-testcases/basic-link_external-destination.xml (revision 642740)
+++ test/layoutengine/standard-testcases/basic-link_external-destination.xml Sun Mar 30 16:49:53 CEST 2008
@@ -38,7 +38,7 @@
-
-
+
+
--- src/java/org/apache/fop/pdf/PDFGoToRemote.java (revision 642740)
+++ src/java/org/apache/fop/pdf/PDFGoToRemote.java Sun Mar 30 15:37:05 CEST 2008
@@ -20,7 +20,7 @@
package org.apache.fop.pdf;
/**
- * class representing a /GoToR object.
+ * Class representing a /GoToR object.
*/
public class PDFGoToRemote extends PDFAction {
@@ -30,17 +30,21 @@
private PDFFileSpec pdfFileSpec;
private int pageReference = 0;
private String destination = null;
+ private boolean newWindow = false;
/**
- * create an GoToR object.
+ * Create an GoToR object.
*
* @param pdfFileSpec the fileSpec associated with the action
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
*/
- public PDFGoToRemote(PDFFileSpec pdfFileSpec) {
+ public PDFGoToRemote(PDFFileSpec pdfFileSpec, boolean newWindow) {
/* generic creation of object */
super();
this.pdfFileSpec = pdfFileSpec;
+ this.newWindow = newWindow;
}
/**
@@ -48,13 +52,16 @@
*
* @param pdfFileSpec the fileSpec associated with the action
* @param page a page reference within the remote document
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
*/
- public PDFGoToRemote(PDFFileSpec pdfFileSpec, int page) {
+ public PDFGoToRemote(PDFFileSpec pdfFileSpec, int page, boolean newWindow) {
/* generic creation of object */
super();
this.pdfFileSpec = pdfFileSpec;
this.pageReference = page;
+ this.newWindow = newWindow;
}
/**
@@ -62,13 +69,16 @@
*
* @param pdfFileSpec the fileSpec associated with the action
* @param dest a named destination within the remote document
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
*/
- public PDFGoToRemote(PDFFileSpec pdfFileSpec, String dest) {
+ public PDFGoToRemote(PDFFileSpec pdfFileSpec, String dest, boolean newWindow) {
/* generic creation of object */
super();
this.pdfFileSpec = pdfFileSpec;
this.destination = dest;
+ this.newWindow = newWindow;
}
/**
@@ -86,14 +96,20 @@
public String toPDFString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getObjectID());
- sb.append("<<\n/S /GoToR\n/F " + pdfFileSpec.referencePDF() + "\n");
+ sb.append("<<\n/S /GoToR\n/F ");
+ sb.append(pdfFileSpec.referencePDF());
+ sb.append("\n");
if (destination != null) {
- sb.append("/D (" + this.destination + ")");
+ sb.append("/D (").append(this.destination).append(")");
} else {
- sb.append("/D [ " + this.pageReference + " /XYZ null null null ]");
+ sb.append("/D [ ").append(this.pageReference).append(" /XYZ null null null ]");
}
+ if (newWindow) {
+ sb.append("/NewWindow true");
+ }
+
sb.append(" \n>>\nendobj\n");
return sb.toString();
@@ -142,7 +158,7 @@
}
}
- return true;
+ return (this.newWindow == remote.newWindow);
}
}
--- src/java/org/apache/fop/fo/FOPropertyMapping.java (revision 642740)
+++ src/java/org/apache/fop/fo/FOPropertyMapping.java Sun Mar 30 13:02:04 CEST 2008
@@ -258,7 +258,7 @@
/**
* Return a (possibly cached) enum property based in the enum value.
- * @param enum A enum value from Constants.java.
+ * @param enumValue A enum value from Constants.java.
* @param text the text value by which this enum property is known
* @return An EnumProperty instance.
*/
@@ -371,9 +371,8 @@
|| ((id & Constants.PROPERTY_MASK) == 0)) {
return (String) s_htPropIds.get(new Integer(id));
} else {
- return (String) s_htPropIds.get(new Integer(
- id & Constants.PROPERTY_MASK)) + "." + s_htPropIds.get(
- new Integer(id & Constants.COMPOUND_MASK));
+ return s_htPropIds.get(new Integer(id & Constants.PROPERTY_MASK))
+ + "." + s_htPropIds.get(new Integer(id & Constants.COMPOUND_MASK));
}
}
@@ -2019,8 +2018,10 @@
addPropertyMaker("internal-destination", m);
// show-destination
- m = new ToBeImplementedProperty.Maker(PR_SHOW_DESTINATION);
+ m = new EnumProperty.Maker(PR_SHOW_DESTINATION);
m.setInherited(false);
+ m.addEnum("new", getEnumProperty(EN_NEW, "NEW"));
+ m.addEnum("replace", getEnumProperty(EN_REPLACE, "REPLACE"));
m.setDefault("replace");
addPropertyMaker("show-destination", m);
--- src/java/org/apache/fop/fo/flow/BasicLink.java (revision 642740)
+++ src/java/org/apache/fop/fo/flow/BasicLink.java Sun Mar 30 13:05:03 CEST 2008
@@ -27,19 +27,21 @@
import org.apache.fop.fo.ValidationException;
/**
- * Class modelling the fo:basic-link object.
+ * Class modelling the
+ * fo:basic-link
object.
*
* This class contains the logic to determine the link represented by this FO,
* and whether that link is external (uses a URI) or internal (an id
* reference).
*/
public class BasicLink extends Inline {
+
// The value of properties relevant for fo:basic-link.
// private ToBeImplementedProperty destinationPlacementOffset;
private String externalDestination;
// private ToBeImplementedProperty indicateDestination;
private String internalDestination;
- // private ToBeImplementedProperty showDestination;
+ private int showDestination;
// private ToBeImplementedProperty targetProcessingContext;
// private ToBeImplementedProperty targetPresentationContext;
// private ToBeImplementedProperty targetStylesheet;
@@ -51,22 +53,23 @@
private boolean blockOrInlineItemFound = false;
/**
- * @param parent FONode that is the parent of this object
+ * Construct a BasicLink instance with the given {@link FONode}
+ * as its parent.
+ *
+ * @param parent {@link FONode} that is the parent of this object
*/
public BasicLink(FONode parent) {
super(parent);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
// destinationPlacementOffset = pList.get(PR_DESTINATION_PLACEMENT_OFFSET);
externalDestination = pList.get(PR_EXTERNAL_DESTINATION).getString();
// indicateDestination = pList.get(PR_INDICATE_DESTINATION);
internalDestination = pList.get(PR_INTERNAL_DESTINATION).getString();
- // showDestination = pList.get(PR_SHOW_DESTINATION);
+ showDestination = pList.get(PR_SHOW_DESTINATION).getEnum();
// targetProcessingContext = pList.get(PR_TARGET_PROCESSING_CONTEXT);
// targetPresentationContext = pList.get(PR_TARGET_PRESENTATION_CONTEXT);
// targetStylesheet = pList.get(PR_TARGET_STYLESHEET);
@@ -81,26 +84,19 @@
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startLink(this);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void endOfNode() throws FOPException {
super.endOfNode();
getFOEventHandler().endLink();
}
- /**
- * {@inheritDoc} String, String)
- * XSL Content Model: marker* (#PCDATA|%inline;|%block;)*
- */
+ /** {@inheritDoc} */
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI) && localName.equals("marker")) {
@@ -115,33 +111,52 @@
}
/**
- * @return the "internal-destination" property.
+ * Get the value of the internal-destination
property.
+ *
+ * @return the "internal-destination" property
*/
public String getInternalDestination() {
return internalDestination;
}
/**
- * @return the "external-destination" property.
+ * Get the value of the external-destination
property.
+ *
+ * @return the "external-destination" property
*/
public String getExternalDestination() {
return externalDestination;
}
/**
- * @return whether or not this basic link has an internal destination or not
+ * Convenience method to check if this instance has an internal destination.
+ *
+ * @return true
if this basic link has an internal destination;
+ * false
otherwise
*/
public boolean hasInternalDestination() {
return internalDestination != null && internalDestination.length() > 0;
}
/**
- * @return whether or not this basic link has an external destination or not
+ * Convenience method to check if this instance has an external destination
+ *
+ * @return true
if this basic link has an external destination;
+ * false
otherwise
*/
public boolean hasExternalDestination() {
return externalDestination != null && externalDestination.length() > 0;
}
+ /**
+ * Get the value of the show-destination
property.
+ *
+ * @return the "show-destination" property
+ */
+ public int getShowDestination() {
+ return this.showDestination;
+ }
+
/** {@inheritDoc} */
public String getLocalName() {
return "basic-link";
--- src/java/org/apache/fop/pdf/PDFFactory.java (revision 642740)
+++ src/java/org/apache/fop/pdf/PDFFactory.java Sun Mar 30 16:32:15 CEST 2008
@@ -737,7 +737,7 @@
List theCone;
PDFPattern myPattern;
//PDFColorSpace theColorSpace;
- double interpolation = (double)1.000;
+ double interpolation = 1.000;
List theFunctions = new ArrayList();
int currentPosition;
@@ -961,7 +961,7 @@
}
/**
- * make a link object
+ * Make a {@link PDFLink} object
*
* @param rect the clickable rectangle
* @param destination the destination file
@@ -976,7 +976,7 @@
PDFLink link = new PDFLink(rect);
if (linkType == PDFLink.EXTERNAL) {
- link.setAction(getExternalAction(destination));
+ link.setAction(getExternalAction(destination, false));
} else {
// linkType is internal
String goToReference = getGoToReference(destination, yoffset);
@@ -999,9 +999,11 @@
*
* @param target The external target. This may be a PDF file name
* (optionally with internal page number or destination) or any type of URI.
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
* @return the PDFAction thus created or found
*/
- public PDFAction getExternalAction(String target) {
+ public PDFAction getExternalAction(String target, boolean newWindow) {
int index;
String targetLo = target.toLowerCase();
// HTTP URL?
@@ -1009,17 +1011,17 @@
return new PDFUri(target);
// Bare PDF file name?
} else if (targetLo.endsWith(".pdf")) {
- return getGoToPDFAction(target, null, -1);
+ return getGoToPDFAction(target, null, -1, newWindow);
// PDF file + page?
} else if ((index = targetLo.indexOf(".pdf#page=")) > 0) {
String filename = target.substring(0, index + 4);
int page = Integer.parseInt(target.substring(index + 10));
- return getGoToPDFAction(filename, null, page);
+ return getGoToPDFAction(filename, null, page, newWindow);
// PDF file + destination?
} else if ((index = targetLo.indexOf(".pdf#dest=")) > 0) {
String filename = target.substring(0, index + 4);
String dest = target.substring(index + 10);
- return getGoToPDFAction(filename, dest, -1);
+ return getGoToPDFAction(filename, dest, -1, newWindow);
// None of the above? Default to URI:
} else {
return new PDFUri(target);
@@ -1069,9 +1071,11 @@
* @param file the pdf file name
* @param dest the remote name destination, may be null
* @param page the remote page number, -1 means not specified
+ * @param newWindow boolean indicating whether the target should be
+ * displayed in a new window
* @return the pdf goto remote object
*/
- private PDFGoToRemote getGoToPDFAction(String file, String dest, int page) {
+ private PDFGoToRemote getGoToPDFAction(String file, String dest, int page, boolean newWindow) {
getDocument().getProfile().verifyActionAllowed();
PDFFileSpec fileSpec = new PDFFileSpec(file);
PDFFileSpec oldspec = getDocument().findFileSpec(fileSpec);
@@ -1083,11 +1087,11 @@
PDFGoToRemote remote;
if (dest == null && page == -1) {
- remote = new PDFGoToRemote(fileSpec);
+ remote = new PDFGoToRemote(fileSpec, newWindow);
} else if (dest != null) {
- remote = new PDFGoToRemote(fileSpec, dest);
+ remote = new PDFGoToRemote(fileSpec, dest, newWindow);
} else {
- remote = new PDFGoToRemote(fileSpec, page);
+ remote = new PDFGoToRemote(fileSpec, page, newWindow);
}
PDFGoToRemote oldremote = getDocument().findGoToRemote(remote);
if (oldremote == null) {
@@ -1458,6 +1462,7 @@
try {
in = new java.net.URL(source.getSystemId()).openStream();
} catch (MalformedURLException e) {
+ //TODO: why construct a new exception when it is not thrown?
new FileNotFoundException(
"File not found. URL could not be resolved: "
+ e.getMessage());
@@ -1563,7 +1568,6 @@
/**
* Create a PDFICCStream
* @see PDFImageXObject
- * @see org.apache.fop.image.JpegImage
* @see org.apache.fop.pdf.PDFDeviceColorSpace
* @return the new PDF ICC stream object
*/
--- src/java/org/apache/fop/fo/Constants.java (revision 642740)
+++ src/java/org/apache/fop/fo/Constants.java Sun Mar 30 12:39:56 CEST 2008
@@ -1092,7 +1092,11 @@
/** Enumeration constant -- for instream-foreign-object and external-graphic, XSL 1.1 */
int EN_SCALE_DOWN_TO_FIT = 187;
/** Enumeration constant -- for instream-foreign-object and external-graphic, XSL 1.1 */
- int EN_SCALE_UP_TO_FIT = 188;
+ int EN_SCALE_UP_TO_FIT = 188;
+ /** Enumeration constant -- for fo:basic-link show-destination */
+ int EN_REPLACE = 189;
+ /** Enumeration constant -- for fo:basic-link show-destination */
+ int EN_NEW = 190;
/** Number of enumeration constants defined */
- int ENUM_COUNT = 188;
+ int ENUM_COUNT = 190;
}
--- src/java/org/apache/fop/area/Trait.java (revision 642740)
+++ src/java/org/apache/fop/area/Trait.java Sun Mar 30 16:52:26 CEST 2008
@@ -194,7 +194,7 @@
public static final Integer OVERLINE_COLOR = new Integer(35);
/** Trait for color of linethrough decorations when rendering inline parent. */
public static final Integer LINETHROUGH_COLOR = new Integer(36);
-
+
/** Maximum value used by trait keys */
public static final int MAX_TRAIT_KEY = 36;
@@ -226,7 +226,7 @@
// Create a hashmap mapping trait code to name for external representation
//put(ID_LINK, new TraitInfo("id-link", String.class));
put(INTERNAL_LINK, new TraitInfo("internal-link", InternalLink.class));
- put(EXTERNAL_LINK, new TraitInfo("external-link", String.class));
+ put(EXTERNAL_LINK, new TraitInfo("external-link", ExternalLink.class));
put(FONT, new TraitInfo("font", FontTriplet.class));
put(FONT_SIZE, new TraitInfo("font-size", Integer.class));
put(COLOR, new TraitInfo("color", Color.class));
@@ -277,7 +277,7 @@
new TraitInfo("is-reference-area", Boolean.class));
put(IS_VIEWPORT_AREA,
new TraitInfo("is-viewport-area", Boolean.class));
-
+
}
/**
@@ -548,6 +548,51 @@
}
/**
+ * External Link trait structure
+ */
+ public static class ExternalLink implements Serializable {
+
+ private String destination;
+ private boolean newWindow;
+
+ /**
+ * Constructs an ExternalLink object with the given destination
+ *
+ * @param destination target of the link
+ * @param newWindow true if the target should be opened in a new window
+ */
+ public ExternalLink(String destination, boolean newWindow) {
+ this.destination = destination;
+ this.newWindow = newWindow;
+ }
+
+ /**
+ * Get the target/destination of the link
+ * @return the destination of the link
+ */
+ public String getDestination() {
+ return this.destination;
+ }
+
+ /**
+ * Check if the target has to be displayed in a new window
+ * @return true if the target has to be displayed in a new window
+ */
+ public boolean newWindow() {
+ return this.newWindow;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ StringBuffer sb = new StringBuffer(32);
+ sb.append(ExternalLink.class.getName());
+ sb.append("[dest=").append(this.destination);
+ sb.append(";newWindow=").append(newWindow).append("]");
+ return sb.toString();
+ }
+ }
+
+ /**
* Background trait structure.
* Used for storing back trait information which are related.
*/
--- src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java (revision 642740)
+++ src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java Sun Mar 30 13:40:39 CEST 2008
@@ -68,8 +68,6 @@
*/
private static Log log = LogFactory.getLog(InlineLayoutManager.class);
- private InlineLevel fobj;
-
private CommonMarginInline inlineProps = null;
private CommonBorderPaddingBackground borderProps = null;
@@ -105,7 +103,6 @@
// The node should be FObjMixed
public InlineLayoutManager(InlineLevel node) {
super(node);
- fobj = node;
}
private Inline getInlineFO() {
@@ -114,6 +111,8 @@
/** {@inheritDoc} */
public void initialize() {
+ InlineLevel fobj = (InlineLevel) this.fobj;
+
int padding = 0;
FontInfo fi = fobj.getFOEventHandler().getFontInfo();
FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
@@ -557,7 +556,8 @@
if (returnList instanceof BlockKnuthSequence) {
return;
}
- CommonBorderPaddingBackground borderAndPadding = fobj.getCommonBorderPaddingBackground();
+ CommonBorderPaddingBackground borderAndPadding =
+ ((InlineLevel)fobj).getCommonBorderPaddingBackground();
if (borderAndPadding != null) {
int ipStart = borderAndPadding.getBorderStartWidth(false)
+ borderAndPadding.getPaddingStart(false, this);
@@ -581,7 +581,8 @@
if (returnList instanceof BlockKnuthSequence) {
return;
}
- CommonBorderPaddingBackground borderAndPadding = fobj.getCommonBorderPaddingBackground();
+ CommonBorderPaddingBackground borderAndPadding =
+ ((InlineLevel)fobj).getCommonBorderPaddingBackground();
if (borderAndPadding != null) {
int ipEnd = borderAndPadding.getBorderEndWidth(false)
+ borderAndPadding.getPaddingEnd(false, this);
--- src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java (revision 642740)
+++ src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java Sun Mar 30 16:31:17 CEST 2008
@@ -21,7 +21,7 @@
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.fo.flow.BasicLink;
-import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.fo.Constants;
import org.apache.fop.layoutmgr.PageSequenceLayoutManager;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.Trait;
@@ -31,7 +31,6 @@
* LayoutManager for the fo:basic-link formatting object
*/
public class BasicLinkLayoutManager extends InlineLayoutManager {
- private BasicLink fobj;
/**
* Create an fo:basic-link layout manager.
@@ -40,23 +39,22 @@
*/
public BasicLinkLayoutManager(BasicLink node) {
super(node);
- fobj = node;
}
/** {@inheritDoc} */
protected InlineArea createArea(boolean bInlineParent) {
InlineArea area = super.createArea(bInlineParent);
- setupBasicLinkArea(parentLM, area);
+ setupBasicLinkArea(area);
return area;
}
/*
* Detect internal or external link and add it as an area trait
*
- * @param parentLM the parent LayoutManager
* @param area the basic-link's area
*/
- private void setupBasicLinkArea(LayoutManager parentLM, InlineArea area) {
+ private void setupBasicLinkArea(InlineArea area) {
+ BasicLink fobj = (BasicLink) this.fobj;
// internal destinations take precedence:
if (fobj.hasInternalDestination()) {
String idref = fobj.getInternalDestination();
@@ -70,8 +68,10 @@
}
} else if (fobj.hasExternalDestination()) {
String url = URISpecification.getURL(fobj.getExternalDestination());
+ boolean newWindow = (fobj.getShowDestination() == Constants.EN_NEW);
if (url.length() > 0) {
- area.addTrait(Trait.EXTERNAL_LINK, url);
+ area.addTrait(Trait.EXTERNAL_LINK,
+ new Trait.ExternalLink(url, newWindow));
}
}
}
--- src/java/org/apache/fop/render/pdf/PDFRenderer.java (revision 642740)
+++ src/java/org/apache/fop/render/pdf/PDFRenderer.java Sun Mar 30 15:33:42 CEST 2008
@@ -1382,14 +1382,17 @@
// no INTERNAL_LINK, look for EXTERNAL_LINK
if (!linkTraitFound) {
- String extDest = (String) ip.getTrait(Trait.EXTERNAL_LINK);
+ Trait.ExternalLink extLink = (Trait.ExternalLink) ip.getTrait(Trait.EXTERNAL_LINK);
+ if (extLink != null) {
+ String extDest = extLink.getDestination();
- if (extDest != null && extDest.length() > 0) {
- linkTraitFound = true;
- if (annotsAllowed) {
+ if (extDest != null && extDest.length() > 0) {
+ linkTraitFound = true;
+ if (annotsAllowed) {
- action = factory.getExternalAction(extDest);
+ action = factory.getExternalAction(extDest, extLink.newWindow());
- }
- }
- }
+ }
+ }
+ }
+ }
// warn if link trait found but not allowed, else create link
if (linkTraitFound) {
@@ -1618,7 +1621,7 @@
* Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced.
* @param uri URL of the bitmap
* @param pos Position of the bitmap
- * @deprecated Use {@link @putImage(String, Rectangle2D, Map)} instead.
+ * @deprecated Use {@link #putImage(String, Rectangle2D, Map)} instead.
*/
protected void putImage(String uri, Rectangle2D pos) {
putImage(uri, pos, null);