diff options
-rw-r--r-- | build.xml | 2 | ||||
-rw-r--r-- | src/java/org/apache/fop/events/LoggingEventListener.java | 12 | ||||
-rw-r--r-- | src/java/org/apache/fop/image/loader/batik/GenericFOPBridgeContext.java | 111 | ||||
-rw-r--r-- | src/java/org/apache/fop/image/loader/batik/GenericFOPImageElementBridge.java | 46 | ||||
-rw-r--r-- | src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java | 26 | ||||
-rw-r--r-- | status.xml | 2 | ||||
-rw-r--r-- | test/java/org/apache/fop/threading/AvalonAdapter.java | 58 | ||||
-rw-r--r-- | test/java/org/apache/fop/threading/FOPTestbed.java | 28 | ||||
-rw-r--r-- | test/java/org/apache/fop/threading/FOProcessorImpl.java | 37 | ||||
-rw-r--r-- | test/java/org/apache/fop/threading/IFProcessorImpl.java | 124 | ||||
-rw-r--r-- | test/java/org/apache/fop/threading/Processor.java (renamed from test/java/org/apache/fop/threading/FOProcessor.java) | 4 | ||||
-rw-r--r-- | test/java/org/apache/fop/threading/sample.cfg.xml | 4 |
12 files changed, 399 insertions, 55 deletions
@@ -144,7 +144,7 @@ list of possible build targets. <property name="Name" value="Apache FOP"/> <property name="name" value="fop"/> <property name="NAME" value="FOP"/> - <property name="version" value="1.0"/> + <property name="version" value="svn-trunk"/> <property name="year" value="1999-2010"/> <property name="javac.debug" value="on"/> <property name="javac.optimize" value="off"/> diff --git a/src/java/org/apache/fop/events/LoggingEventListener.java b/src/java/org/apache/fop/events/LoggingEventListener.java index 03467303e..58fbb7f97 100644 --- a/src/java/org/apache/fop/events/LoggingEventListener.java +++ b/src/java/org/apache/fop/events/LoggingEventListener.java @@ -79,10 +79,18 @@ public class LoggingEventListener implements EventListener { } else if (severity == EventSeverity.WARN) { log.warn(msg); } else if (severity == EventSeverity.ERROR) { - log.error(msg); + if (event.getParam("e") != null) { + log.error(msg, (Throwable)event.getParam("e")); + } else { + log.error(msg); + } } else if (severity == EventSeverity.FATAL) { if (!skipFatal) { - log.fatal(msg); + if (event.getParam("e") != null) { + log.fatal(msg, (Throwable)event.getParam("e")); + } else { + log.fatal(msg); + } } } else { assert false; diff --git a/src/java/org/apache/fop/image/loader/batik/GenericFOPBridgeContext.java b/src/java/org/apache/fop/image/loader/batik/GenericFOPBridgeContext.java new file mode 100644 index 000000000..b1808a7b9 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/GenericFOPBridgeContext.java @@ -0,0 +1,111 @@ +/* + * 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.image.loader.batik; + +import java.awt.geom.AffineTransform; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.DocumentLoader; +import org.apache.batik.bridge.UserAgent; +import org.apache.batik.dom.svg.SVGOMDocument; + +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.svg.AbstractFOPBridgeContext; +import org.apache.fop.svg.SVGUserAgent; + +/** + * BridgeContext which registers the custom bridges for Java2D output. + */ +class GenericFOPBridgeContext extends AbstractFOPBridgeContext { + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param documentLoader the Document Loader to use for referenced documents. + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null + */ + public GenericFOPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader, + FontInfo fontInfo, ImageManager imageManager, + ImageSessionContext imageSessionContext, + AffineTransform linkTransform) { + super(userAgent, documentLoader, fontInfo, + imageManager, imageSessionContext, linkTransform); + } + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + */ + public GenericFOPBridgeContext(UserAgent userAgent, FontInfo fontInfo, + ImageManager imageManager, ImageSessionContext imageSessionContext) { + super(userAgent, fontInfo, imageManager, imageSessionContext); + } + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null + */ + public GenericFOPBridgeContext(SVGUserAgent userAgent, FontInfo fontInfo, + ImageManager imageManager, ImageSessionContext imageSessionContext, + AffineTransform linkTransform) { + super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform); + } + + /** {@inheritDoc} */ + public void registerSVGBridges() { + super.registerSVGBridges(); + + //This makes Batik load images via FOP and the XGC image loading framework + putBridge(new GenericFOPImageElementBridge()); + } + + /** {@inheritDoc} */ + public BridgeContext createBridgeContext(SVGOMDocument doc) { + return createBridgeContext(); + } + + /** {@inheritDoc} */ + public BridgeContext createBridgeContext() { + return new GenericFOPBridgeContext(getUserAgent(), getDocumentLoader(), + fontInfo, + getImageManager(), + getImageSessionContext(), + linkTransform); + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/GenericFOPImageElementBridge.java b/src/java/org/apache/fop/image/loader/batik/GenericFOPImageElementBridge.java new file mode 100644 index 000000000..7a14025c8 --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/GenericFOPImageElementBridge.java @@ -0,0 +1,46 @@ +/* + * 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.image.loader.batik; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; + +import org.apache.fop.svg.AbstractFOPImageElementBridge; + +/** + * Image Element Bridge class for the SVG to Java2D converter, used to make Batik load images + * through FOP and XGC's image loading framework. + */ +class GenericFOPImageElementBridge extends AbstractFOPImageElementBridge { + + /** + * Constructs a new bridge for the <image> element. + */ + public GenericFOPImageElementBridge() { } + + private final ImageFlavor[] supportedFlavors = new ImageFlavor[] + {ImageFlavor.GRAPHICS2D, + BatikImageFlavors.SVG_DOM}; + + /** {@inheritDoc} */ + protected ImageFlavor[] getSupportedFlavours() { + return supportedFlavors; + } + +} diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 2bb521dc9..9efc2aaf0 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -37,7 +37,9 @@ import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageProcessingHints; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.xmlgraphics.image.loader.XMLNamespaceEnabledImageFlavor; import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter; import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; @@ -77,7 +79,16 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { } UserAgent ua = createBatikUserAgent(pxToMillimeter); GVTBuilder builder = new GVTBuilder(); - final BridgeContext ctx = new BridgeContext(ua); + + final ImageManager imageManager = (ImageManager)hints.get( + ImageProcessingHints.IMAGE_MANAGER); + final ImageSessionContext sessionContext = (ImageSessionContext)hints.get( + ImageProcessingHints.IMAGE_SESSION_CONTEXT); + + boolean useEnhancedBridgeContext = (imageManager != null && sessionContext != null); + final BridgeContext ctx = (useEnhancedBridgeContext + ? new GenericFOPBridgeContext(ua, null, imageManager, sessionContext) + : new BridgeContext(ua)); Document doc = svg.getDocument(); //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine) @@ -117,9 +128,20 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { /** {@inheritDoc} */ public void displayMessage(String message) { //TODO Refine and pipe through to caller - log.debug(message); + log.info(message); + } + + /** {@inheritDoc} */ + public void displayError(Exception e) { + log.error("Error converting SVG to a Java2D graphic", e); } + /** {@inheritDoc} */ + public void displayError(String message) { + log.error(message); + } + + }; } diff --git a/status.xml b/status.xml index faf620aad..4bb58aebc 100644 --- a/status.xml +++ b/status.xml @@ -57,6 +57,8 @@ users, i.e. when the behaviour changes and could affect the layout of existing documents. Example: the fix of marks layering will be such a case when it's done. --> + <release version="FOP Trunk" date="TBD"> + </release> <release version="1.0" date="July 2010"> <action context="Renderers" dev="JM" type="fix"> AFP Output: Fixed positioning of Java2D-based images (when GOCA is enabled). diff --git a/test/java/org/apache/fop/threading/AvalonAdapter.java b/test/java/org/apache/fop/threading/AvalonAdapter.java new file mode 100644 index 000000000..bfe0a5010 --- /dev/null +++ b/test/java/org/apache/fop/threading/AvalonAdapter.java @@ -0,0 +1,58 @@ +/* + * 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.threading; + +import org.apache.avalon.framework.logger.Logger; + +import org.apache.fop.events.Event; +import org.apache.fop.events.EventFormatter; +import org.apache.fop.events.EventListener; +import org.apache.fop.events.model.EventSeverity; + +/** + * Redirects events to an Avalon logger. + */ +class AvalonAdapter implements EventListener { + + private final Logger logger; + private String filename; + + public AvalonAdapter(Logger logger, String filename) { + this.logger = logger; + this.filename = filename; + } + + public void processEvent(Event event) { + String msg = EventFormatter.format(event); + EventSeverity severity = event.getSeverity(); + if (severity == EventSeverity.INFO) { + //logger.info(filename + ": " + msg); + } else if (severity == EventSeverity.WARN) { + //logger.warn(filename + ": " + msg); + } else if (severity == EventSeverity.ERROR) { + logger.error(filename + ": " + msg); + } else if (severity == EventSeverity.FATAL) { + logger.fatalError(filename + ": " + msg); + } else { + assert false; + } + } + +}
\ No newline at end of file diff --git a/test/java/org/apache/fop/threading/FOPTestbed.java b/test/java/org/apache/fop/threading/FOPTestbed.java index 737317bec..8424260a9 100644 --- a/test/java/org/apache/fop/threading/FOPTestbed.java +++ b/test/java/org/apache/fop/threading/FOPTestbed.java @@ -56,7 +56,7 @@ public class FOPTestbed extends AbstractLogEnabled private int threads; private File outputDir; private Configuration fopCfg; - private FOProcessor foprocessor; + private Processor foprocessor; private boolean writeToDevNull; private int counter = 0; @@ -74,7 +74,7 @@ public class FOPTestbed extends AbstractLogEnabled for (int i = 0; i < entries.length; i++) { this.taskList.add(new TaskDef(entries[i])); } - this.fopCfg = configuration.getChild("foprocessor"); + this.fopCfg = configuration.getChild("processor"); } /** {@inheritDoc} */ @@ -177,11 +177,11 @@ public class FOPTestbed extends AbstractLogEnabled * Creates a new FOProcessor. * @return the newly created instance */ - public FOProcessor createFOProcessor() { + public Processor createFOProcessor() { try { Class clazz = Class.forName(this.fopCfg.getAttribute("class", "org.apache.fop.threading.FOProcessorImpl")); - FOProcessor fop = (FOProcessor)clazz.newInstance(); + Processor fop = (Processor)clazz.newInstance(); ContainerUtil.enableLogging(fop, getLogger()); ContainerUtil.configure(fop, this.fopCfg); ContainerUtil.initialize(fop); @@ -206,13 +206,15 @@ public class FOPTestbed extends AbstractLogEnabled this.fo = cfg.getAttribute("fo", null); if (this.fo == null) { this.xml = cfg.getAttribute("xml"); - this.xslt = cfg.getAttribute("xslt"); - TransformerFactory factory = TransformerFactory.newInstance(); - Source xsltSource = new StreamSource(new File(xslt)); - try { - this.templates = factory.newTemplates(xsltSource); - } catch (TransformerConfigurationException tce) { - throw new ConfigurationException("Invalid XSLT", tce); + this.xslt = cfg.getAttribute("xslt", null); + if (this.xslt != null) { + TransformerFactory factory = TransformerFactory.newInstance(); + Source xsltSource = new StreamSource(new File(xslt)); + try { + this.templates = factory.newTemplates(xsltSource); + } catch (TransformerConfigurationException tce) { + throw new ConfigurationException("Invalid XSLT", tce); + } } } } @@ -249,9 +251,9 @@ public class FOPTestbed extends AbstractLogEnabled private TaskDef def; private int num; - private FOProcessor fop; + private Processor fop; - public Task(TaskDef def, int num, FOProcessor fop) { + public Task(TaskDef def, int num, Processor fop) { this.def = def; this.num = num; this.fop = fop; diff --git a/test/java/org/apache/fop/threading/FOProcessorImpl.java b/test/java/org/apache/fop/threading/FOProcessorImpl.java index 2b580bbd0..3702d87e7 100644 --- a/test/java/org/apache/fop/threading/FOProcessorImpl.java +++ b/test/java/org/apache/fop/threading/FOProcessorImpl.java @@ -43,16 +43,12 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.events.Event; -import org.apache.fop.events.EventFormatter; -import org.apache.fop.events.EventListener; -import org.apache.fop.events.model.EventSeverity; /** - * Default implementation of the FOProcessor interface using FOP. + * Default implementation of the {@link Processor} interface using FOP. */ public class FOProcessorImpl extends AbstractLogEnabled - implements FOProcessor, Configurable, Initializable { + implements Processor, Configurable, Initializable { private FopFactory fopFactory = FopFactory.newInstance(); private TransformerFactory factory = TransformerFactory.newInstance(); @@ -83,7 +79,8 @@ public class FOProcessorImpl extends AbstractLogEnabled try { URL url = new URL(src.getSystemId()); String filename = FilenameUtils.getName(url.getPath()); - foUserAgent.getEventBroadcaster().addEventListener(new AvalonAdapter(filename)); + foUserAgent.getEventBroadcaster().addEventListener( + new AvalonAdapter(getLogger(), filename)); } catch (MalformedURLException mfue) { throw new RuntimeException(mfue); } @@ -107,30 +104,4 @@ public class FOProcessorImpl extends AbstractLogEnabled public String getTargetFileExtension() { return this.fileExtension; } - - private class AvalonAdapter implements EventListener { - - private String filename; - - public AvalonAdapter(String filename) { - this.filename = filename; - } - - public void processEvent(Event event) { - String msg = EventFormatter.format(event); - EventSeverity severity = event.getSeverity(); - if (severity == EventSeverity.INFO) { - //getLogger().info(filename + ": " + msg); - } else if (severity == EventSeverity.WARN) { - //getLogger().warn(filename + ": " + msg); - } else if (severity == EventSeverity.ERROR) { - getLogger().error(filename + ": " + msg); - } else if (severity == EventSeverity.FATAL) { - getLogger().fatalError(filename + ": " + msg); - } else { - assert false; - } - } - - } }
\ No newline at end of file diff --git a/test/java/org/apache/fop/threading/IFProcessorImpl.java b/test/java/org/apache/fop/threading/IFProcessorImpl.java new file mode 100644 index 000000000..34873d76b --- /dev/null +++ b/test/java/org/apache/fop/threading/IFProcessorImpl.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.threading; + +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamResult; + +import org.xml.sax.ContentHandler; + +import org.apache.avalon.framework.activity.Initializable; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.commons.io.FilenameUtils; + +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.render.intermediate.IFDocumentHandler; +import org.apache.fop.render.intermediate.IFException; +import org.apache.fop.render.intermediate.IFParser; +import org.apache.fop.render.intermediate.IFUtil; + +/** + * Implementation of the {@link Processor} interface that renders IF XML to a final output format. + */ +public class IFProcessorImpl extends AbstractLogEnabled + implements Processor, Configurable, Initializable { + + private FopFactory fopFactory = FopFactory.newInstance(); + private TransformerFactory factory = TransformerFactory.newInstance(); + private String userconfig; + private String mime; + private String fileExtension; + + /** {@inheritDoc} */ + public void configure(Configuration configuration) throws ConfigurationException { + this.userconfig = configuration.getChild("userconfig").getValue(null); + this.mime = configuration.getChild("mime").getValue(MimeConstants.MIME_PDF); + this.fileExtension = configuration.getChild("extension").getValue(".pdf"); + } + + /** {@inheritDoc} */ + public void initialize() throws Exception { + if (this.userconfig != null) { + getLogger().debug("Setting user config: " + userconfig); + fopFactory.setUserConfig(this.userconfig); + } + } + + /** {@inheritDoc} + * @throws IFException */ + public void process(Source src, Templates templates, OutputStream out) + throws org.apache.fop.apps.FOPException, java.io.IOException, IFException { + FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); + foUserAgent.setBaseURL(src.getSystemId()); + try { + URL url = new URL(src.getSystemId()); + String filename = FilenameUtils.getName(url.getPath()); + foUserAgent.getEventBroadcaster().addEventListener( + new AvalonAdapter(getLogger(), filename)); + } catch (MalformedURLException mfue) { + throw new RuntimeException(mfue); + } + + //Setup target handler + IFDocumentHandler targetHandler = fopFactory.getRendererFactory().createDocumentHandler( + foUserAgent, mime); + + //Setup fonts + IFUtil.setupFonts(targetHandler); + targetHandler.setResult(new StreamResult(out)); + + try { + Transformer transformer; + if (templates == null) { + transformer = factory.newTransformer(); + } else { + transformer = templates.newTransformer(); + } + IFParser parser = new IFParser(); + ContentHandler contentHandler = parser.getContentHandler(targetHandler, foUserAgent); + Result res = new SAXResult(contentHandler); + transformer.transform(src, res); + } catch (TransformerException e) { + throw new FOPException(e); + } + } + + /** {@inheritDoc} */ + public String getTargetFileExtension() { + return this.fileExtension; + } + +}
\ No newline at end of file diff --git a/test/java/org/apache/fop/threading/FOProcessor.java b/test/java/org/apache/fop/threading/Processor.java index dd663da05..9c86fc382 100644 --- a/test/java/org/apache/fop/threading/FOProcessor.java +++ b/test/java/org/apache/fop/threading/Processor.java @@ -25,9 +25,9 @@ import javax.xml.transform.Source; import javax.xml.transform.Templates; /** - * Represents an FO processor. + * Represents a processor. */ -public interface FOProcessor { +public interface Processor { /** * Process a file. diff --git a/test/java/org/apache/fop/threading/sample.cfg.xml b/test/java/org/apache/fop/threading/sample.cfg.xml index 0be7dc539..a4de0d754 100644 --- a/test/java/org/apache/fop/threading/sample.cfg.xml +++ b/test/java/org/apache/fop/threading/sample.cfg.xml @@ -2,13 +2,13 @@ <config prompt="false"> <threads>2</threads> <output-dir>C:/Dev/FOP/temp/out</output-dir> - <foprocessor class="org.apache.fop.threading.FOProcessorImpl"> + <processor class="org.apache.fop.threading.FOProcessorImpl"> <!-- <userconfig>C:/Dev/FOP/temp/userconfig.xml</userconfig> --> <mime>application/pdf</mime> <extension>.pdf</extension> - </foprocessor> + </processor> <tasks repeat="2"> <task fo="C:/Dev/FOP/temp/helloworld.fo"/> <task xml="C:/Dev/FOP/temp/page-x-of-y.xml" xslt="C:/Dev/FOP/temp/page-x-of-y.xsl"/> |