aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/embedding/java/embedding/ExampleFO2JPSPrint.java143
-rw-r--r--src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory1
-rw-r--r--src/java/org/apache/fop/apps/FOPException.java2
-rw-r--r--src/java/org/apache/fop/area/PageViewport.java1
-rw-r--r--src/java/org/apache/fop/area/RenderPagesModel.java9
-rw-r--r--src/java/org/apache/fop/fo/pagination/PageProductionException.java106
-rw-r--r--src/java/org/apache/fop/fo/pagination/PageSequence.java4
-rw-r--r--src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java4
-rw-r--r--src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java14
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageProvider.java51
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderer.java9
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DRenderer.java30
-rw-r--r--src/java/org/apache/fop/render/print/PageableRenderer.java214
-rw-r--r--src/java/org/apache/fop/render/print/PrintRenderer.java176
-rw-r--r--src/java/org/apache/fop/render/rtf/RTFHandler.java3
-rw-r--r--status.xml4
17 files changed, 545 insertions, 231 deletions
diff --git a/examples/embedding/java/embedding/ExampleFO2JPSPrint.java b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java
new file mode 100644
index 000000000..a67e2bdad
--- /dev/null
+++ b/examples/embedding/java/embedding/ExampleFO2JPSPrint.java
@@ -0,0 +1,143 @@
+/*
+ * 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 embedding;
+
+// Java
+import java.io.File;
+import java.io.IOException;
+
+import javax.print.Doc;
+import javax.print.DocFlavor;
+import javax.print.DocPrintJob;
+import javax.print.PrintException;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.print.ServiceUI;
+import javax.print.SimpleDoc;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+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.StreamSource;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.render.print.PageableRenderer;
+
+/**
+ * This class demonstrates printing an FO file using JPS (Java Printing System).
+ */
+public class ExampleFO2JPSPrint {
+
+ // configure fopFactory as desired
+ private FopFactory fopFactory = FopFactory.newInstance();
+
+ private DocPrintJob createDocPrintJob() {
+ PrintService[] services = PrintServiceLookup.lookupPrintServices(
+ DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
+ PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
+ PrintService printService = ServiceUI.printDialog(null, 50, 50,
+ services, services[0], null, attributes);
+ if (printService != null) {
+ return printService.createPrintJob();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Prints an FO file using JPS.
+ * @param fo the FO file
+ * @throws IOException In case of an I/O problem
+ * @throws FOPException In case of a FOP problem
+ * @throws TransformerException In case of a problem during XSLT processing
+ * @throws PrintException If an error occurs while printing
+ */
+ public void printFO(File fo)
+ throws IOException, FOPException, TransformerException, PrintException {
+
+ //Set up DocPrintJob instance
+ DocPrintJob printJob = createDocPrintJob();
+
+ //Set up a custom user agent so we can supply our own renderer instance
+ FOUserAgent userAgent = fopFactory.newFOUserAgent();
+
+ PageableRenderer renderer = new PageableRenderer();
+ renderer.setUserAgent(userAgent);
+ userAgent.setRendererOverride(renderer);
+
+ // Construct FOP with desired output format
+ Fop fop = fopFactory.newFop(userAgent);
+
+ // Setup JAXP using identity transformer
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer(); // identity transformer
+
+ // Setup input stream
+ Source src = new StreamSource(fo);
+
+ // Resulting SAX events (the generated FO) must be piped through to FOP
+ Result res = new SAXResult(fop.getDefaultHandler());
+
+ // Start XSLT transformation and FOP processing
+ transformer.transform(src, res);
+
+ Doc doc = new SimpleDoc(renderer, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
+ printJob.print(doc, null);
+ }
+
+ /**
+ * Main method.
+ * @param args command-line arguments
+ */
+ public static void main(String[] args) {
+ try {
+ System.out.println("FOP ExampleFO2JPSPrint\n");
+ System.out.println("Preparing...");
+
+ //Setup directories
+ File baseDir = new File(".");
+ File outDir = new File(baseDir, "out");
+ outDir.mkdirs();
+
+ //Setup input and output files
+ File fofile = new File(baseDir, "xml/fo/helloworld.fo");
+
+ System.out.println("Input: XSL-FO (" + fofile + ")");
+ System.out.println("Output: JPS (Java Printing System)");
+ System.out.println();
+ System.out.println("Transforming...");
+
+ ExampleFO2JPSPrint app = new ExampleFO2JPSPrint();
+ app.printFO(fofile);
+
+ System.out.println("Success!");
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ System.exit(-1);
+ }
+ }
+}
diff --git a/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory b/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory
index 9fa7b8d04..1ad959188 100644
--- a/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory
+++ b/src/java/META-INF/services/org.apache.fop.events.EventExceptionManager$ExceptionFactory
@@ -2,3 +2,4 @@ org.apache.fop.events.ValidationExceptionFactory
org.apache.fop.events.PropertyExceptionFactory
org.apache.fop.events.UnsupportedOperationExceptionFactory
org.apache.fop.layoutmgr.LayoutException$LayoutExceptionFactory
+org.apache.fop.fo.pagination.PageProductionException$PageProductionExceptionFactory
diff --git a/src/java/org/apache/fop/apps/FOPException.java b/src/java/org/apache/fop/apps/FOPException.java
index 851712b09..d8ac2e2f7 100644
--- a/src/java/org/apache/fop/apps/FOPException.java
+++ b/src/java/org/apache/fop/apps/FOPException.java
@@ -103,7 +103,7 @@ public class FOPException extends SAXException {
* @param systemId the system id of the FO document which is associated with the exception;
* may be null.
* @param line line number in the FO document which is associated with the exception.
- * @param column clolumn number in the line which is associated with the exception.
+ * @param column column number in the line which is associated with the exception.
*/
public void setLocation(String systemId, int line, int column) {
this.systemId = systemId;
diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java
index da7ef1def..745160d44 100644
--- a/src/java/org/apache/fop/area/PageViewport.java
+++ b/src/java/org/apache/fop/area/PageViewport.java
@@ -124,6 +124,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl
if (original.extensionAttachments != null) {
this.extensionAttachments = new java.util.ArrayList(original.extensionAttachments);
}
+ this.pageIndex = original.pageIndex;
this.pageNumber = original.pageNumber;
this.pageNumberString = original.pageNumberString;
this.page = (Page)original.page.clone();
diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java
index b21566902..64159cca7 100644
--- a/src/java/org/apache/fop/area/RenderPagesModel.java
+++ b/src/java/org/apache/fop/area/RenderPagesModel.java
@@ -31,6 +31,7 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.Renderer;
+import org.apache.fop.render.RendererEventProducer;
/**
* This uses the AreaTreeModel to store the pages
@@ -115,8 +116,12 @@ public class RenderPagesModel extends AreaTreeModel {
String err = "Error while rendering page " + page.getPageNumberString();
log.error(err, re);
throw re;
- } catch (Exception e) {
- //TODO use error handler to handle this FOP or IO Exception or propagate exception
+ } catch (IOException ioe) {
+ RendererEventProducer eventProducer = RendererEventProducer.Provider.get(
+ renderer.getUserAgent().getEventBroadcaster());
+ eventProducer.ioError(this, ioe);
+ } catch (FOPException e) {
+ //TODO use error handler to handle this FOPException or propagate exception
String err = "Error while rendering page " + page.getPageNumberString();
log.error(err, e);
throw new IllegalStateException("Fatal error occurred. Cannot continue. "
diff --git a/src/java/org/apache/fop/fo/pagination/PageProductionException.java b/src/java/org/apache/fop/fo/pagination/PageProductionException.java
new file mode 100644
index 000000000..068e38ff8
--- /dev/null
+++ b/src/java/org/apache/fop/fo/pagination/PageProductionException.java
@@ -0,0 +1,106 @@
+/*
+ * 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.pagination;
+
+import java.util.Locale;
+
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.LocatorImpl;
+
+import org.apache.fop.events.Event;
+import org.apache.fop.events.EventFormatter;
+import org.apache.fop.events.EventExceptionManager.ExceptionFactory;
+
+/**
+ * Exception thrown by FOP if there is a problem while producing new pages.
+ */
+public class PageProductionException extends RuntimeException {
+
+ private static final long serialVersionUID = -5126033718398975158L;
+
+ private String localizedMessage;
+ private Locator locator;
+
+ /**
+ * Creates a new PageProductionException.
+ * @param message the message
+ * @param locator the optional locator that points to the error in the source file
+ */
+ public PageProductionException(String message, Locator locator) {
+ super(message);
+ setLocator(locator);
+ }
+
+ /**
+ * Set a location associated with the exception.
+ * @param locator the locator holding the location.
+ */
+ public void setLocator(Locator locator) {
+ this.locator = new LocatorImpl(locator);
+ }
+
+
+ /**
+ * Returns the locattion associated with the exception.
+ * @return the locator or null if the location information is not available
+ */
+ public Locator getLocator() {
+ return this.locator;
+ }
+
+ /**
+ * Sets the localized message for this exception.
+ * @param msg the localized message
+ */
+ public void setLocalizedMessage(String msg) {
+ this.localizedMessage = msg;
+ }
+
+ /** {@inheritDoc} */
+ public String getLocalizedMessage() {
+ if (this.localizedMessage != null) {
+ return this.localizedMessage;
+ } else {
+ return super.getLocalizedMessage();
+ }
+ }
+
+ /** Exception factory for {@link PageProductionException}. */
+ public static class PageProductionExceptionFactory implements ExceptionFactory {
+
+ /** {@inheritDoc} */
+ public Throwable createException(Event event) {
+ Object obj = event.getParam("loc");
+ Locator loc = (obj instanceof Locator ? (Locator)obj : null);
+ String msg = EventFormatter.format(event, Locale.ENGLISH);
+ PageProductionException ex = new PageProductionException(msg, loc);
+ if (!Locale.ENGLISH.equals(Locale.getDefault())) {
+ ex.setLocalizedMessage(EventFormatter.format(event));
+ }
+ return ex;
+ }
+
+ /** {@inheritDoc} */
+ public Class getExceptionClass() {
+ return PageProductionException.class;
+ }
+
+ }
+}
diff --git a/src/java/org/apache/fop/fo/pagination/PageSequence.java b/src/java/org/apache/fop/fo/pagination/PageSequence.java
index 3d155a1da..3c7cfb197 100644
--- a/src/java/org/apache/fop/fo/pagination/PageSequence.java
+++ b/src/java/org/apache/fop/fo/pagination/PageSequence.java
@@ -371,13 +371,13 @@ public class PageSequence extends AbstractPageSequence {
* page sequence
* @param isBlank indicator whether the page will be blank
* @return the SimplePageMaster to use for this page
- * @throws FOPException if there's a problem determining the page master
+ * @throws PageProductionException if there's a problem determining the page master
*/
public SimplePageMaster getNextSimplePageMaster(int page,
boolean isFirstPage,
boolean isLastPage,
boolean isOnlyPage,
- boolean isBlank) throws FOPException {
+ boolean isBlank) throws PageProductionException {
if (pageSequenceMaster == null) {
return simplePageMaster;
diff --git a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java
index 4258a1139..b6c8c0f6b 100644
--- a/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java
+++ b/src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java
@@ -189,14 +189,14 @@ public class PageSequenceMaster extends FObj {
* @param isOnlyPage True if the next page is the only page
* @param isBlankPage True if the next page is blank
* @return the requested page master
- * @throws FOPException if there's a problem determining the next page master
+ * @throws PageProductionException if there's a problem determining the next page master
*/
public SimplePageMaster getNextSimplePageMaster(boolean isOddPage,
boolean isFirstPage,
boolean isLastPage,
boolean isOnlyPage,
boolean isBlankPage)
- throws FOPException {
+ throws PageProductionException {
if (currentSubSequence == null) {
currentSubSequence = getNextSubSequence();
if (currentSubSequence == null) {
diff --git a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java
index 5da4945f1..0bad65a7c 100644
--- a/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java
+++ b/src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java
@@ -19,7 +19,6 @@
package org.apache.fop.fo.pagination;
-import org.apache.fop.apps.FOPException;
/**
* Classes that implement this interface can be added to a PageSequenceMaster,
@@ -35,14 +34,14 @@ public interface SubSequenceSpecifier {
* @param isOnlyPage True if the next page is the only page
* @param isBlankPage True if the next page is blank
* @return the page master name
- * @throws FOPException if there's a problem determining the next page master
+ * @throws PageProductionException if there's a problem determining the next page master
*/
String getNextPageMasterName(boolean isOddPage,
boolean isFirstPage,
boolean isLastPage,
boolean isOnlyPage,
boolean isBlankPage)
- throws FOPException;
+ throws PageProductionException;
/**
* Called before a new page sequence is rendered so subsequences can reset
diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java
index c31a70477..b1dd7ef5d 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java
@@ -21,9 +21,9 @@ package org.apache.fop.layoutmgr;
import org.xml.sax.Locator;
-import org.apache.fop.apps.FOPException;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.events.EventProducer;
+import org.apache.fop.fo.pagination.PageProductionException;
/**
* Event producer interface for block-level layout managers.
@@ -136,22 +136,22 @@ public interface BlockLevelEventProducer extends EventProducer {
* @param pageSequenceMasterName the name of the page sequence master
* @param canRecover indicates whether FOP can recover from this problem and continue working
* @param loc the location of the error or null
- * @throws FOPException the error provoked by the method call
+ * @throws PageProductionException the error provoked by the method call
* @event.severity FATAL
*/
void pageSequenceMasterExhausted(Object source, String pageSequenceMasterName,
- boolean canRecover, Locator loc) throws FOPException;
+ boolean canRecover, Locator loc) throws PageProductionException;
/**
* No subsequences in page sequence master.
* @param source the event source
* @param pageSequenceMasterName the name of the page sequence master
* @param loc the location of the error or null
- * @throws FOPException the error provoked by the method call
+ * @throws PageProductionException the error provoked by the method call
* @event.severity FATAL
*/
void missingSubsequencesInPageSequenceMaster(Object source, String pageSequenceMasterName,
- Locator loc) throws FOPException;
+ Locator loc) throws PageProductionException;
/**
* No single-page-master matching in page sequence master.
@@ -159,10 +159,10 @@ public interface BlockLevelEventProducer extends EventProducer {
* @param pageSequenceMasterName the name of the page sequence master
* @param pageMasterName the name of the page master not matching
* @param loc the location of the error or null
- * @throws FOPException the error provoked by the method call
+ * @throws PageProductionException the error provoked by the method call
* @event.severity FATAL
*/
void noMatchingPageMaster(Object source, String pageSequenceMasterName,
- String pageMasterName, Locator loc) throws FOPException;
+ String pageMasterName, Locator loc) throws PageProductionException;
}
diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java
index 037f02094..a7918db6e 100644
--- a/src/java/org/apache/fop/layoutmgr/PageProvider.java
+++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java
@@ -24,7 +24,6 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.apps.FOPException;
import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.pagination.PageSequence;
@@ -196,10 +195,10 @@ public class PageProvider implements Constants {
}
/**
- *
- * @param isBlank true if the Page should be a blank one
+ * Returns a Page.
+ * @param isBlank true if the Page should be a blank one
* @param index the Page's index
- * @return a Page instance
+ * @return a Page instance
*/
protected Page getPage(boolean isBlank, int index) {
boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex);
@@ -251,31 +250,25 @@ public class PageProvider implements Constants {
}
private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) {
- try {
- String pageNumberString = pageSeq.makeFormattedPageNumber(index);
- SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
- index, (startPageOfPageSequence == index), isLastPage, false, isBlank);
-
- Region body = spm.getRegion(FO_REGION_BODY);
- if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
- // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
- // any region), but we don't support it yet.
- BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
- pageSeq.getUserAgent().getEventBroadcaster());
- eventProducer.flowNotMappingToRegionBody(this,
- pageSeq.getMainFlow().getFlowName(), spm.getMasterName(), spm.getLocator());
- }
- Page page = new Page(spm, index, pageNumberString, isBlank);
- //Set unique key obtained from the AreaTreeHandler
- page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
- page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
- cachedPages.add(page);
- return page;
- } catch (FOPException e) {
- //TODO Maybe improve. It'll mean to propagate this exception up several
- //methods calls.
- throw new IllegalStateException(e.getMessage());
+ String pageNumberString = pageSeq.makeFormattedPageNumber(index);
+ SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
+ index, (startPageOfPageSequence == index), isLastPage, false, isBlank);
+
+ Region body = spm.getRegion(FO_REGION_BODY);
+ if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
+ // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
+ // any region), but we don't support it yet.
+ BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
+ pageSeq.getUserAgent().getEventBroadcaster());
+ eventProducer.flowNotMappingToRegionBody(this,
+ pageSeq.getMainFlow().getFlowName(), spm.getMasterName(), spm.getLocator());
}
+ Page page = new Page(spm, index, pageNumberString, isBlank);
+ //Set unique key obtained from the AreaTreeHandler
+ page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
+ page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
+ cachedPages.add(page);
+ return page;
}
-
+
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index ca3d007d0..816fa4067 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -124,12 +124,19 @@ public abstract class AbstractRenderer
/** {@inheritDoc} */
public FOUserAgent getUserAgent() {
+ if (userAgent == null) {
+ throw new IllegalStateException("FOUserAgent has not been set on Renderer");
+ }
return userAgent;
}
/** {@inheritDoc} */
public void startRenderer(OutputStream outputStream)
- throws IOException { }
+ throws IOException {
+ if (userAgent == null) {
+ throw new IllegalStateException("FOUserAgent has not been set on Renderer");
+ }
+ }
/** {@inheritDoc} */
public void stopRenderer()
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
index 1f3194949..db8ed6250 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -198,6 +198,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
/** {@inheritDoc} */
public void startRenderer(OutputStream out) throws IOException {
+ super.startRenderer(out);
// do nothing by default
}
@@ -232,7 +233,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
}
/**
+ * Returns the number of pages available. This method is also part of the Pageable interface.
* @return The 0-based total number of rendered pages
+ * @see java.awt.print.Pageable
*/
public int getNumberOfPages() {
return pageViewportList.size();
@@ -250,7 +253,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
/**
* This method override only stores the PageViewport in a List. No actual
* rendering is performed here. A renderer override renderPage() to get the
- * freshly produced PageViewport, and rendere them on the fly (producing the
+ * freshly produced PageViewport, and render them on the fly (producing the
* desired BufferedImages by calling getPageImage(), which lazily starts the
* rendering process).
*
@@ -260,12 +263,23 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
* @see org.apache.fop.render.Renderer
*/
public void renderPage(PageViewport pageViewport) throws IOException {
- // TODO clone?
- pageViewportList.add(pageViewport.clone());
+ rememberPage((PageViewport)pageViewport.clone());
+ //The clone() call is necessary as we store the page for later. Otherwise, the
+ //RenderPagesModel calls PageViewport.clear() to release memory as early as possible.
currentPageNumber++;
}
/**
+ * Stores the pageViewport in a list of page viewports so they can be rendered later.
+ * Subclasses can override this method to filter pages, for example.
+ * @param pageViewport the page viewport
+ */
+ protected void rememberPage(PageViewport pageViewport) {
+ assert pageViewport.getPageIndex() >= 0;
+ pageViewportList.add(pageViewport);
+ }
+
+ /**
* Generates a desired page from the renderer's page viewport list.
*
* @param pageViewport the PageViewport to be rendered
@@ -362,17 +376,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
/**
* Returns a page viewport.
- * @param pageNum the page number
+ * @param pageIndex the page index (zero-based)
* @return the requested PageViewport instance
* @exception FOPException If the page is out of range.
*/
- public PageViewport getPageViewport(int pageNum) throws FOPException {
- if (pageNum < 0 || pageNum >= pageViewportList.size()) {
- throw new FOPException("Requested page number is out of range: " + pageNum
+ public PageViewport getPageViewport(int pageIndex) throws FOPException {
+ if (pageIndex < 0 || pageIndex >= pageViewportList.size()) {
+ throw new FOPException("Requested page number is out of range: " + pageIndex
+ "; only " + pageViewportList.size()
+ " page(s) available.");
}
- return (PageViewport) pageViewportList.get(pageNum);
+ return (PageViewport) pageViewportList.get(pageIndex);
}
/**
diff --git a/src/java/org/apache/fop/render/print/PageableRenderer.java b/src/java/org/apache/fop/render/print/PageableRenderer.java
new file mode 100644
index 000000000..947708cef
--- /dev/null
+++ b/src/java/org/apache/fop/render/print/PageableRenderer.java
@@ -0,0 +1,214 @@
+/*
+ * 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.print;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Paper;
+import java.awt.print.Printable;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.render.java2d.Java2DRenderer;
+
+/**
+ * Renderer that prints through java.awt.PrintJob.
+ * The actual printing is handled by Java2DRenderer
+ * since both PrintRenderer and AWTRenderer need to
+ * support printing.
+ */
+public class PageableRenderer extends Java2DRenderer implements Pageable {
+
+ /**
+ * Printing parameter: the pages to be printed (all, even or odd),
+ * datatype: the strings "all", "even" or "odd" or one of PagesMode.*
+ */
+ public static final String PAGES_MODE = "even-odd";
+
+ /**
+ * Printing parameter: the page number (1-based) of the first page to be printed,
+ * datatype: a positive Integer
+ */
+ public static final String START_PAGE = "start-page";
+
+ /**
+ * Printing parameter: the page number (1-based) of the last page to be printed,
+ * datatype: a positive Integer
+ */
+ public static final String END_PAGE = "end-page";
+
+
+ /** first valid page number (1-based) */
+ protected int startNumber = 0;
+ /** last valid page number (1-based) */
+ protected int endNumber = -1;
+
+ /** indicates which pages are valid: odd, even or all */
+ protected PagesMode mode = PagesMode.ALL;
+
+ private PageFilter pageFilter;
+
+ /**
+ * Creates a new PageableRenderer.
+ */
+ public PageableRenderer() {
+ }
+
+ /** {@inheritDoc} */
+ public void setUserAgent(FOUserAgent agent) {
+ super.setUserAgent(agent);
+
+ Map rendererOptions = agent.getRendererOptions();
+ processOptions(rendererOptions);
+ this.pageFilter = new DefaultPageFilter();
+ }
+
+ private void processOptions(Map rendererOptions) {
+ Object o = rendererOptions.get(PageableRenderer.PAGES_MODE);
+ if (o != null) {
+ if (o instanceof PagesMode) {
+ this.mode = (PagesMode)o;
+ } else if (o instanceof String) {
+ this.mode = PagesMode.byName((String)o);
+ } else {
+ throw new IllegalArgumentException(
+ "Renderer option " + PageableRenderer.PAGES_MODE
+ + " must be an 'all', 'even', 'odd' or a PagesMode instance.");
+ }
+ }
+
+ o = rendererOptions.get(PageableRenderer.START_PAGE);
+ if (o != null) {
+ this.startNumber = getPositiveInteger(o);
+ }
+ o = rendererOptions.get(PageableRenderer.END_PAGE);
+ if (o != null) {
+ this.endNumber = getPositiveInteger(o);
+ }
+ if (this.endNumber >= 0 && this.endNumber < this.endNumber) {
+ this.endNumber = this.startNumber;
+ }
+ }
+
+ /**
+ * Converts an object into a positive integer value if possible. The method throws an
+ * {@link IllegalArgumentException} if the value is invalid.
+ * @param o the object to be converted
+ * @return the positive integer
+ */
+ protected int getPositiveInteger(Object o) {
+ if (o instanceof Integer) {
+ Integer i = (Integer)o;
+ if (i.intValue() < 1) {
+ throw new IllegalArgumentException(
+ "Value must be a positive Integer");
+ }
+ return i.intValue();
+ } else if (o instanceof String) {
+ return Integer.parseInt((String)o);
+ } else {
+ throw new IllegalArgumentException(
+ "Value must be a positive integer");
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void stopRenderer() throws IOException {
+ super.stopRenderer();
+
+ if (endNumber == -1) {
+ // was not set on command line
+ endNumber = getNumberOfPages();
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void rememberPage(PageViewport pageViewport) {
+ if (this.pageFilter.isValid(pageViewport)) {
+ super.rememberPage(pageViewport);
+ }
+ }
+
+ private interface PageFilter {
+ boolean isValid(PageViewport page);
+ }
+
+ private class DefaultPageFilter implements PageFilter {
+
+ public boolean isValid(PageViewport page) {
+ int pageNum = page.getPageIndex() + 1;
+ assert pageNum >= 0;
+ if (pageNum < startNumber || (endNumber >= 0 && pageNum > endNumber)) {
+ return false;
+ } else if (mode != PagesMode.ALL) {
+ if (mode == PagesMode.EVEN && (pageNum % 2 != 0)) {
+ return false;
+ } else if (mode == PagesMode.ODD && (pageNum % 2 == 0)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public PageFormat getPageFormat(int pageIndex)
+ throws IndexOutOfBoundsException {
+ try {
+ if (pageIndex >= getNumberOfPages()) {
+ return null;
+ }
+
+ PageFormat pageFormat = new PageFormat();
+
+ Paper paper = new Paper();
+
+ Rectangle2D dim = getPageViewport(pageIndex).getViewArea();
+ double width = dim.getWidth();
+ double height = dim.getHeight();
+
+ // if the width is greater than the height assume landscape mode
+ // and swap the width and height values in the paper format
+ if (width > height) {
+ paper.setImageableArea(0, 0, height / 1000d, width / 1000d);
+ paper.setSize(height / 1000d, width / 1000d);
+ pageFormat.setOrientation(PageFormat.LANDSCAPE);
+ } else {
+ paper.setImageableArea(0, 0, width / 1000d, height / 1000d);
+ paper.setSize(width / 1000d, height / 1000d);
+ pageFormat.setOrientation(PageFormat.PORTRAIT);
+ }
+ pageFormat.setPaper(paper);
+ return pageFormat;
+ } catch (FOPException fopEx) {
+ throw new IndexOutOfBoundsException(fopEx.getMessage());
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Printable getPrintable(int pageIndex)
+ throws IndexOutOfBoundsException {
+ return this;
+ }
+}
diff --git a/src/java/org/apache/fop/render/print/PrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java
index 2774b5373..888776ecb 100644
--- a/src/java/org/apache/fop/render/print/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/print/PrintRenderer.java
@@ -19,20 +19,12 @@
package org.apache.fop.render.print;
-import java.awt.geom.Rectangle2D;
-import java.awt.print.PageFormat;
-import java.awt.print.Pageable;
-import java.awt.print.Paper;
-import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.IOException;
import java.util.Map;
-import java.util.Vector;
-import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.render.java2d.Java2DRenderer;
/**
* Renderer that prints through java.awt.PrintJob.
@@ -40,7 +32,7 @@ import org.apache.fop.render.java2d.Java2DRenderer;
* since both PrintRenderer and AWTRenderer need to
* support printing.
*/
-public class PrintRenderer extends Java2DRenderer implements Pageable {
+public class PrintRenderer extends PageableRenderer {
/**
* Printing parameter: the preconfigured PrinterJob to use,
@@ -49,45 +41,21 @@ public class PrintRenderer extends Java2DRenderer implements Pageable {
public static final String PRINTER_JOB = "printerjob";
/**
- * Printing parameter: the pages to be printed (all, even or odd),
- * datatype: the strings "all", "even" or "odd" or one of PagesMode.*
- */
- public static final String PAGES_MODE = "even-odd";
-
- /**
- * Printing parameter: the page number (1-based) of the first page to be printed,
- * datatype: a positive Integer
- */
- public static final String START_PAGE = "start-page";
-
- /**
- * Printing parameter: the page number (1-based) of the last page to be printed,
- * datatype: a positive Integer
- */
- public static final String END_PAGE = "end-page";
-
- /**
* Printing parameter: the number of copies of the document to be printed,
* datatype: a positive Integer
*/
public static final String COPIES = "copies";
- private int startNumber = 0;
- private int endNumber = -1;
-
- private PagesMode mode = PagesMode.ALL;
-
private int copies = 1;
private PrinterJob printerJob;
/**
- * Creates a new PrintRenderer with the options set from system properties if a custom
+ * Creates a new PrintRenderer with the options set through the renderer options if a custom
* PrinterJob is not given in FOUserAgent's renderer options.
*/
public PrintRenderer() {
- setupFromSystemProperties();
}
/**
@@ -117,18 +85,6 @@ public class PrintRenderer extends Java2DRenderer implements Pageable {
}
}
- private void setupFromSystemProperties() {
- //TODO Remove me! This is not a beautiful way to do this.
- // read from command-line options
- copies = getIntProperty("copies", 1);
- startNumber = getIntProperty("start", 1);
- endNumber = getIntProperty("end", -1);
- String str = System.getProperty("even");
- if (str != null) {
- mode = Boolean.valueOf(str).booleanValue() ? PagesMode.EVEN : PagesMode.ODD;
- }
- }
-
/** {@inheritDoc} */
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
@@ -146,53 +102,13 @@ public class PrintRenderer extends Java2DRenderer implements Pageable {
printerJob = (PrinterJob)printerJobO;
printerJob.setPageable(this);
}
- Object o = rendererOptions.get(PrintRenderer.PAGES_MODE);
- if (o != null) {
- if (o instanceof PagesMode) {
- this.mode = (PagesMode)o;
- } else if (o instanceof String) {
- this.mode = PagesMode.byName((String)o);
- } else {
- throw new IllegalArgumentException(
- "Renderer option " + PrintRenderer.PAGES_MODE
- + " must be an 'all', 'even', 'odd' or a PagesMode instance.");
- }
- }
-
- o = rendererOptions.get(PrintRenderer.START_PAGE);
- if (o != null) {
- this.startNumber = getPositiveInteger(o);
- }
- o = rendererOptions.get(PrintRenderer.END_PAGE);
- if (o != null) {
- this.endNumber = getPositiveInteger(o);
- }
- if (this.endNumber >= 0 && this.endNumber < this.endNumber) {
- this.endNumber = this.startNumber;
- }
- o = rendererOptions.get(PrintRenderer.COPIES);
+ Object o = rendererOptions.get(PrintRenderer.COPIES);
if (o != null) {
this.copies = getPositiveInteger(o);
}
initializePrinterJob();
}
- private int getPositiveInteger(Object o) {
- if (o instanceof Integer) {
- Integer i = (Integer)o;
- if (i.intValue() < 1) {
- throw new IllegalArgumentException(
- "Value must be a positive Integer");
- }
- return i.intValue();
- } else if (o instanceof String) {
- return Integer.parseInt((String)o);
- } else {
- throw new IllegalArgumentException(
- "Value must be a positive integer");
- }
- }
-
/** @return the PrinterJob instance that this renderer prints to */
public PrinterJob getPrinterJob() {
return this.printerJob;
@@ -228,17 +144,6 @@ public class PrintRenderer extends Java2DRenderer implements Pageable {
public void stopRenderer() throws IOException {
super.stopRenderer();
- if (endNumber == -1) {
- // was not set on command line
- endNumber = getNumberOfPages();
- }
-
- Vector numbers = getInvalidPageNumbers();
- for (int i = numbers.size() - 1; i > -1; i--) {
- int page = ((Integer)numbers.elementAt(i)).intValue();
- pageViewportList.remove(page - 1);
- }
-
try {
printerJob.print();
} catch (PrinterException e) {
@@ -249,79 +154,4 @@ public class PrintRenderer extends Java2DRenderer implements Pageable {
clearViewportList();
}
- private static int getIntProperty(String name, int def) {
- String propValue = System.getProperty(name);
- if (propValue != null) {
- try {
- return Integer.parseInt(propValue);
- } catch (Exception e) {
- return def;
- }
- } else {
- return def;
- }
- }
-
- private Vector getInvalidPageNumbers() {
- Vector vec = new Vector();
- int max = getNumberOfPages();
- boolean isValid;
- for (int i = 1; i <= max; i++) {
- isValid = true;
- if (i < startNumber || i > endNumber) {
- isValid = false;
- } else if (mode != PagesMode.ALL) {
- if (mode == PagesMode.EVEN && (i % 2 != 0)) {
- isValid = false;
- } else if (mode == PagesMode.ODD && (i % 2 == 0)) {
- isValid = false;
- }
- }
-
- if (!isValid) {
- vec.add(new Integer(i));
- }
- }
- return vec;
- }
-
- /** {@inheritDoc} */
- public PageFormat getPageFormat(int pageIndex)
- throws IndexOutOfBoundsException {
- try {
- if (pageIndex >= getNumberOfPages()) {
- return null;
- }
-
- PageFormat pageFormat = new PageFormat();
-
- Paper paper = new Paper();
-
- Rectangle2D dim = getPageViewport(pageIndex).getViewArea();
- double width = dim.getWidth();
- double height = dim.getHeight();
-
- // if the width is greater than the height assume lanscape mode
- // and swap the width and height values in the paper format
- if (width > height) {
- paper.setImageableArea(0, 0, height / 1000d, width / 1000d);
- paper.setSize(height / 1000d, width / 1000d);
- pageFormat.setOrientation(PageFormat.LANDSCAPE);
- } else {
- paper.setImageableArea(0, 0, width / 1000d, height / 1000d);
- paper.setSize(width / 1000d, height / 1000d);
- pageFormat.setOrientation(PageFormat.PORTRAIT);
- }
- pageFormat.setPaper(paper);
- return pageFormat;
- } catch (FOPException fopEx) {
- throw new IndexOutOfBoundsException(fopEx.getMessage());
- }
- }
-
- /** {@inheritDoc} */
- public Printable getPrintable(int pageIndex)
- throws IndexOutOfBoundsException {
- return this;
- }
}
diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java
index 88e34e17a..05aade551 100644
--- a/src/java/org/apache/fop/render/rtf/RTFHandler.java
+++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java
@@ -242,9 +242,6 @@ public class RTFHandler extends FOEventHandler {
bFooterSpecified = false;
} catch (IOException ioe) {
handleIOTrouble(ioe);
- } catch (FOPException fope) {
- // TODO could we throw Exception in all FOEventHandler events?
- log.error("startPageSequence: " + fope.getMessage(), fope);
}
}
diff --git a/status.xml b/status.xml
index c2bb24a52..009c827c9 100644
--- a/status.xml
+++ b/status.xml
@@ -59,6 +59,10 @@
<action context="Renderers" dev="AC" importance="high" type="add">
Added de-duplication and externalization support for IOCA and GOCA data resource objects.
</action>
+ <action context="Renderers" dev="JM" type="add">
+ Added support for rendering pages using JPS (Java Printing System). See new example:
+ examples/embedding/java/ExamplesFO2JPSPrint.java
+ </action>
<action context="Renderers" dev="JM" type="add" fixes-bug="41687">
Restored ability to specify from/to and odd/even pages as well as the number of copies
for printing from the command-line.