You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ga...@apache.org on 2013/09/13 15:56:19 UTC

svn commit: r1522934 - in /xmlgraphics/fop/trunk: ./ src/java/META-INF/services/ src/java/org/apache/fop/fo/extensions/ src/java/org/apache/fop/pdf/ src/java/org/apache/fop/render/intermediate/ src/java/org/apache/fop/render/pdf/ src/java/org/apache/fo...

Author: gadams
Date: Fri Sep 13 13:56:18 2013
New Revision: 1522934

URL: http://svn.apache.org/r1522934
Log:
FOP-2298: Enable support for PDF Transitions by defining low-level mechanism to augment /Catalog and /Page dictionaries.

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFDictionaryElement.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryType.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileAttachment.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandlerFactory.java   (with props)
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml   (with props)
Removed:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/extensions/ExtensionObj.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileExtensionAttachment.java
Modified:
    xmlgraphics/fop/trunk/findbugs-exclude.xml
    xmlgraphics/fop/trunk/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumber.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/AbstractXMLWritingIFDocumentHandler.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFExtensionElement.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFElementMapping.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileElement.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionAttachment.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandler.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/tools/fontlist/FontListMain.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/util/GenerationHelperContentHandler.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java
    xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java
    xmlgraphics/fop/trunk/status.xml

Modified: xmlgraphics/fop/trunk/findbugs-exclude.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/findbugs-exclude.xml?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/findbugs-exclude.xml (original)
+++ xmlgraphics/fop/trunk/findbugs-exclude.xml Fri Sep 13 13:56:18 2013
@@ -5413,4 +5413,24 @@
      </Or>
      <Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED"/>
    </Match>
+   <Match>
+      <Class name="org.apache.fop.render.pdf.extensions.PDFExtensionHandlerFactory"/>
+      <Method name="getSupportedNamespaces"/>
+      <Bug pattern="EI_EXPOSE_REP"/>
+   </Match>
+   <Match>
+      <Class name="org.apache.fop.render.pdf.extensions.PDFDictionaryEntryExtension"/>
+      <Method name="getValueAsNumber"/>
+      <Bug pattern="FE_FLOATING_POINT_EQUALITY"/>
+   </Match>
+   <Match>
+      <Class name="org.apache.fop.render.pdf.extensions.PDFDictionaryType"/>
+      <Method name="hasValueOfElementName"/>
+      <Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/>
+   </Match>
+   <Match>
+      <Class name="org.apache.fop.render.pdf.extensions.PDFDictionaryEntryType"/>
+      <Method name="hasValueOfElementName"/>
+      <Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"/>
+   </Match>
 </FindBugsFilter>

Modified: xmlgraphics/fop/trunk/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory (original)
+++ xmlgraphics/fop/trunk/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory Fri Sep 13 13:56:18 2013
@@ -1,3 +1,4 @@
 org.apache.fop.render.afp.extensions.AFPExtensionHandlerFactory
+org.apache.fop.render.pdf.extensions.PDFExtensionHandlerFactory
 org.apache.fop.render.ps.extensions.PSExtensionHandlerFactory
 org.apache.fop.fo.extensions.xmp.XMPContentHandlerFactory

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumber.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumber.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumber.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumber.java Fri Sep 13 13:56:18 2013
@@ -29,6 +29,14 @@ public class PDFNumber extends PDFObject
 
     private Number number;
 
+    public PDFNumber() {
+        this.number = Integer.valueOf(0);
+    }
+
+    public PDFNumber(Number number) {
+        this.number = number;
+    }
+
     /**
      * Returns the number.
      * @return the number

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/AbstractXMLWritingIFDocumentHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/AbstractXMLWritingIFDocumentHandler.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/AbstractXMLWritingIFDocumentHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/AbstractXMLWritingIFDocumentHandler.java Fri Sep 13 13:56:18 2013
@@ -54,10 +54,10 @@ public abstract class AbstractXMLWriting
         if (result instanceof SAXResult) {
             SAXResult saxResult = (SAXResult)result;
             this.handler = new GenerationHelperContentHandler(
-                    saxResult.getHandler(), getMainNamespace());
+                    saxResult.getHandler(), getMainNamespace(), getContext());
         } else {
             this.handler = new GenerationHelperContentHandler(
-                    createContentHandler(result), getMainNamespace());
+                    createContentHandler(result), getMainNamespace(), getContext());
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java Fri Sep 13 13:56:18 2013
@@ -55,6 +55,8 @@ public class IFContext {
 
     private boolean hyphenated;
 
+    private int pageIndex = -1;
+
     /**
      * Main constructor.
      * @param ua the user agent
@@ -216,4 +218,20 @@ public class IFContext {
         return hyphenated;
     }
 
+    /**
+     * Record current page index.
+     * @param pageIndex a zero based page index or -1 (no page)
+     */
+    public void setPageIndex(int pageIndex) {
+        this.pageIndex = pageIndex;
+    }
+
+    /**
+     * Obtain current page index.
+     * @return a zero based page index or -1 (no page)
+     */
+    public int getPageIndex() {
+        return this.pageIndex;
+    }
+
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java Fri Sep 13 13:56:18 2013
@@ -571,6 +571,7 @@ public class IFRenderer extends Abstract
             Dimension dim = new Dimension(viewArea.width, viewArea.height);
 
             establishForeignAttributes(page.getForeignAttributes());
+            documentHandler.getContext().setPageIndex(page.getPageIndex());
             documentHandler.startPage(page.getPageIndex(), page.getPageNumberString(),
                     page.getSimplePageMasterName(), dim);
             resetForeignAttributes();
@@ -598,6 +599,7 @@ public class IFRenderer extends Abstract
 
             establishForeignAttributes(page.getForeignAttributes());
             documentHandler.endPage();
