diff options
Diffstat (limited to 'src/java/org')
21 files changed, 883 insertions, 164 deletions
diff --git a/src/java/org/apache/fop/area/AbstractOffDocumentItem.java b/src/java/org/apache/fop/area/AbstractOffDocumentItem.java new file mode 100644 index 000000000..4f56b026d --- /dev/null +++ b/src/java/org/apache/fop/area/AbstractOffDocumentItem.java @@ -0,0 +1,70 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation. + * + * Licensed 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.area; + +/** + * Abstract base class for objects that are processed by the renderer outside + * of the actual document. + * This object can be handled by the renderer according to these + * possibilities: IMMEDIATELY, AFTER_PAGE, START_OF_DOC or END_OF_DOC. + */ +public abstract class AbstractOffDocumentItem implements OffDocumentItem { + + /** + * Process this extension immediately when + * being handled by the area tree. + */ + public static final int IMMEDIATELY = 0; + + /** + * Process this extension after the next page is rendered + * or prepared when being handled by the area tree. + */ + public static final int AFTER_PAGE = 1; + + /** + * Process this extension at the end of the document once + * all pages have been fully rendered. + */ + public static final int END_OF_DOC = 2; + + /** + * Process this extension at the start of the document right + * before the first page-sequence is processed. + */ + public static final int START_OF_DOC = 2; + + + /** Indicates in what phase the item should be processed. */ + protected int whenToProcess = IMMEDIATELY; + + /** + * Get an indicator of when this item should be processed + * @return int constant (IMMEDIATELY, AFTER_PAGE, START_OF_DOC, END_OF_DOC) + */ + public int getWhenToProcess() { + return whenToProcess; + } + + /** + * Return a human-readable name for this ODI (for error messages, etc.) + * @return String name of ODI + */ + public abstract String getName(); +} diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index 47b5c1634..183ca8896 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -15,6 +15,7 @@ */ /* $Id$ */ + package org.apache.fop.area; // Java @@ -37,6 +38,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FormattingResults; import org.apache.fop.fo.FOEventHandler; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.Root; import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; @@ -250,6 +252,26 @@ public class AreaTreeHandler extends FOEventHandler { } } + /** @see org.apache.fop.fo.FOEventHandler */ + public void startPageSequence(PageSequence pageSequence) { + rootFObj = pageSequence.getRoot(); + + //extension attachments from fo:root + wrapAndAddExtensionAttachments(rootFObj.getExtensionAttachments()); + //extension attachments from fo:declarations + if (rootFObj.getDeclarations() != null) { + wrapAndAddExtensionAttachments(rootFObj.getDeclarations().getExtensionAttachments()); + } + } + + private void wrapAndAddExtensionAttachments(List list) { + Iterator i = list.iterator(); + while (i.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment)i.next(); + addOffDocumentItem(new OffDocumentExtensionAttachment(attachment)); + } + } + /** * End the PageSequence. * The PageSequence formats Pages and adds them to the AreaTree. @@ -264,8 +286,6 @@ public class AreaTreeHandler extends FOEventHandler { log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb"); } - rootFObj = pageSequence.getRoot(); - // If no main flow, nothing to layout! if (pageSequence.getMainFlow() != null) { PageSequenceLayoutManager pageSLM; @@ -275,6 +295,11 @@ public class AreaTreeHandler extends FOEventHandler { } } + /** + * Called by the PageSequenceLayoutManager when it is finished with a page-sequence. + * @param pageSequence the page-sequence just finished + * @param pageCount The number of pages generated for the page-sequence + */ public void notifyPageSequenceFinished(PageSequence pageSequence, int pageCount) { this.results.haveFormattedPageSequence(pageSequence, diff --git a/src/java/org/apache/fop/area/BookmarkData.java b/src/java/org/apache/fop/area/BookmarkData.java index 06c72d57b..92f008d97 100644 --- a/src/java/org/apache/fop/area/BookmarkData.java +++ b/src/java/org/apache/fop/area/BookmarkData.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. + * Copyright 1999-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import org.apache.fop.fo.pagination.bookmarks.Bookmark; * its child bookmark-items, or a bookmark-item and the child * child bookmark-items under it. */ -public class BookmarkData extends OffDocumentItem implements Resolvable { +public class BookmarkData extends AbstractOffDocumentItem implements Resolvable { private ArrayList subData = new ArrayList(); // bookmark-title for this fo:bookmark diff --git a/src/java/org/apache/fop/area/OffDocumentExtensionAttachment.java b/src/java/org/apache/fop/area/OffDocumentExtensionAttachment.java new file mode 100644 index 000000000..4797fbaab --- /dev/null +++ b/src/java/org/apache/fop/area/OffDocumentExtensionAttachment.java @@ -0,0 +1,55 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.area; + +import org.apache.fop.fo.extensions.ExtensionAttachment; + +/** + * This class wraps ExtensionAttachments which cannot be transported inside the area tree but + * need to be handled in the AreaTreeHandler. These attachments are schedules for processing + * before the first page-sequence, i.e. at the start of the document. + */ +public class OffDocumentExtensionAttachment implements OffDocumentItem { + + private ExtensionAttachment attachment; + + /** + * Main constructor + * @param attachment the extension attachment to wrap. + */ + public OffDocumentExtensionAttachment(ExtensionAttachment attachment) { + this.attachment = attachment; + } + + /** @return the extension attachment. */ + public ExtensionAttachment getAttachment() { + return this.attachment; + } + + /** @see org.apache.fop.area.OffDocumentItem#getWhenToProcess() */ + public int getWhenToProcess() { + return OffDocumentItem.IMMEDIATELY; + } + + /** @see org.apache.fop.area.OffDocumentItem#getName() */ + public String getName() { + return attachment.getCategory(); + } + +} diff --git a/src/java/org/apache/fop/area/OffDocumentItem.java b/src/java/org/apache/fop/area/OffDocumentItem.java index 72f3b2e37..6bac6800d 100644 --- a/src/java/org/apache/fop/area/OffDocumentItem.java +++ b/src/java/org/apache/fop/area/OffDocumentItem.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. + * Copyright 2004-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,45 +19,42 @@ package org.apache.fop.area; /** - * Abstract base class for objects that are processed by the renderer outside + * Interface for objects that are processed by the renderer outside * of the actual document. - * This object can be handled by the renderer according to three - * possibilities, IMMEDIATELY, AFTER_PAGE, or END_OF_DOC. + * An object implementing this interface can be handled by the renderer according to these + * possibilities: IMMEDIATELY, AFTER_PAGE or END_OF_DOC. */ -public abstract class OffDocumentItem { +public interface OffDocumentItem { /** * Process this extension immediately when * being handled by the area tree. */ - public static final int IMMEDIATELY = 0; + int IMMEDIATELY = 0; /** * Process this extension after the next page is rendered * or prepared when being handled by the area tree. */ - public static final int AFTER_PAGE = 1; + int AFTER_PAGE = 1; /** * Process this extension at the end of the document once * all pages have been fully rendered. */ - public static final int END_OF_DOC = 2; + int END_OF_DOC = 2; - - protected int whenToProcess = IMMEDIATELY; /** * Get an indicator of when this item should be processed * @return int constant (IMMEDIATELY, AFTER_PAGE, END_OF_DOC) */ - public int getWhenToProcess() { - return whenToProcess; - } + int getWhenToProcess(); /** * Return a human-readable name for this ODI (for error messages, etc.) * @return String name of ODI */ - public abstract String getName(); + String getName(); + } diff --git a/src/java/org/apache/fop/fo/FOElementMapping.java b/src/java/org/apache/fop/fo/FOElementMapping.java index cca493cdc..bf376de2a 100644 --- a/src/java/org/apache/fop/fo/FOElementMapping.java +++ b/src/java/org/apache/fop/fo/FOElementMapping.java @@ -25,7 +25,9 @@ import java.util.HashMap; * Element mapping class for all XSL-FO elements. */ public class FOElementMapping extends ElementMapping { - public static String URI = "http://www.w3.org/1999/XSL/Format"; + + /** The XSL-FO namespace URI */ + public static final String URI = "http://www.w3.org/1999/XSL/Format"; /** * Basic constructor; inititializes the namespace URI for the fo: namespace diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java index 0e00b7006..86011004e 100644 --- a/src/java/org/apache/fop/fo/FONode.java +++ b/src/java/org/apache/fop/fo/FONode.java @@ -29,17 +29,19 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fo.extensions.svg.SVGElementMapping; import org.apache.fop.fo.pagination.Root; import org.apache.fop.util.CharUtilities; /** - * base class for nodes in the XML tree + * Base class for nodes in the XML tree */ public abstract class FONode implements Cloneable { - protected static String FO_URI = FOElementMapping.URI; + /** the XSL-FO namespace URI */ + protected static final String FO_URI = FOElementMapping.URI; /** Parent FO node */ protected FONode parent; @@ -50,10 +52,12 @@ public abstract class FONode implements Cloneable { * information */ public Locator locator; + //TODO Make private or protected and access via getLocator() /** Logger for fo-tree related messages **/ - private static Log log = LogFactory.getLog(FONode.class); - + protected static Log log = LogFactory.getLog(FONode.class); + //TODO Remove getLogger() method! + /** * Main constructor. * @param parent parent of this node @@ -68,9 +72,10 @@ public abstract class FONode implements Cloneable { * @param parent the intended parent of the clone * @param removeChildren if true, clean the list of child nodes * @return the cloned FO node + * @throws FOPException if there's a problem while cloning the node */ public FONode clone(FONode parent, boolean removeChildren) - throws FOPException { + throws FOPException { FONode foNode = (FONode) clone(); foNode.parent = parent; parent.addChildNode(foNode); @@ -86,8 +91,9 @@ public abstract class FONode implements Cloneable { protected Object clone() { try { return super.clone(); - } catch (CloneNotSupportedException e) { } - return null; + } catch (CloneNotSupportedException e) { + return null; + } } /** @@ -100,6 +106,11 @@ public abstract class FONode implements Cloneable { } } + /** @return the location information for this element or null, if not available */ + public Locator getLocator() { + return this.locator; + } + /** * Recursively goes up the FOTree hierarchy until the fo:root is found, * which returns the parent FOEventHandler. @@ -132,11 +143,15 @@ public abstract class FONode implements Cloneable { * @param elementName element name (e.g., "fo:block") * @param locator Locator object (ignored by default) * @param attlist Collection of attributes passed to us from the parser. + * @param parent the property list of the parent node * @throws FOPException for errors or inconsistencies in the attributes */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList parent) throws FOPException { - log.debug("name = " + elementName); + if (log.isDebugEnabled()) { + log.debug("Unhandled element: " + elementName + + (locator != null ? " at " + getLocatorString(locator) : "")); + } } /** @@ -146,8 +161,10 @@ public abstract class FONode implements Cloneable { * @param foEventHandler The FOEventHandler where the PropertyListMaker * instance can be found. * @return A new property list. + * @throws FOPException if there's a problem during processing */ - protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) throws FOPException { + protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) + throws FOPException { return null; } @@ -156,12 +173,15 @@ public abstract class FONode implements Cloneable { * incoming node is valid for the this (parent) node (e.g., checking to * see that fo:table is not an immediate child of fo:root) * called within FObj constructor + * @param loc location in the FO source file * @param namespaceURI namespace of incoming node * @param localName (e.g. "table" for "fo:table") * @throws ValidationException if incoming node not valid for parent */ protected void validateChildNode(Locator loc, String namespaceURI, String localName) - throws ValidationException {} + throws ValidationException { + //nop + } /** * Adds characters (does nothing here) @@ -179,25 +199,31 @@ public abstract class FONode implements Cloneable { } /** - * - */ + * Called after processNode() is called. Subclasses can do additional processing. + * @throws FOPException if there's a problem during processing + */ protected void startOfNode() throws FOPException { // do nothing by default } /** - * Primarily used for making final content model validation checks - * and/or informing the FOEventHandler that the end of this FO - * has been reached. + * Primarily used for making final content model validation checks + * and/or informing the FOEventHandler that the end of this FO + * has been reached. + * @throws FOPException if there's a problem during processing */ protected void endOfNode() throws FOPException { // do nothing by default } /** + * Adds a node as a child of this node. The default implementation of this method + * just ignores any child node being added. * @param child child node to be added to the childNodes of this node + * @throws FOPException if there's a problem during processing */ protected void addChildNode(FONode child) throws FOPException { + // do nothing by default } /** @@ -260,9 +286,10 @@ public abstract class FONode implements Cloneable { return "fox:" + localName; } else if (namespaceURI.equals(SVGElementMapping.URI)) { return "svg:" + localName; - } else - return "(Namespace URI: \"" + namespaceURI + "\", " + - "Local Name: \"" + localName + "\")"; + } else { + return "(Namespace URI: \"" + namespaceURI + "\", " + + "Local Name: \"" + localName + "\")"; + } } /** @@ -270,11 +297,12 @@ public abstract class FONode implements Cloneable { * (e.g., not specifying either an internal- or an external-destination * property for an FO:link) * @param problem text to display that indicates the problem + * @throws ValidationException the validation error provoked by the method call */ protected void attributeError(String problem) - throws ValidationException { - throw new ValidationException(errorText(locator) + getName() + ", " + - problem, locator); + throws ValidationException { + throw new ValidationException(errorText(locator) + getName() + + ", " + problem, locator); } /** @@ -283,7 +311,7 @@ public abstract class FONode implements Cloneable { * @param problem text to display that indicates the problem */ protected void attributeWarning(String problem) { - getLogger().warn(errorText(locator) + getName() + ", " + problem); + log.warn(errorText(locator) + getName() + ", " + problem); } /** @@ -292,11 +320,12 @@ public abstract class FONode implements Cloneable { * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param nsURI namespace URI of incoming invalid node * @param lName local name (i.e., no prefix) of incoming node + * @throws ValidationException the validation error provoked by the method call */ protected void tooManyNodesError(Locator loc, String nsURI, String lName) - throws ValidationException { - throw new ValidationException(errorText(loc) + "For " + getName() + - ", only one " + getNodeString(nsURI, lName) + " may be declared.", + throws ValidationException { + throw new ValidationException(errorText(loc) + "For " + getName() + + ", only one " + getNodeString(nsURI, lName) + " may be declared.", loc); } @@ -306,11 +335,12 @@ public abstract class FONode implements Cloneable { * This overrloaded method helps make the caller code better self-documenting * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param offendingNode incoming node that would cause a duplication. + * @throws ValidationException the validation error provoked by the method call */ protected void tooManyNodesError(Locator loc, String offendingNode) - throws ValidationException { - throw new ValidationException(errorText(loc) + "For " + getName() + - ", only one " + offendingNode + " may be declared.", loc); + throws ValidationException { + throw new ValidationException(errorText(loc) + "For " + getName() + + ", only one " + offendingNode + " may be declared.", loc); } /** @@ -319,6 +349,7 @@ public abstract class FONode implements Cloneable { * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param tooLateNode string name of node that should be earlier in document * @param tooEarlyNode string name of node that should be later in document + * @throws ValidationException the validation error provoked by the method call */ protected void nodesOutOfOrderError(Locator loc, String tooLateNode, String tooEarlyNode) throws ValidationException { @@ -332,9 +363,10 @@ public abstract class FONode implements Cloneable { * @param loc org.xml.sax.Locator object of the error (*not* parent node) * @param nsURI namespace URI of incoming invalid node * @param lName local name (i.e., no prefix) of incoming node + * @throws ValidationException the validation error provoked by the method call */ protected void invalidChildError(Locator loc, String nsURI, String lName) - throws ValidationException { + throws ValidationException { invalidChildError(loc, nsURI, lName, null); } @@ -345,62 +377,71 @@ public abstract class FONode implements Cloneable { * @param nsURI namespace URI of incoming invalid node * @param lName local name (i.e., no prefix) of incoming node * @param ruleViolated text explanation of problem + * @throws ValidationException the validation error provoked by the method call */ protected void invalidChildError(Locator loc, String nsURI, String lName, - String ruleViolated) - throws ValidationException { - throw new ValidationException(errorText(loc) + getNodeString(nsURI, lName) + - " is not a valid child element of " + getName() + String ruleViolated) + throws ValidationException { + throw new ValidationException(errorText(loc) + getNodeString(nsURI, lName) + + " is not a valid child element of " + getName() + ((ruleViolated != null) ? ": " + ruleViolated : "."), loc); } /** * Helper function to throw an error caused by missing mandatory child elements. * E.g., fo:layout-master-set not having any page-master child element. - * @param contentModel The XSL Content Model for the fo: object or a similar description indicating the necessary child elements. + * @param contentModel The XSL Content Model for the fo: object or a similar description + * indicating the necessary child elements. + * @throws ValidationException the validation error provoked by the method call */ protected void missingChildElementError(String contentModel) - throws ValidationException { - throw new ValidationException(errorText(locator) + getName() + - " is missing child elements. \nRequired Content Model: " + throws ValidationException { + throw new ValidationException(errorText(locator) + getName() + + " is missing child elements. \nRequired Content Model: " + contentModel, locator); } /** * Helper function to throw an error caused by missing mandatory properties * @param propertyName the name of the missing property. + * @throws ValidationException the validation error provoked by the method call */ protected void missingPropertyError(String propertyName) - throws ValidationException { - throw new ValidationException(errorText(locator) + getName() + - " is missing required \"" + propertyName + "\" property.", locator); + throws ValidationException { + throw new ValidationException(errorText(locator) + getName() + + " is missing required \"" + propertyName + "\" property.", locator); } /** - * Helper function to return "Error (line#/column#)" string for + * Helper function to return "Error(line#/column#)" string for * above exception messages * @param loc org.xml.sax.Locator object * @return String opening error text */ protected static String errorText(Locator loc) { - if (loc == null) { - return "Error(Unknown location): "; - } else { - return "Error(" + loc.getLineNumber() + "/" + loc.getColumnNumber() + "): "; - } + return "Error(" + getLocatorString(loc) + "): "; } /** - * Helper function to return "Warning (line#/column#)" string for + * Helper function to return "Warning(line#/column#)" string for * warning messages * @param loc org.xml.sax.Locator object * @return String opening warning text */ protected static String warningText(Locator loc) { + return "Warning(" + getLocatorString(loc) + "): "; + } + + /** + * Helper function to format a Locator instance. + * @param loc org.xml.sax.Locator object + * @return String the formatted text + */ + protected static String getLocatorString(Locator loc) { if (loc == null) { - return "Warning(Unknown location): "; + return "Unknown location"; } else { - return "Warning(" + loc.getLineNumber() + "/" + loc.getColumnNumber() + "): "; + return loc.getLineNumber() + "/" + loc.getColumnNumber(); } } @@ -429,5 +470,16 @@ public abstract class FONode implements Cloneable { return Constants.FO_UNKNOWN_NODE; } + /** + * This method is overridden by extension elements and allows the extension element + * to return a pass-through attachment which the parent formatting objects should simply + * carry with them but otherwise ignore. This mechanism is used to pass non-standard + * information from the FO tree through to the layout engine and the renderers. + * @return the extension attachment if one is created by the extension element, null otherwise. + */ + public ExtensionAttachment getExtensionAttachment() { + return null; + } + } diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java index 0aa4f4758..58942036f 100644 --- a/src/java/org/apache/fop/fo/FOTreeBuilder.java +++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java @@ -135,6 +135,7 @@ public class FOTreeBuilder extends DefaultHandler { addElementMapping("org.apache.fop.fo.extensions.svg.SVGElementMapping"); addElementMapping("org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping"); addElementMapping("org.apache.fop.fo.extensions.ExtensionElementMapping"); + addElementMapping("org.apache.fop.render.ps.extensions.PSExtensionElementMapping"); // add mappings from available services Iterator providers = Service.providers(ElementMapping.class); diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 3e82c2911..c96c4ecc7 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -18,6 +18,7 @@ package org.apache.fop.fo; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; @@ -26,6 +27,7 @@ import java.util.Set; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.PercentBase; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.flow.Marker; import org.apache.fop.fo.properties.PropertyMaker; import org.xml.sax.Attributes; @@ -35,11 +37,16 @@ import org.xml.sax.Locator; * Base class for representation of formatting objects and their processing. */ public abstract class FObj extends FONode implements Constants { - public static PropertyMaker[] propertyListTable = null; + + /** the list of property makers */ + private static PropertyMaker[] propertyListTable = null; /** The immediate child nodes of this node. */ - public List childNodes = null; + protected List childNodes = null; + /** The list of extension attachments, null if none */ + private List extensionAttachments = null; + /** Used to indicate if this FO is either an Out Of Line FO (see rec) or a descendant of one. Used during validateChildNode() FO validation. @@ -64,7 +71,7 @@ public abstract class FObj extends FONode implements Constants { // determine if isOutOfLineFODescendant should be set if (parent != null && parent instanceof FObj) { - if (((FObj)parent).getIsOutOfLineFODescendant() == true) { + if (((FObj)parent).getIsOutOfLineFODescendant()) { isOutOfLineFODescendant = true; } else { int foID = getNameId(); @@ -97,6 +104,15 @@ public abstract class FObj extends FONode implements Constants { } return fobj; } + + /** + * Returns the PropertyMaker for a given property ID. + * @param propId the property ID + * @return the requested Property Maker + */ + public static PropertyMaker getPropertyMakerFor(int propId) { + return propertyListTable[propId]; + } /** * @see org.apache.fop.fo.FONode#processNode @@ -111,6 +127,7 @@ public abstract class FObj extends FONode implements Constants { /** * Create a default property list for this element. + * @see org.apache.fop.fo.FONode */ protected PropertyList createPropertyList(PropertyList parent, FOEventHandler foEventHandler) throws FOPException { @@ -122,7 +139,7 @@ public abstract class FObj extends FONode implements Constants { * Must be overridden in all FObj subclasses that have properties * applying to it. * @param pList the PropertyList where the properties can be found. - * @throws FOPException + * @throws FOPException if there is a problem binding the values */ public void bind(PropertyList pList) throws FOPException { } @@ -132,16 +149,18 @@ public abstract class FObj extends FONode implements Constants { * Most formatting objects can have an id that can be referenced. * This methods checks that the id isn't already used by another * fo and sets the id attribute of this object. + * @param id ID to check + * @throws ValidationException if the ID is already defined elsewhere */ - protected void checkId(String id) throws ValidationException { + protected void checkId(String id) throws ValidationException { if (!id.equals("")) { Set idrefs = getFOEventHandler().getIDReferences(); if (!idrefs.contains(id)) { idrefs.add(id); } else { - throw new ValidationException("Property id \"" + id + - "\" previously used; id values must be unique" + - " in document.", locator); + throw new ValidationException("Property id \"" + id + + "\" previously used; id values must be unique" + + " in document.", locator); } } } @@ -158,14 +177,20 @@ public abstract class FObj extends FONode implements Constants { * @see org.apache.fop.fo.FONode#addChildNode(FONode) */ protected void addChildNode(FONode child) throws FOPException { - if (PropertySets.canHaveMarkers(getNameId()) && - child.getNameId() == FO_MARKER) { - addMarker((Marker) child); + if (PropertySets.canHaveMarkers(getNameId()) && child.getNameId() == FO_MARKER) { + addMarker((Marker)child); } else { - if (childNodes == null) { - childNodes = new java.util.ArrayList(); + ExtensionAttachment attachment = child.getExtensionAttachment(); + if (attachment != null) { + //This removes the element from the normal children, so no layout manager + //is being created for them as they are only additional information. + addExtensionAttachment(attachment); + } else { + if (childNodes == null) { + childNodes = new java.util.ArrayList(); + } + childNodes.add(child); } - childNodes.add(child); } } @@ -194,6 +219,7 @@ public abstract class FObj extends FONode implements Constants { * Assign the size of a layout dimension to the key. * @param key the Layout dimension, from PercentBase. * @param dimension The layout length. + * TODO Remove when possible! */ public void setLayoutDimension(PercentBase.LayoutDimension key, int dimension) { if (layoutDimension == null) { @@ -206,6 +232,7 @@ public abstract class FObj extends FONode implements Constants { * Assign the size of a layout dimension to the key. * @param key the Layout dimension, from PercentBase. * @param dimension The layout length. + * TODO Remove when possible! */ public void setLayoutDimension(PercentBase.LayoutDimension key, float dimension) { if (layoutDimension == null) { @@ -218,6 +245,7 @@ public abstract class FObj extends FONode implements Constants { * Return the size associated with the key. * @param key The layout dimension key. * @return the length. + * TODO Remove when possible! */ public Number getLayoutDimension(PercentBase.LayoutDimension key) { if (layoutDimension != null) { @@ -349,14 +377,14 @@ public abstract class FObj extends FONode implements Constants { * @return true if a member, false if not */ protected boolean isBlockItem(String nsURI, String lName) { - return (FO_URI.equals(nsURI) && - (lName.equals("block") - || lName.equals("table") - || lName.equals("table-and-caption") - || lName.equals("block-container") - || lName.equals("list-block") - || lName.equals("float") - || isNeutralItem(nsURI, lName))); + return (FO_URI.equals(nsURI) + && (lName.equals("block") + || lName.equals("table") + || lName.equals("table-and-caption") + || lName.equals("block-container") + || lName.equals("list-block") + || lName.equals("float") + || isNeutralItem(nsURI, lName))); } /** @@ -368,21 +396,22 @@ public abstract class FObj extends FONode implements Constants { * @return true if a member, false if not */ protected boolean isInlineItem(String nsURI, String lName) { - return (FO_URI.equals(nsURI) && - (lName.equals("bidi-override") - || lName.equals("character") - || lName.equals("external-graphic") - || lName.equals("instream-foreign-object") - || lName.equals("inline") - || lName.equals("inline-container") - || lName.equals("leader") - || lName.equals("page-number") - || lName.equals("page-number-citation") - || lName.equals("basic-link") - || (lName.equals("multi-toggle") - && (getNameId() == FO_MULTI_CASE || findAncestor(FO_MULTI_CASE) > 0)) - || (lName.equals("footnote") && !isOutOfLineFODescendant) - || isNeutralItem(nsURI, lName))); + return (FO_URI.equals(nsURI) + && (lName.equals("bidi-override") + || lName.equals("character") + || lName.equals("external-graphic") + || lName.equals("instream-foreign-object") + || lName.equals("inline") + || lName.equals("inline-container") + || lName.equals("leader") + || lName.equals("page-number") + || lName.equals("page-number-citation") + || lName.equals("basic-link") + || (lName.equals("multi-toggle") + && (getNameId() == FO_MULTI_CASE + || findAncestor(FO_MULTI_CASE) > 0)) + || (lName.equals("footnote") && !isOutOfLineFODescendant) + || isNeutralItem(nsURI, lName))); } /** @@ -406,12 +435,12 @@ public abstract class FObj extends FONode implements Constants { * @return true if a member, false if not */ protected boolean isNeutralItem(String nsURI, String lName) { - return (FO_URI.equals(nsURI) && - (lName.equals("multi-switch") - || lName.equals("multi-properties") - || lName.equals("wrapper") - || (!isOutOfLineFODescendant && lName.equals("float")) - || lName.equals("retrieve-marker"))); + return (FO_URI.equals(nsURI) + && (lName.equals("multi-switch") + || lName.equals("multi-properties") + || lName.equals("wrapper") + || (!isOutOfLineFODescendant && lName.equals("float")) + || lName.equals("retrieve-marker"))); } /** @@ -433,5 +462,33 @@ public abstract class FObj extends FONode implements Constants { } return -1; } + + /** + * Add a new extension attachment to this FObj. See org.apache.fop.fo.FONode for details. + * @param attachment the attachment to add. + */ + public void addExtensionAttachment(ExtensionAttachment attachment) { + if (attachment == null) { + throw new NullPointerException("Parameter attachment must not be null"); + } + if (extensionAttachments == null) { + extensionAttachments = new java.util.ArrayList(); + } + if (log.isDebugEnabled()) { + getLogger().debug("ExtensionAttachment of category " + attachment.getCategory() + + " added to " + getName() + ": " + attachment); + } + extensionAttachments.add(attachment); + } + + /** @return the extension attachments of this FObj. */ + public List getExtensionAttachments() { + if (extensionAttachments == null) { + return Collections.EMPTY_LIST; + } else { + return extensionAttachments; + } + } + } diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java index 64553c156..09545055a 100644 --- a/src/java/org/apache/fop/fo/PropertyList.java +++ b/src/java/org/apache/fop/fo/PropertyList.java @@ -452,7 +452,7 @@ abstract public class PropertyList { if (propId < 1 || propId > Constants.PROPERTY_COUNT) { return null; } else { - return FObj.propertyListTable[propId]; + return FObj.getPropertyMakerFor(propId); } } diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionAttachment.java b/src/java/org/apache/fop/fo/extensions/ExtensionAttachment.java new file mode 100644 index 000000000..2a611f74e --- /dev/null +++ b/src/java/org/apache/fop/fo/extensions/ExtensionAttachment.java @@ -0,0 +1,38 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.fo.extensions; + +/** + * This interface is implemented by objects that are returned by special extension element + * through the FONode.getExtensionAttachment() method. Such objects are carried in the FO tree + * and made available to the layout managers that support processing extension attachments or + * support passing them on to the area tree where they can be picked up by renderers. + * <p> + * NOTE: Classes which implement this interface need to be Serializable! + */ +public interface ExtensionAttachment { + + /** + * This method returns a category URI that allows a processor (layout manager or renderer) + * to determine if it supports this object. + * @return the category URI + */ + String getCategory(); + +} diff --git a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java index 62d9371e4..cfe90d07f 100644 --- a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -327,4 +327,10 @@ public class InstreamForeignObject extends FObj { protected void addChildNode(FONode child) throws FOPException { super.addChildNode(child); } + + /** @return the XMLObj child node of the instream-foreign-object. */ + public XMLObj getChildXMLObj() { + return (XMLObj) childNodes.get(0); + } + } diff --git a/src/java/org/apache/fop/fo/pagination/Declarations.java b/src/java/org/apache/fop/fo/pagination/Declarations.java index 110f8e2a8..57f1fd825 100644 --- a/src/java/org/apache/fop/fo/pagination/Declarations.java +++ b/src/java/org/apache/fop/fo/pagination/Declarations.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 The Apache Software Foundation. + * Copyright 1999-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ package org.apache.fop.fo.pagination; // Java import java.util.Iterator; -import java.util.List; import java.util.Map; import org.xml.sax.Locator; @@ -30,8 +29,6 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.XMLObj; - /** * Declarations formatting object. @@ -43,7 +40,6 @@ import org.apache.fop.fo.XMLObj; public class Declarations extends FObj { private Map colorProfiles = null; - private List external = null; /** * @param parent FONode that is the parent of this object @@ -62,11 +58,11 @@ public class Declarations extends FObj { /** * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) - XSL 1.0: (color-profile)+ (and non-XSL NS nodes) - FOP/XSL 1.1: (color-profile)* (and non-XSL NS nodes) + * XSL 1.0: (color-profile)+ (and non-XSL NS nodes) + * FOP/XSL 1.1: (color-profile)* (and non-XSL NS nodes) */ protected void validateChildNode(Locator loc, String nsURI, String localName) - throws ValidationException { + throws ValidationException { if (FO_URI.equals(nsURI)) { if (!localName.equals("color-profile")) { invalidChildError(loc, nsURI, localName); @@ -75,8 +71,9 @@ public class Declarations extends FObj { } /** - * At the end of this element sort out the child into - * a hashmap of color profiles and a list of external xml. + * At the end of this element sort out the children into + * a hashmap of color profiles and a list of extension attachments. + * @see org.apache.fop.fo.FONode#endOfNode() */ protected void endOfNode() throws FOPException { if (childNodes != null) { @@ -97,13 +94,9 @@ public class Declarations extends FObj { } else { getLogger().warn("color-profile-name required for color profile"); } - } else if (node instanceof XMLObj) { - if (external == null) { - external = new java.util.ArrayList(); - } - external.add(node); } else { - getLogger().warn("invalid element " + node.getName() + " inside declarations"); + getLogger().debug("Ignoring element " + node.getName() + + " inside fo:declarations."); } } } diff --git a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java index ee7bcce1c..47e7a1e53 100644 --- a/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java +++ b/src/java/org/apache/fop/fo/pagination/SimplePageMaster.java @@ -106,8 +106,8 @@ public class SimplePageMaster extends FObj { */ protected void endOfNode() throws FOPException { if (!hasRegionBody) { - missingChildElementError("(region-body, region-before?," + - " region-after?, region-start?, region-end?)"); + missingChildElementError( + "(region-body, region-before?, region-after?, region-start?, region-end?)"); } } @@ -182,8 +182,12 @@ public class SimplePageMaster extends FObj { /** * @see org.apache.fop.fo.FONode#addChildNode(FONode) */ - protected void addChildNode(FONode child) { - addRegion((Region)child); + protected void addChildNode(FONode child) throws FOPException { + if (child instanceof Region) { + addRegion((Region)child); + } else { + super.addChildNode(child); + } } /** @@ -229,45 +233,32 @@ public class SimplePageMaster extends FObj { return false; } - /** - * Return the Common Margin Properties-Block. - */ + /** @return the Common Margin Properties-Block. */ public CommonMarginBlock getCommonMarginBlock() { return commonMarginBlock; } - /** - * Return "master-name" property. - */ + /** @return "master-name" property. */ public String getMasterName() { return masterName; } - /** - * Return the "page-width" property. - */ + /** @return the "page-width" property. */ public Length getPageWidth() { return pageWidth; } - /** - * Return the "page-height" property. - */ + /** @return the "page-height" property. */ public Length getPageHeight() { return pageHeight; } - - /** - * Return the "writing-mode" property. - */ + /** @return the "writing-mode" property. */ public int getWritingMode() { return writingMode; } - /** - * Return the "reference-orientation" property. - */ + /** @return the "reference-orientation" property. */ public int getReferenceOrientation() { return referenceOrientation.getValue(); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java index c7dea09c8..995bfc6c2 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java @@ -57,7 +57,7 @@ public class InstreamForeignObjectLM extends LeafNodeLayoutManager { * @return the viewport inline area */ private Viewport getInlineArea() { - XMLObj child = (XMLObj) fobj.childNodes.get(0); + XMLObj child = (XMLObj) fobj.getChildXMLObj(); // viewport size is determined by block-progression-dimension // and inline-progression-dimension diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java index 3abb69dfd..f674942bb 100644 --- a/src/java/org/apache/fop/render/ps/PSRenderer.java +++ b/src/java/org/apache/fop/render/ps/PSRenderer.java @@ -22,6 +22,7 @@ package org.apache.fop.render.ps; import java.awt.Color; import java.awt.geom.Rectangle2D; import java.io.IOException; +import java.io.LineNumberReader; import java.io.OutputStream; import java.util.Iterator; import java.util.List; @@ -34,6 +35,9 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.area.Area; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.CTM; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.OffDocumentExtensionAttachment; +import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; @@ -46,6 +50,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.datatypes.ColorType; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.Typeface; import org.apache.fop.image.EPSImage; @@ -54,6 +59,7 @@ import org.apache.fop.image.ImageFactory; import org.apache.fop.image.XMLImage; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.ps.extensions.PSSetupCode; import org.apache.fop.util.CharUtilities; import org.w3c.dom.Document; @@ -93,7 +99,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer { private boolean ioTrouble = false; private boolean inTextMode = false; + private boolean firstPageSequenceReceived = false; + /** Used to temporarily store PSSetupCode instance until they can be written. */ + private List setupCodeList; + /** * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) */ @@ -568,17 +578,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer { gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS); gen.writeDSCComment(DSCConstants.END_DEFAULTS); - //Prolog - gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); - PSProcSets.writeFOPStdProcSet(gen); - PSProcSets.writeFOPEPSProcSet(gen); - gen.writeDSCComment(DSCConstants.END_PROLOG); - - //Setup - gen.writeDSCComment(DSCConstants.BEGIN_SETUP); - PSProcSets.writeFontDict(gen, fontInfo); - gen.writeln("FOPFonts begin"); - gen.writeDSCComment(DSCConstants.END_SETUP); + //Prolog and Setup written right before the first page-sequence, see startPageSequence() } /** @@ -592,6 +592,76 @@ public class PSRenderer extends AbstractPathOrientedRenderer { gen.flush(); } + /** @see org.apache.fop.render.Renderer */ + public void processOffDocumentItem(OffDocumentItem oDI) { + log.debug("Handling OffDocumentItem: " + oDI.getName()); + if (oDI instanceof OffDocumentExtensionAttachment) { + ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment(); + if (PSSetupCode.CATEGORY.equals(attachment.getCategory())) { + PSSetupCode setupCode = (PSSetupCode)attachment; + if (setupCodeList == null) { + setupCodeList = new java.util.ArrayList(); + } + setupCodeList.add(setupCode); + } + } + super.processOffDocumentItem(oDI); + } + + /** @see org.apache.fop.render.Renderer#startPageSequence(org.apache.fop.area.LineArea) */ + public void startPageSequence(LineArea seqTitle) { + super.startPageSequence(seqTitle); + if (!firstPageSequenceReceived) { + //Do this only once, as soon as we have all the content for the Setup section! + try { + //Prolog + gen.writeDSCComment(DSCConstants.BEGIN_PROLOG); + PSProcSets.writeFOPStdProcSet(gen); + PSProcSets.writeFOPEPSProcSet(gen); + gen.writeDSCComment(DSCConstants.END_PROLOG); + + //Setup + gen.writeDSCComment(DSCConstants.BEGIN_SETUP); + writeSetupCodeList(setupCodeList, "SetupCode"); + PSProcSets.writeFontDict(gen, fontInfo); + gen.writeln("FOPFonts begin"); + gen.writeDSCComment(DSCConstants.END_SETUP); + } catch (IOException ioe) { + handleIOTrouble(ioe); + } + + firstPageSequenceReceived = true; + } + } + + /** + * Formats and writes a List of PSSetupCode instances to the output stream. + * @param setupCodeList a List of PSSetupCode instances + * @param type the type of code section + */ + private void writeSetupCodeList(List setupCodeList, String type) throws IOException { + if (setupCodeList != null) { + Iterator i = setupCodeList.iterator(); + while (i.hasNext()) { + PSSetupCode setupCode = (PSSetupCode)i.next(); + gen.commentln("%FOPBegin" + type + ": (" + + (setupCode.getName() != null ? setupCode.getName() : "") + + ")"); + LineNumberReader reader = new LineNumberReader( + new java.io.StringReader(setupCode.getContent())); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.length() > 0) { + gen.writeln(line.trim()); + } + } + gen.commentln("%FOPEnd" + type); + i.remove(); + } + } + } + /** * @see org.apache.fop.render.Renderer#renderPage(PageViewport) */ @@ -641,7 +711,23 @@ public class PSRenderer extends AbstractPathOrientedRenderer { } gen.writeDSCComment(DSCConstants.PAGE_RESOURCES, new Object[] {PSGenerator.ATEND}); + gen.commentln("%FOPSimplePageMaster: " + page.getSPM().getMasterName()); gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP); + + //Handle PSSetupCode instances on simple-page-master + if (page.getSPM().getExtensionAttachments().size() > 0) { + List list = new java.util.ArrayList(); + //Extract all PSSetupCode instances from the attachment list on the s-p-m + Iterator i = page.getSPM().getExtensionAttachments().iterator(); + while (i.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment)i.next(); + if (PSSetupCode.CATEGORY.equals(attachment.getCategory())) { + list.add(attachment); + } + } + writeSetupCodeList(list, "PageSetupCode"); + } + if (rotate) { gen.writeln(Math.round(pspageheight) + " 0 translate"); gen.writeln("90 rotate"); @@ -652,7 +738,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer { + Math.round(pspageheight) + "]"); gen.writeln("/ImagingBBox null"); gen.writeln(">> setpagedevice"); - //gen.writeln("0.001 0.001 scale"); concatMatrix(1, 0, 0, -1, 0, pageheight / 1000f); gen.writeDSCComment(DSCConstants.END_PAGE_SETUP); diff --git a/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java new file mode 100644 index 000000000..789fea2a8 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/AbstractPSExtensionObject.java @@ -0,0 +1,96 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +// FOP +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +/** + * Base class for the PostScript-specific extension elements. + */ +public abstract class AbstractPSExtensionObject extends FONode { + + private PSSetupCode setupCode = new PSSetupCode(); + + /** + * @see org.apache.fop.fo.FONode#FONode(FONode) + */ + public AbstractPSExtensionObject(FONode parent) { + super(parent); + } + + /** + * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) + * here, blocks XSL FO's from having non-FO parents. + */ + protected void validateChildNode(Locator loc, String nsURI, String localName) + throws ValidationException { + if (FO_URI.equals(nsURI)) { + invalidChildError(loc, nsURI, localName); + } + } + + /** @see org.apache.fop.fo.FONode */ + protected void addCharacters(char[] data, int start, int length, + PropertyList pList, Locator locator) { + if (setupCode.getContent() != null) { + StringBuffer sb = new StringBuffer(setupCode.getContent()); + sb.append(data, start, length - start); + setupCode.setContent(sb.toString()); + } else { + setupCode.setContent(new String(data, start, length - start)); + } + } + + /** @see org.apache.fop.fo.XMLObj#getNameSpace() */ + public String getNameSpace() { + return PSExtensionElementMapping.NAMESPACE; + } + + /** @see org.apache.fop.fo.FONode#processNode */ + public void processNode(String elementName, Locator locator, + Attributes attlist, PropertyList propertyList) + throws FOPException { + String name = attlist.getValue("name"); + if (name != null && name.length() > 0) { + setupCode.setName(name); + } + } + + /** @see org.apache.fop.fo.FONode#endOfNode() */ + protected void endOfNode() throws FOPException { + super.endOfNode(); + String s = setupCode.getContent(); + if (s == null || s.length() == 0) { + missingChildElementError("#PCDATA"); + } + } + + /** @see org.apache.fop.fo.FONode#getExtensionAttachment() */ + public ExtensionAttachment getExtensionAttachment() { + return this.setupCode; + } +} + diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java new file mode 100644 index 000000000..3903d7bcb --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java @@ -0,0 +1,58 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.ElementMapping; + +/** + * This class provides the element mapping for the PostScript-specific extensions. + */ +public class PSExtensionElementMapping extends ElementMapping { + + /** Namespace for the extension */ + public static final String NAMESPACE = "http://xmlgraphics.apache.org/fop/postscript"; + + /** Main constructor */ + public PSExtensionElementMapping() { + this.namespaceURI = NAMESPACE; + } + + /** @see org.apache.fop.fo.ElementMapping#initialize() */ + protected void initialize() { + if (foObjs == null) { + foObjs = new java.util.HashMap(); + foObjs.put("ps-setup-code", new PSSetupCodeMaker()); + foObjs.put("ps-page-setup-code", new PSPageSetupCodeMaker()); + } + } + + static class PSSetupCodeMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new PSSetupCodeElement(parent); + } + } + + static class PSPageSetupCodeMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new PSPageSetupCodeElement(parent); + } + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java new file mode 100644 index 000000000..7d3eed41c --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSPageSetupCodeElement.java @@ -0,0 +1,52 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.ValidationException; + +/** + * Extension element for fox:ps-page-setup-code. + */ +public class PSPageSetupCodeElement extends AbstractPSExtensionObject { + + /** + * Main constructor + * @param parent parent FO node + */ + public PSPageSetupCodeElement(FONode parent) { + super(parent); + } + + /** @see org.apache.fop.fo.FONode#startOfNode() */ + protected void startOfNode() throws FOPException { + super.startOfNode(); + if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) { + throw new ValidationException(getName() + " must be a child of fo:simple-page-master."); + } + } + + /** @see org.apache.fop.fo.FONode#getName() */ + public String getName() { + return "fox:ps-page-setup-code"; + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java new file mode 100644 index 000000000..846946f99 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java @@ -0,0 +1,89 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import java.io.Serializable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; + +/** + * This is the pass-through value object for the PostScript extension. + */ +public class PSSetupCode implements ExtensionAttachment, Serializable { + + /** The category URI for this extension attachment. */ + public static final String CATEGORY = "apache:fop:extensions:postscript"; + + private String name; + private String content; + + /** + * No-argument contructor. + */ + public PSSetupCode() { + //nop + } + + /** + * Default constructor. + * @param name the name of the setup code object, may be null + * @param content the content of the setup code object + */ + public PSSetupCode(String name, String content) { + this.name = name; + this.content = content; + } + + /** @return the content */ + public String getContent() { + return content; + } + + /** + * Sets the content for the setup code object. + * @param content The content to set. + */ + public void setContent(String content) { + this.content = content; + } + + /** @return the name */ + public String getName() { + return name; + } + + /** + * Sets the name of the setup code object. + * @param name The name to set. + */ + public void setName(String name) { + this.name = name; + } + + /** @see org.apache.fop.fo.extensions.ExtensionAttachment#getCategory() */ + public String getCategory() { + return CATEGORY; + } + + + /** @see java.lang.Object#toString() */ + public String toString() { + return "PSSetupCode(name=" + getName() + ")"; + } +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java new file mode 100644 index 000000000..bbf3580f1 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCodeElement.java @@ -0,0 +1,52 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.ValidationException; + +/** + * Extension element for fox:ps-setup-code. + */ +public class PSSetupCodeElement extends AbstractPSExtensionObject { + + /** + * Main constructor + * @param parent parent FO node + */ + public PSSetupCodeElement(FONode parent) { + super(parent); + } + + /** @see org.apache.fop.fo.FONode#startOfNode() */ + protected void startOfNode() throws FOPException { + super.startOfNode(); + if (parent.getNameId() != Constants.FO_DECLARATIONS) { + throw new ValidationException(getName() + " must be a child of fo:declarations."); + } + } + + /** @see org.apache.fop.fo.FONode#getName() */ + public String getName() { + return "fox:ps-setup-code"; + } + +} |