diff options
11 files changed, 564 insertions, 8 deletions
diff --git a/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory b/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory new file mode 100644 index 000000000..d7533c599 --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.util.ContentHandlerFactory @@ -0,0 +1 @@ +org.apache.fop.render.ps.extensions.PSExtensionHandlerFactory
\ No newline at end of file diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 32e2bce1e..ad1017505 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -51,11 +51,14 @@ import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; import org.apache.fop.fo.ElementMappingRegistry; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.image.FopImage; import org.apache.fop.image.ImageFactory; import org.apache.fop.traits.BorderProps; +import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.ContentHandlerFactoryRegistry; import org.apache.fop.util.DefaultErrorListener; import org.w3c.dom.DOMImplementation; @@ -182,6 +185,7 @@ public class AreaTreeParser { delegateStack.push(qName); delegate.startElement(uri, localName, qName, attributes); } else if (domImplementation != null) { + //domImplementation is set so we need to start a new DOM building sub-process TransformerHandler handler; try { handler = tFactory.newTransformerHandler(); @@ -196,6 +200,7 @@ public class AreaTreeParser { ((ForeignObject)parent).setDocument(doc); //activate delegate for nested foreign document + domImplementation = null; //Not needed anymore now this.delegate = handler; delegateStack.push(qName); delegate.startDocument(); @@ -405,15 +410,31 @@ public class AreaTreeParser { setTraits(attributes, foreign); getCurrentViewport().setContent(foreign); areaStack.push(foreign); + } else if ("extension-attachments".equals(localName)) { + //TODO implement me } else { handled = false; } } else { - handled = false; + ContentHandlerFactory factory + = ContentHandlerFactoryRegistry.getInstance().getFactory(uri); + if (factory != null) { + delegate = factory.createContentHandler(); + delegateStack.push(qName); + delegate.startDocument(); + delegate.startElement(uri, localName, qName, attributes); + } else { + handled = false; + } } if (!handled) { - throw new SAXException("Unhandled element " + localName - + " in namespace: " + uri); + if (uri == null || uri.length() == 0) { + throw new SAXException("Unhandled element " + localName + + " in namespace: " + uri); + } else { + log.warn("Unhandled element " + localName + + " in namespace: " + uri); + } } } } @@ -438,6 +459,25 @@ public class AreaTreeParser { } } + /** + * Handles objects created by "sub-parsers" that implement the ObjectSource interface. + * An example of object handled here are ExtensionAttachments. + * @param obj the Object to be handled. + */ + protected void handleExternallyGeneratedObject(Object obj) { + if (areaStack.size() == 0 && obj instanceof ExtensionAttachment) { + ExtensionAttachment attachment = (ExtensionAttachment)obj; + if (this.currentPageViewport == null) { + this.treeModel.handleOffDocumentItem( + new OffDocumentExtensionAttachment(attachment)); + } else { + this.currentPageViewport.addExtensionAttachment(attachment); + } + } else { + log.warn("Don't know how to handle externally generated object: " + obj); + } + } + /** @see org.xml.sax.helpers.DefaultHandler */ public void endElement(String uri, String localName, String qName) throws SAXException { if (delegate != null) { @@ -445,8 +485,11 @@ public class AreaTreeParser { delegateStack.pop(); if (delegateStack.size() == 0) { delegate.endDocument(); - delegate = null; - domImplementation = null; + if (delegate instanceof ContentHandlerFactory.ObjectSource) { + Object obj = ((ContentHandlerFactory.ObjectSource)delegate).getObject(); + handleExternallyGeneratedObject(obj); + } + delegate = null; //Sub-document is processed, return to normal processing } } else { if ("".equals(uri)) { diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index b516b3446..fedc4284f 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -32,6 +32,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fo.pagination.SimplePageMaster; /** @@ -492,6 +493,17 @@ public class PageViewport implements Resolvable, Cloneable { return this.simplePageMasterName; } + /** + * Adds a new ExtensionAttachment instance to this page. + * @param attachment the ExtensionAttachment + */ + public void addExtensionAttachment(ExtensionAttachment attachment) { + if (this.extensionAttachments == null) { + this.extensionAttachments = new java.util.ArrayList(); + } + extensionAttachments.add(attachment); + } + /** @return the list of extension attachments for this page */ public List getExtensionAttachments() { return this.extensionAttachments; diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java new file mode 100644 index 000000000..e22951236 --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandler.java @@ -0,0 +1,88 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.area.AreaTreeParser; +import org.apache.fop.util.ContentHandlerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * ContentHandler (parser) for restoring PSExtension objects from XML. + */ +public class PSExtensionHandler extends DefaultHandler + implements ContentHandlerFactory.ObjectSource { + + /** Logger instance */ + protected static Log log = LogFactory.getLog(PSExtensionHandler.class); + + private StringBuffer content = new StringBuffer(); + private Attributes lastAttributes; + + private PSSetupCode returnedObject; + + /** @see org.xml.sax.helpers.DefaultHandler */ + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + boolean handled = false; + if (PSSetupCode.CATEGORY.equals(uri)) { + lastAttributes = attributes; + handled = true; + if ("ps-setup-code".equals(localName)) { + //handled in endElement + } else { + handled = false; + } + } + if (!handled) { + if (PSSetupCode.CATEGORY.equals(uri)) { + throw new SAXException("Unhandled element " + localName + + " in namespace: " + uri); + } else { + log.warn("Unhandled element " + localName + + " in namespace: " + uri); + } + } + } + + /** @see org.xml.sax.helpers.DefaultHandler */ + public void endElement(String uri, String localName, String qName) throws SAXException { + if (PSSetupCode.CATEGORY.equals(uri)) { + if ("ps-setup-code".equals(localName)) { + String name = lastAttributes.getValue("name"); + this.returnedObject = new PSSetupCode(name, content.toString()); + } + } + content.setLength(0); //Reset text buffer (see characters()) + } + + /** @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) */ + public void characters(char[] ch, int start, int length) throws SAXException { + content.append(ch, start, length); + } + + /** @see org.apache.fop.area.AreaTreeParser.ObjectSource#getObject() */ + public Object getObject() { + return returnedObject; + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java new file mode 100644 index 000000000..e2b85adbf --- /dev/null +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionHandlerFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.ps.extensions; + +import org.apache.fop.util.ContentHandlerFactory; +import org.xml.sax.ContentHandler; + +/** + * Factory for the ContentHandler that handles serialized PSSetupCode instances. + */ +public class PSExtensionHandlerFactory implements ContentHandlerFactory { + + private static final String[] NAMESPACES = new String[] {PSSetupCode.CATEGORY}; + + /** @see org.apache.fop.util.ContentHandlerFactory#getSupportedNamespaces() */ + public String[] getSupportedNamespaces() { + return NAMESPACES; + } + + /** @see org.apache.fop.util.ContentHandlerFactory#createContentHandler() */ + public ContentHandler createContentHandler() { + return new PSExtensionHandler(); + } + +} diff --git a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java index 846946f99..49cb22979 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSSetupCode.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 The Apache Software Foundation. + * Copyright 2005-2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,11 +21,15 @@ package org.apache.fop.render.ps.extensions; import java.io.Serializable; import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.fop.util.XMLizable; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; /** * This is the pass-through value object for the PostScript extension. */ -public class PSSetupCode implements ExtensionAttachment, Serializable { +public class PSSetupCode implements ExtensionAttachment, Serializable, XMLizable { /** The category URI for this extension attachment. */ public static final String CATEGORY = "apache:fop:extensions:postscript"; @@ -81,9 +85,26 @@ public class PSSetupCode implements ExtensionAttachment, Serializable { return CATEGORY; } - /** @see java.lang.Object#toString() */ public String toString() { return "PSSetupCode(name=" + getName() + ")"; } + + private static final String ATT_NAME = "name"; + private static final String ELEMENT = "ps-setup-code"; + + /** @see org.apache.fop.util.XMLizable#toSAX(org.xml.sax.ContentHandler) */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + if (name != null && name.length() > 0) { + atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); + } + handler.startElement(CATEGORY, ELEMENT, ELEMENT, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, ELEMENT, ELEMENT); + } + } diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 1b9afc566..982d138bc 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -43,6 +43,7 @@ import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.XMLHandler; +import org.apache.fop.util.XMLizable; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.MimeConstants; @@ -56,6 +57,8 @@ import org.apache.fop.area.NormalFlow; import org.apache.fop.area.Footnote; import org.apache.fop.area.LineArea; import org.apache.fop.area.MainReference; +import org.apache.fop.area.OffDocumentExtensionAttachment; +import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; import org.apache.fop.area.RegionViewport; @@ -75,6 +78,7 @@ import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.WordArea; import org.apache.fop.fo.Constants; +import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; @@ -114,6 +118,9 @@ public class XMLRenderer extends PrintRenderer { /** The OutputStream to write the generated XML to. */ protected OutputStream out; + + /** A list of ExtensionAttachements received through processOffDocumentItem() */ + protected List extensionAttachments; /** * Creates a new XML renderer. @@ -357,6 +364,28 @@ public class XMLRenderer extends PrintRenderer { + (int) rect.getWidth() + " " + (int) rect.getHeight(); } + private void handleDocumentExtensionAttachments() { + if (extensionAttachments != null && extensionAttachments.size() > 0) { + handleExtensionAttachments(extensionAttachments); + extensionAttachments.clear(); + } + } + + /** @see org.apache.fop.render.AbstractRenderer#processOffDocumentItem() */ + public void processOffDocumentItem(OffDocumentItem oDI) { + if (oDI instanceof OffDocumentExtensionAttachment) { + ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment(); + if (extensionAttachments == null) { + extensionAttachments = new java.util.ArrayList(); + } + extensionAttachments.add(attachment); + } else { + String warn = "Ignoring OffDocumentItem: " + oDI; + comment("WARNING: " + warn); + log.warn(warn); + } + } + /** * @see org.apache.fop.render.Renderer#startRenderer(OutputStream) */ @@ -416,15 +445,45 @@ public class XMLRenderer extends PrintRenderer { addAttribute("nr", page.getPageNumberString()); startElement("pageViewport", atts); startElement("page"); + + handlePageExtensionAttachments(page); super.renderPage(page); + endElement("page"); endElement("pageViewport"); } + private void handleExtensionAttachments(List attachments) { + if (attachments != null && attachments.size() > 0) { + startElement("extension-attachments"); + Iterator i = attachments.iterator(); + while (i.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment)i.next(); + if (attachment instanceof XMLizable) { + try { + ((XMLizable)attachment).toSAX(this.handler); + } catch (SAXException e) { + log.error("Error while serializing Extension Attachment", e); + } + } else { + String warn = "Ignoring non-XMLizable ExtensionAttachment: " + attachment; + comment("WARNING: " + warn); + log.warn(warn); + } + } + endElement("extension-attachments"); + } + } + + private void handlePageExtensionAttachments(PageViewport page) { + handleExtensionAttachments(page.getExtensionAttachments()); + } + /** * @see org.apache.fop.render.Renderer#startPageSequence(LineArea) */ public void startPageSequence(LineArea seqTitle) { + handleDocumentExtensionAttachments(); if (startedSequence) { endElement("pageSequence"); } diff --git a/src/java/org/apache/fop/util/ContentHandlerFactory.java b/src/java/org/apache/fop/util/ContentHandlerFactory.java new file mode 100644 index 000000000..da615cc54 --- /dev/null +++ b/src/java/org/apache/fop/util/ContentHandlerFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.util; + +import org.xml.sax.ContentHandler; + +/** + * Factory interface implemented by classes that can instantiate ContentHandler subclasses which + * parse a SAX stream into Java objects. + */ +public interface ContentHandlerFactory { + + /** + * @return an array of supported namespaces. + */ + String[] getSupportedNamespaces(); + + /** + * @return a new ContentHandler to handle a SAX stream + */ + ContentHandler createContentHandler(); + + /** + * Interface that ContentHandler implementations that parse Java objects from XML can implement + * to return these objects. + */ + public interface ObjectSource { + + /** + * @return the object parsed from the SAX stream (call valid after parsing) + */ + Object getObject(); + + } + +} diff --git a/src/java/org/apache/fop/util/ContentHandlerFactoryRegistry.java b/src/java/org/apache/fop/util/ContentHandlerFactoryRegistry.java new file mode 100644 index 000000000..68e215b45 --- /dev/null +++ b/src/java/org/apache/fop/util/ContentHandlerFactoryRegistry.java @@ -0,0 +1,129 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.util; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.util.Service; + +/** + * This class holds references to various XML handlers used by FOP. It also + * supports automatic discovery of additional XML handlers available through + * the class path. + */ +public class ContentHandlerFactoryRegistry { + + /** the logger */ + private static Log log = LogFactory.getLog(ContentHandlerFactoryRegistry.class); + + private static ContentHandlerFactoryRegistry instance; + + /** Map from namespace URIs to ContentHandlerFactories */ + private Map factories = new java.util.HashMap(); + + /** + * @return a singleton instance of the ContentHandlerFactoryRegistry. + */ + public static ContentHandlerFactoryRegistry getInstance() { + if (instance == null) { + instance = new ContentHandlerFactoryRegistry(); + } + return instance; + } + + /** + * Default constructor. + */ + public ContentHandlerFactoryRegistry() { + discover(); + } + + /** + * Add an XML handler. The handler itself is inspected to find out what it supports. + * @param classname the fully qualified class name + */ + public void addContentHandlerFactory(String classname) { + try { + ContentHandlerFactory factory + = (ContentHandlerFactory)Class.forName(classname).newInstance(); + addContentHandlerFactory(factory); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + + classname); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Could not instantiate " + + classname); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Could not access " + + classname); + } catch (ClassCastException e) { + throw new IllegalArgumentException(classname + + " is not an " + + ContentHandlerFactory.class.getName()); + } + } + + /** + * Add an ContentHandlerFactory. The instance is inspected to find out what it supports. + * @param factory the ContentHandlerFactory instance + */ + public void addContentHandlerFactory(ContentHandlerFactory factory) { + String[] ns = factory.getSupportedNamespaces(); + for (int i = 0; i < ns.length; i++) { + factories.put(ns[i], factory); + } + } + + /** + * Retrieves a ContentHandlerFactory instance of a given namespace URI. + * @param namespaceURI the namespace to be handled. + * @return the ContentHandlerFactory or null, if no suitable instance is available. + */ + public ContentHandlerFactory getFactory(String namespaceURI) { + ContentHandlerFactory factory = (ContentHandlerFactory)factories.get(namespaceURI); + return factory; + } + + /** + * Discovers ContentHandlerFactory implementations through the classpath and dynamically + * registers them. + */ + private void discover() { + // add mappings from available services + Iterator providers = Service.providers(ContentHandlerFactory.class); + if (providers != null) { + while (providers.hasNext()) { + String str = (String)providers.next(); + try { + if (log.isDebugEnabled()) { + log.debug("Dynamically adding ContentHandlerFactory: " + str); + } + addContentHandlerFactory(str); + } catch (IllegalArgumentException e) { + log.error("Error while adding ContentHandlerFactory", e); + } + + } + } + } +} diff --git a/src/java/org/apache/fop/util/XMLizable.java b/src/java/org/apache/fop/util/XMLizable.java new file mode 100644 index 000000000..ea02963ef --- /dev/null +++ b/src/java/org/apache/fop/util/XMLizable.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2004 The Apache Software Foundation. + * + * Licensed 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.util; + +/* + * Copied from Apache Excalibur: + * https://svn.apache.org/repos/asf/excalibur/trunk/components/xmlutil/ + * src/java/org/apache/excalibur/xml/sax/XMLizable.java + */ + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * This interface can be implemented by classes willing to provide an XML representation + * of their current state as SAX events. + */ +public interface XMLizable { + + /** + * Generates SAX events representing the object's state. + * @param handler ContentHandler instance to send the SAX events to + * @throws SAXException if there's a problem generating the SAX events + */ + void toSAX(ContentHandler handler) throws SAXException; + +} diff --git a/test/layoutengine/standard-testcases/ps-extension_1.xml b/test/layoutengine/standard-testcases/ps-extension_1.xml new file mode 100644 index 000000000..beadbef00 --- /dev/null +++ b/test/layoutengine/standard-testcases/ps-extension_1.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2006 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- $Id$ --> +<testcase> + <info> + <p> + This test checks the PostScript extension for custom setup code. The extension attachments need to show + up in the area tree XML so the AreaTreeParser can fully restore the area tree. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ps="http://xmlgraphics.apache.org/fop/postscript"> + <fo:layout-master-set> + <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in"> + <fo:region-body/> + <ps:ps-page-setup-code name="media-dict">%FOPTestPSPageSetupCode: MediaDict!</ps:ps-page-setup-code> + <ps:ps-page-setup-code name="bla">%FOPTestPSPageSetupCode: Blah blah!</ps:ps-page-setup-code> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:declarations> + <ps:ps-setup-code>%FOPTestPSSetupCode: General setup code here!</ps:ps-setup-code> + <ps:ps-setup-code name="multi-line"> +%FOPTestPSSetupCode: Line 1 +%FOPTestPSSetupCode: Line 2 + </ps:ps-setup-code> + </fo:declarations> + <fo:page-sequence master-reference="normal"> + <fo:flow flow-name="xsl-region-body"> + <fo:block>Text on page <fo:page-number/>.</fo:block> + <fo:block break-before="page">Text on page <fo:page-number/>.</fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="2" xpath="count(/areaTree/extension-attachments/child::*)"/> + <eval expected="%FOPTestPSSetupCode: General setup code here!" xpath="/areaTree/extension-attachments/child::*[1]"/> + <true xpath="contains(/areaTree/extension-attachments/child::*[2], '%FOPTestPSSetupCode: Line 1')"/> + <eval expected="multi-line" xpath="/areaTree/extension-attachments/child::*[2]/@name"/> + + <eval expected="2" xpath="count(/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*)"/> + <eval expected="media-dict" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[1]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: MediaDict!" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[1]"/> + <eval expected="bla" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[2]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: Blah blah!" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[2]"/> + + <eval expected="2" xpath="count(/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*)"/> + <eval expected="media-dict" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[1]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: MediaDict!" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[1]"/> + <eval expected="bla" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[2]/@name"/> + <eval expected="%FOPTestPSPageSetupCode: Blah blah!" xpath="/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*[2]"/> + </checks> +</testcase> |