xmlgraphics-fop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gad...@apache.org
Subject svn commit: r1537948 [2/3] - in /xmlgraphics/fop/trunk: ./ src/documentation/intermediate-format-ng/ src/java/org/apache/fop/area/ src/java/org/apache/fop/fo/ src/java/org/apache/fop/fo/extensions/ src/java/org/apache/fop/layoutmgr/ src/java/org/apache...
Date Fri, 01 Nov 2013 14:34:20 GMT
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=1537948&r1=1537947&r2=1537948&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 Nov  1 14:34:18 2013
@@ -27,6 +27,7 @@ import java.io.OutputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.EnumMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.io.IOUtils;
@@ -55,24 +56,33 @@ import org.apache.fop.pdf.PDFFileSpec;
 import org.apache.fop.pdf.PDFICCBasedColorSpace;
 import org.apache.fop.pdf.PDFICCStream;
 import org.apache.fop.pdf.PDFInfo;
+import org.apache.fop.pdf.PDFLayer;
 import org.apache.fop.pdf.PDFMetadata;
 import org.apache.fop.pdf.PDFName;
 import org.apache.fop.pdf.PDFNames;
+import org.apache.fop.pdf.PDFNavigator;
+import org.apache.fop.pdf.PDFNull;
 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.PDFSetOCGStateAction;
 import org.apache.fop.pdf.PDFText;
+import org.apache.fop.pdf.PDFTransitionAction;
 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.PDFActionExtension;
+import org.apache.fop.render.pdf.extensions.PDFArrayExtension;
+import org.apache.fop.render.pdf.extensions.PDFCollectionEntryExtension;
 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 org.apache.fop.render.pdf.extensions.PDFObjectType;
+import org.apache.fop.render.pdf.extensions.PDFPageExtension;
+import org.apache.fop.render.pdf.extensions.PDFReferenceExtension;
 
 import static org.apache.fop.render.pdf.PDFEncryptionOption.ENCRYPTION_PARAMS;
 import static org.apache.fop.render.pdf.PDFEncryptionOption.NO_ACCESSCONTENT;
