]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Added option to place AFP NOPs right before the end of a named page group (page-seque...
authorJeremias Maerki <jeremias@apache.org>
Fri, 22 Apr 2011 07:44:46 +0000 (07:44 +0000)
committerJeremias Maerki <jeremias@apache.org>
Fri, 22 Apr 2011 07:44:46 +0000 (07:44 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1095882 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/trunk/output.xml
src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
src/java/org/apache/fop/render/afp/extensions/ExtensionPlacement.java [new file with mode: 0644]
status.xml

index bc4d870888dabdd1ec363f038db9d04632f7a333..c71f6abf894de73c042fc15765a859ce0b162ae1 100644 (file)
@@ -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">
index f45baaff671bfa7b4eea21654aba2af168b06932..4dd7df324c726b6a7d7e148bd8ec959ce45ce7bf 100644 (file)
@@ -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} */
index d916738eb3090d166eb10cdea1db62d834b597ce..14a34a0b385fe4a766c4869f6354709b45673ae3 100644 (file)
@@ -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());
index b72a30c84408cb1cd3c512bf2116be75d4c05aa2..2d30f3ae8afd6e2ac7bb8a3c5ef6cc220a499760 100644 (file)
@@ -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();
     }
 }
index b5b05191a390fb79024df12c80982163374feac2..42be9bfe0136033f5de279d7e3915c163cb55d24 100644 (file)
@@ -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 (file)
index 0000000..7d31203
--- /dev/null
@@ -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);
+    }
+
+}
index 7ed6635ba74a1e2a1fd3630ffdb6ed4d4754e563..0030dab0db296b4e9de8082f6f0130a5ceffa2b2 100644 (file)
       documents. Example: the fix of marks layering will be such a case when it's done.
     -->
     <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>