Index: src/java/META-INF/services/org.apache.fop.fo.ElementMapping =================================================================== --- src/java/META-INF/services/org.apache.fop.fo.ElementMapping (revision 676141) +++ src/java/META-INF/services/org.apache.fop.fo.ElementMapping (working copy) @@ -1,4 +1,5 @@ org.apache.fop.fo.FOElementMapping +org.apache.fop.fo.extensions.pdf.PDFExtensionElementMapping org.apache.fop.fo.extensions.svg.SVGElementMapping org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping org.apache.fop.fo.extensions.ExtensionElementMapping Index: src/java/org/apache/fop/fo/extensions/pdf/AbstractPDFExtension.java =================================================================== --- src/java/org/apache/fop/fo/extensions/pdf/AbstractPDFExtension.java (revision 0) +++ src/java/org/apache/fop/fo/extensions/pdf/AbstractPDFExtension.java (revision 0) @@ -0,0 +1,57 @@ +/* + * 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.fo.extensions.pdf; + +import org.apache.fop.fo.extensions.ExtensionObj; +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.fo.FONode; + +public abstract class AbstractPDFExtension extends ExtensionObj { + + /** + * Create a new AbstractPDFExtension that is a child of the given + * {@link FONode} + * + * @param parent the parent {@link FONode} + */ + public AbstractPDFExtension(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + public ExtensionAttachment getExtensionAttachment() { + return new PDFExtensionAttachment(this); + } + + /** + * {@inheritDoc} + * @return {@link PDFExtensionElementMapping#URI} + */ + public String getNamespaceURI() { + return PDFExtensionElementMapping.URI; + } + + /** + * {@inheritDoc} + * @return {@link PDFExtensionElementMapping#PREFIX} + */ + public String getNormalNamespacePrefix() { + return PDFExtensionElementMapping.PREFIX; + } + +} Property changes on: src/java/org/apache/fop/fo/extensions/pdf/AbstractPDFExtension.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/fop/fo/extensions/pdf/PDFDictionaryExtension.java =================================================================== --- src/java/org/apache/fop/fo/extensions/pdf/PDFDictionaryExtension.java (revision 0) +++ src/java/org/apache/fop/fo/extensions/pdf/PDFDictionaryExtension.java (revision 0) @@ -0,0 +1,127 @@ +/* + * 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.fo.extensions.pdf; + +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.extensions.ExtensionObj; +import org.apache.fop.apps.FOPException; +import org.apache.xmlgraphics.util.QName; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; + +import java.nio.CharBuffer; +import java.util.ListIterator; + +/** + * Class modelling the pdf:dictionary extension object. + * + * This extension, in co-operation with {@link PDFEntryExtension} allows + * the user to build dictionaries that will be injected into the + * PDF document. + * If the type is specified as "catalog", the entries will be added to + * the document catalog. + */ +public class PDFDictionaryExtension extends AbstractPDFExtension { + + public static final int TYPE_CATALOG = 0; + public static final int TYPE_NORMAL = 1; + + static final String[] TYPES = { "catalog", "normal" }; + + private int type; + private String name; + + /** + * Create a new PDFDictionaryExtension instance that is + * a child of the given {@link FONode}. + * + * @param parent the parent {@link FONode} + */ + public PDFDictionaryExtension(FONode parent) { + super(parent); + } + + private static int getType(String typeString) { + for (int i = TYPES.length; --i >= 0;) { + if (TYPES[i].equals(typeString)) { + return i; + } + } + assert false; + return -1; + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + String dictType = attlist.getValue("type"); + if (dictType == null || "".equals(dictType)) { + //assume "normal" if absent + dictType = TYPES[TYPE_NORMAL]; + } + this.type = getType(dictType); + this.name = attlist.getValue("name"); + } + + /** {@inheritDoc} */ + protected void validateChildNode(Locator loc, String namespaceURI, String localName) throws ValidationException { + if (PDFExtensionElementMapping.URI.equals(namespaceURI)) { + if ("entry".equals(localName) || "dictionary".equals(localName)) { + return; //no problem + } + } + //TODO: Replace by extension-specific event (?) + this.invalidChildError(loc, namespaceURI, localName); + } + + /** + * Return an int identifying the type of PDF dictionary. + * + * @return one of {@link #TYPE_CATALOG}, or {@link #TYPE_NORMAL} + */ + public int getType() { + return this.type; + } + + /** + * Return a java.lang.String naming the type of PDF dictionary. + * + * @return one of "catalog" or "normal" + */ + public String getTypeName() { + return TYPES[this.type]; + } + + /** + * Return the name of this dictionary + * + * @return the name of the dictionary + */ + public String getName() { + return this.name; + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "dictionary"; + } + +} Index: src/java/org/apache/fop/fo/extensions/pdf/PDFEntryExtension.java =================================================================== --- src/java/org/apache/fop/fo/extensions/pdf/PDFEntryExtension.java (revision 0) +++ src/java/org/apache/fop/fo/extensions/pdf/PDFEntryExtension.java (revision 0) @@ -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.fo.extensions.pdf; + +import org.apache.fop.fo.FONode; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.fo.ValidationException; +import org.apache.fop.apps.FOPException; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; + +import java.nio.CharBuffer; + +/** + * Class modelling the pdf:entry extension object. + * This extension can be used to create PDF entries in a + * pdf:dictionary object. + * The object is mapped virtually one-on-one to PDF. + *

+ * <pdf:entry name="PageMode">FullScreen</pdf:entry> + *

+ * will result in "/PageMode FullScreen" being added as an entry + * to the dictionary. + */ +public class PDFEntryExtension extends AbstractPDFExtension { + + private String entryName; + private CharBuffer entryValue; + + /** + * Construct a new PDFEntryExtension instance that is a child + * of the given {@link org.apache.fop.fo.FONode} + * + * @param parent the parent {@link org.apache.fop.fo.FONode} + */ + public PDFEntryExtension(FONode parent) { + super(parent); + } + + /** {@inheritDoc} */ + protected void validateChildNode(Locator loc, String namespaceURI, String localName) throws ValidationException { + //TODO: Replace by extension-specific event (?) + this.invalidChildError(loc, namespaceURI, localName); + } + + /** {@inheritDoc} */ + public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList) throws FOPException { + this.entryName = attlist.getValue("name"); + if (this.entryName == null || "".equals(this.entryName)) { + this.missingPropertyError("name"); + } + super.processNode(elementName, locator, attlist, pList); + } + + /** {@inheritDoc} */ + protected void addCharacters(char[] data, int start, int length, PropertyList pList, Locator locator) throws FOPException { + if (this.entryValue == null) { + this.entryValue = CharBuffer.allocate(length); + } else { + CharBuffer newExpr = CharBuffer.allocate( + this.entryValue.length() + length); + this.entryValue.position(0); + newExpr.put(this.entryValue); + this.entryValue = newExpr; + } + this.entryValue.put(data, start, length); + } + + /** + * Return the name of the PDF entry. + * + * @return the name of the entry + */ + public String getEntryName() { + return this.entryName; + } + + /** + * Return the value of the PDF entry (= the #PCDATA + * content of the node in the source document) + * + * @return the value of the entry + */ + public String getEntryValue() { + this.entryValue.rewind(); + return this.entryValue.toString(); + } + + /** {@inheritDoc} */ + public String getLocalName() { + return "entry"; + } + +} Property changes on: src/java/org/apache/fop/fo/extensions/pdf/PDFEntryExtension.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionAttachment.java =================================================================== --- src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionAttachment.java (revision 0) +++ src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionAttachment.java (revision 0) @@ -0,0 +1,47 @@ +/* + * 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.fo.extensions.pdf; + +import org.apache.fop.fo.extensions.ExtensionAttachment; + +import java.io.Serializable; + +public class PDFExtensionAttachment implements ExtensionAttachment, Serializable { + + private AbstractPDFExtension ext; + + public PDFExtensionAttachment() { + //nop + } + + public PDFExtensionAttachment(AbstractPDFExtension ext) { + this.ext = ext; + } + + public AbstractPDFExtension getExtensionObject() { + return this.ext; + } + + /** + * {@inheritDoc} + * @return {@link PDFExtensionElementMapping#URI} + */ + public String getCategory() { + return PDFExtensionElementMapping.URI; + } +} Property changes on: src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionAttachment.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionElementMapping.java =================================================================== --- src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionElementMapping.java (revision 0) +++ src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionElementMapping.java (revision 0) @@ -0,0 +1,70 @@ +/* + * 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.fo.extensions.pdf; + +import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.fo.ElementMapping; +import org.apache.fop.fo.FONode; + +import java.util.HashMap; + +public class PDFExtensionElementMapping extends ExtensionElementMapping { + + /** The FOP PDF extension namespace URI */ + public static final String URI = "http://xmlgraphics.apache.org/fop/extensions/pdf"; + + /** The standard namespace prefix */ + public static final String PREFIX = "pdf"; + /** + * Constructor. + */ + public PDFExtensionElementMapping() { + namespaceURI = URI; + } + + /** + * Initialize the data structures. + */ + protected void initialize() { + if (foObjs == null) { + foObjs = new HashMap(); + foObjs.put("dictionary", new PDFDictionaryExtensionMaker()); + foObjs.put("entry", new PDFEntryExtensionMaker()); + } + } + + /** Inner class for making instances of {@link PDFDictionaryExtension} */ + static class PDFDictionaryExtensionMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new PDFDictionaryExtension(parent); + } + } + + /** Inner class for making instances of {@link PDFEntryExtension} */ + static class PDFEntryExtensionMaker extends ElementMapping.Maker { + public FONode make(FONode parent) { + return new PDFEntryExtension(parent); + } + } + + /** {@inheritDoc} */ + public String getStandardPrefix() { + return PREFIX; + } + +} Property changes on: src/java/org/apache/fop/fo/extensions/pdf/PDFExtensionElementMapping.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/fop/render/pdf/PDFRenderer.java =================================================================== --- src/java/org/apache/fop/render/pdf/PDFRenderer.java (revision 676141) +++ src/java/org/apache/fop/render/pdf/PDFRenderer.java (working copy) @@ -76,6 +76,11 @@ import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.fo.extensions.pdf.AbstractPDFExtension; +import org.apache.fop.fo.extensions.pdf.PDFDictionaryExtension; +import org.apache.fop.fo.extensions.pdf.PDFEntryExtension; +import org.apache.fop.fo.extensions.pdf.PDFExtensionAttachment; +import org.apache.fop.fo.extensions.pdf.PDFExtensionElementMapping; import org.apache.fop.fo.extensions.xmp.XMPMetadata; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.LazyFont; @@ -98,6 +103,7 @@ import org.apache.fop.pdf.PDFInfo; import org.apache.fop.pdf.PDFLink; import org.apache.fop.pdf.PDFMetadata; +import org.apache.fop.pdf.PDFName; import org.apache.fop.pdf.PDFNumber; import org.apache.fop.pdf.PDFNumsArray; import org.apache.fop.pdf.PDFOutline; @@ -548,6 +554,9 @@ if (XMPMetadata.CATEGORY.equals(attachment.getCategory())) { renderXMPMetadata((XMPMetadata)attachment); } + if (PDFExtensionElementMapping.URI.equals(attachment.getCategory())) { + renderPDFExtension((PDFExtensionAttachment)attachment); + } } } @@ -621,6 +630,29 @@ pdfDoc.getRoot().setMetadata(pdfMetadata); } + private void renderPDFExtension(PDFExtensionAttachment ext) { + AbstractPDFExtension extNode = ext.getExtensionObject(); + if (extNode instanceof PDFDictionaryExtension) { + PDFDictionaryExtension dict = (PDFDictionaryExtension)extNode; + if (dict.getType() == PDFDictionaryExtension.TYPE_CATALOG) { + //add the entries/subdictionaries to pdfDoc.getRoot() + AbstractPDFExtension entry; + PDFExtensionAttachment att; + for (Iterator entryIter = dict.getExtensionAttachments().iterator(); entryIter.hasNext();) { + att = (PDFExtensionAttachment)entryIter.next(); + entry = att.getExtensionObject(); + if (entry instanceof PDFEntryExtension) { + pdfDoc.getRoot().put( + ((PDFEntryExtension)entry).getEntryName(), + new PDFName(((PDFEntryExtension)entry).getEntryValue())); + } + } + } else { + //TODO?? + } + } + } + /** {@inheritDoc} */ public Graphics2DAdapter getGraphics2DAdapter() { return new PDFGraphics2DAdapter(this);