+            documentHandler.getContext().setPageIndex(-1);
             resetForeignAttributes();
         } catch (IFException e) {
             handleIFException(e);

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java Fri Sep 13 13:56:18 2013
@@ -303,6 +303,7 @@ implements IFConstants, IFPainter, IFDoc
             addAttribute(atts, "width", Integer.toString(size.width));
             addAttribute(atts, "height", Integer.toString(size.height));
             addForeignAttributes(atts);
+            getContext().setPageIndex(index);
             handler.startElement(EL_PAGE, atts);
         } catch (SAXException e) {
             throw new IFException("SAX error in startPage()", e);
@@ -379,6 +380,7 @@ implements IFConstants, IFPainter, IFDoc
     public void endPage() throws IFException {
         try {
             handler.endElement(EL_PAGE);
+            getContext().setPageIndex(-1);
         } catch (SAXException e) {
             throw new IFException("SAX error in endPage()", e);
         }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java Fri Sep 13 13:56:18 2013
@@ -50,7 +50,8 @@ import org.apache.fop.render.intermediat
 import org.apache.fop.render.intermediate.IFException;
 import org.apache.fop.render.intermediate.IFPainter;
 import org.apache.fop.render.pdf.PDFRendererConfig.PDFRendererConfigParser;
-import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileExtensionAttachment;
+import org.apache.fop.render.pdf.extensions.PDFDictionaryAttachment;
+import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileAttachment;
 
 /**
  * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation that produces PDF.
@@ -296,17 +297,22 @@ public class PDFDocumentHandler extends 
         } else if (extension instanceof Metadata) {
             XMPMetadata wrapper = new XMPMetadata(((Metadata) extension));
             pdfUtil.renderXMPMetadata(wrapper);
-        } else if (extension instanceof PDFEmbeddedFileExtensionAttachment) {
-            PDFEmbeddedFileExtensionAttachment embeddedFile
-                = (PDFEmbeddedFileExtensionAttachment)extension;
+        } else if (extension instanceof PDFEmbeddedFileAttachment) {
+            PDFEmbeddedFileAttachment embeddedFile
+                = (PDFEmbeddedFileAttachment)extension;
             try {
                 pdfUtil.addEmbeddedFile(embeddedFile);
             } catch (IOException ioe) {
                 throw new IFException("Error adding embedded file: " + embeddedFile.getSrc(), ioe);
             }
-        } else {
+        } else if (extension instanceof PDFDictionaryAttachment) {
+            PDFDictionaryAttachment dictionaryExtension = (PDFDictionaryAttachment) extension;
+            pdfUtil.renderDictionaryExtension(dictionaryExtension, currentPage);
+        } else if (extension != null) {
             log.debug("Don't know how to handle extension object. Ignoring: "
                     + extension + " (" + extension.getClass().getName() + ")");
+        } else {
+            log.debug("Ignoring null extension object.");
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java Fri Sep 13 13:56:18 2013
@@ -56,15 +56,23 @@ import org.apache.fop.pdf.PDFICCBasedCol
 import org.apache.fop.pdf.PDFICCStream;
 import org.apache.fop.pdf.PDFInfo;
 import org.apache.fop.pdf.PDFMetadata;
+import org.apache.fop.pdf.PDFName;
 import org.apache.fop.pdf.PDFNames;
+import org.apache.fop.pdf.PDFNumber;
 import org.apache.fop.pdf.PDFOutputIntent;
+import org.apache.fop.pdf.PDFPage;
 import org.apache.fop.pdf.PDFPageLabels;
 import org.apache.fop.pdf.PDFReference;
 import org.apache.fop.pdf.PDFText;
 import org.apache.fop.pdf.PDFXMode;
 import org.apache.fop.pdf.Version;
 import org.apache.fop.pdf.VersionController;
-import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileExtensionAttachment;
+import org.apache.fop.render.pdf.extensions.PDFDictionaryAttachment;
+import org.apache.fop.render.pdf.extensions.PDFDictionaryEntryExtension;
+import org.apache.fop.render.pdf.extensions.PDFDictionaryEntryType;
+import org.apache.fop.render.pdf.extensions.PDFDictionaryExtension;
+import org.apache.fop.render.pdf.extensions.PDFDictionaryType;
+import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileAttachment;
 
 import static org.apache.fop.render.pdf.PDFEncryptionOption.ENCRYPTION_PARAMS;
 import static org.apache.fop.render.pdf.PDFEncryptionOption.NO_ACCESSCONTENT;
@@ -250,6 +258,46 @@ class PDFRenderingUtil {
         }
     }
 
+    public void renderDictionaryExtension(PDFDictionaryAttachment attachment, PDFPage currentPage) {
+        PDFDictionaryExtension extension = attachment.getExtension();
+        if (extension.getDictionaryType() == PDFDictionaryType.Catalog) {
+            augmentDictionary(pdfDoc.getRoot(), extension);
+        } else if (extension.getDictionaryType() == PDFDictionaryType.Page) {
+            if (extension.matchesPageNumber(currentPage.getPageIndex() + 1)) {
+                augmentDictionary(currentPage, extension);
+            }
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
+    private PDFDictionary augmentDictionary(PDFDictionary dictionary, PDFDictionaryExtension extension) {
+        for (PDFDictionaryEntryExtension entry : extension.getEntries()) {
+            if (entry instanceof PDFDictionaryExtension) {
+                dictionary.put(entry.getKey(), augmentDictionary(new PDFDictionary(dictionary), (PDFDictionaryExtension) entry));
+            } else {
+                augmentDictionary(dictionary, entry);
+            }
+        }
+        return dictionary;
+    }
+
+    private void augmentDictionary(PDFDictionary dictionary, PDFDictionaryEntryExtension entry) {
+        PDFDictionaryEntryType type = entry.getType();
+        String key = entry.getKey();
+        if (type == PDFDictionaryEntryType.Boolean) {
+            dictionary.put(key, entry.getValueAsBoolean());
+        } else if (type == PDFDictionaryEntryType.Name) {
+            dictionary.put(key, new PDFName(entry.getValueAsString()));
+        } else if (type == PDFDictionaryEntryType.Number) {
+            dictionary.put(key, new PDFNumber(entry.getValueAsNumber()));
+        } else if (type == PDFDictionaryEntryType.String) {
+            dictionary.put(key, entry.getValueAsString());
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
     public PDFDocument setupPDFDocument(OutputStream out) throws IOException {
         if (this.pdfDoc != null) {
             throw new IllegalStateException("PDFDocument already set up");
@@ -315,7 +363,7 @@ class PDFRenderingUtil {
      * @param embeddedFile the object representing the embedded file to be added
      * @throws IOException if an I/O error occurs
      */
-    public void addEmbeddedFile(PDFEmbeddedFileExtensionAttachment embeddedFile)
+    public void addEmbeddedFile(PDFEmbeddedFileAttachment embeddedFile)
             throws IOException {
         this.pdfDoc.getProfile().verifyEmbeddedFilesAllowed();
         PDFNames names = this.pdfDoc.getRoot().getNames();

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFDictionaryElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFDictionaryElement.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFDictionaryElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFDictionaryElement.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,43 @@
+/*
+ * 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.pdf.extensions;
+
+import org.apache.fop.fo.FONode;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Base class for the PDF dictionary related extension elements.
+ */
+public abstract class AbstractPDFDictionaryElement extends AbstractPDFExtensionElement {
+
+    public static final String ATT_KEY = PDFDictionaryEntryExtension.PROPERTY_KEY;
+
+    /**
+     * Default constructor
+     *
+     * @param parent parent of this node
+     * @see org.apache.fop.fo.FONode#FONode(FONode)
+     */
+    public AbstractPDFDictionaryElement(FONode parent) {
+        super(parent);
+    }
+}
+

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFDictionaryElement.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFExtensionElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFExtensionElement.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFExtensionElement.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/AbstractPDFExtensionElement.java Fri Sep 13 13:56:18 2013
@@ -19,10 +19,11 @@
 
 package org.apache.fop.render.pdf.extensions;
 
-// FOP
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 
+// CSOFF: LineLengthCheck
+
 /**
  * Base class for the PDF-specific extension elements.
  */
@@ -67,7 +68,9 @@ public abstract class AbstractPDFExtensi
      * Instantiates extension attachment object.
      * @return extension attachment
      */
-    protected abstract ExtensionAttachment instantiateExtensionAttachment();
+    protected ExtensionAttachment instantiateExtensionAttachment() {
+        return null;
+    }
 
 }
 

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,125 @@
+/*
+ * 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.pdf.extensions;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.util.GenerationHelperContentHandler;
+
+// CSOFF: LineLengthCheck
+
+public class PDFDictionaryAttachment extends PDFExtensionAttachment {
+
+    private static final long serialVersionUID = -5576832955238384505L;
+
+    private PDFDictionaryExtension extension;
+
+    public PDFDictionaryAttachment(PDFDictionaryExtension extension) {
+        this.extension = extension;
+    }
+
+    public PDFDictionaryExtension getExtension() {
+        return extension;
+    }
+
+    @Override
+    public void toSAX(ContentHandler handler) throws SAXException {
+        PDFDictionaryType dictionaryType = extension.getDictionaryType();
+        int pageNumber = 0;
+        if (dictionaryType == PDFDictionaryType.Page) {
+            if (handler instanceof GenerationHelperContentHandler) {
+                Object context = ((GenerationHelperContentHandler) handler).getContentHandlerContext();
+                if (context instanceof IFContext) {
+                    int pageIndex = ((IFContext) context).getPageIndex();
+                    if ((pageIndex >= 0) && extension.matchesPageNumber(pageIndex + 1)) {
+                        pageNumber = pageIndex + 1;
+                    } else {
+                        pageNumber = -1;
+                    }
+                }
+            }
+        }
+        if (pageNumber >= 0) {
+            toSAX(handler, extension);
+        }
+    }
+
+    private void toSAX(ContentHandler handler, PDFDictionaryExtension dictionary) throws SAXException {
+        AttributesImpl attributes = new AttributesImpl();
+        String ln = dictionary.getElementName();
+        String qn = PREFIX + ":" + ln;
+        attributes = extractIFAttributes(attributes, dictionary);
+        handler.startElement(CATEGORY, ln, qn, attributes);
+        for (PDFDictionaryEntryExtension entry : dictionary.getEntries()) {
+            toSAX(handler, entry);
+        }
+        handler.endElement(CATEGORY, ln, qn);
+    }
+
+    private void toSAX(ContentHandler handler, PDFDictionaryEntryExtension entry) throws SAXException {
+        if (entry instanceof PDFDictionaryExtension) {
+            toSAX(handler, (PDFDictionaryExtension) entry);
+        } else {
+            AttributesImpl attributes = new AttributesImpl();
+            String ln = entry.getElementName();
+            String qn = PREFIX + ":" + ln;
+            attributes = extractIFAttributes(attributes, entry);
+            handler.startElement(CATEGORY, ln, qn, attributes);
+            char[] characters = entry.getValueAsXMLEscapedString().toCharArray();
+            if (characters.length > 0) {
+                handler.characters(characters, 0, characters.length);
+            }
+            handler.endElement(CATEGORY, ln, qn);
+        }
+    }
+
+    private static AttributesImpl extractIFAttributes(AttributesImpl attributes, PDFDictionaryExtension dictionary) {
+        PDFDictionaryType type = dictionary.getDictionaryType();
+        if (type == PDFDictionaryType.Catalog) {
+            // no specific attriburtes
+        } else if (type == PDFDictionaryType.Page) {
+            String pageNumbersName = PDFDictionaryExtension.PROPERTY_PAGE_NUMBERS;
+            String pageNumbers = dictionary.getProperty(pageNumbersName);
+            if (pageNumbers != null) {
+                attributes.addAttribute(null, pageNumbersName, pageNumbersName, "CDATA", pageNumbers);
+            }
+        } else if (type == PDFDictionaryType.Dictionary) {
+            String keyName = PDFDictionaryEntryExtension.PROPERTY_KEY;
+            String key = dictionary.getKey();
+            if (key != null) {
+                attributes.addAttribute(null, keyName, keyName, "CDATA", key);
+            }
+        }
+        return attributes;
+    }
+
+    private static AttributesImpl extractIFAttributes(AttributesImpl attributes, PDFDictionaryEntryExtension entry) {
+        String keyName = PDFDictionaryEntryExtension.PROPERTY_KEY;
+        String key = entry.getKey();
+        if (key != null) {
+            attributes.addAttribute(null, keyName, keyName, "CDATA", key);
+        }
+        return attributes;
+    }
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,126 @@
+/*
+ * 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.pdf.extensions;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Extension element for dictionaries: pdf:{catalog,page,dictionary}. The specific type
+ * of dictionary is established at construction type.
+ */
+public class PDFDictionaryElement extends AbstractPDFDictionaryElement {
+
+    public static final String ATT_PAGE_NUMBERS = PDFDictionaryExtension.PROPERTY_PAGE_NUMBERS;
+
+    private PDFDictionaryExtension extension;
+
+    /**
+     * Main constructor
+     * @param parent parent FO node
+     */
+    PDFDictionaryElement(FONode parent, PDFDictionaryType type) {
+        super(parent);
+        this.extension = new PDFDictionaryExtension(type);
+    }
+
+    public PDFDictionaryExtension getExtension() {
+        return extension;
+    }
+
+    @Override
+    public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException {
+        if (extension.getDictionaryType() == PDFDictionaryType.Catalog) {
+            // no specific properties
+        } else if (extension.getDictionaryType() == PDFDictionaryType.Page) {
+            String pageNumbers = attlist.getValue(ATT_PAGE_NUMBERS);
+            if (pageNumbers != null) {
+                extension.setProperty(ATT_PAGE_NUMBERS, pageNumbers);
+            }
+        } else if (extension.getDictionaryType() == PDFDictionaryType.Dictionary) {
+            String key = attlist.getValue(ATT_KEY);
+            if (key == null) {
+                missingPropertyError(ATT_KEY);
+            } else if (key.isEmpty()) {
+                invalidPropertyValueError(ATT_KEY, key, null);
+            } else {
+                extension.setKey(key);
+            }
+        }
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+        String localName = getLocalName();
+        if (localName.equals("catalog")) {
+            if (parent.getNameId() != Constants.FO_DECLARATIONS) {
+                invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfDeclarations");
+            }
+        } else if (localName.equals("page")) {
+            if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
+                invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfSPM");
+            }
+        } else if (localName.equals("dictionary")) {
+            if (!PDFDictionaryType.hasValueOfElementName(parent.getLocalName())) {
+                invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), null);
+            }
+        } else {
+            throw new IllegalStateException("unknown name: " + localName);
+        }
+    }
+
+    @Override
+    protected void addChildNode(FONode child) throws FOPException {
+        if (child instanceof PDFDictionaryElement) {
+            PDFDictionaryExtension extension = ((PDFDictionaryElement) child).getExtension();
+            if (extension.getDictionaryType() == PDFDictionaryType.Dictionary) {
+                this.extension.addEntry(extension);
+            }
+        } else if (child instanceof PDFDictionaryEntryElement) {
+            PDFDictionaryEntryExtension extension = ((PDFDictionaryEntryElement) child).getExtension();
+            this.extension.addEntry(extension);
+        }
+    }
+
+    @Override
+    public void endOfNode() throws FOPException {
+        super.endOfNode();
+    }
+
+    @Override
+    public String getLocalName() {
+        return extension.getDictionaryType().elementName();
+    }
+
+    @Override
+    protected ExtensionAttachment instantiateExtensionAttachment() {
+        return new PDFDictionaryAttachment(extension);
+    }
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,109 @@
+/*
+ * 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.pdf.extensions;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Extension element for dictionary entries: pdf:{boolean,name,number,string}. The specific type
+ * of entry is established at construction type.
+ */
+public class PDFDictionaryEntryElement extends AbstractPDFDictionaryElement {
+
+    private PDFDictionaryEntryExtension extension;
+    private StringBuffer characters;
+
+    /**
+     * Main constructor
+     * @param parent parent FO node
+     */
+    PDFDictionaryEntryElement(FONode parent, PDFDictionaryEntryType type) {
+        super(parent);
+        this.extension = new PDFDictionaryEntryExtension(type);
+    }
+
+    public PDFDictionaryEntryExtension getExtension() {
+        return extension;
+    }
+
+    @Override
+    public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException {
+        String key = attlist.getValue("key");
+        if (key == null) {
+            missingPropertyError("key");
+        } else if (key.isEmpty()) {
+            invalidPropertyValueError("key", key, null);
+        } else {
+            extension.setKey(key);
+        }
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+        if (!PDFDictionaryType.hasValueOfElementName(parent.getLocalName())) {
+            invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), null);
+        }
+    }
+
+    @Override
+    protected void characters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException {
+        if (characters == null) {
+            characters = new StringBuffer((length < 16) ? 16 : length);
+        }
+        characters.append(data, start, length);
+    }
+
+    @Override
+    public void endOfNode() throws FOPException {
+        String value = (characters != null) ? characters.toString() : "";
+        if (extension.getType() == PDFDictionaryEntryType.Boolean) {
+            if (!value.equals("true") && !value.equals("false")) {
+                invalidPropertyValueError("<value>", value, null);
+            }
+        } else if (extension.getType() == PDFDictionaryEntryType.Name) {
+            if (value.isEmpty()) {
+                invalidPropertyValueError("<value>", value, null);
+            }
+        } else if (extension.getType() == PDFDictionaryEntryType.Number) {
+            try {
+                Double.valueOf(value);
+            } catch (NumberFormatException e) {
+                invalidPropertyValueError("<value>", value, null);
+            }
+        } else if (extension.getType() != PDFDictionaryEntryType.String) {
+            throw new IllegalStateException();
+        }
+        extension.setValue(value);
+        super.endOfNode();
+    }
+
+    @Override
+    public String getLocalName() {
+        return extension.getType().elementName();
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,110 @@
+/*
+ * 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.pdf.extensions;
+
+import org.apache.fop.util.XMLUtil;
+
+// CSOFF: LineLengthCheck
+
+public class PDFDictionaryEntryExtension {
+
+    public static final String PROPERTY_KEY = "key";
+
+    private PDFDictionaryEntryType type;
+    private String key = "";
+    private Object value;
+
+    PDFDictionaryEntryExtension() {
+    }
+
+    PDFDictionaryEntryExtension(PDFDictionaryEntryType type) {
+        this.type = type;
+    }
+
+    public PDFDictionaryEntryType getType() {
+        return type;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * Obtain entry value as Boolean.
+     * @return entry value
+     */
+    public Boolean getValueAsBoolean() {
+        if (value instanceof String) {
+            return Boolean.valueOf((String)value);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Obtain entry value as Number.
+     * @return entry value
+     */
+    public Number getValueAsNumber() {
+        if (value instanceof String) {
+            double d = Double.parseDouble((String) value);
+            if (Math.floor(d) == d) {
+                return Long.valueOf((long) d);
+            } else {
+                return Double.valueOf(d);
+            }
+        } else {
+            return Integer.valueOf(0);
+        }
+    }
+
+    public String getValueAsString() {
+        if (value instanceof String) {
+            return (String) value;
+        } else {
+            return "";
+        }
+    }
+
+    public String getValueAsXMLEscapedString() {
+        return XMLUtil.escape(getValueAsString());
+    }
+
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    public String getElementName() {
+        return type.elementName();
+    }
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryType.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryType.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryType.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryType.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,56 @@
+/*
+ * 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.pdf.extensions;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Enumeration type for leaf PDF dictionary entry extension elements.
+ */
+public enum PDFDictionaryEntryType {
+    Boolean("boolean"),         // boolean valued entry
+    Dictionary("dictionary"),   // dictionary valued entry
+    Name("name"),               // name valued entry
+    Number("number"),           // number valued entry
+    String("string");           // string valued entry
+
+    private String elementName;
+    PDFDictionaryEntryType(String elementName) {
+        this.elementName = elementName;
+    }
+    public String elementName() {
+        return elementName;
+    }
+    static PDFDictionaryEntryType valueOfElementName(String elementName) {
+        for (PDFDictionaryEntryType type : values()) {
+            if (type.elementName.equals(elementName)) {
+                return type;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+    static boolean hasValueOfElementName(String elementName) {
+        try {
+            return valueOfElementName(elementName) != null;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryType.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,124 @@
+/*
+ * 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.pdf.extensions;
+
+import java.util.List;
+import java.util.Map;
+
+// CSOFF: LineLengthCheck
+
+public class PDFDictionaryExtension extends PDFDictionaryEntryExtension {
+
+    public static final String PROPERTY_PAGE_NUMBERS = "page-numbers";
+
+    private static final long serialVersionUID = -1L;
+
+    private PDFDictionaryType dictionaryType;
+    private Map<String, String> properties;
+    private List<PDFDictionaryEntryExtension> entries;
+
+    PDFDictionaryExtension() {
+    }
+
+    PDFDictionaryExtension(PDFDictionaryType dictionaryType) {
+        super(PDFDictionaryEntryType.Dictionary);
+        this.dictionaryType = dictionaryType;
+        this.properties = new java.util.HashMap<String, String>();
+        this.entries = new java.util.ArrayList<PDFDictionaryEntryExtension>();
+    }
+
+    public PDFDictionaryType getDictionaryType() {
+        return dictionaryType;
+    }
+
+    public void setProperty(String name, String value) {
+        properties.put(name, value);
+    }
+
+    public String getProperty(String name) {
+        return properties.get(name);
+    }
+
+    public void addEntry(PDFDictionaryEntryExtension entry) {
+        entries.add(entry);
+    }
+
+    public List<PDFDictionaryEntryExtension> getEntries() {
+        return entries;
+    }
+
+    public PDFDictionaryEntryExtension getLastEntry() {
+        if (entries.size() > 0) {
+            return entries.get(entries.size() - 1);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Determine if page dictionary and page number matches.
+     * @param pageNumber page number, where first page number is 1
+     * @return true if this dictionary is a page dictionary and specified page number matches specified page-number property
+     */
+    public boolean matchesPageNumber(int pageNumber) {
+        if (dictionaryType != PDFDictionaryType.Page) {
+            return false;
+        }
+        String pageNumbers = getProperty(PROPERTY_PAGE_NUMBERS);
+        if ((pageNumbers == null) || pageNumbers.isEmpty()) {
+            return false;
+        } else if (pageNumbers.equals("*")) {
+            return true;
+        } else {
+            for (String interval : pageNumbers.split("\\s*,\\s*")) {
+                String[] components = interval.split("\\s*-\\s*");
+                if (components.length < 1) {
+                    continue;
+                } else {
+                    try {
+                        int start = Integer.parseInt(components[0]);
+                        int end = 0;
+                        if (components.length > 1) {
+                            if (!components[1].equals("LAST")) {
+                                end = Integer.parseInt(components[1]);
+                            }
+                        }
+                        if ((end == 0) && (pageNumber == start)) {
+                            return true;
+                        } else if ((end > start) && (pageNumber >= start) && (pageNumber < end)) {
+                            return true;
+                        } else {
+                            continue;
+                        }
+                    } catch (NumberFormatException e) {
+                        continue;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String getElementName() {
+        return dictionaryType.elementName();
+    }
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,54 @@
+/*
+ * 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.pdf.extensions;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Enumeration type for PDF dictionary extension elements.
+ */
+public enum PDFDictionaryType {
+    Dictionary("dictionary"),   // generic (nested) dictionary element
+    Catalog("catalog"),         // catalog dictionary element
+    Page("page");               // page dictionary element
+
+    private String elementName;
+    PDFDictionaryType(String elementName) {
+        this.elementName = elementName;
+    }
+    public String elementName() {
+        return elementName;
+    }
+    static PDFDictionaryType valueOfElementName(String elementName) {
+        for (PDFDictionaryType type : values()) {
+            if (type.elementName.equals(elementName)) {
+                return type;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+    static boolean hasValueOfElementName(String elementName) {
+        try {
+            return valueOfElementName(elementName) != null;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFElementMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFElementMapping.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFElementMapping.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFElementMapping.java Fri Sep 13 13:56:18 2013
@@ -22,6 +22,8 @@ package org.apache.fop.render.pdf.extens
 import org.apache.fop.fo.ElementMapping;
 import org.apache.fop.fo.FONode;
 
+// CSOFF: LineLengthCheck
+
 /**
  * This class provides the element mapping for the PDF-specific extensions.
  */
@@ -39,13 +41,43 @@ public class PDFElementMapping extends E
     protected void initialize() {
         if (foObjs == null) {
             foObjs = new java.util.HashMap<String, Maker>();
-            foObjs.put(PDFEmbeddedFileElement.ELEMENT, new PDFEmbeddedFileMaker());
+            // pdf:embedded-file
+            foObjs.put(PDFEmbeddedFileElement.ELEMENT, new PDFEmbeddedFileElementMaker());
+            // pdf:{catalog,page} et al.
+            for (PDFDictionaryType type : PDFDictionaryType.values()) {
+                foObjs.put(type.elementName(), new PDFDictionaryElementMaker(type));
+            }
+            for (PDFDictionaryEntryType type : PDFDictionaryEntryType.values()) {
+                if (type != PDFDictionaryEntryType.Dictionary) {
+                    foObjs.put(type.elementName(), new PDFDictionaryEntryElementMaker(type));
+                }
+            }
         }
     }
 
-    static class PDFEmbeddedFileMaker extends ElementMapping.Maker {
+    static class PDFEmbeddedFileElementMaker extends ElementMapping.Maker {
         public FONode make(FONode parent) {
             return new PDFEmbeddedFileElement(parent);
         }
     }
+
+    static class PDFDictionaryElementMaker extends ElementMapping.Maker {
+        private PDFDictionaryType dictionaryType;
+        PDFDictionaryElementMaker(PDFDictionaryType dictionaryType) {
+            this.dictionaryType = dictionaryType;
+        }
+        public FONode make(FONode parent) {
+            return new PDFDictionaryElement(parent, dictionaryType);
+        }
+    }
+
+    static class PDFDictionaryEntryElementMaker extends ElementMapping.Maker {
+        private PDFDictionaryEntryType entryType;
+        PDFDictionaryEntryElementMaker(PDFDictionaryEntryType entryType) {
+            this.entryType = entryType;
+        }
+        public FONode make(FONode parent) {
+            return new PDFDictionaryEntryElement(parent, entryType);
+        }
+    }
 }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileAttachment.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileAttachment.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileAttachment.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileAttachment.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,156 @@
+/*
+ * 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.pdf.extensions;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * This is the pass-through value object for the PDF extension.
+ */
+public class PDFEmbeddedFileAttachment extends PDFExtensionAttachment {
+
+    private static final long serialVersionUID = -1L;
+
+    /** element name */
+    protected static final String ELEMENT = "embedded-file";
+
+    /** name of file to be embedded */
+    private static final String ATT_NAME = "filename";
+
+    /** source of file to be embedded (URI) */
+    private static final String ATT_SRC = "src";
+
+    /** a description of the file to be embedded */
+    private static final String ATT_DESC = "desc";
+
+    /** filename attribute */
+    private String filename = null;
+
+    /** description attribute (optional) */
+    private String desc = null;
+
+    /** source name attribute */
+    private String src = null;
+
+    /**
+     * No-argument contructor.
+     */
+    public PDFEmbeddedFileAttachment() {
+        super();
+    }
+
+    /**
+     * Default constructor.
+     * @param filename the name of the file
+     * @param src the location of the file
+     * @param desc the description of the file
+     */
+    public PDFEmbeddedFileAttachment(String filename, String src, String desc) {
+        super();
+        this.filename = filename;
+        this.src = src;
+        this.desc = desc;
+    }
+
+    /**
+     * Returns the file name.
+     * @return the file name
+     */
+    public String getFilename() {
+        return filename;
+    }
+
+    /**
+     * Sets the file name.
+     * @param name The file name to set.
+     */
+    public void setFilename(String name) {
+        this.filename = name;
+    }
+
+    /**
+     * Returns the file description.
+     * @return the description
+     */
+    public String getDesc() {
+        return desc;
+    }
+
+    /**
+     * Sets the description of the file.
+     * @param desc the description to set
+     */
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    /**
+     * Returns the source URI of the file.
+     * @return the source URI
+     */
+    public String getSrc() {
+        return src;
+    }
+
+    /**
+     * Sets the source URI of the file.
+     * @param src the source URI
+     */
+    public void setSrc(String src) {
+        this.src = src;
+    }
+
+    /** {@inheritDoc} */
+    public String getCategory() {
+        return CATEGORY;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return "PDFEmbeddedFile(name=" + getFilename() + ", " + getSrc() + ")";
+    }
+
+    /**
+     * @return the element name
+     */
+    protected String getElement() {
+        return ELEMENT;
+    }
+
+    /** {@inheritDoc} */
+    public void toSAX(ContentHandler handler) throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+        if (filename != null && filename.length() > 0) {
+            atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", filename);
+        }
+        if (src != null && src.length() > 0) {
+            atts.addAttribute(null, ATT_SRC, ATT_SRC, "CDATA", src);
+        }
+        if (desc != null && desc.length() > 0) {
+            atts.addAttribute(null, ATT_DESC, ATT_DESC, "CDATA", desc);
+        }
+        String element = getElement();
+        handler.startElement(CATEGORY, element, element, atts);
+        handler.endElement(CATEGORY, element, element);
+    }
+
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileAttachment.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileElement.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileElement.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFEmbeddedFileElement.java Fri Sep 13 13:56:18 2013
@@ -30,7 +30,6 @@ import org.apache.fop.datatypes.URISpeci
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.PropertyList;
-import org.apache.fop.fo.extensions.ExtensionAttachment;
 
 /**
  * Extension element for pdf:embedded-file.
@@ -44,11 +43,11 @@ public class PDFEmbeddedFileElement exte
      * Main constructor
      * @param parent parent FO node
      */
-    protected PDFEmbeddedFileElement(FONode parent) {
+    PDFEmbeddedFileElement(FONode parent) {
         super(parent);
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void startOfNode() throws FOPException {
         super.startOfNode();
         if (parent.getNameId() != Constants.FO_DECLARATIONS) {
@@ -57,12 +56,12 @@ public class PDFEmbeddedFileElement exte
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void processNode(String elementName, Locator locator,
                             Attributes attlist, PropertyList propertyList)
                                 throws FOPException {
-        PDFEmbeddedFileExtensionAttachment embeddedFile
-            = (PDFEmbeddedFileExtensionAttachment)getExtensionAttachment();
+        PDFEmbeddedFileAttachment embeddedFile
+            = (PDFEmbeddedFileAttachment)getExtensionAttachment();
         String desc = attlist.getValue("description");
         if (desc != null && desc.length() > 0) {
             embeddedFile.setDesc(desc);
@@ -94,13 +93,8 @@ public class PDFEmbeddedFileElement exte
         embeddedFile.setFilename(filename);
     }
 
-    /** {@inheritDoc} */
+    @Override
     public String getLocalName() {
         return ELEMENT;
     }
-
-    /** {@inheritDoc} */
-    protected ExtensionAttachment instantiateExtensionAttachment() {
-        return new PDFEmbeddedFileExtensionAttachment();
-    }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionAttachment.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionAttachment.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionAttachment.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionAttachment.java Fri Sep 13 13:56:18 2013
@@ -23,43 +23,28 @@ import org.apache.xmlgraphics.util.XMLiz
 
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 
-/**
- * This is the pass-through value object for the PDF extension.
- */
+// CSOFF: LineLengthCheck
+
 public abstract class PDFExtensionAttachment implements ExtensionAttachment, XMLizable {
 
     /** The category URI for this extension attachment. */
     public static final String CATEGORY = "apache:fop:extensions:pdf";
 
+    /** The prefix to use with qualified names for this extension attachment. */
+    public static final String PREFIX = "pdf";
+
     /**
      * Default constructor.
      */
     public PDFExtensionAttachment() {
-        //nop
     }
 
-    /**
-     * @return the category URI
-     * @see org.apache.fop.fo.extensions.ExtensionAttachment#getCategory()
-     */
-    public String getCategory() {
-        return CATEGORY;
+    public String getPrefix() {
+        return PREFIX;
     }
 
-    /** @return type name */
-    public String getType() {
-        String className = getClass().getName();
-        return className.substring(className.lastIndexOf('.') + 3);
-    }
-
-    /**
-     * @return a string representation of this object
-     * @see java.lang.Object#toString()
-     */
-    public String toString() {
-        return getType();
+    @Override
+    public String getCategory() {
+        return CATEGORY;
     }
-
-    /** @return element */
-    protected abstract String getElement();
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandler.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandler.java Fri Sep 13 13:56:18 2013
@@ -19,6 +19,8 @@
 
 package org.apache.fop.render.pdf.extensions;
 
+import java.util.Stack;
+
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
@@ -30,68 +32,127 @@ import org.apache.commons.logging.LogFac
 import org.apache.fop.util.ContentHandlerFactory;
 import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener;
 
+// CSOFF: LineLengthCheck
+
 /**
  * ContentHandler (parser) for restoring PDF extension objects from XML.
  */
-public class PDFExtensionHandler extends DefaultHandler
-            implements ContentHandlerFactory.ObjectSource {
+public class PDFExtensionHandler extends DefaultHandler implements ContentHandlerFactory.ObjectSource {
 
     /** Logger instance */
     protected static final Log log = LogFactory.getLog(PDFExtensionHandler.class);
 
-    private Attributes lastAttributes;
-
     private PDFExtensionAttachment returnedObject;
     private ObjectBuiltListener listener;
 
-    /** {@inheritDoc} */
-    public void startElement(String uri, String localName, String qName, Attributes attributes)
-                throws SAXException {
-        boolean handled = false;
+    // PDFEmbeddedFileAttachment related state
+    private Attributes lastAttributes;
+
+    // PDFDictionaryAttachment related
+    private Stack<PDFDictionaryExtension> dictionaries = new Stack<PDFDictionaryExtension>();
+    private boolean captureContent;
+    private StringBuffer characters;
+
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
         if (PDFExtensionAttachment.CATEGORY.equals(uri)) {
-            lastAttributes = new AttributesImpl(attributes);
-            handled = false;
-            if (localName.equals(PDFEmbeddedFileExtensionAttachment.ELEMENT)) {
-                //handled in endElement
-                handled = true;
+            if (localName.equals(PDFEmbeddedFileAttachment.ELEMENT)) {
+                lastAttributes = new AttributesImpl(attributes);
+            } else if (PDFDictionaryType.hasValueOfElementName(localName)) {
+                PDFDictionaryExtension dictionary = new PDFDictionaryExtension(PDFDictionaryType.valueOfElementName(localName));
+                String key = attributes.getValue(PDFDictionaryEntryExtension.PROPERTY_KEY);
+                if (key != null) {
+                    dictionary.setKey(key);
+                }
+                if (dictionary.getDictionaryType() == PDFDictionaryType.Page) {
+                    String pageNumbers = attributes.getValue(PDFDictionaryElement.ATT_PAGE_NUMBERS);
+                    if (pageNumbers != null) {
+                        dictionary.setProperty(PDFDictionaryElement.ATT_PAGE_NUMBERS, pageNumbers);
+                    }
+                }
+                dictionaries.push(dictionary);
+            } else if (PDFDictionaryEntryType.hasValueOfElementName(localName)) {
+                PDFDictionaryEntryExtension entry = new PDFDictionaryEntryExtension(PDFDictionaryEntryType.valueOfElementName(localName));
+                String key = attributes.getValue(PDFDictionaryEntryElement.ATT_KEY);
+                if (key != null) {
+                    entry.setKey(key);
+                }
+                if (!dictionaries.empty()) {
+                    PDFDictionaryExtension dictionary = dictionaries.peek();
+                    dictionary.addEntry(entry);
+                    captureContent = true;
+                }
+            } else {
+                throw new SAXException("Unhandled element " + localName + " in namespace: " + uri);
             }
+        } else {
+            log.warn("Unhandled element " + localName + " in namespace: " + uri);
         }
-        if (!handled) {
-            if (PDFExtensionAttachment.CATEGORY.equals(uri)) {
-                throw new SAXException("Unhandled element " + localName
-                        + " in namespace: " + uri);
-            } else {
-                log.warn("Unhandled element " + localName
-                        + " in namespace: " + uri);
+    }
+
+    @Override
+    public void characters(char[] data, int start, int length) throws SAXException {
+        if (captureContent) {
+            if (characters == null) {
+                characters = new StringBuffer((length < 16) ? 16 : length);
             }
+            characters.append(data, start, length);
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void endElement(String uri, String localName, String qName) throws SAXException {
         if (PDFExtensionAttachment.CATEGORY.equals(uri)) {
-            if (PDFEmbeddedFileExtensionAttachment.ELEMENT.equals(localName)) {
+            if (PDFEmbeddedFileAttachment.ELEMENT.equals(localName)) {
                 String name = lastAttributes.getValue("name");
                 String src = lastAttributes.getValue("src");
                 String desc = lastAttributes.getValue("description");
-                this.returnedObject = new PDFEmbeddedFileExtensionAttachment(name, src, desc);
+                this.returnedObject = new PDFEmbeddedFileAttachment(name, src, desc);
+            } else if (PDFDictionaryType.hasValueOfElementName(localName)) {
+                if (!dictionaries.empty()) {
+                    PDFDictionaryExtension dictionary = dictionaries.pop();
+                    if ((dictionary.getDictionaryType() == PDFDictionaryType.Catalog) || (dictionary.getDictionaryType() == PDFDictionaryType.Page)) {
+                        this.returnedObject = new PDFDictionaryAttachment(dictionary);
+                    } else if (!dictionaries.empty()) {
+                        PDFDictionaryExtension dictionaryOuter = dictionaries.peek();
+                        dictionaryOuter.addEntry(dictionary);
+                    }
+                } else {
+                    throw new SAXException(new IllegalStateException("no active dictionary"));
+                }
+            } else if (PDFDictionaryEntryType.hasValueOfElementName(localName)) {
+                if (!dictionaries.empty()) {
+                    PDFDictionaryExtension dictionary = dictionaries.peek();
+                    PDFDictionaryEntryExtension entry = dictionary.getLastEntry();
+                    if (entry != null) {
+                        if (characters != null) {
+                            entry.setValue(characters.toString());
+                            characters = null;
+                        }
+                    } else {
+                        throw new SAXException(new IllegalStateException("no active entry"));
+                    }
+                } else {
+                    throw new SAXException(new IllegalStateException("no active dictionary"));
+                }
             }
         }
+        captureContent = false;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void endDocument() throws SAXException {
         if (listener != null) {
             listener.notifyObjectBuilt(getObject());
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public Object getObject() {
         return returnedObject;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void setObjectBuiltListener(ObjectBuiltListener listener) {
         this.listener = listener;
     }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandlerFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandlerFactory.java?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandlerFactory.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandlerFactory.java Fri Sep 13 13:56:18 2013
@@ -0,0 +1,44 @@
+/*
+ * 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.pdf.extensions;
+
+import org.xml.sax.ContentHandler;
+
+import org.apache.fop.util.ContentHandlerFactory;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Factory for the ContentHandler that handles serialized PDFExtensionAttachment instances.
+ */
+public class PDFExtensionHandlerFactory implements ContentHandlerFactory {
+
+    private static final String[] NAMESPACES = new String[] {PDFExtensionAttachment.CATEGORY};
+
+    /** {@inheritDoc} */
+    public String[] getSupportedNamespaces() {
+        return NAMESPACES;
+    }
+
+    /** {@inheritDoc} */
+    public ContentHandler createContentHandler() {
+        return new PDFExtensionHandler();
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFExtensionHandlerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/tools/fontlist/FontListMain.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/tools/fontlist/FontListMain.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/tools/fontlist/FontListMain.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/tools/fontlist/FontListMain.java Fri Sep 13 13:56:18 2013
@@ -117,7 +117,7 @@ public final class FontListMain {
         }
         try {
             GenerationHelperContentHandler helper = new GenerationHelperContentHandler(
-                    handler, null);
+                    handler, null, null);
             FontListSerializer serializer = new FontListSerializer();
             serializer.generateSAX(fontFamilies, singleFamily, helper);
         } finally {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/util/GenerationHelperContentHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/util/GenerationHelperContentHandler.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/GenerationHelperContentHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/util/GenerationHelperContentHandler.java Fri Sep 13 13:56:18 2013
@@ -35,6 +35,7 @@ public class GenerationHelperContentHand
     private static final Attributes EMPTY_ATTS = new AttributesImpl();
 
     private String mainNamespace;
+    private Object contentHandlerContext;
 
     /**
      * Main constructor. If the given handler also implements any of the EntityResolver,
@@ -42,10 +43,12 @@ public class GenerationHelperContentHand
      * @param handler the SAX content handler to delegate all calls to
      * @param mainNamespace the main namespace used for generated XML content when abbreviated
      *                          ContentHandler calls are used.
+     * @param contentHandlerContext additional content handler context state
      */
-    public GenerationHelperContentHandler(ContentHandler handler, String mainNamespace) {
+    public GenerationHelperContentHandler(ContentHandler handler, String mainNamespace, Object contentHandlerContext) {
         super(handler);
         this.mainNamespace = mainNamespace;
+        this.contentHandlerContext = contentHandlerContext;
     }
 
     /**
@@ -66,6 +69,14 @@ public class GenerationHelperContentHand
     }
 
     /**
+     * Returns the context object (may be null).
+     * @return the context object
+     */
+    public Object getContentHandlerContext() {
+        return this.contentHandlerContext;
+    }
+
+    /**
      * Convenience method to generate a startElement SAX event.
      * @param localName the local name of the element
      * @param atts the attributes

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java Fri Sep 13 13:56:18 2013
@@ -300,4 +300,35 @@ public final class XMLUtil implements XM
         }
     }
 
+    /**
+     * Escape '<', '>' and '&' using NCRs.
+     * @param unescaped string
+     * @return escaped string
+     */
+    public static String escape(String unescaped) {
+        int needsEscape = 0;
+        for (int i = 0, n = unescaped.length(); i < n; ++i) {
+            char c = unescaped.charAt(i);
+            if ((c == '<') || (c == '>') || (c == '&')) {
+                ++needsEscape;
+            }
+        }
+        if (needsEscape > 0) {
+            StringBuffer sb = new StringBuffer(unescaped.length() + 6 * needsEscape);
+            for (int i = 0, n = unescaped.length(); i < n; ++i) {
+                char c = unescaped.charAt(i);
+                if ((c == '<') || (c == '>') || (c == '&')) {
+                    sb.append("&#x");
+                    sb.append(Integer.toString(c, 16));
+                    sb.append(';');
+                } else {
+                    sb.append(c);
+                }
+            }
+            return sb.toString();
+        } else {
+            return unescaped;
+        }
+    }
+
 }

Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGDocumentHandler.java Fri Sep 13 13:56:18 2013
@@ -229,7 +229,7 @@ public class SVGDocumentHandler extends 
     }
 
     private GenerationHelperContentHandler decorate(ContentHandler contentHandler) {
-        return new GenerationHelperContentHandler(contentHandler, getMainNamespace());
+        return new GenerationHelperContentHandler(contentHandler, getMainNamespace(), getContext());
     }
 
     private void closeCurrentStream() {

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=1522934&r1=1522933&r2=1522934&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Fri Sep 13 13:56:18 2013
@@ -59,6 +59,9 @@
       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="GA" type="add" fixes-bug="FOP-2298">
+          Enable support for PDF page transitions.
+      </action>
       <action context="Code" dev="PH" type="fix" fixes-bug="FOP-2211" due-to="Alexios Giotis, PH">
           Fix and improve the handling of temporary files using the new URI resource resolvers
       </action>

Added: xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml?rev=1522934&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml (added)
+++ xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml Fri Sep 13 13:56:18 2013
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks the PDF dictionary extensions.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:pdf="http://xmlgraphics.apache.org/fop/extensions/pdf">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="simple">
+          <fo:region-body/>
+          <fo:region-before/>
+          <fo:region-after/>
+          <pdf:page page-numbers="*">
+            <pdf:number key="Dur">5</pdf:number>
+          </pdf:page>
+          <pdf:page page-numbers="1">
+            <pdf:dictionary key="Trans">
+              <pdf:name key="Type">Trans</pdf:name>
+              <pdf:number key="D">1</pdf:number>
+              <pdf:name key="S">Glitter</pdf:name>
+              <pdf:number key="Di">0</pdf:number>
+            </pdf:dictionary>
+          </pdf:page>
+          <pdf:page page-numbers="2">
+            <pdf:dictionary key="Trans">
+              <pdf:name key="Type">Trans</pdf:name>
+              <pdf:number key="D">1</pdf:number>
+              <pdf:name key="S">Push</pdf:name>
+              <pdf:number key="Di">180</pdf:number>
+            </pdf:dictionary>
+          </pdf:page>
+          <pdf:page page-numbers="3">
+            <pdf:dictionary key="Trans">
+              <pdf:name key="Type">Trans</pdf:name>
+              <pdf:number key="D">1</pdf:number>
+              <pdf:name key="S">Cover</pdf:name>
+              <pdf:number key="Di">270</pdf:number>
+            </pdf:dictionary>
+          </pdf:page>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:declarations>
+        <pdf:catalog>
+          <pdf:name key="Foo">Bar</pdf:name>
+        </pdf:catalog>
+      </fo:declarations>
+      <fo:page-sequence master-reference="simple">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block page-break-before="always">SLIDE 1</fo:block>
+          <fo:block page-break-before="always">SLIDE 2</fo:block>
+          <fo:block page-break-before="always">SLIDE 3</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks xmlns:pdf="apache:fop:extensions:pdf">
+    <eval expected="Foo" xpath="/areaTree/extension-attachments/pdf:catalog/pdf:name/@key"/>
+    <eval expected="Bar" xpath="/areaTree/extension-attachments/pdf:catalog/pdf:name"/>
+    <eval expected="Dur" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/pdf:page/pdf:number/@key"/>
+    <eval expected="5" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/pdf:page/pdf:number"/>
+  </checks>
+  <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate" xmlns:pdf="apache:fop:extensions:pdf">
+    <eval expected="Foo" xpath="/if:document/if:header/pdf:catalog/pdf:name/@key"/>
+    <eval expected="Bar" xpath="/if:document/if:header/pdf:catalog/pdf:name"/>
+    <eval expected="Dur" xpath="//if:page[@name=1]/if:page-header/pdf:page/pdf:number/@key"/>
+    <eval expected="5" xpath="//if:page[@name=1]/if:page-header/pdf:page/pdf:number"/>
+    <eval expected="2" xpath="count(//if:page[@name=1]/if:page-header/pdf:page)"/>
+    <eval expected="2" xpath="count(//if:page[@name=2]/if:page-header/pdf:page)"/>
+    <eval expected="2" xpath="count(//if:page[@name=3]/if:page-header/pdf:page)"/>
+  </if-checks>
+</testcase>

Propchange: xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/pdf-dictionary-extension_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org