aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/documentation/content/xdocs/trunk/output.xml15
-rw-r--r--src/java/org/apache/fop/render/afp/AFPDocumentHandler.java45
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java12
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java41
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java12
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/ExtensionPlacement.java53
-rw-r--r--status.xml4
7 files changed, 162 insertions, 20 deletions
diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml
index bc4d87088..c71f6abf8 100644
--- a/src/documentation/content/xdocs/trunk/output.xml
+++ b/src/documentation/content/xdocs/trunk/output.xml
@@ -962,14 +962,19 @@ Note that the value of the encoding attribute in the example is the double-byte
</fo:layout-master-set>
]]></source>
<p>The no-operation extension element can appear as child of
- simple-page-master (appears after "Begin Page" BPG),
- page-sequence (appears after "Begin Named Page Group" BNG
- and declarations (appears after "Begin Document" BDT).
+ <code>simple-page-master</code> (appears after "Begin Page" BPG),
+ <code>page-sequence</code> (appears after "Begin Named Page Group" BNG
+ and <code>declarations</code> (appears after "Begin Document" BDT).
Multiple no-operation extension elements inside the same formatting object are allowed.
Each NOP will appear right after the respective "Begin" field indicated above even if it
- is specified as the last child under its parent. However, the order inside the parent
+ is specified as the last child under its parent. The order inside the parent
will be maintained.
- The name attribute is mandatory but will not appear inside the AFP stream.
+ The "placement" attribute can be used to have the NOP appear before
+ the "End" field of the object rather than after the "Begin" field. Specify
+ <code>placement="before-end"</code> to do that. Please note that, at the moment, this only
+ has an effect for NOPs that are children of the <code>page-sequence</code> formatting
+ object.
+ The "name" attribute is mandatory but will not appear inside the AFP stream.
</p>
</section>
<section id="afp-invoke-medium-map">
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index f45baaff6..4dd7df324 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -23,6 +23,8 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.apache.fop.afp.AFPDitheredRectanglePainter;
@@ -49,6 +51,7 @@ import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap;
import org.apache.fop.render.afp.extensions.AFPPageOverlay;
import org.apache.fop.render.afp.extensions.AFPPageSegmentElement;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
+import org.apache.fop.render.afp.extensions.ExtensionPlacement;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
@@ -89,6 +92,10 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
private Location location = Location.ELSEWHERE;
+ /** temporary holds extensions that have to be deferred until the end of the page-sequence */
+ private List<AFPPageSetup> deferredPageSequenceExtensions
+ = new java.util.LinkedList<AFPPageSetup>();
+
/** the shading mode for filled rectangles */
private AFPShadingMode shadingMode = AFPShadingMode.COLOR;
@@ -208,7 +215,25 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
/** {@inheritDoc} */
public void endPageSequence() throws IFException {
- //nop
+ try {
+ //Process deferred page-sequence-level extensions
+ Iterator<AFPPageSetup> iter = this.deferredPageSequenceExtensions.iterator();
+ while (iter.hasNext()) {
+ AFPPageSetup aps = iter.next();
+ iter.remove();
+ if (AFPElementMapping.NO_OPERATION.equals(aps.getElementName())) {
+ handleNOP(aps);
+ } else {
+ throw new UnsupportedOperationException("Don't know how to handle " + aps);
+ }
+ }
+
+ //End page sequence
+ dataStream.endPageGroup();
+ } catch (IOException ioe) {
+ throw new IFException("I/O error in endPageSequence()", ioe);
+ }
+ this.location = Location.ELSEWHERE;
}
/**
@@ -302,13 +327,14 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
}
} else if (AFPElementMapping.NO_OPERATION.equals(element)) {
switch (this.location) {
- case IN_DOCUMENT_HEADER:
case FOLLOWING_PAGE_SEQUENCE:
- case IN_PAGE_HEADER:
- String content = aps.getContent();
- if (content != null) {
- dataStream.createNoOperation(content);
+ if (aps.getPlacement() == ExtensionPlacement.BEFORE_END) {
+ this.deferredPageSequenceExtensions.add(aps);
+ break;
}
+ case IN_DOCUMENT_HEADER:
+ case IN_PAGE_HEADER:
+ handleNOP(aps);
break;
default:
throw new IFException(
@@ -372,6 +398,13 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
}
}
+ private void handleNOP(AFPPageSetup nop) {
+ String content = nop.getContent();
+ if (content != null) {
+ dataStream.createNoOperation(content);
+ }
+ }
+
// ---=== AFPCustomizable ===---
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
index d916738eb..14a34a0b3 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
@@ -50,6 +50,7 @@ public class AFPExtensionHandler extends DefaultHandler
private ObjectBuiltListener listener;
/** {@inheritDoc} */
+ @Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
boolean handled = false;
@@ -79,6 +80,7 @@ public class AFPExtensionHandler extends DefaultHandler
}
/** {@inheritDoc} */
+ @Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (AFPExtensionAttachment.CATEGORY.equals(uri)) {
if (AFPElementMapping.INCLUDE_FORM_MAP.equals(localName)) {
@@ -130,14 +132,18 @@ public class AFPExtensionHandler extends DefaultHandler
pageSetupExtn = new AFPPageSetup(localName);
this.returnedObject = pageSetupExtn;
}
- String name = lastAttributes.getValue("name");
+ String name = lastAttributes.getValue(AFPPageSetup.ATT_NAME);
if (name != null) {
returnedObject.setName(name);
}
- String value = lastAttributes.getValue("value");
+ String value = lastAttributes.getValue(AFPPageSetup.ATT_VALUE);
if (value != null && pageSetupExtn != null) {
pageSetupExtn.setValue(value);
}
+ String placement = lastAttributes.getValue(AFPPageSetup.ATT_PLACEMENT);
+ if (placement != null && placement.length() > 0) {
+ pageSetupExtn.setPlacement(ExtensionPlacement.fromXMLValue(placement));
+ }
if (content.length() > 0 && pageSetupExtn != null) {
pageSetupExtn.setContent(content.toString());
content.setLength(0); //Reset text buffer (see characters())
@@ -148,6 +154,7 @@ public class AFPExtensionHandler extends DefaultHandler
}
/** {@inheritDoc} */
+ @Override
public void characters(char[] ch, int start, int length) throws SAXException {
content.append(ch, start, length);
}
@@ -155,6 +162,7 @@ public class AFPExtensionHandler extends DefaultHandler
/**
* {@inheritDoc}
*/
+ @Override
public void endDocument() throws SAXException {
if (listener != null) {
listener.notifyObjectBuilt(getObject());
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
index b72a30c84..2d30f3ae8 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
@@ -31,6 +31,9 @@ public class AFPPageSetup extends AFPExtensionAttachment {
/** value attribute */
protected static final String ATT_VALUE = "value";
+ /** placement attribute */
+ protected static final String ATT_PLACEMENT = "placement";
+
/**
* the extension content
*/
@@ -41,6 +44,9 @@ public class AFPPageSetup extends AFPExtensionAttachment {
*/
protected String value;
+ /** defines where to place the extension in the generated file */
+ protected ExtensionPlacement placement = ExtensionPlacement.DEFAULT;
+
/**
* Default constructor.
*
@@ -84,6 +90,26 @@ public class AFPPageSetup extends AFPExtensionAttachment {
this.content = content;
}
+ /**
+ * Returns the intended placement of the extension inside the generated file.
+ * @return the intended placement
+ */
+ public ExtensionPlacement getPlacement() {
+ return this.placement;
+ }
+
+ /**
+ * Sets the intended placement of the extension inside the generated file.
+ * @param placement the intended placement
+ */
+ public void setPlacement(ExtensionPlacement placement) {
+ if (!AFPElementMapping.NO_OPERATION.equals(getElementName())) {
+ throw new UnsupportedOperationException(
+ "The attribute 'placement' can currently only be set for NOPs!");
+ }
+ this.placement = placement;
+ }
+
/** {@inheritDoc} */
public void toSAX(ContentHandler handler) throws SAXException {
AttributesImpl atts = new AttributesImpl();
@@ -93,6 +119,9 @@ public class AFPPageSetup extends AFPExtensionAttachment {
if (value != null && value.length() > 0) {
atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value);
}
+ if (this.placement != ExtensionPlacement.DEFAULT) {
+ atts.addAttribute(null, ATT_PLACEMENT, ATT_PLACEMENT, "CDATA", placement.getXMLValue());
+ }
handler.startElement(CATEGORY, elementName, elementName, atts);
if (content != null && content.length() > 0) {
char[] chars = content.toCharArray();
@@ -102,8 +131,16 @@ public class AFPPageSetup extends AFPExtensionAttachment {
}
/** {@inheritDoc} */
+ @Override
public String toString() {
- return "AFPPageSetup(element-name=" + getElementName()
- + " name=" + getName() + " value=" + getValue() + ")";
+ StringBuilder sb = new StringBuilder("AFPPageSetup(");
+ sb.append("element-name=").append(getElementName());
+ sb.append(" name=").append(getName());
+ sb.append(" value=").append(getValue());
+ if (getPlacement() != ExtensionPlacement.DEFAULT) {
+ sb.append(" placement=").append(getPlacement());
+ }
+ sb.append(")");
+ return sb.toString();
}
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
index b5b05191a..42be9bfe0 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
@@ -30,13 +30,11 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
/**
* This class extends the org.apache.fop.extensions.ExtensionObj class. The
- * object faciliates extraction of elements from formatted objects based on
+ * object facilitates extraction of elements from formatted objects based on
* the static list as defined in the AFPElementMapping implementation.
- * <p/>
*/
public class AFPPageSetupElement extends AbstractAFPExtensionObject {
- private static final String ATT_VALUE = "value";
private static final String ATT_SRC = "src";
/**
@@ -101,13 +99,17 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject {
missingPropertyError(ATT_SRC);
}
} else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
- String attr = attlist.getValue(ATT_VALUE);
+ String attr = attlist.getValue(AFPPageSetup.ATT_VALUE);
if (attr != null && attr.length() > 0) {
pageSetup.setValue(attr);
} else {
- missingPropertyError(ATT_VALUE);
+ missingPropertyError(AFPPageSetup.ATT_VALUE);
}
}
+ String placement = attlist.getValue(AFPPageSetup.ATT_PLACEMENT);
+ if (placement != null && placement.length() > 0) {
+ pageSetup.setPlacement(ExtensionPlacement.fromXMLValue(placement));
+ }
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/afp/extensions/ExtensionPlacement.java b/src/java/org/apache/fop/render/afp/extensions/ExtensionPlacement.java
new file mode 100644
index 000000000..7d3120333
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/extensions/ExtensionPlacement.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp.extensions;
+
+/**
+ * An enumeration for placement instruction for AFP extensions.
+ */
+public enum ExtensionPlacement {
+
+ /** Place the extension at its default/usual position. */
+ DEFAULT,
+ /** Place the extension right before the "End" structured field. */
+ BEFORE_END;
+
+ /**
+ * Returns the XML value that corresponds to this enum value.
+ * @return the XML value
+ */
+ public String getXMLValue() {
+ String xmlName = name().toLowerCase();
+ xmlName = xmlName.replace('_', '-');
+ return xmlName;
+ }
+
+ /**
+ * Returns the enum value from the given XML value for this enumeration.
+ * @param value the XML value
+ * @return the enum value
+ */
+ public static ExtensionPlacement fromXMLValue(String value) {
+ String name = value.toUpperCase();
+ name = name.replace('-', '_');
+ return ExtensionPlacement.valueOf(name);
+ }
+
+}
diff --git a/status.xml b/status.xml
index 7ed6635ba..0030dab0d 100644
--- a/status.xml
+++ b/status.xml
@@ -60,6 +60,10 @@
-->
<release version="FOP Trunk" date="TBD">
<action context="Renderers" dev="JM" type="add">
+ Added option to place AFP NOPs right before the end of a named page group (page-sequence),
+ rather than after the start.
+ </action>
+ <action context="Renderers" dev="JM" type="add">
Added option for PostScript output to optimize for file size rather than quality.
</action>
<action context="Renderers" dev="JM" type="add">