From: Jeremias Maerki Date: Fri, 22 Apr 2011 07:44:46 +0000 (+0000) Subject: Added option to place AFP NOPs right before the end of a named page group (page-seque... X-Git-Tag: fop-1_1rc1old~226 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8cccb5909b2f1a7f2ab5cdb1afa5dd2337d3ef9c;p=xmlgraphics-fop.git Added option to place AFP NOPs right before the end of a named page group (page-sequence), rather than after the start. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1095882 13f79535-47bb-0310-9956-ffa450edef68 --- 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 ]]>

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). + simple-page-master (appears after "Begin Page" BPG), + page-sequence (appears after "Begin Named Page Group" BNG + and declarations (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 + placement="before-end" to do that. Please note that, at the moment, this only + has an effect for NOPs that are children of the page-sequence formatting + object. + The "name" attribute is mandatory but will not appear inside the AFP stream.

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 deferredPageSequenceExtensions + = new java.util.LinkedList(); + /** 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 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. - *

*/ 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 @@ -59,6 +59,10 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + Added option to place AFP NOPs right before the end of a named page group (page-sequence), + rather than after the start. + Added option for PostScript output to optimize for file size rather than quality.