@@ -260,10 +270,189 @@ class PDFRenderingUtil {
 
     public void renderDictionaryExtension(PDFDictionaryAttachment attachment, PDFPage currentPage) {
         PDFDictionaryExtension extension = attachment.getExtension();
-        if (extension.getDictionaryType() == PDFDictionaryType.Catalog) {
+        PDFDictionaryType type = extension.getDictionaryType();
+        if (type == PDFDictionaryType.Action) {
+            addNavigatorAction(extension);
+        } else if (type == PDFDictionaryType.Layer) {
+            addLayer(extension);
+        } else if (type == PDFDictionaryType.Navigator) {
+            addNavigator(extension);
+        } else {
+            renderDictionaryExtension(extension, currentPage);
+        }
+    }
+
+    public void addLayer(PDFDictionaryExtension extension) {
+        assert extension.getDictionaryType() == PDFDictionaryType.Layer;
+        String id = extension.getProperty(PDFDictionaryExtension.PROPERTY_ID);
+        if ((id != null) && (id.length() > 0)) {
+            PDFLayer layer = pdfDoc.getFactory().makeLayer(id);
+            layer.setResolver(new PDFLayer.Resolver(layer, extension) {
+                public void performResolution() {
+                    PDFDictionaryExtension extension = (PDFDictionaryExtension) getExtension();
+                    Object name = extension.findEntryValue("Name");
+                    Object intent = extension.findEntryValue("Intent");
+                    Object usage = makeDictionary(extension.findEntryValue("Usage"));
+                    getLayer().populate(name, intent, usage);
+                }
+            });
+        }
+    }
+
+    public void addNavigatorAction(PDFDictionaryExtension extension) {
+        assert extension.getDictionaryType() == PDFDictionaryType.Action;
+        String id = extension.getProperty(PDFDictionaryExtension.PROPERTY_ID);
+        if ((id != null) && (id.length() > 0)) {
+            String type = extension.getProperty(PDFActionExtension.PROPERTY_TYPE);
+            if (type != null) {
+                if (type.equals("SetOCGState")) {
+                    PDFSetOCGStateAction action = pdfDoc.getFactory().makeSetOCGStateAction(id);
+                    action.setResolver(new PDFSetOCGStateAction.Resolver(action, extension) {
+                        public void performResolution() {
+                            PDFDictionaryExtension extension = (PDFDictionaryExtension) getExtension();
+                            Object state = makeArray(extension.findEntryValue("State"));
+                            Object preserveRB = extension.findEntryValue("PreserveRB");
+                            Object nextAction = makeDictionaryOrArray(extension.findEntryValue("Next"));
+                            getAction().populate(state, preserveRB, nextAction);
+                        }
+                    });
+                } else if (type.equals("Trans")) {
+                    PDFTransitionAction action = pdfDoc.getFactory().makeTransitionAction(id);
+                    action.setResolver(new PDFTransitionAction.Resolver(action, extension) {
+                        public void performResolution() {
+                            PDFDictionaryExtension extension = (PDFDictionaryExtension) getExtension();
+                            Object transition = makeDictionary(extension.findEntryValue("Trans"));
+                            Object nextAction = makeDictionaryOrArray(extension.findEntryValue("Next"));
+                            getAction().populate(transition, nextAction);
+                        }
+                    });
+                } else {
+                    throw new UnsupportedOperationException();
+                }
+            }
+        }
+    }
+
+    public void addNavigator(PDFDictionaryExtension extension) {
+        assert extension.getDictionaryType() == PDFDictionaryType.Navigator;
+        String id = extension.getProperty(PDFDictionaryExtension.PROPERTY_ID);
+        if ((id != null) && (id.length() > 0)) {
+            PDFNavigator navigator = pdfDoc.getFactory().makeNavigator(id);
+            navigator.setResolver(new PDFNavigator.Resolver(navigator, extension) {
+                public void performResolution() {
+                    PDFDictionaryExtension extension = (PDFDictionaryExtension) getExtension();
+                    Object nextAction = makeDictionary(extension.findEntryValue("NA"));
+                    Object next = makeDictionary(extension.findEntryValue("Next"));
+                    Object prevAction = makeDictionary(extension.findEntryValue("PA"));
+                    Object prev = makeDictionary(extension.findEntryValue("Prev"));
+                    Object duration = extension.findEntryValue("Dur");
+                    getNavigator().populate(nextAction, next, prevAction, prev, duration);
+                }
+            });
+        }
+    }
+
+    private Object makeArray(Object value) {
+        if (value == null) {
+            return null;
+        } else if (value instanceof PDFReferenceExtension) {
+            return resolveReference((PDFReferenceExtension) value);
+        } else if (value instanceof List<?>) {
+            return populateArray(new PDFArray(), (List<?>) value);
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    private Object populateArray(PDFArray array, List<?> entries) {
+        for (PDFCollectionEntryExtension entry : (List<PDFCollectionEntryExtension>) entries) {
+            PDFObjectType type = entry.getType();
+            if (type == PDFObjectType.Array) {
+                array.add(makeArray(entry.getValue()));
+            } else if (type == PDFObjectType.Boolean) {
+                array.add(entry.getValueAsBoolean());
+            } else if (type == PDFObjectType.Dictionary) {
+                array.add(makeDictionary(entry.getValue()));
+            } else if (type == PDFObjectType.Name) {
+                array.add(new PDFName(entry.getValueAsString()));
+            } else if (type == PDFObjectType.Number) {
+                array.add(new PDFNumber(entry.getValueAsNumber()));
+            } else if (type == PDFObjectType.Reference) {
+                array.add(resolveReference((PDFReferenceExtension) entry));
+            } else if (type == PDFObjectType.String) {
+                array.add(entry.getValue());
+            }
+        }
+        return array;
+    }
+
+    private Object makeDictionary(Object value) {
+        if (value == null) {
+            return null;
+        } else if (value instanceof PDFReferenceExtension) {
+            return resolveReference((PDFReferenceExtension) value);
+        } else if (value instanceof List<?>) {
+            return populateDictionary(new PDFDictionary(), (List<?>) value);
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    private Object populateDictionary(PDFDictionary dictionary, List<?> entries) {
+        for (PDFCollectionEntryExtension entry : (List<PDFCollectionEntryExtension>) entries) {
+            PDFObjectType type = entry.getType();
+            String key = entry.getKey();
+            if (type == PDFObjectType.Array) {
+                dictionary.put(key, makeArray(entry.getValue()));
+            } else if (type == PDFObjectType.Boolean) {
+                dictionary.put(key, entry.getValueAsBoolean());
+            } else if (type == PDFObjectType.Dictionary) {
+                dictionary.put(key, makeDictionary(entry.getValue()));
+            } else if (type == PDFObjectType.Name) {
+                dictionary.put(key, new PDFName(entry.getValueAsString()));
+            } else if (type == PDFObjectType.Number) {
+                dictionary.put(key, new PDFNumber(entry.getValueAsNumber()));
+            } else if (type == PDFObjectType.Reference) {
+                dictionary.put(key, resolveReference((PDFReferenceExtension) entry));
+            } else if (type == PDFObjectType.String) {
+                dictionary.put(key, entry.getValue());
+            }
+        }
+        return dictionary;
+    }
+
+    private Object makeDictionaryOrArray(Object value) {
+        if (value == null) {
+            return null;
+        } else if (value instanceof PDFReferenceExtension) {
+            return resolveReference((PDFReferenceExtension) value);
+        } else if (value instanceof List<?>) {
+            if (hasKeyedEntry((List<?>) value)) {
+                return populateDictionary(new PDFDictionary(), (List<?>) value);
+            } else {
+                return populateArray(new PDFArray(), (List<?>) value);
+            }
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    private boolean hasKeyedEntry(List<?> entries) {
+        for (PDFCollectionEntryExtension entry : (List<PDFCollectionEntryExtension>) entries) {
+            if (entry.getKey() != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void renderDictionaryExtension(PDFDictionaryExtension extension, PDFPage currentPage) {
+        PDFDictionaryType type = extension.getDictionaryType();
+        if (type == PDFDictionaryType.Catalog) {
             augmentDictionary(pdfDoc.getRoot(), extension);
-        } else if (extension.getDictionaryType() == PDFDictionaryType.Page) {
-            if (extension.matchesPageNumber(currentPage.getPageIndex() + 1)) {
+        } else if (type == PDFDictionaryType.Page) {
+            assert extension instanceof PDFPageExtension;
+            if (((PDFPageExtension) extension).matchesPageNumber(currentPage.getPageIndex() + 1)) {
                 augmentDictionary(currentPage, extension);
             }
         } else {
@@ -272,9 +461,11 @@ class PDFRenderingUtil {
     }
 
     private PDFDictionary augmentDictionary(PDFDictionary dictionary, PDFDictionaryExtension extension) {
-        for (PDFDictionaryEntryExtension entry : extension.getEntries()) {
+        for (PDFCollectionEntryExtension entry : extension.getEntries()) {
             if (entry instanceof PDFDictionaryExtension) {
                 dictionary.put(entry.getKey(), augmentDictionary(new PDFDictionary(dictionary), (PDFDictionaryExtension) entry));
+            } else if (entry instanceof PDFArrayExtension) {
+                dictionary.put(entry.getKey(), augmentArray(new PDFArray(dictionary), (PDFArrayExtension) entry));
             } else {
                 augmentDictionary(dictionary, entry);
             }
@@ -282,22 +473,68 @@ class PDFRenderingUtil {
         return dictionary;
     }
 
-    private void augmentDictionary(PDFDictionary dictionary, PDFDictionaryEntryExtension entry) {
-        PDFDictionaryEntryType type = entry.getType();
+    private void augmentDictionary(PDFDictionary dictionary, PDFCollectionEntryExtension entry) {
+        PDFObjectType type = entry.getType();
         String key = entry.getKey();
-        if (type == PDFDictionaryEntryType.Boolean) {
+        if (type == PDFObjectType.Boolean) {
             dictionary.put(key, entry.getValueAsBoolean());
-        } else if (type == PDFDictionaryEntryType.Name) {
+        } else if (type == PDFObjectType.Name) {
             dictionary.put(key, new PDFName(entry.getValueAsString()));
-        } else if (type == PDFDictionaryEntryType.Number) {
+        } else if (type == PDFObjectType.Number) {
             dictionary.put(key, new PDFNumber(entry.getValueAsNumber()));
-        } else if (type == PDFDictionaryEntryType.String) {
+        } else if (type == PDFObjectType.Reference) {
+            assert entry instanceof PDFReferenceExtension;
+            dictionary.put(key, resolveReference((PDFReferenceExtension) entry));
+        } else if (type == PDFObjectType.String) {
             dictionary.put(key, entry.getValueAsString());
         } else {
             throw new IllegalStateException();
         }
     }
 
+    private Object resolveReference(PDFReferenceExtension entry) {
+        PDFReference reference = (PDFReference) entry.getResolvedReference();
+        if (reference == null) {
+            reference = pdfDoc.resolveExtensionReference(entry.getReferenceId());
+            if (reference != null) {
+                entry.setResolvedReference(reference);
+            }
+            return reference;
+        }
+        return PDFNull.INSTANCE;
+    }
+
+    private PDFArray augmentArray(PDFArray array, PDFArrayExtension extension) {
+        for (PDFCollectionEntryExtension entry : extension.getEntries()) {
+            if (entry instanceof PDFDictionaryExtension) {
+                array.add(augmentDictionary(new PDFDictionary(array), (PDFDictionaryExtension) entry));
+            } else if (entry instanceof PDFArrayExtension) {
+                array.add(augmentArray(new PDFArray(array), (PDFArrayExtension) entry));
+            } else {
+                augmentArray(array, entry);
+            }
+        }
+        return array;
+    }
+
+    private void augmentArray(PDFArray array, PDFCollectionEntryExtension entry) {
+        PDFObjectType type = entry.getType();
+        if (type == PDFObjectType.Boolean) {
+            array.add(entry.getValueAsBoolean());
+        } else if (type == PDFObjectType.Name) {
+            array.add(new PDFName(entry.getValueAsString()));
+        } else if (type == PDFObjectType.Number) {
+            array.add(new PDFNumber(entry.getValueAsNumber()));
+        } else if (type == PDFObjectType.Reference) {
+            assert entry instanceof PDFReferenceExtension;
+            array.add(resolveReference((PDFReferenceExtension) entry));
+        } else if (type == PDFObjectType.String) {
+            array.add(entry.getValueAsString());
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
     public PDFDocument setupPDFDocument(OutputStream out) throws IOException {
         if (this.pdfDoc != null) {
             throw new IllegalStateException("PDFDocument already set up");

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionElement.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionElement.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Extension element for pdf:action.
+ */
+public class PDFActionElement extends PDFDictionaryElement {
+
+    public static final String ATT_TYPE = PDFActionExtension.PROPERTY_TYPE;
+
+    /**
+     * Main constructor
+     * @param parent parent FO node
+     */
+    PDFActionElement(FONode parent) {
+        super(parent, PDFDictionaryType.Action);
+    }
+
+    @Override
+    public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException {
+        super.processNode(elementName, locator, attlist, propertyList);
+        String type = attlist.getValue(ATT_TYPE);
+        if (type != null) {
+            getDictionaryExtension().setProperty(PDFActionExtension.PROPERTY_TYPE, type);
+        }
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+        if (parent.getNameId() != Constants.FO_DECLARATIONS) {
+            invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfDeclarations");
+        }
+    }
+
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionExtension.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFActionExtension.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,32 @@
+/*
+ * 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
+
+public class PDFActionExtension extends PDFDictionaryExtension {
+
+    public static final String PROPERTY_TYPE = "type";
+
+    PDFActionExtension() {
+        super(PDFDictionaryType.Action);
+    }
+
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayElement.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayElement.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,82 @@
+/*
+ * 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 pdf:array.
+ */
+public class PDFArrayElement extends PDFCollectionEntryElement {
+
+    private PDFArrayExtension extension;
+
+    /**
+     * Main constructor
+     * @param parent parent FO node
+     */
+    PDFArrayElement(FONode parent) {
+        super(parent, PDFObjectType.Array, new PDFArrayExtension());
+    }
+
+    public PDFArrayExtension getArrayExtension() {
+        assert getExtension() instanceof PDFArrayExtension;
+        return (PDFArrayExtension) getExtension();
+    }
+
+    @Override
+    public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException {
+        super.processNode(elementName, locator, attlist, propertyList);
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+    }
+
+    @Override
+    protected void addChildNode(FONode child) throws FOPException {
+        PDFArrayExtension extension = getArrayExtension();
+        if (child instanceof PDFCollectionEntryElement) {
+            PDFCollectionEntryExtension entry = ((PDFCollectionEntryElement) child).getExtension();
+            if (entry.getKey() == null) {
+                extension.addEntry(entry);
+            }
+        }
+    }
+
+    @Override
+    public void endOfNode() throws FOPException {
+        super.endOfNode();
+    }
+
+    @Override
+    public String getLocalName() {
+        return PDFObjectType.Array.elementName();
+    }
+
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayExtension.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFArrayExtension.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,84 @@
+/*
+ * 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 PDFArrayExtension extends PDFCollectionExtension {
+
+    private static final long serialVersionUID = -1L;
+
+    private Map<String, String> properties;
+    private List<PDFCollectionEntryExtension> entries;
+
+    PDFArrayExtension() {
+        super(PDFObjectType.Array);
+        this.properties = new java.util.HashMap<String, String>();
+        this.entries = new java.util.ArrayList<PDFCollectionEntryExtension>();
+    }
+
+    @Override
+    public void setValue(Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getValue() {
+        return getEntries();
+    }
+
+    public void setProperty(String name, String value) {
+        properties.put(name, value);
+    }
+
+    public String getProperty(String name) {
+        return properties.get(name);
+    }
+
+    @Override
+    public void addEntry(PDFCollectionEntryExtension entry) {
+        if (entry.getKey() != null) {
+            throw new IllegalArgumentException();
+        } else {
+            entries.add(entry);
+        }
+    }
+
+    public List<PDFCollectionEntryExtension> getEntries() {
+        return entries;
+    }
+
+    public PDFCollectionEntryExtension getLastEntry() {
+        if (entries.size() > 0) {
+            return entries.get(entries.size() - 1);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getElementName() {
+        return PDFObjectType.Array.elementName();
+    }
+
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogElement.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogElement.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,45 @@
+/*
+ * 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.apps.FOPException;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Extension element for pdf:catalog.
+ */
+public class PDFCatalogElement extends PDFDictionaryElement {
+
+    PDFCatalogElement(FONode parent) {
+        super(parent, PDFDictionaryType.Catalog);
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+        if (parent.getNameId() != Constants.FO_DECLARATIONS) {
+            invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfDeclarations");
+        }
+    }
+
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogExtension.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCatalogExtension.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,29 @@
+/*
+ * 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
+
+public class PDFCatalogExtension extends PDFDictionaryExtension {
+
+    PDFCatalogExtension() {
+        super(PDFDictionaryType.Catalog);
+    }
+}

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

Copied: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionEntryElement.java (from r1537941, 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/PDFCollectionEntryElement.java?p2=xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionEntryElement.java&p1=xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java&r1=1537941&r2=1537948&rev=1537948&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryElement.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionEntryElement.java Fri Nov  1 14:34:18 2013
@@ -29,76 +29,113 @@ import org.apache.fop.fo.PropertyList;
 // CSOFF: LineLengthCheck
 
 /**
- * Extension element for dictionary entries: pdf:{boolean,name,number,string}. The specific type
+ * Extension element for collection entries: pdf:{array,boolean,dictionary,name,number,reference,string}. The specific type
  * of entry is established at construction type.
  */
-public class PDFDictionaryEntryElement extends AbstractPDFDictionaryElement {
+public class PDFCollectionEntryElement extends AbstractPDFExtensionElement {
 
-    private PDFDictionaryEntryExtension extension;
+    public static final String ATT_KEY = PDFCollectionEntryExtension.PROPERTY_KEY;
+
+    private PDFCollectionEntryExtension extension;
     private StringBuffer characters;
 
-    /**
-     * Main constructor
-     * @param parent parent FO node
-     */
-    PDFDictionaryEntryElement(FONode parent, PDFDictionaryEntryType type) {
+    PDFCollectionEntryElement(FONode parent, PDFObjectType type, PDFCollectionEntryExtension extension) {
         super(parent);
-        this.extension = new PDFDictionaryEntryExtension(type);
+        this.extension = extension;
+    }
+
+    PDFCollectionEntryElement(FONode parent, PDFObjectType type) {
+        this(parent, type, createExtension(type));
     }
 
-    public PDFDictionaryEntryExtension getExtension() {
+    private static PDFCollectionEntryExtension createExtension(PDFObjectType type) {
+        if (type == PDFObjectType.Reference) {
+            return new PDFReferenceExtension();
+        } else {
+            return new PDFCollectionEntryExtension(type);
+        }
+    }
+
+    public PDFCollectionEntryExtension 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.length() == 0) {
-            invalidPropertyValueError("key", key, null);
-        } else {
-            extension.setKey(key);
+        if (parent instanceof PDFDictionaryElement) {
+            String key = attlist.getValue(ATT_KEY);
+            if (key == null) {
+                missingPropertyError(ATT_KEY);
+            } else if (key.length() == 0) {
+                invalidPropertyValueError(ATT_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);
+        if (parent instanceof PDFDictionaryElement) {
+            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);
+        if (capturePCData(extension.getType())) {
+            if (characters == null) {
+                characters = new StringBuffer((length < 16) ? 16 : length);
+            }
+            characters.append(data, start, length);
+        }
+    }
+
+    private boolean capturePCData(PDFObjectType type) {
+        if (type == PDFObjectType.Array) {
+            return false;
+        } else if (type == PDFObjectType.Dictionary) {
+            return false;
+        } else {
+            return (type != PDFObjectType.Reference);
         }
-        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.length() == 0) {
-                invalidPropertyValueError("<value>", value, null);
-            }
-        } else if (extension.getType() == PDFDictionaryEntryType.Number) {
-            try {
-                Double.valueOf(value);
-            } catch (NumberFormatException e) {
-                invalidPropertyValueError("<value>", value, null);
+        if (capturePCData(extension.getType())) {
+            if (extension.getType() == PDFObjectType.Boolean) {
+                String value = (characters != null) ? characters.toString() : "";
+                if (!value.equals("true") && !value.equals("false")) {
+                    invalidPropertyValueError("<value>", value, null);
+                }
+                extension.setValue(Boolean.valueOf(value));
+            } else if (extension.getType() == PDFObjectType.Name) {
+                String value = (characters != null) ? characters.toString() : "";
+                if (value.length() == 0) {
+                    invalidPropertyValueError("<value>", value, null);
+                }
+                extension.setValue(value);
+            } else if (extension.getType() == PDFObjectType.Number) {
+                String value = (characters != null) ? characters.toString() : "";
+                try {
+                    double d = Double.parseDouble(value);
+                    if (Math.abs(Math.floor(d) - d) < 1E-10) {
+                        extension.setValue(Long.valueOf((long) d));
+                    } else {
+                        extension.setValue(Double.valueOf(d));
+                    }
+                } catch (NumberFormatException e) {
+                    invalidPropertyValueError("<value>", value, null);
+                }
+            } else if (extension.getType() == PDFObjectType.String) {
+                String value = (characters != null) ? characters.toString() : "";
+                extension.setValue(value);
             }
-        } else if (extension.getType() != PDFDictionaryEntryType.String) {
-            throw new IllegalStateException();
         }
-        extension.setValue(value);
         super.endOfNode();
     }
 

Copied: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionEntryExtension.java (from r1537941, 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/PDFCollectionEntryExtension.java?p2=xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionEntryExtension.java&p1=xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java&r1=1537941&r2=1537948&rev=1537948&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryEntryExtension.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionEntryExtension.java Fri Nov  1 14:34:18 2013
@@ -19,27 +19,17 @@
 
 package org.apache.fop.render.pdf.extensions;
 
-import org.apache.fop.util.XMLUtil;
-
 // CSOFF: LineLengthCheck
 
-public class PDFDictionaryEntryExtension {
+public class PDFCollectionEntryExtension extends PDFObjectExtension {
 
     public static final String PROPERTY_KEY = "key";
 
-    private PDFDictionaryEntryType type;
-    private String key = "";
-    private Object value;
-
-    PDFDictionaryEntryExtension() {
-    }
-
-    PDFDictionaryEntryExtension(PDFDictionaryEntryType type) {
-        this.type = type;
-    }
+    /* Non-empty key if used as dictionary entry, otherwise must be null. */
+    private String key;
 
-    public PDFDictionaryEntryType getType() {
-        return type;
+    PDFCollectionEntryExtension(PDFObjectType type) {
+        super(type);
     }
 
     public String getKey() {
@@ -50,61 +40,4 @@ public class PDFDictionaryEntryExtension
         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();
-    }
-
 }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionExtension.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFCollectionExtension.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,34 @@
+/*
+ * 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
+
+public abstract class PDFCollectionExtension extends PDFCollectionEntryExtension {
+
+    protected PDFCollectionExtension(PDFObjectType type) {
+        super(type);
+    }
+
+    public abstract void addEntry(PDFCollectionEntryExtension entry);
+
+    public abstract PDFCollectionEntryExtension getLastEntry();
+
+}

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

Modified: 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=1537948&r1=1537947&r2=1537948&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryAttachment.java Fri Nov  1 14:34:18 2013
@@ -43,14 +43,13 @@ public class PDFDictionaryAttachment ext
     }
 
     public void toSAX(ContentHandler handler) throws SAXException {
-        PDFDictionaryType dictionaryType = extension.getDictionaryType();
         int pageNumber = 0;
-        if (dictionaryType == PDFDictionaryType.Page) {
+        if (extension instanceof PDFPageExtension) {
             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)) {
+                    if ((pageIndex >= 0) && ((PDFPageExtension) extension).matchesPageNumber(pageIndex + 1)) {
                         pageNumber = pageIndex + 1;
                     } else {
                         pageNumber = -1;
@@ -69,24 +68,40 @@ public class PDFDictionaryAttachment ext
         String qn = PREFIX + ":" + ln;
         attributes = extractIFAttributes(attributes, dictionary);
         handler.startElement(CATEGORY, ln, qn, attributes);
-        for (PDFDictionaryEntryExtension entry : dictionary.getEntries()) {
+        for (PDFCollectionEntryExtension entry : dictionary.getEntries()) {
             toSAX(handler, entry);
         }
         handler.endElement(CATEGORY, ln, qn);
     }
 
-    private void toSAX(ContentHandler handler, PDFDictionaryEntryExtension entry) throws SAXException {
+    private void toSAX(ContentHandler handler, PDFArrayExtension array) throws SAXException {
+        AttributesImpl attributes = new AttributesImpl();
+        String ln = array.getElementName();
+        String qn = PREFIX + ":" + ln;
+        attributes = extractIFAttributes(attributes, array);
+        handler.startElement(CATEGORY, ln, qn, attributes);
+        for (PDFCollectionEntryExtension entry : array.getEntries()) {
+            toSAX(handler, entry);
+        }
+        handler.endElement(CATEGORY, ln, qn);
+    }
+
+    private void toSAX(ContentHandler handler, PDFCollectionEntryExtension entry) throws SAXException {
         if (entry instanceof PDFDictionaryExtension) {
             toSAX(handler, (PDFDictionaryExtension) entry);
+        } else if (entry instanceof PDFArrayExtension) {
+            toSAX(handler, (PDFArrayExtension) 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);
+            if (!(entry instanceof PDFReferenceExtension)) {
+                char[] characters = entry.getValueAsXMLEscapedString().toCharArray();
+                if (characters.length > 0) {
+                    handler.characters(characters, 0, characters.length);
+                }
             }
             handler.endElement(CATEGORY, ln, qn);
         }
@@ -94,16 +109,27 @@ public class PDFDictionaryAttachment ext
 
     private static AttributesImpl extractIFAttributes(AttributesImpl attributes, PDFDictionaryExtension dictionary) {
         PDFDictionaryType type = dictionary.getDictionaryType();
-        if (type == PDFDictionaryType.Catalog) {
-            // no specific attriburtes
+        if (dictionary.usesIDAttribute()) {
+            String idName = PDFDictionaryElement.ATT_ID;
+            String id = dictionary.getProperty(PDFDictionaryExtension.PROPERTY_ID);
+            if (id != null) {
+                attributes.addAttribute(null, idName, idName, "ID", id);
+            }
+        }
+        if (type == PDFDictionaryType.Action) {
+            String actionTypeName = PDFActionElement.ATT_TYPE;
+            String actionType = dictionary.getProperty(PDFActionExtension.PROPERTY_TYPE);
+            if (actionType != null) {
+                attributes.addAttribute(null, actionTypeName, actionTypeName, "CDATA", actionType);
+            }
         } else if (type == PDFDictionaryType.Page) {
-            String pageNumbersName = PDFDictionaryExtension.PROPERTY_PAGE_NUMBERS;
+            String pageNumbersName = PDFPageExtension.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 keyName = PDFCollectionEntryElement.ATT_KEY;
             String key = dictionary.getKey();
             if (key != null) {
                 attributes.addAttribute(null, keyName, keyName, "CDATA", key);
@@ -112,12 +138,28 @@ public class PDFDictionaryAttachment ext
         return attributes;
     }
 
-    private static AttributesImpl extractIFAttributes(AttributesImpl attributes, PDFDictionaryEntryExtension entry) {
-        String keyName = PDFDictionaryEntryExtension.PROPERTY_KEY;
+    private static AttributesImpl extractIFAttributes(AttributesImpl attributes, PDFArrayExtension array) {
+        String keyName = PDFCollectionEntryExtension.PROPERTY_KEY;
+        String key = array.getKey();
+        if (key != null) {
+            attributes.addAttribute(null, keyName, keyName, "CDATA", key);
+        }
+        return attributes;
+    }
+
+    private static AttributesImpl extractIFAttributes(AttributesImpl attributes, PDFCollectionEntryExtension entry) {
+        String keyName = PDFCollectionEntryElement.ATT_KEY;
         String key = entry.getKey();
         if (key != null) {
             attributes.addAttribute(null, keyName, keyName, "CDATA", key);
         }
+        if (entry instanceof PDFReferenceExtension) {
+            String refid = ((PDFReferenceExtension) entry).getReferenceId();
+            if (refid != null) {
+                String refidName = PDFReferenceElement.ATT_REFID;
+                attributes.addAttribute(null, refidName, refidName, "IDREF", refid);
+            }
+        }
         return attributes;
     }
 

Modified: 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=1537948&r1=1537947&r2=1537948&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryElement.java Fri Nov  1 14:34:18 2013
@@ -23,7 +23,6 @@ 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;
@@ -34,38 +33,54 @@ import org.apache.fop.fo.extensions.Exte
  * Extension element for dictionaries: pdf:{catalog,page,dictionary}. The specific type
  * of dictionary is established at construction type.
  */
-public class PDFDictionaryElement extends AbstractPDFDictionaryElement {
+public class PDFDictionaryElement extends PDFCollectionEntryElement {
 
-    public static final String ATT_PAGE_NUMBERS = PDFDictionaryExtension.PROPERTY_PAGE_NUMBERS;
-
-    private PDFDictionaryExtension extension;
+    public static final String ATT_ID = PDFDictionaryExtension.PROPERTY_ID;
 
     /**
      * Main constructor
      * @param parent parent FO node
      */
     PDFDictionaryElement(FONode parent, PDFDictionaryType type) {
-        super(parent);
-        this.extension = new PDFDictionaryExtension(type);
+        super(parent, PDFObjectType.Dictionary, createExtension(type));
+    }
+
+    private static PDFDictionaryExtension createExtension(PDFDictionaryType type) {
+        if (type == PDFDictionaryType.Action) {
+            return new PDFActionExtension();
+        } else if (type == PDFDictionaryType.Catalog) {
+            return new PDFCatalogExtension();
+        } else if (type == PDFDictionaryType.Layer) {
+            return new PDFLayerExtension();
+        } else if (type == PDFDictionaryType.Navigator) {
+            return new PDFNavigatorExtension();
+        } else if (type == PDFDictionaryType.Page) {
+            return new PDFPageExtension();
+        } else {
+            return new PDFDictionaryExtension(type);
+        }
     }
 
-    public PDFDictionaryExtension getExtension() {
-        return extension;
+    public PDFDictionaryExtension getDictionaryExtension() {
+        assert getExtension() instanceof PDFDictionaryExtension;
+        return (PDFDictionaryExtension) getExtension();
     }
 
     @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);
+        PDFDictionaryExtension extension = getDictionaryExtension();
+        if (extension.usesIDAttribute()) {
+            String id = attlist.getValue(ATT_ID);
+            if (id != null) {
+                extension.setProperty(PDFDictionaryExtension.PROPERTY_ID, id);
             }
-        } else if (extension.getDictionaryType() == PDFDictionaryType.Dictionary) {
+        }
+        if (extension.getDictionaryType() == PDFDictionaryType.Dictionary) {
             String key = attlist.getValue(ATT_KEY);
             if (key == null) {
-                missingPropertyError(ATT_KEY);
+                if (parent instanceof PDFDictionaryElement) {
+                    missingPropertyError(ATT_KEY);
+                }
             } else if (key.length() == 0) {
                 invalidPropertyValueError(ATT_KEY, key, null);
             } else {
@@ -78,16 +93,18 @@ public class PDFDictionaryElement extend
     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");
-            }
+        if (localName.equals("action")) {
+            // handled in PDFActionElement subclass
+        } else if (localName.equals("catalog")) {
+            // handled in PDFCatalogElement subclass
+        } else if (localName.equals("layer")) {
+            // handled in PDFLayerElement subclass
+        } else if (localName.equals("navigator")) {
+            // handled in PDFNavigattorElement subclass
         } else if (localName.equals("page")) {
-            if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
-                invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfSPM");
-            }
+            // handled in PDFPageElement subclass
         } else if (localName.equals("dictionary")) {
-            if (!PDFDictionaryType.hasValueOfElementName(parent.getLocalName())) {
+            if (!PDFDictionaryType.hasValueOfElementName(parent.getLocalName()) && !PDFObjectType.Array.elementName().equals(parent.getLocalName())) {
                 invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), null);
             }
         } else {
@@ -97,14 +114,15 @@ public class PDFDictionaryElement extend
 
     @Override
     protected void addChildNode(FONode child) throws FOPException {
+        PDFDictionaryExtension extension = getDictionaryExtension();
         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);
+            PDFDictionaryExtension entry = ((PDFDictionaryElement) child).getDictionaryExtension();
+            if (entry.getDictionaryType() == PDFDictionaryType.Dictionary) {
+                extension.addEntry(entry);
+            }
+        } else if (child instanceof PDFCollectionEntryElement) {
+            PDFCollectionEntryExtension entry = ((PDFCollectionEntryElement) child).getExtension();
+            extension.addEntry(entry);
         }
     }
 
@@ -115,12 +133,13 @@ public class PDFDictionaryElement extend
 
     @Override
     public String getLocalName() {
+        PDFDictionaryExtension extension = getDictionaryExtension();
         return extension.getDictionaryType().elementName();
     }
 
     @Override
     protected ExtensionAttachment instantiateExtensionAttachment() {
-        return new PDFDictionaryAttachment(extension);
+        return new PDFDictionaryAttachment(getDictionaryExtension());
     }
 
 }

Modified: 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=1537948&r1=1537947&r2=1537948&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryExtension.java Fri Nov  1 14:34:18 2013
@@ -24,24 +24,36 @@ import java.util.Map;
 
 // CSOFF: LineLengthCheck
 
-public class PDFDictionaryExtension extends PDFDictionaryEntryExtension {
+public class PDFDictionaryExtension extends PDFCollectionExtension {
 
+    public static final String PROPERTY_ID = "id";
     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;
+    private List<PDFCollectionEntryExtension> entries;
 
     PDFDictionaryExtension() {
+        this(PDFDictionaryType.Dictionary);
     }
 
     PDFDictionaryExtension(PDFDictionaryType dictionaryType) {
-        super(PDFDictionaryEntryType.Dictionary);
+        super(PDFObjectType.Dictionary);
         this.dictionaryType = dictionaryType;
         this.properties = new java.util.HashMap<String, String>();
-        this.entries = new java.util.ArrayList<PDFDictionaryEntryExtension>();
+        this.entries = new java.util.ArrayList<PDFCollectionEntryExtension>();
+    }
+
+    @Override
+    public void setValue(Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getValue() {
+        return getEntries();
     }
 
     public PDFDictionaryType getDictionaryType() {
@@ -56,15 +68,40 @@ public class PDFDictionaryExtension exte
         return properties.get(name);
     }
 
-    public void addEntry(PDFDictionaryEntryExtension entry) {
-        entries.add(entry);
+    @Override
+    public void addEntry(PDFCollectionEntryExtension entry) {
+        if ((entry.getKey() == null) || (entry.getKey().length() == 0)) {
+            throw new IllegalArgumentException();
+        } else {
+            entries.add(entry);
+        }
     }
 
-    public List<PDFDictionaryEntryExtension> getEntries() {
+    public List<PDFCollectionEntryExtension> getEntries() {
         return entries;
     }
 
-    public PDFDictionaryEntryExtension getLastEntry() {
+    public PDFCollectionEntryExtension findEntry(String key) {
+        for (PDFCollectionEntryExtension entry : entries) {
+            String entryKey = entry.getKey();
+            if ((entryKey != null) && entryKey.equals(key)) {
+                return entry;
+            }
+        }
+        return null;
+    }
+
+    public Object findEntryValue(String key) {
+        for (PDFCollectionEntryExtension entry : entries) {
+            String entryKey = entry.getKey();
+            if ((entryKey != null) && entryKey.equals(key)) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+
+    public PDFCollectionEntryExtension getLastEntry() {
         if (entries.size() > 0) {
             return entries.get(entries.size() - 1);
         } else {
@@ -72,48 +109,8 @@ public class PDFDictionaryExtension exte
         }
     }
 
-    /**
-     * 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.length() == 0)) {
-            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;
+    public boolean usesIDAttribute() {
+        return dictionaryType.usesIDAttribute();
     }
 
     @Override

Modified: 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=1537948&r1=1537947&r2=1537948&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFDictionaryType.java Fri Nov  1 14:34:18 2013
@@ -25,17 +25,28 @@ package org.apache.fop.render.pdf.extens
  * 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
+    Action("action", true),             // action dictionary element
+    Catalog("catalog"),                 // catalog dictionary element
+    Dictionary("dictionary"),           // generic (nested) dictionary element
+    Layer("layer", true),               // optional content group dictionary element
+    Navigator("navigator", true),       // navigation node dictionary element
+    Page("page");                       // page dictionary element
 
     private String elementName;
-    PDFDictionaryType(String elementName) {
+    private boolean usesIDAttribute;
+    PDFDictionaryType(String elementName, boolean usesIDAttribute) {
         this.elementName = elementName;
+        this.usesIDAttribute = usesIDAttribute;
+    }
+    PDFDictionaryType(String elementName) {
+        this(elementName, false);
     }
     public String elementName() {
         return elementName;
     }
+    public boolean usesIDAttribute() {
+        return usesIDAttribute;
+    }
     static PDFDictionaryType valueOfElementName(String elementName) {
         for (PDFDictionaryType type : values()) {
             if (type.elementName.equals(elementName)) {

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=1537948&r1=1537947&r2=1537948&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 Nov  1 14:34:18 2013
@@ -41,17 +41,56 @@ public class PDFElementMapping extends E
     protected void initialize() {
         if (foObjs == null) {
             foObjs = new java.util.HashMap<String, Maker>();
+            // pdf:action
+            foObjs.put(PDFDictionaryType.Action.elementName(), new PDFActionElementMaker());
+            // pdf:array
+            foObjs.put(PDFObjectType.Array.elementName(), new PDFArrayElementMaker());
+            // pdf:boolean
+            foObjs.put(PDFObjectType.Boolean.elementName(), new PDFCollectionEntryElementMaker(PDFObjectType.Boolean));
+            // pdf:catalog
+            foObjs.put(PDFDictionaryType.Catalog.elementName(), new PDFCatalogElementMaker());
+            // pdf:dictionary
+            foObjs.put(PDFDictionaryType.Dictionary.elementName(), new PDFDictionaryElementMaker());
             // 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));
-                }
-            }
+            // pdf:name
+            foObjs.put(PDFObjectType.Name.elementName(), new PDFCollectionEntryElementMaker(PDFObjectType.Name));
+            // pdf:number
+            foObjs.put(PDFObjectType.Number.elementName(), new PDFCollectionEntryElementMaker(PDFObjectType.Number));
+            // pdf:navigator
+            foObjs.put(PDFDictionaryType.Navigator.elementName(), new PDFNavigatorElementMaker());
+            // pdf:layer
+            foObjs.put(PDFDictionaryType.Layer.elementName(), new PDFLayerElementMaker());
+            // pdf:page
+            foObjs.put(PDFDictionaryType.Page.elementName(), new PDFPageElementMaker());
+            // pdf:reference
+            foObjs.put(PDFObjectType.Reference.elementName(), new PDFReferenceElementMaker());
+            // pdf:string
+            foObjs.put(PDFObjectType.String.elementName(), new PDFCollectionEntryElementMaker(PDFObjectType.String));
+        }
+    }
+
+    static class PDFActionElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFActionElement(parent);
+        }
+    }
+
+    static class PDFArrayElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFArrayElement(parent);
+        }
+    }
+
+    static class PDFCatalogElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFCatalogElement(parent);
+        }
+    }
+
+    static class PDFDictionaryElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFDictionaryElement(parent, PDFDictionaryType.Dictionary);
         }
     }
 
@@ -61,23 +100,38 @@ public class PDFElementMapping extends E
         }
     }
 
-    static class PDFDictionaryElementMaker extends ElementMapping.Maker {
-        private PDFDictionaryType dictionaryType;
-        PDFDictionaryElementMaker(PDFDictionaryType dictionaryType) {
-            this.dictionaryType = dictionaryType;
+    static class PDFLayerElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFLayerElement(parent);
         }
+    }
+
+    static class PDFNavigatorElementMaker extends ElementMapping.Maker {
         public FONode make(FONode parent) {
-            return new PDFDictionaryElement(parent, dictionaryType);
+            return new PDFNavigatorElement(parent);
         }
     }
 
-    static class PDFDictionaryEntryElementMaker extends ElementMapping.Maker {
-        private PDFDictionaryEntryType entryType;
-        PDFDictionaryEntryElementMaker(PDFDictionaryEntryType entryType) {
+    static class PDFPageElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFPageElement(parent);
+        }
+    }
+
+    static class PDFCollectionEntryElementMaker extends ElementMapping.Maker {
+        private PDFObjectType entryType;
+        PDFCollectionEntryElementMaker(PDFObjectType entryType) {
             this.entryType = entryType;
         }
         public FONode make(FONode parent) {
-            return new PDFDictionaryEntryElement(parent, entryType);
+            return new PDFCollectionEntryElement(parent, entryType);
         }
     }
+
+    static class PDFReferenceElementMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new PDFReferenceElement(parent);
+        }
+    }
+
 }

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=1537948&r1=1537947&r2=1537948&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 Nov  1 14:34:18 2013
@@ -49,7 +49,7 @@ public class PDFExtensionHandler extends
     private Attributes lastAttributes;
 
     // PDFDictionaryAttachment related
-    private Stack<PDFDictionaryExtension> dictionaries = new Stack<PDFDictionaryExtension>();
+    private Stack<PDFCollectionExtension> collections = new Stack<PDFCollectionExtension>();
     private boolean captureContent;
     private StringBuffer characters;
 
@@ -58,29 +58,78 @@ public class PDFExtensionHandler extends
         if (PDFExtensionAttachment.CATEGORY.equals(uri)) {
             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);
+            } else if (PDFDictionaryType.Action.elementName().equals(localName)) {
+                PDFActionExtension action = new PDFActionExtension();
+                String id = attributes.getValue(PDFDictionaryElement.ATT_ID);
+                if (id != null) {
+                    action.setProperty(PDFDictionaryExtension.PROPERTY_ID, id);
+                }
+                String type = attributes.getValue(PDFActionElement.ATT_TYPE);
+                if (type != null) {
+                    action.setProperty(PDFActionExtension.PROPERTY_TYPE, type);
+                }
+                collections.push(action);
+            } else if (PDFObjectType.Array.elementName().equals(localName)) {
+                PDFArrayExtension array = new PDFArrayExtension();
+                String key = attributes.getValue(PDFCollectionEntryElement.ATT_KEY);
+                if (key != null) {
+                    array.setKey(key);
+                }
+                collections.push(array);
+            } else if (PDFDictionaryType.Catalog.elementName().equals(localName)) {
+                PDFCatalogExtension catalog = new PDFCatalogExtension();
+                collections.push(catalog);
+            } else if (PDFDictionaryType.Dictionary.elementName().equals(localName)) {
+                PDFDictionaryExtension dictionary = new PDFDictionaryExtension();
+                String key = attributes.getValue(PDFCollectionEntryElement.ATT_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);
-                    }
+                collections.push(dictionary);
+            } else if (PDFDictionaryType.Layer.elementName().equals(localName)) {
+                PDFLayerExtension layer = new PDFLayerExtension();
+                String id = attributes.getValue(PDFDictionaryElement.ATT_ID);
+                if (id != null) {
+                    layer.setProperty(PDFDictionaryExtension.PROPERTY_ID, id);
+                }
+                collections.push(layer);
+            } else if (PDFDictionaryType.Navigator.elementName().equals(localName)) {
+                PDFNavigatorExtension navigator = new PDFNavigatorExtension();
+                String id = attributes.getValue(PDFDictionaryElement.ATT_ID);
+                if (id != null) {
+                    navigator.setProperty(PDFDictionaryExtension.PROPERTY_ID, id);
+                }
+                collections.push(navigator);
+            } else if (PDFDictionaryType.Page.elementName().equals(localName)) {
+                PDFPageExtension page = new PDFPageExtension();
+                String pageNumbers = attributes.getValue(PDFPageElement.ATT_PAGE_NUMBERS);
+                if (pageNumbers != null) {
+                    page.setProperty(PDFPageExtension.PROPERTY_PAGE_NUMBERS, pageNumbers);
+                }
+                collections.push(page);
+            } else if (PDFObjectType.hasValueOfElementName(localName)) {
+                PDFCollectionEntryExtension entry;
+                if (PDFObjectType.Reference.elementName().equals(localName)) {
+                    entry = new PDFReferenceExtension();
+                } else {
+                    entry = new PDFCollectionEntryExtension(PDFObjectType.valueOfElementName(localName));
                 }
-                dictionaries.push(dictionary);
-            } else if (PDFDictionaryEntryType.hasValueOfElementName(localName)) {
-                PDFDictionaryEntryExtension entry = new PDFDictionaryEntryExtension(PDFDictionaryEntryType.valueOfElementName(localName));
-                String key = attributes.getValue(PDFDictionaryEntryElement.ATT_KEY);
+                String key = attributes.getValue(PDFCollectionEntryElement.ATT_KEY);
                 if (key != null) {
                     entry.setKey(key);
                 }
-                if (!dictionaries.empty()) {
-                    PDFDictionaryExtension dictionary = dictionaries.peek();
-                    dictionary.addEntry(entry);
-                    captureContent = true;
+                if (entry instanceof PDFReferenceExtension) {
+                    String refid = attributes.getValue(PDFReferenceElement.ATT_REFID);
+                    if (refid != null) {
+                        ((PDFReferenceExtension) entry).setReferenceId(refid);
+                    }
+                }
+                if (!collections.empty()) {
+                    PDFCollectionExtension collection = collections.peek();
+                    collection.addEntry(entry);
+                    if (!(entry instanceof PDFReferenceExtension)) {
+                        captureContent = true;
+                    }
                 }
             } else {
                 throw new SAXException("Unhandled element " + localName + " in namespace: " + uri);
@@ -107,33 +156,48 @@ public class PDFExtensionHandler extends
                 String name = lastAttributes.getValue("name");
                 String src = lastAttributes.getValue("src");
                 String desc = lastAttributes.getValue("description");
+                this.lastAttributes = null;
                 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)) {
+                if (!collections.empty() && (collections.peek() instanceof PDFDictionaryExtension)) {
+                    PDFDictionaryExtension dictionary = (PDFDictionaryExtension) collections.pop();
+                    if (!collections.empty()) {
+                        PDFCollectionExtension collectionOuter = collections.peek();
+                        collectionOuter.addEntry(dictionary);
+                    } else if (dictionary.getDictionaryType() != PDFDictionaryType.Dictionary) {
                         this.returnedObject = new PDFDictionaryAttachment(dictionary);
-                    } else if (!dictionaries.empty()) {
-                        PDFDictionaryExtension dictionaryOuter = dictionaries.peek();
-                        dictionaryOuter.addEntry(dictionary);
+                    } else {
+                        throw new SAXException(new IllegalStateException("generic dictionary not permitted at outer level"));
+                    }
+                } else {
+                    throw new SAXException(new IllegalStateException("collections stack is empty or not a dictionary"));
+                }
+            } else if (PDFObjectType.Array.elementName().equals(localName)) {
+                if (!collections.empty() && (collections.peek() instanceof PDFArrayExtension)) {
+                    PDFArrayExtension array = (PDFArrayExtension) collections.pop();
+                    if (!collections.empty()) {
+                        PDFCollectionExtension collectionOuter = collections.peek();
+                        collectionOuter.addEntry(array);
+                    } else {
+                        throw new SAXException(new IllegalStateException("array not permitted at outer level"));
                     }
                 } else {
-                    throw new SAXException(new IllegalStateException("no active dictionary"));
+                    throw new SAXException(new IllegalStateException("collections stack is empty or not an array"));
                 }
-            } else if (PDFDictionaryEntryType.hasValueOfElementName(localName)) {
-                if (!dictionaries.empty()) {
-                    PDFDictionaryExtension dictionary = dictionaries.peek();
-                    PDFDictionaryEntryExtension entry = dictionary.getLastEntry();
+            } else if (PDFObjectType.hasValueOfElementName(localName)) {
+                if (!collections.empty()) {
+                    PDFCollectionExtension collection = collections.peek();
+                    PDFCollectionEntryExtension entry = collection.getLastEntry();
                     if (entry != null) {
                         if (characters != null) {
                             entry.setValue(characters.toString());
                             characters = null;
                         }
                     } else {
-                        throw new SAXException(new IllegalStateException("no active entry"));
+                        throw new SAXException(new IllegalStateException("no current entry"));
                     }
                 } else {
-                    throw new SAXException(new IllegalStateException("no active dictionary"));
+                    throw new SAXException(new IllegalStateException("entry not permitted at outer level"));
                 }
             }
         }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerElement.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerElement.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,45 @@
+/*
+ * 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.apps.FOPException;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Extension element for pdf:layer.
+ */
+public class PDFLayerElement extends PDFDictionaryElement {
+
+    PDFLayerElement(FONode parent) {
+        super(parent, PDFDictionaryType.Layer);
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+        if (parent.getNameId() != Constants.FO_DECLARATIONS) {
+            invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfDeclarations");
+        }
+    }
+
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerExtension.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerExtension.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerExtension.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFLayerExtension.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,29 @@
+/*
+ * 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
+
+public class PDFLayerExtension extends PDFDictionaryExtension {
+
+    PDFLayerExtension() {
+        super(PDFDictionaryType.Layer);
+    }
+}

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

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFNavigatorElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFNavigatorElement.java?rev=1537948&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFNavigatorElement.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/extensions/PDFNavigatorElement.java Fri Nov  1 14:34:18 2013
@@ -0,0 +1,45 @@
+/*
+ * 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.apps.FOPException;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+
+// CSOFF: LineLengthCheck
+
+/**
+ * Extension element for pdf:navigator.
+ */
+public class PDFNavigatorElement extends PDFDictionaryElement {
+
+    PDFNavigatorElement(FONode parent) {
+        super(parent, PDFDictionaryType.Navigator);
+    }
+
+    @Override
+    public void startOfNode() throws FOPException {
+        super.startOfNode();
+        if (parent.getNameId() != Constants.FO_DECLARATIONS) {
+            invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(), "rule.childOfDeclarations");
+        }
+    }
+
+}

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



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


Mime
View raw message