aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/org/apache/fop/apps/CommandLineOptions.java40
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java22
-rw-r--r--src/java/org/apache/fop/apps/Fop.java7
-rw-r--r--src/java/org/apache/fop/area/PageViewport.java4
-rw-r--r--src/java/org/apache/fop/fo/Constants.java8
-rw-r--r--src/java/org/apache/fop/render/RendererFactory.java6
-rw-r--r--src/java/org/apache/fop/render/awt/AWTRenderer.java1115
-rw-r--r--src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java209
-rw-r--r--src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java12
-rw-r--r--src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif11
-rw-r--r--src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg126
-rw-r--r--src/java/org/apache/fop/render/bitmap/PNGRenderer.java116
-rw-r--r--src/java/org/apache/fop/render/bitmap/PNGRenderer_onthefly.java117
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFRenderer.java194
-rw-r--r--src/java/org/apache/fop/render/java2d/FontMetricsMapper.java (renamed from src/java/org/apache/fop/render/awt/FontMetricsMapper.java)12
-rw-r--r--src/java/org/apache/fop/render/java2d/FontSetup.java (renamed from src/java/org/apache/fop/render/awt/FontSetup.java)2
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java (renamed from src/java/org/apache/fop/render/awt/AWTFontMetrics.java)6
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java (renamed from src/java/org/apache/fop/render/awt/AWTGraphicsState.java)49
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DRenderer.java1114
-rw-r--r--src/java/org/apache/fop/render/java2d/RendererState.java (renamed from src/java/org/apache/fop/render/awt/RendererState.java)2
-rw-r--r--src/java/org/apache/fop/render/print/PrintRenderer.java (renamed from src/java/org/apache/fop/render/awt/AWTPrintRenderer.java)111
-rw-r--r--src/java/org/apache/fop/render/svg/SVGRenderer.java2
-rw-r--r--src/java/org/apache/fop/tools/anttasks/Fop.java11
23 files changed, 2109 insertions, 1187 deletions
diff --git a/src/java/org/apache/fop/apps/CommandLineOptions.java b/src/java/org/apache/fop/apps/CommandLineOptions.java
index edd0d8e5e..1462397e0 100644
--- a/src/java/org/apache/fop/apps/CommandLineOptions.java
+++ b/src/java/org/apache/fop/apps/CommandLineOptions.java
@@ -167,6 +167,10 @@ public class CommandLineOptions implements Constants {
i = i + parseMIFOutputOption(args, i);
} else if (args[i].equals("-rtf")) {
i = i + parseRTFOutputOption(args, i);
+ } else if (args[i].equals("-tiff")) {
+ i = i + parseTIFFOutputOption(args, i);
+ } else if (args[i].equals("-png")) {
+ i = i + parsePNGOutputOption(args, i);
} else if (args[i].equals("-print")) {
i = i + parsePrintOutputOption(args, i);
// show print help
@@ -304,6 +308,28 @@ public class CommandLineOptions implements Constants {
}
}
+ private int parseTIFFOutputOption(String[] args, int i) throws FOPException {
+ setOutputMode(RENDER_TIFF);
+ if ((i + 1 == args.length)
+ || (args[i + 1].charAt(0) == '-')) {
+ throw new FOPException("you must specify the tiff output file");
+ } else {
+ outfile = new File(args[i + 1]);
+ return 1;
+ }
+ }
+
+ private int parsePNGOutputOption(String[] args, int i) throws FOPException {
+ setOutputMode(RENDER_PNG);
+ if ((i + 1 == args.length)
+ || (args[i + 1].charAt(0) == '-')) {
+ throw new FOPException("you must specify the png output file");
+ } else {
+ outfile = new File(args[i + 1]);
+ return 1;
+ }
+ }
+
private int parsePrintOutputOption(String[] args, int i) throws FOPException {
setOutputMode(RENDER_PRINT);
return 0;
@@ -495,6 +521,8 @@ public class CommandLineOptions implements Constants {
case RENDER_TXT:
case RENDER_SVG:
case RENDER_RTF:
+ case RENDER_TIFF:
+ case RENDER_PNG:
return outputmode;
case RENDER_XML:
foUserAgent.getRendererOptions().put("fineDetail", isCoarseAreaXml());
@@ -607,7 +635,7 @@ public class CommandLineOptions implements Constants {
public static void printUsage() {
System.err.println(
"\nUSAGE\nFop [options] [-fo|-xml] infile [-xsl file] "
- + "[-awt|-pdf|-mif|-rtf|-pcl|-ps|-txt|-at|-print] <outfile>\n"
+ + "[-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl|-ps|-txt|-at|-print] <outfile>\n"
+ " [OPTIONS] \n"
+ " -d debug mode \n"
+ " -x dump configuration settings \n"
@@ -630,6 +658,8 @@ public class CommandLineOptions implements Constants {
+ " -awt input will be displayed on screen \n"
+ " -mif outfile input will be rendered as mif file (outfile req'd)\n"
+ " -rtf outfile input will be rendered as rtf file (outfile req'd)\n"
+ + " -tiff outfile input will be rendered as tiff file (outfile req'd)\n"
+ + " -png outfile input will be rendered as png file (outfile req'd)\n"
+ " -pcl outfile input will be rendered as pcl file (outfile req'd) \n"
+ " -ps outfile input will be rendered as PostScript file (outfile req'd) \n"
+ " -txt outfile input will be rendered as text file (outfile req'd) \n"
@@ -701,6 +731,14 @@ public class CommandLineOptions implements Constants {
log.info("rtf");
log.info("output file: " + outfile.toString());
break;
+ case RENDER_TIFF:
+ log.info("tiff");
+ log.info("output file: " + outfile.toString());
+ break;
+ case RENDER_PNG:
+ log.info("png");
+ log.info("output file: " + outfile.toString());
+ break;
case RENDER_PRINT:
log.info("print directly");
if (outfile != null) {
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index d15b5d735..2e5592ee4 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -19,12 +19,13 @@
package org.apache.fop.apps;
// Java
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
-import java.io.IOException;
-import java.io.InputStream;
// avalon configuration
import org.apache.avalon.framework.configuration.Configuration;
@@ -73,6 +74,7 @@ public class FOUserAgent {
private float px2mm = (25.4f / 72); //dpi (=25.4/dpi)
private HashMap rendererOptions = new java.util.HashMap();
private InputHandler inputHandler = null;
+ private File outputFile = null;
private Renderer rendererOverride = null;
private FOEventHandler foEventHandlerOverride = null;
private LayoutManagerMaker lmMakerOverride = null;
@@ -418,6 +420,22 @@ public class FOUserAgent {
}
/**
+ * Sets the output File.
+ * @param the output File
+ */
+ public void setOutputFile(File f){
+ this.outputFile = f;
+ }
+
+ /**
+ * Gets the output File.
+ * @return the output File
+ */
+ public File getOutputFile(){
+ return outputFile;
+ }
+
+ /**
* Returns the conversion factor from pixel units to millimeters. This
* depends on the desired reolution.
* @return float conversion factor
diff --git a/src/java/org/apache/fop/apps/Fop.java b/src/java/org/apache/fop/apps/Fop.java
index 90fb83d39..243448d29 100644
--- a/src/java/org/apache/fop/apps/Fop.java
+++ b/src/java/org/apache/fop/apps/Fop.java
@@ -1,6 +1,6 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
+ * Copyright 1999-2005 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
@@ -69,6 +69,8 @@ public class Fop implements Constants {
* <li>Fop.RENDER_TXT</li>
* <li>Fop.RENDER_SVG</li>
* <li>Fop.RENDER_RTF</li>
+ * <li>Fop.RENDER_TIFF</li>
+ * <li>Fop.RENDER_PNG</li>
* </ul>
* @param ua FOUserAgent object
* @throws IllegalArgumentException if an unsupported renderer type was requested.
@@ -149,6 +151,7 @@ public class Fop implements Constants {
bos = new BufferedOutputStream(new FileOutputStream(
options.getOutputFile()));
fop.setOutputStream(bos);
+ foUserAgent.setOutputFile(options.getOutputFile());
}
foUserAgent.getInputHandler().render(fop);
} finally {
diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java
index 2f1f7786d..cb7b524cf 100644
--- a/src/java/org/apache/fop/area/PageViewport.java
+++ b/src/java/org/apache/fop/area/PageViewport.java
@@ -170,7 +170,8 @@ public class PageViewport implements Resolvable, Cloneable {
* @return true if the page is resolved and can be rendered
*/
public boolean isResolved() {
- return unresolvedIDRefs == null;
+ return unresolvedIDRefs == null
+ || unresolvedIDRefs.size() == 0;
}
/**
@@ -395,6 +396,7 @@ public class PageViewport implements Resolvable, Cloneable {
Page p = (Page)page.clone();
PageViewport ret = new PageViewport(spm, pageNumberString,
p, (Rectangle2D)viewArea.clone());
+ ret.pageNumberString = pageNumberString;
return ret;
}
diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java
index 9a0423bc4..833105498 100644
--- a/src/java/org/apache/fop/fo/Constants.java
+++ b/src/java/org/apache/fop/fo/Constants.java
@@ -27,7 +27,7 @@ public interface Constants {
/** render constants for bounds checking */
int RENDER_MIN_CONST = 1;
- int RENDER_MAX_CONST = 10;
+ int RENDER_MAX_CONST = 12;
/** input / output not set */
int NOT_SET = 0;
/** input: fo file */
@@ -54,7 +54,11 @@ public interface Constants {
int RENDER_XML = 9;
/** output: RTF file */
int RENDER_RTF = 10;
-
+ /** output: TIFF file */
+ int RENDER_TIFF = 11;
+ /** output: PNG file */
+ int RENDER_PNG = 12;
+
// element constants
int FO_UNKNOWN_NODE = 0; // FObj base class
int FO_BASIC_LINK = 1;
diff --git a/src/java/org/apache/fop/render/RendererFactory.java b/src/java/org/apache/fop/render/RendererFactory.java
index 0cb87e29c..dbd94119d 100644
--- a/src/java/org/apache/fop/render/RendererFactory.java
+++ b/src/java/org/apache/fop/render/RendererFactory.java
@@ -53,9 +53,13 @@ public class RendererFactory {
case Constants.RENDER_AWT:
return new org.apache.fop.render.awt.AWTRenderer();
case Constants.RENDER_PRINT:
- return new org.apache.fop.render.awt.AWTPrintRenderer();
+ return new org.apache.fop.render.print.PrintRenderer();
case Constants.RENDER_PCL:
return new org.apache.fop.render.pcl.PCLRenderer();
+ case Constants.RENDER_TIFF:
+ return new org.apache.fop.render.bitmap.TIFFRenderer();
+ case Constants.RENDER_PNG:
+ return new org.apache.fop.render.bitmap.PNGRenderer();
case Constants.RENDER_PS:
return new org.apache.fop.render.ps.PSRenderer();
case Constants.RENDER_TXT:
diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java
index ecc8e28cf..a771a739f 100644
--- a/src/java/org/apache/fop/render/awt/AWTRenderer.java
+++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java
@@ -26,145 +26,46 @@ package org.apache.fop.render.awt;
*/
// Java
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.RenderingHints;
import java.awt.Toolkit;
-import java.awt.color.ColorSpace;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Line2D;
-import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferByte;
-import java.awt.image.MemoryImageSource;
-import java.awt.image.PixelInterleavedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.SampleModel;
-import java.awt.image.WritableRaster;
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.io.IOException;
-import java.io.OutputStream;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.GVTBuilder;
-import org.apache.batik.bridge.ViewBox;
-import org.apache.batik.gvt.GraphicsNode;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.BlockViewport;
-import org.apache.fop.area.CTM;
-import org.apache.fop.area.Page;
import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.Trait;
-import org.apache.fop.area.inline.Character;
-import org.apache.fop.area.inline.ForeignObject;
-import org.apache.fop.area.inline.Image;
-import org.apache.fop.area.inline.InlineArea;
-import org.apache.fop.area.inline.Leader;
-import org.apache.fop.area.inline.TextArea;
import org.apache.fop.datatypes.ColorType;
-import org.apache.fop.fo.Constants;
import org.apache.fop.fo.properties.ColorTypeProperty;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontMetrics;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.image.ImageFactory;
-import org.apache.fop.image.XMLImage;
-import org.apache.fop.render.AbstractRenderer;
-import org.apache.fop.render.RendererContext;
import org.apache.fop.render.awt.viewer.PreviewDialog;
import org.apache.fop.render.awt.viewer.Translator;
-import org.apache.fop.render.pdf.CTMHelper;
-import org.apache.fop.svg.SVGUserAgent;
-import org.apache.fop.traits.BorderProps;
-import org.w3c.dom.Document;
-import org.w3c.dom.svg.SVGDocument;
-import org.w3c.dom.svg.SVGSVGElement;
+import org.apache.fop.render.java2d.Java2DRenderer;
/**
- * The <code>Java2DRenderer</code> class provides the abstract technical
- * foundation for all rendering with the Java2D API. Renderers like
- * <code>AWTRenderer</code> subclass it and provide the concrete output paths.
- * <p>
- * A lot of the logic is performed by <code>AbstractRenderer</code>. The
- * class-variables <code>currentIPPosition</code> and
- * <code>currentBPPosition</code> hold the position of the currently rendered
- * area.
- * <p>
- * <code>AWTGraphicsState state</code> holds the <code>Graphics2D</code>,
- * which is used along the whole rendering. <code>state</code> also acts as a
- * stack (<code>state.push()</code> and <code>state.pop()</code>).
- * <p>
- * The rendering process is basically always the same:
- * <p>
- * <code>void renderXXXXX(Area area) {
- * //calculate the currentPosition
- * state.updateFont(name, size, null);
- * state.updateColor(ct, false, null);
- * state.getGraph.draw(new Shape(args));
- * }</code>
- *
+ * The AWTRender outputs the pages generated by the layout engine to a Swing
+ * window. This Swing window serves as default viewer for the -awt switch and as
+ * an example of how to embed the AWTRenderer into an AWT/Swing application.
*/
-public class AWTRenderer extends AbstractRenderer implements Printable,
- Pageable {
+public class AWTRenderer extends Java2DRenderer implements Pageable, Printable {
/** The MIME type for AWT-Rendering */
- public static final String MIME_TYPE = "application/awt";
-
- protected double scaleFactor = 100.0;
-
- protected int pageNumber = 0;
-
- private int pageWidth = 0;
-
- private int pageHeight = 0;
-
- private Vector pageViewportList = new java.util.Vector();
-
- private Vector pageList = new java.util.Vector();
-
- private Vector bufferedImageList = new java.util.Vector();
-
- protected BufferedImage currentPageImage = null;
-
- protected boolean antialiasing = true;
-
- protected boolean qualityRendering = true;
-
- /** The current state, holds a Graphics2D and its context */
- protected AWTGraphicsState state;
-
- /** a Line2D.Float used to draw text decorations and leaders */
- protected Line2D.Float line = new Line2D.Float();
-
- /** Font configuration */
- protected FontInfo fontInfo;
+ public static final String MIME_TYPE = "application/X-awt";
/** The resource bundle used for AWT messages. */
protected Translator translator = null;
- private Map fontNames = new java.util.Hashtable();
-
- private Map fontStyles = new java.util.Hashtable();
+ /** flag for debugging */
+ public boolean debug;
/**
* The preview dialog frame used for display of the documents. Also used as
@@ -172,95 +73,34 @@ public class AWTRenderer extends AbstractRenderer implements Printable,
*/
protected PreviewDialog frame;
- /** Flag for visual-debugging */
- public boolean debug = false;
-
public AWTRenderer() {
translator = new Translator();
}
public void setUserAgent(FOUserAgent foUserAgent) {
super.setUserAgent(foUserAgent);
- userAgent.setRendererOverride(this); // for document regeneration
createPreviewDialog();
}
- public FOUserAgent getUserAgent() {
- return userAgent;
- }
-
- /**
- * @see org.apache.fop.render.Renderer
- */
- public boolean supportsOutOfOrder() {
- return false;
- }
-
- public Translator getTranslator() {
- return translator;
- }
-
- /** @see org.apache.fop.render.AbstractRenderer */
- public String getMimeType() {
- return MIME_TYPE;
- }
-
- public void setupFontInfo(FontInfo inFontInfo) {
- // create a temp Image to test font metrics on
- fontInfo = inFontInfo;
- BufferedImage fontImage = new BufferedImage(100, 100,
- BufferedImage.TYPE_INT_RGB);
- FontSetup.setup(fontInfo, fontImage.createGraphics());
- }
-
- public int getPageNumber() {
- return pageNumber;
- }
-
- public void setPageNumber(int aValue) {
- pageNumber = aValue;
- }
+ public void renderPage(PageViewport pageViewport) throws IOException,
+ FOPException {
- public void setScaleFactor(double newScaleFactor) {
- scaleFactor = newScaleFactor;
- }
+ super.renderPage(pageViewport);
- public double getScaleFactor() {
- return scaleFactor;
- }
+ // Shows the page if it's the first one
+ if (getCurrentPageNumber() == 1) {
+ frame.showPage();
+ }
+ frame.setInfo();
- public void startRenderer(OutputStream out) throws IOException {
- // empty pageViewportList, in case of a reload from PreviewDialog
- pageViewportList.removeAllElements();
- pageList.removeAllElements();
- bufferedImageList.removeAllElements();
- System.out.println("\nRegion Types: 0-Before/Top, 1-Start/Left,"
- + " 2-Body, 3-End/Right, 4-After/Bottom");
}
public void stopRenderer() throws IOException {
+ super.stopRenderer();
frame.setStatus(translator.getString("Status.Show"));
- frame.showPage();
- // TODO set all vars to null for gc
- }
-
- // Printable Interface
- public PageFormat getPageFormat(int pos) {
- return null;
- }
-
- public Printable getPrintable(int pos) {
- return null;
- }
-
- public int getNumberOfPages() {
- return pageViewportList.size();
- }
-
- public int print(Graphics g, PageFormat format, int pos) {
- return 0;
}
+ /** Creates and initialize the AWT Viewer main window */
private PreviewDialog createPreviewDialog() {
frame = new PreviewDialog(userAgent);
frame.addWindowListener(new WindowAdapter() {
@@ -280,320 +120,92 @@ public class AWTRenderer extends AbstractRenderer implements Printable,
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
- frame.setVisible(true);
frame.setStatus(translator.getString("Status.Build.FO.tree"));
+ frame.setVisible(true);
return frame;
}
/**
- * This method override only stores the PageViewport in a vector. No actual
- * rendering performed -- this is done by getPageImage(pageNum) instead.
- *
- * @param pageViewport the <code>PageViewport</code> object supplied by
- * the Area Tree
- * @see org.apache.fop.render.Renderer
- */
- public void renderPage(PageViewport pageViewport) throws IOException,
- FOPException {
- pageViewportList.add(pageViewport);
- pageList.add(pageViewport.getPage().clone());
- bufferedImageList
- .add(getPageImage(pageViewport, pageViewport.getPage()));
- }
-
- public BufferedImage getBufferedPageImage(int pageNum) throws FOPException {
- return (BufferedImage) bufferedImageList.get(pageNum);
- }
-
- /**
- * Generates a desired page from the renderer's page viewport vector.
- *
- * @param pageNum the 0-based page number to generate
- * @return the <code>java.awt.image.BufferedImage</code> corresponding to
- * the page
- * @throws FOPException in case of an out-of-range page number requested
+ * @see java.awt.print.Printable#print(java.awt.Graphics,
+ * java.awt.print.PageFormat, int)
*/
- public BufferedImage getPageImage(PageViewport pageViewport, Page page)
- throws FOPException {
-
- Rectangle2D bounds = pageViewport.getViewArea();
- pageWidth = (int) Math.round(bounds.getWidth() / 1000f);
- pageHeight = (int) Math.round(bounds.getHeight() / 1000f);
-
- getLogger().info(
- "Rendering Page " + pageViewport.getPageNumberString()
- + " (pageWidth " + pageWidth + ", pageHeight "
- + pageHeight + ")");
-
- currentPageImage = new BufferedImage(
- (int) ((pageWidth * (int) scaleFactor) / 100),
- (int) ((pageHeight * (int) scaleFactor) / 100),
- BufferedImage.TYPE_INT_RGB);
-
- Graphics2D graphics = currentPageImage.createGraphics();
- graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
- RenderingHints.VALUE_FRACTIONALMETRICS_ON);
- if (antialiasing) {
- graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- }
- if (qualityRendering) {
- graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
- RenderingHints.VALUE_RENDER_QUALITY);
+ public int print(Graphics g, PageFormat pageFormat, int pageIndex)
+ throws PrinterException {
+ if (pageIndex >= getNumberOfPages()) {
+ return NO_SUCH_PAGE;
}
- // transform page based on scale factor supplied
- AffineTransform at = graphics.getTransform();
- at.scale(scaleFactor / 100.0, scaleFactor / 100.0);
- graphics.setTransform(at);
+ Graphics2D g2 = (Graphics2D) g;
- // draw page frame
- graphics.setColor(Color.white);
- graphics.fillRect(0, 0, pageWidth, pageHeight);
- graphics.setColor(Color.black);
- graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2);
- graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2);
- graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3);
- graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2);
- graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3);
-
- state = new AWTGraphicsState(graphics, this.fontInfo);
+ BufferedImage image;
+ try {
+ image = getPageImage(pageIndex);
+ } catch (FOPException e) {
+ e.printStackTrace();
+ return NO_SUCH_PAGE;
+ }
- // reset the current Positions
- currentBPPosition = 0;
- currentIPPosition = 0;
+ g2.drawImage(image, null, 0, 0);
- // this toggles the rendering of all areas
- renderPageAreas(page);
- return currentPageImage;
+ return PAGE_EXISTS;
}
- /**
- * Generates a desired page from the renderer's page viewport vector.
- *
- * @param pageNum the 0-based page number to generate
- * @return the <code>java.awt.image.BufferedImage</code> corresponding to
- * the page
- * @throws FOPException in case of an out-of-range page number requested
- */
- public BufferedImage getPageImage(int pageNum) throws FOPException {
- if (pageNum < 0 || pageNum >= pageViewportList.size()) {
- throw new FOPException("out-of-range page number (" + pageNum
- + ") requested; only " + pageViewportList.size()
- + " page(s) available.");
- }
- PageViewport pageViewport = (PageViewport) pageViewportList
- .get(pageNum);
- Page page = (Page) pageList.get(pageNum);
- return getPageImage(pageViewport, page);
- }
+ /** @see java.awt.print.Pageable#getPageFormat(int) */
+ public PageFormat getPageFormat(int pageIndex)
+ throws IndexOutOfBoundsException {
+ if (pageIndex >= getNumberOfPages())
+ return null;
- /**
- * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
- */
- protected void startVParea(CTM ctm) {
+ PageFormat pageFormat = new PageFormat();
- // push (and save) the current graphics state
- state.push();
+ Paper paper = new Paper();
+ pageFormat.setPaper(paper);
- // Set the given CTM in the graphics state
- state.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
+ Rectangle2D dim = getPageViewport(pageIndex).getViewArea();
+ double width = dim.getWidth();
+ double height = dim.getHeight();
- // TODO Set clip?
+ // 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);
+ }
+ return pageFormat;
}
- /**
- * @see org.apache.fop.render.AbstractRenderer#endVParea()
- */
- protected void endVParea() {
- state.pop();
+ /** @see java.awt.print.Pageable#getPrintable(int) */
+ public Printable getPrintable(int pageIndex)
+ throws IndexOutOfBoundsException {
+ return this;
}
- /**
- * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport,
- * List)
- */
- protected void renderBlockViewport(BlockViewport bv, List children) {
- // clip and position viewport if necessary
-
- // save positions
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- CTM ctm = bv.getCTM();
- int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
- int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
- float x, y;
- x = (float) (bv.getXOffset() + containingIPPosition) / 1000f;
- y = (float) (bv.getYOffset() + containingBPPosition) / 1000f;
-
- if (bv.getPositioning() == Block.ABSOLUTE
- || bv.getPositioning() == Block.FIXED) {
- // TODO not tested yet
- // For FIXED, we need to break out of the current viewports to the
- // one established by the page. We save the state stack for
- // restoration
- // after the block-container has been painted. See below.
- List breakOutList = null;
- if (bv.getPositioning() == Block.FIXED) {
- getLogger().debug("Block.FIXED --> break out");
- breakOutList = new java.util.ArrayList();
- Graphics2D graph;
- while (true) {
- graph = state.getGraph();
- if (state.pop() == null) {
- break;
- }
- breakOutList.add(0, graph); // Insert because of
- // stack-popping
- getLogger().debug("Adding to break out list: " + graph);
- }
- }
-
- CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
- ctm = tempctm.multiply(ctm);
-
- // This is the content-rect
- float width = (float) bv.getIPD() / 1000f;
- float height = (float) bv.getBPD() / 1000f;
-
- // Adjust for spaces (from margin or indirectly by start-indent etc.
- Integer spaceStart = (Integer) bv.getTrait(Trait.SPACE_START);
- if (spaceStart != null) {
- x += spaceStart.floatValue() / 1000;
- }
- Integer spaceBefore = (Integer) bv.getTrait(Trait.SPACE_BEFORE);
- if (spaceBefore != null) {
- y += spaceBefore.floatValue() / 1000;
- }
-
- float bpwidth = (borderPaddingStart + bv
- .getBorderAndPaddingWidthEnd()) / 1000f;
- float bpheight = (borderPaddingBefore + bv
- .getBorderAndPaddingWidthAfter()) / 1000f;
-
- drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight);
-
- // Now adjust for border/padding
- x += borderPaddingStart / 1000f;
- y += borderPaddingBefore / 1000f;
-
- if (bv.getClip()) {
- // saves the graphics state in a stack
- state.push();
-
- clip(x, y, width, height);
- }
-
- startVParea(ctm);
-
- renderBlocks(bv, children);
- endVParea();
-
- if (bv.getClip()) {
- // restores the last graphics state from the stack
- state.pop();
- }
-
- // clip if necessary
-
- if (breakOutList != null) {
- getLogger().debug(
- "Block.FIXED --> restoring context after break-out");
- Graphics2D graph;
- Iterator i = breakOutList.iterator();
- while (i.hasNext()) {
- graph = (Graphics2D) i.next();
- getLogger().debug("Restoring: " + graph);
- state.push();
- }
- }
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
-
- } else { // orientation = Block.STACK or RELATIVE
-
- Integer spaceBefore = (Integer) bv.getTrait(Trait.SPACE_BEFORE);
- if (spaceBefore != null) {
- currentBPPosition += spaceBefore.intValue();
- }
-
- // borders and background in the old coordinate system
- handleBlockTraits(bv);
-
- CTM tempctm = new CTM(containingIPPosition, currentBPPosition
- + containingBPPosition);
- ctm = tempctm.multiply(ctm);
-
- // Now adjust for border/padding
- x += borderPaddingStart / 1000f;
- y += borderPaddingBefore / 1000f;
-
- // clip if necessary
- if (bv.getClip()) {
- // saves the graphics state in a stack
- state.push();
- float width = (float) bv.getIPD() / 1000f;
- float height = (float) bv.getBPD() / 1000f;
- clip(x, y, width, height);
- }
-
- if (ctm != null) {
- startVParea(ctm);
- }
- renderBlocks(bv, children);
- if (ctm != null) {
- endVParea();
- }
-
- if (bv.getClip()) {
- // restores the last graphics state from the stack
- state.pop();
- }
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
-
- // Adjust BP position (alloc BPD + spaces)
- if (spaceBefore != null) {
- currentBPPosition += spaceBefore.intValue();
- }
- currentBPPosition += (int) (bv.getAllocBPD());
- Integer spaceAfter = (Integer) bv.getTrait(Trait.SPACE_AFTER);
- if (spaceAfter != null) {
- currentBPPosition += spaceAfter.intValue();
- }
- }
+ /** @see org.apache.fop.render.Renderer */
+ public boolean supportsOutOfOrder() {
+ return true; // TODO true?
}
- /**
- * Clip an area.
- */
- protected void clip() {
- // TODO via AWTGraphicsState.updateClip();
- // currentStream.add("W\n");
- // currentStream.add("n\n");
+ /** @return the Translator for this renderer */
+ public Translator getTranslator() {
+ return translator;
}
- /**
- * Clip an area. write a clipping operation given coordinates in the current
- * transform.
- * @param x the x coordinate
- * @param y the y coordinate
- * @param width the width of the area
- * @param height the height of the area
- */
- protected void clip(float x, float y, float width, float height) {
- // TODO via AWTGraphicsState.updateClip();
- // currentStream.add(x + " " + y + " " + width + " " + height + "
- // re ");
- clip();
+ /** @see org.apache.fop.render.AbstractRenderer */
+ public String getMimeType() {
+ return MIME_TYPE;
}
/**
- * Draw the background and borders. This draws the background and border
- * traits for an area given the position.
+ * Draws the background and borders and adds a basic debug view // TODO
+ * implement visual-debugging as standalone
+ *
+ * @see org.apache.fop.render.java2d.Java2DRenderer#drawBackAndBorders(org.apache.fop.area.Area,
+ * float, float, float, float)
*
* @param block the area to get the traits from
* @param startx the start x position
@@ -604,130 +216,11 @@ public class AWTRenderer extends AbstractRenderer implements Printable,
protected void drawBackAndBorders(Area area, float startx, float starty,
float width, float height) {
- if (debug) { // TODO implement visual-debugging as standalone
- // Renderer
+ if (debug) {
debugBackAndBorders(area, startx, starty, width, height);
}
- BorderProps bpsBefore = (BorderProps) area
- .getTrait(Trait.BORDER_BEFORE);
- BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER);
- BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START);
- BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END);
-
- // draw background
- Trait.Background back;
- back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
- if (back != null) {
-
- // Calculate padding rectangle
- float sx = startx;
- float sy = starty;
- float paddRectWidth = width;
- float paddRectHeight = height;
-
- if (bpsStart != null) {
- sx += bpsStart.width / 1000f;
- paddRectWidth -= bpsStart.width / 1000f;
- }
- if (bpsBefore != null) {
- sy += bpsBefore.width / 1000f;
- paddRectHeight -= bpsBefore.width / 1000f;
- }
- if (bpsEnd != null) {
- paddRectWidth -= bpsEnd.width / 1000f;
- }
- if (bpsAfter != null) {
- paddRectHeight -= bpsAfter.width / 1000f;
- }
-
- if (back.getColor() != null) {
- drawBackground(back, sx, sy, paddRectWidth, paddRectHeight);
- }
-
- // background image
- if (back.getFopImage() != null) {
- FopImage fopimage = back.getFopImage();
- if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
- clip(sx, sy, paddRectWidth, paddRectHeight);
- int horzCount = (int) ((paddRectWidth * 1000 / fopimage
- .getIntrinsicWidth()) + 1.0f);
- int vertCount = (int) ((paddRectHeight * 1000 / fopimage
- .getIntrinsicHeight()) + 1.0f);
- if (back.getRepeat() == EN_NOREPEAT) {
- horzCount = 1;
- vertCount = 1;
- } else if (back.getRepeat() == EN_REPEATX) {
- vertCount = 1;
- } else if (back.getRepeat() == EN_REPEATY) {
- horzCount = 1;
- }
- // change from points to millipoints
- sx *= 1000;
- sy *= 1000;
- if (horzCount == 1) {
- sx += back.getHoriz();
- }
- if (vertCount == 1) {
- sy += back.getVertical();
- }
- for (int x = 0; x < horzCount; x++) {
- for (int y = 0; y < vertCount; y++) {
- // place once
- Rectangle2D pos;
- pos = new Rectangle2D.Float(sx
- + (x * fopimage.getIntrinsicWidth()), sy
- + (y * fopimage.getIntrinsicHeight()),
- fopimage.getIntrinsicWidth(), fopimage
- .getIntrinsicHeight());
- putImage(back.getURL(), pos); // TODO test
- }
- }
-
- } else {
- getLogger().warn(
- "Can't find background image: " + back.getURL());
- }
- }
- }
-
- // draw border
- // BORDER_BEFORE
- if (bpsBefore != null) {
- int borderWidth = (int) Math.round((bpsBefore.width / 1000f)
- * (scaleFactor / 100f));
- state.updateColor(bpsBefore.color);
- state.getGraph().fillRect((int) startx, (int) starty, (int) width,
- borderWidth);
- }
- // BORDER_AFTER
- if (bpsAfter != null) {
- int borderWidth = (int) Math.round((bpsAfter.width / 1000f)
- * (scaleFactor / 100f));
- float sy = starty + height;
- state.updateColor(bpsAfter.color);
- state.getGraph().fillRect((int) startx,
- (int) (starty + height - borderWidth), (int) width,
- borderWidth);
- }
- // BORDER_START
- if (bpsStart != null) {
- int borderWidth = (int) Math.round((bpsStart.width / 1000f)
- * (scaleFactor / 100f));
- state.updateColor(bpsStart.color);
- state.getGraph().fillRect((int) startx, (int) starty, borderWidth,
- (int) height);
- }
- // BORDER_END
- if (bpsEnd != null) {
- int borderWidth = (int) Math.round((bpsEnd.width / 1000f)
- * (scaleFactor / 100f));
- float sx = startx + width;
- state.updateColor(bpsEnd.color);
- state.getGraph().fillRect((int) (startx + width - borderWidth),
- (int) starty, borderWidth, (int) height);
- }
-
+ super.drawBackAndBorders(area, startx, starty, width, height);
}
/** Draws a thin border around every area to help debugging */
@@ -746,452 +239,4 @@ public class AWTRenderer extends AbstractRenderer implements Printable,
// restores the last graphics state from the stack
state.pop();
}
-
- /**
- * Draw the Background Rectangle of a given area.
- *
- * @param back the Trait.Background
- * @param sx x coordinate of the rectangle to be filled.
- * @param sy y the y coordinate of the rectangle to be filled.
- * @param paddRectWidth the width of the rectangle to be filled.
- * @param paddRectHeight the height of the rectangle to be filled.
- */
- protected void drawBackground(Trait.Background back, float sx, float sy,
- float paddRectWidth, float paddRectHeight) {
-
- state.updateColor(back.getColor());
- state.getGraph().fillRect((int) sx, (int) sy, (int) paddRectWidth,
- (int) paddRectHeight);
- }
-
- /**
- * Handle block traits. The block could be any sort of block with any
- * positioning so this should render the traits such as border and
- * background in its position.
- *
- * @param block the block to render the traits
- */
- protected void handleBlockTraits(Block block) {
- // copied from pdf
- int borderPaddingStart = block.getBorderAndPaddingWidthStart();
- int borderPaddingBefore = block.getBorderAndPaddingWidthBefore();
-
- float startx = currentIPPosition / 1000f;
- float starty = currentBPPosition / 1000f;
- float width = block.getIPD() / 1000f;
- float height = block.getBPD() / 1000f;
-
- startx += block.getStartIndent() / 1000f;
- startx -= block.getBorderAndPaddingWidthStart() / 1000f;
- width += borderPaddingStart / 1000f;
- width += block.getBorderAndPaddingWidthEnd() / 1000f;
- height += borderPaddingBefore / 1000f;
- height += block.getBorderAndPaddingWidthAfter() / 1000f;
-
- drawBackAndBorders(block, startx, starty, width, height);
- }
-
- /**
- * @see org.apache.fop.render.Renderer#renderText(TextArea)
- */
- public void renderText(TextArea text) {
-
- float x = currentIPPosition;
- float y = currentBPPosition + text.getOffset(); // baseline
-
- String name = (String) text.getTrait(Trait.FONT_NAME);
- int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
- state.updateFont(name, size, null);
-
- ColorType ct = (ColorType) text.getTrait(Trait.COLOR);
- state.updateColor(ct, false, null);
-
- String s = text.getTextArea();
- state.getGraph().drawString(s, x / 1000f, y / 1000f);
-
- getLogger().debug(
- "renderText(): \"" + s + "\", x: " + x + ", y: " + y + state);
-
- // rendering text decorations
- FontMetrics metrics = fontInfo.getMetricsFor(name);
- Font fs = new Font(name, metrics, size);
- renderTextDecoration(fs, text, y, x);
-
- super.renderText(text);
- }
-
- /**
- * @see org.apache.fop.render.Renderer#renderCharacter(Character)
- */
- public void renderCharacter(Character ch) {
-
- float x = currentIPPosition;
- float y = currentBPPosition + ch.getOffset(); // baseline
-
- String name = (String) ch.getTrait(Trait.FONT_NAME);
- int size = ((Integer) ch.getTrait(Trait.FONT_SIZE)).intValue();
- state.updateFont(name, size, null);
-
- ColorType ct = (ColorType) ch.getTrait(Trait.COLOR);
- state.updateColor(ct, false, null);
-
- String s = ch.getChar();
- state.getGraph().drawString(s, x / 1000f, y / 1000f);
-
- getLogger().debug(
- "renderCharacter(): \"" + s + "\", x: " + x + ", y: " + y
- + state);
-
- // rendering text decorations
- FontMetrics metrics = fontInfo.getMetricsFor(name);
- Font fs = new Font(name, metrics, size);
- renderTextDecoration(fs, ch, y, x);
-
- super.renderCharacter(ch);
- }
-
- /**
- * Paints the text decoration marks.
- * @param fs Current font
- * @param inline inline area to paint the marks for
- * @param baseline position of the baseline
- * @param startIPD start IPD
- */
- protected void renderTextDecoration(Font fs, InlineArea inline,
- float baseline, float startIPD) {
-
- boolean hasTextDeco = inline.hasUnderline() || inline.hasOverline()
- || inline.hasLineThrough();
-
- if (hasTextDeco) {
- state.updateStroke((fs.getDescender() / (-8 * 1000f)),
- Constants.EN_SOLID);
- float endIPD = startIPD + inline.getIPD();
- if (inline.hasUnderline()) {
- ColorType ct = (ColorType) inline
- .getTrait(Trait.UNDERLINE_COLOR);
- state.updateColor(ct, false, null);
- float y = baseline - fs.getDescender() / 2;
- line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f,
- y / 1000f);
- state.getGraph().draw(line);
- }
- if (inline.hasOverline()) {
- ColorType ct = (ColorType) inline
- .getTrait(Trait.OVERLINE_COLOR);
- state.updateColor(ct, false, null);
- float y = (float) (baseline - (1.1 * fs.getCapHeight()));
- line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f,
- y / 1000f);
- state.getGraph().draw(line);
- }
- if (inline.hasLineThrough()) {
- ColorType ct = (ColorType) inline
- .getTrait(Trait.LINETHROUGH_COLOR);
- state.updateColor(ct, false, null);
- float y = (float) (baseline - (0.45 * fs.getCapHeight()));
- line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f,
- y / 1000f);
- state.getGraph().draw(line);
- }
- }
- }
-
- /**
- * Render leader area. This renders a leader area which is an area with a
- * rule.
- *
- * @param area the leader area to render
- */
- public void renderLeader(Leader area) {
-
- // TODO leader-length: 25%, 50%, 75%, 100% not working yet
- // TODO Colors do not work on Leaders yet
-
- float startx = ((float) currentIPPosition) / 1000f;
- float starty = ((currentBPPosition + area.getOffset()) / 1000f);
- float endx = (currentIPPosition + area.getIPD()) / 1000f;
-
- ColorType ct = (ColorType) area.getTrait(Trait.COLOR);
- state.updateColor(ct, true, null);
-
- line.setLine(startx, starty, endx, starty);
- float thickness = area.getRuleThickness() / 1000f;
-
- int style = area.getRuleStyle();
- switch (style) {
- case EN_SOLID:
- case EN_DOTTED:
- case EN_DASHED:
- state.updateStroke(thickness, style);
- state.getGraph().draw(line);
- break;
- case EN_DOUBLE:
-
- state.updateStroke(thickness / 3f, EN_SOLID); // only a third
-
- // upper Leader
- line.setLine(startx, starty, endx, starty);
- state.getGraph().draw(line);
- // lower Leader
- line.setLine(startx, starty + 2 * thickness, endx, starty + 2
- * thickness);
- state.getGraph().draw(line);
-
- break;
-
- case EN_GROOVE:
- // The rule looks as though it were carved into the canvas.
- // (Top/left half of the rule's thickness is the
- // color specified; the other half is white.)
-
- state.updateStroke(thickness / 2f, EN_SOLID); // only the half
-
- // upper Leader
- line.setLine(startx, starty, endx, starty);
- state.getGraph().draw(line);
- // lower Leader
- line.setLine(startx, starty + thickness, endx, starty + thickness);
- state.getGraph().setColor(Color.WHITE);
- state.getGraph().draw(line);
-
- // TODO the implementation could be nicer, f.eg. with triangles at
- // the tip of the lines. See also RenderX's implementation (looks
- // like a button)
-
- break;
-
- case EN_RIDGE:
- // The opposite of "groove", the rule looks as though it were
- // coming out of the canvas. (Bottom/right half of the rule's
- // thickness is the color specified; the other half is white.)
-
- state.updateStroke(thickness / 2f, EN_SOLID); // only the half
-
- // lower Leader
- line.setLine(startx, starty + thickness, endx, starty + thickness);
- state.getGraph().draw(line);
- // upperLeader
- line.setLine(startx, starty, endx, starty);
- state.getGraph().setColor(Color.WHITE);
- state.getGraph().draw(line);
-
- // TODO the implementation could be nicer, f.eg. with triangles at
- // the tip of the lines. See also RenderX's implementation (looks
- // like a button)
-
- break;
-
- case EN_NONE:
- // No rule is drawn
- break;
-
- } // end switch
-
- super.renderLeader(area);
- }
-
- /**
- * @see org.apache.fop.render.AbstractRenderer#renderImage(Image,
- * Rectangle2D)
- */
- public void renderImage(Image image, Rectangle2D pos) {
- // endTextObject();
- String url = image.getURL();
- putImage(url, pos);
- }
-
- /**
- * draws an image
- *
- * @param url URL of the bitmap
- * @param pos Position of the bitmap
- */
- protected void putImage(String pUrl, Rectangle2D pos) {
-
- int x = currentIPPosition; // TODO + area.getXOffset();
- int y = currentBPPosition;
- String url = ImageFactory.getURL(pUrl);
-
- ImageFactory fact = ImageFactory.getInstance();
- FopImage fopimage = fact.getImage(url, userAgent);
-
- if (fopimage == null) {
- return;
- }
- if (!fopimage.load(FopImage.DIMENSIONS)) {
- return;
- }
- int w = fopimage.getWidth();
- int h = fopimage.getHeight();
- String mime = fopimage.getMimeType();
- if ("text/xml".equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
- Document doc = ((XMLImage) fopimage).getDocument();
- String ns = ((XMLImage) fopimage).getNameSpace();
- renderDocument(doc, ns, pos);
-
- } else if ("image/svg+xml".equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
- Document doc = ((XMLImage) fopimage).getDocument();
- renderSVGDocument(doc, pos); // TODO check if ok.
-
- } else if ("image/eps".equals(mime)) {
- getLogger().warn("EPS images are not supported by this renderer");
- currentBPPosition += (h * 1000);
- } else if ("image/jpeg".equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
-
- // TODO Load JPEGs rather through fopimage.load(FopImage.BITMAP),
- // but JpegImage will need to be extended for that
-
- //url = url.substring(7);
- //url = "C:/eclipse/myWorkbenches/fop4/xml-fop/examples/fo" + url;
- java.awt.Image awtImage = new javax.swing.ImageIcon(url).getImage();
-
- state.getGraph().drawImage(awtImage, (int) (x / 1000f),
- (int) (y / 1000f), (int) w, h, null);
- currentBPPosition += (h * 1000);
- } else {
- if (!fopimage.load(FopImage.BITMAP)) {
- getLogger().warn("Loading of bitmap failed: " + url);
- return;
- }
-
- byte[] raw = fopimage.getBitmaps();
-
- //TODO Hardcoded color and sample models, FIX ME!
- ColorModel cm = new ComponentColorModel(
- ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
- false, false, ColorModel.OPAQUE, DataBuffer.TYPE_BYTE);
- SampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
- w, h, 3, w * 3, new int[] {0, 1, 2});
- DataBuffer dbuf = new DataBufferByte(raw, w * h * 3);
-
- WritableRaster raster = Raster.createWritableRaster(sampleModel, dbuf, null);
-
- java.awt.Image awtImage;
- // Combine the color model and raster into a buffered image
- awtImage = new BufferedImage(cm, raster, false, null);
-
- state.getGraph().drawImage(awtImage, (int) (x / 1000f),
- (int) (y / 1000f), (int) w, h, null);
- currentBPPosition += (h * 1000);
- }
- }
-
- /**
- * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject,
- * Rectangle2D)
- */
- public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
- Document doc = fo.getDocument();
- String ns = fo.getNameSpace();
- if (ns.equals("http://www.w3.org/2000/svg")) {
- renderSVGDocument(doc, pos);
- } else {
- renderDocument(doc, ns, pos);
- }
- // this.currentXPosition += area.getContentWidth();
- }
-
- /**
- * Renders an XML document (SVG for example).
- *
- * @param doc DOM document representing the XML document
- * @param ns Namespace for the document
- * @param pos Position on the page
- */
- public void renderDocument(Document doc, String ns, Rectangle2D pos) {
- RendererContext context;
- context = new RendererContext(MIME_TYPE);
- context.setUserAgent(userAgent);
- // TODO implement
- /*
- * context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc);
- * context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream);
- * context.setProperty(PDFXMLHandler.PDF_STATE, currentState);
- * context.setProperty(PDFXMLHandler.PDF_PAGE, currentPage);
- * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext == null ?
- * currentPage : currentContext);
- * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext);
- * context.setProperty(PDFXMLHandler.PDF_STREAM, currentStream);
- * context.setProperty(PDFXMLHandler.PDF_XPOS, new
- * Integer(currentIPPosition + (int) pos.getX()));
- * context.setProperty(PDFXMLHandler.PDF_YPOS, new
- * Integer(currentBPPosition + (int) pos.getY()));
- * context.setProperty(PDFXMLHandler.PDF_FONT_INFO, fontInfo);
- * context.setProperty(PDFXMLHandler.PDF_FONT_NAME, currentFontName);
- * context.setProperty(PDFXMLHandler.PDF_FONT_SIZE, new
- * Integer(currentFontSize));
- * context.setProperty(PDFXMLHandler.PDF_WIDTH, new Integer((int)
- * pos.getWidth())); context.setProperty(PDFXMLHandler.PDF_HEIGHT, new
- * Integer((int) pos.getHeight())); renderXML(userAgent, context, doc,
- * ns);
- */
- }
-
- protected void renderSVGDocument(Document doc, Rectangle2D pos) {
-
- int x = currentIPPosition; // TODO + area.getXOffset();
- int y = currentBPPosition;
-
- RendererContext context;
- context = new RendererContext(MIME_TYPE);
- context.setUserAgent(userAgent);
-
- SVGUserAgent ua = new SVGUserAgent(context.getUserAgent()
- .getPixelUnitToMillimeter(), new AffineTransform());
-
- GVTBuilder builder = new GVTBuilder();
- BridgeContext ctx = new BridgeContext(ua);
-
- GraphicsNode root;
- try {
- root = builder.build(ctx, doc);
- } catch (Exception e) {
- getLogger().error(
- "svg graphic could not be built: " + e.getMessage(), e);
- return;
- }
- float w = (float) ctx.getDocumentSize().getWidth() * 1000f;
- float h = (float) ctx.getDocumentSize().getHeight() * 1000f;
-
- // correct integer roundoff
- state.getGraph().translate(x / 1000, y / 1000);
-
- SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
- AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
- w / 1000f, h / 1000f);
- AffineTransform inverse = null;
- try {
- inverse = at.createInverse();
- } catch (NoninvertibleTransformException e) {
- getLogger().warn(e);
- }
- if (!at.isIdentity()) {
- state.getGraph().transform(at);
- }
-
- try {
- root.paint(state.getGraph());
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- if (inverse != null && !inverse.isIdentity()) {
- state.getGraph().transform(inverse);
- }
- // correct integer roundoff
- // currentState.getCurrentGraphics().translate(-x / 1000f, y / 1000f -
- // pageHeight);
- state.getGraph().translate(-(x + 500) / 1000,
- (y + 500) / 1000 - pageHeight);
- }
}
diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java b/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java
index 340eeec1d..b1e6e0c29 100644
--- a/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java
+++ b/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java
@@ -4,9 +4,9 @@
* 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.
@@ -15,14 +15,17 @@
*/
/* $Id$ */
-
+
+// Originally contributed by:
+// Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com,
+// Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com,
+// Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com
package org.apache.fop.render.awt.viewer;
-//Java
+// Java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
-import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
@@ -44,9 +47,11 @@ import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.JButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
@@ -54,15 +59,9 @@ import org.apache.fop.apps.Fop;
import org.apache.fop.fo.Constants;
import org.apache.fop.render.awt.AWTRenderer;
-/**
- * AWT Viewer main window.
- * Originally contributed by:
- * Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com,
- * Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com,
- * Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com
- */
+/** AWT Viewer main window. */
public class PreviewDialog extends JFrame {
-
+
/** The Translator for localization */
protected Translator translator;
/** The AWT renderer */
@@ -72,12 +71,22 @@ public class PreviewDialog extends JFrame {
/** The Fop object used for refreshing/reloading the view */
protected Fop fop;
+ /** The number of the page which is currently visible */
private int currentPage = 0;
- private int pageCount = 0;
+
+ /** The Reloader, when the user clicks on menu "reload" */
private Reloader reloader;
+
+ /** The JCombobox to rescale the rendered page view */
private JComboBox scale;
+
+ /** The JLabel for the process status bar */
private JLabel processStatus;
+
+ /** The JLabel that holds the rendered page */
private JLabel pageLabel;
+
+ /** The JLabel information status bar */
private JLabel infoStatus;
/**
@@ -92,7 +101,7 @@ public class PreviewDialog extends JFrame {
//Commands aka Actions
Command printAction = new Command(translator.getString("Menu.Print"), "Print") {
public void doit() {
- print();
+ startPrinterJob();
}
};
Command firstPageAction = new Command(translator.getString("Menu.First.page"),
@@ -124,11 +133,16 @@ public class PreviewDialog extends JFrame {
}
};
Command debugAction = new Command(" Debug") {
- //TODO use Translator
+ // TODO use Translator
public void doit() {
debug();
}
};
+ Command aboutAction = new Command("About FOP", "fopLogo") {
+ public void doit() {
+ startHelpAbout();
+ }
+ };
//set the system look&feel
try {
@@ -146,6 +160,8 @@ public class PreviewDialog extends JFrame {
//Page view stuff
pageLabel = new JLabel();
+ pageLabel.setHorizontalAlignment(0 /* CENTER */);
+ pageLabel.setBorder(new EmptyBorder(20, 0, 20, 0));
JScrollPane previewArea = new JScrollPane(pageLabel);
previewArea.getViewport().setBackground(Color.gray);
previewArea.setMinimumSize(new Dimension(50, 50));
@@ -159,20 +175,20 @@ public class PreviewDialog extends JFrame {
scale.addItem("100%");
scale.addItem("150%");
scale.addItem("200%");
+ scale.addItem("400%");
scale.setMaximumSize(new Dimension(80, 24));
scale.setPreferredSize(new Dimension(80, 24));
+ scale.setSelectedItem("100%");
scale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scaleActionPerformed(e);
}
});
- scale.setSelectedItem("100%");
- renderer.setScaleFactor(100.0);
//Menu
setJMenuBar(setupMenu());
- //Toolbar
+ // Toolbar
JToolBar toolBar = new JToolBar();
toolBar.add(printAction);
toolBar.add(reloadAction);
@@ -181,21 +197,24 @@ public class PreviewDialog extends JFrame {
toolBar.add(previousPageAction);
toolBar.add(nextPageAction);
toolBar.add(lastPageAction);
- toolBar.addSeparator();
+ toolBar.addSeparator(new Dimension(20,0));
toolBar.add(new JLabel(translator.getString("Menu.Zoom")));
toolBar.add(scale);
toolBar.addSeparator();
toolBar.add(debugAction);
+ toolBar.addSeparator(new Dimension(60,0));
+ toolBar.add(aboutAction);
getContentPane().add(toolBar, BorderLayout.NORTH);
- //Status bar
+
+ // Status bar
JPanel statusBar = new JPanel();
processStatus = new JLabel();
processStatus.setBorder(BorderFactory.createCompoundBorder(
- BorderFactory.createEtchedBorder(),
+ BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(0, 3, 0, 0)));
infoStatus = new JLabel();
infoStatus.setBorder(BorderFactory.createCompoundBorder(
- BorderFactory.createEtchedBorder(),
+ BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(0, 3, 0, 0)));
statusBar.setLayout(new GridBagLayout());
@@ -229,7 +248,7 @@ public class PreviewDialog extends JFrame {
//Adds mostly the same actions, but without icons
menu.add(new Command(translator.getString("Menu.Print")) {
public void doit() {
- print();
+ startPrinterJob();
}
});
// inputHandler must be set to allow reloading
@@ -305,6 +324,11 @@ public class PreviewDialog extends JFrame {
setScale(200.0);
}
});
+ subMenu.add(new Command("400%") {
+ public void doit() {
+ setScale(400.0);
+ }
+ });
menu.add(subMenu);
menu.addSeparator();
menu.add(new Command(translator.getString("Menu.Default.zoom")) {
@@ -323,9 +347,7 @@ public class PreviewDialog extends JFrame {
return menuBar;
}
- /**
- * Shows the About box
- */
+ /** Shows the About box */
private void startHelpAbout() {
PreviewDialogAboutBox dlg = new PreviewDialogAboutBox(this, translator);
//Centers the box
@@ -343,8 +365,8 @@ public class PreviewDialog extends JFrame {
*/
private void goToPage(int number) {
currentPage = number;
- renderer.setPageNumber(number);
showPage();
+ setInfo();
}
/**
@@ -358,12 +380,11 @@ public class PreviewDialog extends JFrame {
goToPage(currentPage);
}
-
/**
* Shows the next page.
*/
private void goToNextPage() {
- if (currentPage >= pageCount - 1) {
+ if (currentPage >= renderer.getNumberOfPages() - 1) {
return;
}
currentPage++;
@@ -374,10 +395,10 @@ public class PreviewDialog extends JFrame {
* Shows the last page.
*/
private void goToLastPage() {
- if (currentPage == pageCount - 1) {
+ if (currentPage == renderer.getNumberOfPages() - 1) {
return;
}
- currentPage = pageCount - 1;
+ currentPage = renderer.getNumberOfPages() - 1;
goToPage(currentPage);
}
@@ -396,26 +417,38 @@ public class PreviewDialog extends JFrame {
*/
private void debug(){
renderer.debug = !renderer.debug;
- showPage();
+ reload();
}
/**
- * This class is used to reload document in
- * a thread safe way.
+ * This class is used to reload document in a thread safe way.
*/
private class Reloader extends Thread {
public void run() {
+
+ if (!renderer.renderingDone) {
+ // do not allow the reloading while FOP is
+ // still rendering
+ JOptionPane.showMessageDialog(getContentPane(),
+ "Cannot perform the requested operation until "
+ + "all page are rendererd. Please wait",
+ "Please wait ", 1 /* INFORMATION_MESSAGE */);
+ return;
+ }
+
if (fop == null) {
fop = new Fop(Constants.RENDER_AWT, foUserAgent);
}
-
+
pageLabel.setIcon(null);
- infoStatus.setText("");
+ int savedCurrentPage = currentPage;
currentPage = 0;
+ renderer.clearViewportList();
try {
setStatus(translator.getString("Status.Build.FO.tree"));
foUserAgent.getInputHandler().render(fop);
+ goToPage(savedCurrentPage);
setStatus(translator.getString("Status.Show"));
} catch (FOPException e) {
reportException(e);
@@ -433,16 +466,14 @@ public class PreviewDialog extends JFrame {
(int)getLocation().getY() + 50);
d.setVisible(true);
currentPage = d.getPageNumber();
- if (currentPage < 1 || currentPage > pageCount) {
+ if (currentPage < 1 || currentPage > renderer.getNumberOfPages()) {
return;
}
currentPage--;
goToPage(currentPage);
}
- /**
- * Shows the first page.
- */
+ /** Shows the first page. */
private void goToFirstPage() {
if (currentPage == 0) {
return;
@@ -451,24 +482,20 @@ public class PreviewDialog extends JFrame {
goToPage(currentPage);
}
- /**
- * Prints the document
- */
- private void print() {
+ /** Prints the document */
+ private void startPrinterJob() {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPageable(renderer);
if (pj.printDialog()) {
try {
pj.print();
- } catch (PrinterException pe) {
- pe.printStackTrace();
+ } catch (PrinterException e) {
+ e.printStackTrace();
}
}
}
- /**
- * Scales page image
- */
+ /** Scales page image */
private void setScale(double scaleFactor) {
if (scaleFactor == 25.0) {
scale.setSelectedIndex(0);
@@ -482,11 +509,11 @@ public class PreviewDialog extends JFrame {
scale.setSelectedIndex(4);
} else if (scaleFactor == 200.0) {
scale.setSelectedIndex(5);
+ } else if (scaleFactor == 400.0) {
+ scale.setSelectedIndex(6);
}
- renderer.setScaleFactor(scaleFactor);
- if (renderer.getNumberOfPages() != 0) {
- showPage();
- }
+ renderer.setScaleFactor(scaleFactor / 100d);
+ reload();
}
private void scaleActionPerformed(ActionEvent e) {
@@ -502,32 +529,50 @@ public class PreviewDialog extends JFrame {
SwingUtilities.invokeLater(new ShowStatus(message));
}
- /**
- * This class is used to show status in a thread safe way.
- */
+ /** This class is used to show status in a thread safe way. */
private class ShowStatus implements Runnable {
- /**
- * The message to display
- */
+
+ /** The message to display */
private String message;
+
/**
- * Constructs ShowStatus thread
+ * Constructs ShowStatus thread
* @param message message to display
*/
public ShowStatus(String message) {
this.message = message;
}
-
+
public void run() {
processStatus.setText(message.toString());
}
}
/**
- * Starts rendering process and shows the current page.
+ * Updates the message to be shown in the info bar in a thread safe way.
*/
- public void showPage() {
+ public void setInfo() {
+ SwingUtilities.invokeLater(new ShowInfo());
+ }
+
+ /** This class is used to show info in a thread safe way. */
+ private class ShowInfo implements Runnable {
+
+ public void run() {
+
+ String message = translator.getString("Status.Page") + " "
+ + (currentPage + 1) + " "
+ + translator.getString("Status.of") + " "
+ + renderer.getCurrentPageNumber();
+
+ infoStatus.setText(message);
+ }
+ }
+
+ /** Starts rendering process and shows the current page. */
+ public synchronized void showPage() {
ShowPageImage viewer = new ShowPageImage();
+
if (SwingUtilities.isEventDispatchThread()) {
viewer.run();
} else {
@@ -535,38 +580,25 @@ public class PreviewDialog extends JFrame {
}
}
-
- /**
- * This class is used to update the page image
- * in a thread safe way.
- */
+ /** This class is used to render the page image in a thread safe way. */
private class ShowPageImage implements Runnable {
+
/**
- * The run method that does the actual updating
+ * The run method that does the actual rendering of the viewed page
*/
public void run() {
+
+ setStatus(translator.getString("Status.Build.FO.tree"));
+
+ BufferedImage pageImage = null;
try {
- BufferedImage pageImage = null;
- Graphics graphics = null;
-
pageImage = renderer.getPageImage(currentPage);
- if (pageImage == null)
- return;
- graphics = pageImage.getGraphics();
- graphics.setColor(Color.black);
- graphics.drawRect(0, 0, pageImage.getWidth() - 1,
- pageImage.getHeight() - 1);
-
- pageLabel.setIcon(new ImageIcon(pageImage));
- pageCount = renderer.getNumberOfPages();
-
- // Update status bar
- infoStatus.setText(translator.getString("Status.Page") + " "
- + (currentPage + 1) + " "
- + translator.getString("Status.of") + " " + pageCount);
} catch (FOPException e) {
reportException(e);
}
+ pageLabel.setIcon(new ImageIcon(pageImage));
+
+ setStatus(translator.getString("Status.Show"));
}
}
@@ -581,10 +613,9 @@ public class PreviewDialog extends JFrame {
getContentPane(),
"<html><b>" + msg + ":</b><br>"
+ e.getClass().getName() + "<br>"
- + e.getMessage() + "</html>",
+ + e.getMessage() + "</html>",
translator.getString("Exception.Error"),
JOptionPane.ERROR_MESSAGE
);
}
}
-
diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java b/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java
index 9974f841e..45535aa44 100644
--- a/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java
+++ b/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java
@@ -1,12 +1,12 @@
/*
* Copyright 1999-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.
@@ -15,7 +15,7 @@
*/
/* $Id$ */
-
+
package org.apache.fop.render.awt.viewer;
//Java
@@ -65,9 +65,9 @@ public class PreviewDialogAboutBox extends Dialog implements ActionListener {
JPanel insetsPanel3 = new JPanel();
okButton = new JButton();
JLabel imageControl1 = new JLabel();
- imageControl1.setIcon(new ImageIcon(getClass().getResource("images/fop.gif")));
+ imageControl1.setIcon(new ImageIcon(getClass().getResource("images/logo_big.jpg")));
JLabel label1 = new JLabel(translator.getString("About.Product"));
- JLabel label2 = new JLabel(translator.getString("About.Version")
+ JLabel label2 = new JLabel(translator.getString("About.Version")
+ " " + Fop.getVersion());
JLabel label3 = new JLabel(translator.getString("About.Copyright"));
panel1.setLayout(new BorderLayout());
diff --git a/src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif b/src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif
new file mode 100644
index 000000000..3d1a74ee7
--- /dev/null
+++ b/src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif
@@ -0,0 +1,11 @@
+GIF89a,� �#G�<����]k}}}RRX���666wpt������%%%������\\\222iiibbb������BBB���W:���???DED===ppp����������$BWVW���""!ddd���� =```ttu���������RRR��ƴ��xxx�K���llljjjCBE!*&OOO������KKK$---���,,,fff)))**+^^^dcc[Z[ooo������������������vvv�����������������ԗ�������������㖖���³�����sss��������ꇇ��������������������������������ᬬ�������HHH������6 J�����ӌ-6= @pvq'('���N///NNRXW[l8-IJK���GTN�������+! %�����ѩ=���������LLL9=?C/D���qsu���������ghg\D:ggl?���@GE��?��w�����Ԋ������������|*�2`������u5f�Ea�p_�����oyu���"!KPT���^EE���7L����q}�R� .�??T V 433�����˶�?�>PdKMrxvFFL�����貚�#$#���hfl���˵u���,85������W\_���o?O 8���]]]�Fefg?ï¿½ï¿½é¤§ï ª,,.^e_�
+?�A�����̳��F+?@=>��J?0� 5�?Y�UV�N�Et>Ey5IpR?��1$+������h)������!�,,�?�H��C5P�)�4�{4�G��ŋ-���R5w�2V|2Q�Ɍm��#*T��$Ŝ�褦�6� ��줓'`�����-Z\p!A��5FHE"�9��������@��&|�Q�„ )l���F� � 2rk 1n���(A?+�bӘ9$a��gd�":�Dr���!�,t`����v�ȷ�b�o�F�4��(�<�� '8z��_�B�  ����ѯ]���{��I)t
+����%��\tb�G?�����\� �#@EB�oQ������EE?]�
+6p�B
+K���!�wN=�����X�$ZH�? �EV��\DS�5� ��(�G8��C?Hlg�3�?� ���U(�@h�3@�L`�T�H/5tS:�S@rx?1�
+A�$e1�
+� �PB��p��<��1��?)��3�?�sTı6��Yn�?l ��A?�<pG!æˆ ï¿½�ij�1���?h ���Bc�Bg�N�R?Ñ€W�aL?D?D'����="@�M:��PD?=T��!PP�?UP$�J��`Ei�@%S(Q)�XÒŠ*���G ���RL�?]�hIe$x�9�P�=��6�r�=pѨ
+r�$"��`?� lQ�P�@% pF(̈�
+_���P����C��6
+9lca�B!�`h�C?t�In���&
+0H�vH�A1,\`�uT�[�P�_?��s�����n���V�6|��1.QFw��D?L�u0��� d�K#�t0q�+|�Erx`''� �Ȱ!SFtn� o\���@DB �BH3L3CA�?P;
diff --git a/src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg b/src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg
new file mode 100644
index 000000000..f52c79376
--- /dev/null
+++ b/src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg
@@ -0,0 +1,126 @@
+����JFIFHH�� �ExifMM*bj(1r2��i��HHAdobe Photoshop 7.02005:03:18 22:30:26����x�A(& �HH����JFIFHH�� Adobe_CM��Adobed����   
+    
+
+
+   ��Ax"����?
+ 
+  3!1AQa"q?2���B#$R�b34r��C%�S���cs5���&D�TdE£t6�U�e���u��F'�������������Vfv��������7GWgw��������5!1AQaq"2?���B#�R��3$b�r��CScs4�%���&5��D�T�dEU6te����u��F�������������Vfv��������'7GWgw������� ?�\?��98��jd�M��?�?�7��Z���Vfw\��t!�c}GӉ궩ۻc���.C�r��[GB��7W6�w��;hIO�~������m���f���O����?�72[����?�BlO��?�z5���U�����#����)�f���O���_�zw�ŧ��o�EX��s�X���^�,Ϳ�ɉ�?�k]��RS��7��Z���R�ӿ�-?���+ή��j��t��h?F��v�>����6��{�����Wq��rJ}'�oN�����m�Ȫ����v;�sjǦ��s��O���r���I��t�~D{Lײַ�{YkY�VZ�~��z�]���z���ѫ ����ɥ�ٹl��*2�����s��Ǻ��uC���!�-������m�ߧ�m.��oN�����m�Ȭo��:������o�=R�%��
+��k���p�7�8�܌��1��p.ql��?�Q℣�e###�"Ǜ�L��$�y��f���O���_�zw�ŧ��o�Eq���pq�[.<�?����p��?)��#+{�y?����������\�7?F5�[dM��I
+��Ӻ�Ռ�ޛso�~-���>��?i�1�$��������
+����?.;�MQ^GZ��%�]�+]���OC����K?�_����ѕ����A�?����qq]��g��?�]??L��)�Ͷ��KY�n?ٔ��?�뻺Ù°]��D��~�N���j��Rz�o�9�.q�m��G�ʻw����}uÍ·;�@'p��Y�����u\]٦���f6��Ɔ��2˲2�6����\Ous �j�-lnp�2�����q-
+ǀ#�/%�T� 0Y&y']w��H"#��\�/��'�8Ϫ�l�?.(ZL]�S��no��4|�uN:o���>�u�>��`��m-xs�F����cOѷa��A_�} \� f���e����bzUb�G��� �
+"����Zl6{���y����1q|���/�}c���S/����sx ���S����c�?����˶��_?�.��u���%��W�eV�q�S�o����e���O�����4�U��z�Kqm�{�}o��ښ쭦ƹ��;�q?�+���t���P�����{�g�
+�ޒ�=��O"��N�|��?糰}ls�g�ؒ��-�.E�u~���c��R��u�f�o�]_M$�������Ș��T�碼��/զ}b���u��i��o�CI;��v���^���?��Ž��K?�����N�ϴ$�M���0�z���h�;�^��}� �]m,{=+Z�������%骗V��GO���iIO��c��$�@2I?
+Һ\��99y+� ��j�fP��0
+�o��uo���uk��̶4}V
+��O�5%9٭88F�4���6A??��Y��_��ֵ�u�A�4�WAe�]]�����1�6Q�G0������Y��^�9�'�u>�U��ǵ�.��xpi{Y�������� p�@o>�
+��q��\BG�<��)���K�S��k!�k� ˿=q�
+�U5��!����t��~O�8�վ��ޯ��pe����S�9cY�l?� q_:�3�qXÆ–E_h��%��5��ձ5�)Jr2��H��^��]���&s?8ÇœWJ�z�?��d�����A�?`3f��?������Ѿ�bc\6�i��i�:Ó¿i��[�����|o�;o�?Ik۞��4��o�a:ok?�r���-:�Z��Z:��g�#O�w�l���zpcG)$�7��Y��©�cÕ‰sY[�7��u����[����IO������W�xۄ��?.+�Lٷ�]���K��;?�W�zf5v:èµ®o�\Ƈ5.?�3��K�׋�]y{K=V�N�F��rJz�H�:I)�߯�U�~^U�b5��< uoh��� ˯����??i��Q��p6?���h�uu+��]��q�ʻ"���R����Z?�׈��w�c�=Ӳ��wS`�J�����`b�3,T��i�ݨ��ݻ��^��I?�BgUˢ��eO����-�����~�z�.?��j��,k�LK?﫸��-2�:]o�mulq�N0{�C]����w�$���?��S�f;1:uUf��O�)m.%��O��m�������;�'���]@u��L-�?Ö«��󹯵��Cs�/�R�7�^?�,�ŬZ�,#{��r��]hh?�INO�c�O���x?�{c��
+��g��Y����=W����hݰ̇y�.��/�S2݋[�*x��e�ӹ������$�IM��"u�+w�{zIu����[����IO��˧���?"��S�/;I%>���S�i�?���DIy�I)�D�?���DIy�I)���]���R\
+I)����zPhotoshop 3.08BIM%8BIM�HH8BIM&?�8BIM
+8BIM8BIM� 8BIM
+8BIM'
+8BIM�H/fflff/ff���2Z5-8BIM�p��������������������������������������������������������������������������������������������8BIM8BIM8BIM@@8BIM8BIMEAxlogo_bigxAnullboundsObjcRct1Top longLeftlongBtomlongARghtlongxslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin
+autoGeneratedTypeenum
+ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongARghtlongxurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong
+leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM �xAh[h �����JFIFHH�� Adobe_CM��Adobed����   
+    
+
+
+   ��Ax"����?
+ 
+  3!1AQa"q?2���B#$R�b34r��C%�S���cs5���&D�TdE£t6�U�e���u��F'�������������Vfv��������7GWgw��������5!1AQaq"2?���B#�R��3$b�r��CScs4�%���&5��D�T�dEU6te����u��F�������������Vfv��������'7GWgw������� ?�\?��98��jd�M��?�?�7��Z���Vfw\��t!�c}GӉ궩ۻc���.C�r��[GB��7W6�w��;hIO�~������m���f���O����?�72[����?�BlO��?�z5���U�����#����)�f���O���_�zw�ŧ��o�EX��s�X���^�,Ϳ�ɉ�?�k]��RS��7��Z���R�ӿ�-?���+ή��j��t��h?F��v�>����6��{�����Wq��rJ}'�oN�����m�Ȫ����v;�sjǦ��s��O���r���I��t�~D{Lײַ�{YkY�VZ�~��z�]���z���ѫ ����ɥ�ٹl��*2�����s��Ǻ��uC���!�-������m�ߧ�m.��oN�����m�Ȭo��:������o�=R�%��
+��k���p�7�8�܌��1��p.ql��?�Q℣�e###�"Ǜ�L��$�y��f���O���_�zw�ŧ��o�Eq���pq�[.<�?����p��?)��#+{�y?����������\�7?F5�[dM��I
+��Ӻ�Ռ�ޛso�~-���>��?i�1�$��������
+����?.;�MQ^GZ��%�]�+]���OC����K?�_����ѕ����A�?����qq]��g��?�]??L��)�Ͷ��KY�n?ٔ��?�뻺Ù°]��D��~�N���j��Rz�o�9�.q�m��G�ʻw����}uÍ·;�@'p��Y�����u\]٦���f6��Ɔ��2˲2�6����\Ous �j�-lnp�2�����q-
+ǀ#�/%�T� 0Y&y']w��H"#��\�/��'�8Ϫ�l�?.(ZL]�S��no��4|�uN:o���>�u�>��`��m-xs�F����cOѷa��A_�} \� f���e����bzUb�G��� �
+"����Zl6{���y����1q|���/�}c���S/����sx ���S����c�?����˶��_?�.��u���%��W�eV�q�S�o����e���O�����4�U��z�Kqm�{�}o��ښ쭦ƹ��;�q?�+���t���P�����{�g�
+�ޒ�=��O"��N�|��?糰}ls�g�ؒ��-�.E�u~���c��R��u�f�o�]_M$�������Ș��T�碼��/զ}b���u��i��o�CI;��v���^���?��Ž��K?�����N�ϴ$�M���0�z���h�;�^��}� �]m,{=+Z�������%骗V��GO���iIO��c��$�@2I?
+Һ\��99y+� ��j�fP��0
+�o��uo���uk��̶4}V
+��O�5%9٭88F�4���6A??��Y��_��ֵ�u�A�4�WAe�]]�����1�6Q�G0������Y��^�9�'�u>�U��ǵ�.��xpi{Y�������� p�@o>�
+��q��\BG�<��)���K�S��k!�k� ˿=q�
+�U5��!����t��~O�8�վ��ޯ��pe����S�9cY�l?� q_:�3�qXÆ–E_h��%��5��ձ5�)Jr2��H��^��]���&s?8ÇœWJ�z�?��d�����A�?`3f��?������Ѿ�bc\6�i��i�:Ó¿i��[�����|o�;o�?Ik۞��4��o�a:ok?�r���-:�Z��Z:��g�#O�w�l���zpcG)$�7��Y��©�cÕ‰sY[�7��u����[����IO������W�xۄ��?.+�Lٷ�]���K��;?�W�zf5v:èµ®o�\Ƈ5.?�3��K�׋�]y{K=V�N�F��rJz�H�:I)�߯�U�~^U�b5��< uoh��� ˯����??i��Q��p6?���h�uu+��]��q�ʻ"���R����Z?�׈��w�c�=Ӳ��wS`�J�����`b�3,T��i�ݨ��ݻ��^��I?�BgUˢ��eO����-�����~�z�.?��j��,k�LK?﫸��-2�:]o�mulq�N0{�C]����w�$���?��S�f;1:uUf��O�)m.%��O��m�������;�'���]@u��L-�?Ö«��󹯵��Cs�/�R�7�^?�,�ŬZ�,#{��r��]hh?�INO�c�O���x?�{c��
+��g��Y����=W����hݰ̇y�.��/�S2݋[�*x��e�ӹ������$�IM��"u�+w�{zIu����[����IO��˧���?"��S�/;I%>���S�i�?���DIy�I)�D�?���DIy�I)���]���R\
+I)��8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIM��Hhttp://ns.adobe.com/xap/1.0/<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
+<?adobe-xap-filters esc="CR"?>
+<x:xapmeta xmlns:x='adobe:ns:meta/' x:xaptk='XMP toolkit 2.8.2-33, framework 1.5'>
+<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
+
+ <rdf:Description about='uuid:47579067-97f4-11d9-a2dc-e4c74314cde2'
+ xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/'>
+ <xapMM:DocumentID>adobe:docid:photoshop:47579060-97f4-11d9-a2dc-e4c74314cde2</xapMM:DocumentID>
+ </rdf:Description>
+
+</rdf:RDF>
+</x:xapmeta>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xpacket end='w'?>��Adobed@�����Ax����� 
+ 
+  u!"1A2# QBa$3Rq?b�%C���&4r
+��5'�S6��DTsEF7Gc(UVW�����d�t��e�����)8f�u*9:HIJXYZghijvwxyz�������������������������������������������������������m!1"AQ2aqB?#�R�b3 �$��Cr��4%�ScD�&5T6Ed'
+s��Ft����UeuV7��������)�����������(GWf8v��������gw��������HXhx��������9IYiy��������*:JZjz���������� ?��><tOG��EGFt���O^M<�u�ʖi��h��Ye���K#�,Ä’I���Ы�˗ǯ���3���d�?ߺ�^�e�����~���_�?����{������|?L����c��׿�r���>��W�?����^���|z���?�+�G�X��u��\�=χ���#��~�׺��._����������?~��{�/?_���g�E~����u�~�_����'�=é±¾<u��Ɵd��u��Օg?��\'��szl��ᜓ� X��[QV#�^?
+9/����M�.^�
+?�7&>\�$�}���U
+���o�0ݰ�{��?Q�nN���Uxn����04yS�jV̮
+���?�}��J�[PPV����U_w�w~��=�<����o-�����y��L�y�͹R�{QJ��T��yW���e�����~���_�?���/z�z��._����������?~��{�/?_���g�E~����u�ÍŸ?� ?�e�⾃�z�����}��V�u�̦������5=U-D8T����d��20G�u����Ǽ�p�σ1�øp�w���\]��ذ�??����9���,h2����-Lʿ���^�\����M�5<^�*~���|=1�d�qܟ�ʜn8�����7�GBk*�"����^�A���p�&/���i�i��M|���R�Loϫ�x�����{��S�
+�N���������x���wի���w�۵;�yc6?���:�0g.*
+��ob>��׺�Ic�y�O���^ꞿ�����_�B9�]���;����5~?�:��?wv� ��3?���J\��B�]��?C�ּ��q�O�#���j�[�'`u�Y�{#�oq�ޢ�R�խ�cZ:�����\��^����95�[?�������m���5���U~ ����
+m���+���{�a���>���Vu�͟�=��C�����cV6��L�P����;{lo\�-�SE��'�&�t�k����U�������W�}�:�Ϟ">_�0�?;/%���xl?�KG��î—ª9^����VW%��FZ��!�Ț�KU�?�����mC��a���!?�ZV����]�����!��
+{k��� �`�?>�����Pg�[�.�?;�j�=�|og�V�7��tßµY������ܥS�w�5%m8�*LfÔ aJ�ԫ��}/p@W�yv�h� ��nNO�?>�)_\�\����i�� nJ���?��O�&��H�I��� =?�stW,.��>ά޻�hm]��;���nÚ¼� Nz{�I���66��?� ��(��%��� �1E�x�;`R?��W��{�{� ����
+?�C�w���$7����uhx9s�7>����h����߃������o�~n,��]��������H���L��X��7R�ۇ Z)3[gp�d`*�*����,E�׺�ѵo�-�|�^��lo�?�A����y�����׺�������b���w�7L-Y���<��Ti��g_�A�׿uU:��]���������{�_X|P���͔����ao��U����V}�ߺ�Z��ˆ?�C�/M�����/�}��W�2ʇ��c"�^��z�]�
+\]?~okR�~��|�U��fO��H���� ���u3��Wt�R�������KY&�lj��R�5��j*�����{7�o�
+��ڻ�7��5��g�՗������u�WM��/|Z��6�dz�“[���/�?e;���?N����xOp����$��w�(�?�?`팵L��&��~:Q�g�U������P�#�:�q�YC��/�5t��
+��iV=��yr��e��s�S�>��Y�?���Þ£j�w�����u|��&����ˌ�v�� ^��f72�����jn`�O�_KRd|��(��rd�j��QT�p?L�O��u��{�l�w�A���/��S��c�o�c~m�6���ܮ���o=��ܶ$�9\Ff����4A?�~�?���t�A/�(���Hi�i�N�ץ��m����?�׺��>|w�Q�KW��O��O�{�=�u�����]�2���g�|?_n^��M�׿����u�gu�����>cmW �ЮDa��d�i��u �{�^�Z��M��^��{���j��UMս���Wn,��ga���]]���ݴ���W�����������ҸO��G=_������o�M�?�O��y�׺��3�e����,����~��}*d�8c��(�?ɘ[���~�����=��6.�z?�?`��8Ý»���cSR6������a��{�?o�����?v�US6J����=�"7
+E�0��n�������{�_)z�:�웯�>����Ki��{��]����z������~��9����'��d��MMIO�������c1u��ϼ�� ��G��?�G�����8s>��ܼ~���[ߥ�J�Ȣ�[c
+�����WT2/����02rv�\֩��w��nG��!��ۛ߮��o��������i�Yy��~��>����Wu�r�_�J�GW��:}���U?�ͯ����MPh꿋nz��)������=�{��y�
+��U�^���1�}���?���O����%��A��T6�ڽ����LG�:C!Wr**�Z��v�b,mD�¬��������G�^_��'��(�K�c�Wm���s������Ԁ�co�e-)��ߺ�Z��(:yh�J=5M7��'�h������ߺ�_\O~��j��
+S�1��>.g�1��r����z��^�߻�n�6آ���ͽ?�T�W�(<{�^�TO�M������o�������/?�)z?knIÔ¥.��}��U?]��=���ilj��XC�����{��Ӻ?��dMҿ����?~��hY���+��W{�Cz�ʫ뎔^��?Te�,�V����c�y�~Z1?4y�l�=�u���$�ȟ��_1+?���ζo��ǯ���е���Û´?��[#�n.�휖��[K��x�}?�vvO���}��v%em&��
+:�B��3�4���׺�?��̣�����E��@�?4��&ַ�7�Ͽu�Ǵz>J�??�,�緶Z��V����^�Guc�>>��f������{���q���i8f��
+����}��X����a�,ߟ�Y�� >�ru?�>�s��?�<���.�k�����%�K>�z�?��� ^��~o�?��o�]�?�6�Ug P`h?ʪ����U��d9�v-���:���[^���78}�=�K�Z���������[�|_�Ƕ�n��lݱ��nJ]�����}]%W��q�'�}��}�C���P}��V?GeQîs�����g�������%��4���N�h��m�}��6�3O���Gb���=�*���V?k���O
+l?ȧ�FBx�4�?5kG1����ꮞ��A�{�^�Z�?�ͯ��d�;�v�ɤ�g�?�;�?S�h����������?��u~��f�
+�����"��R���M�?�?��*j�����޶ߵJPx5t�1�ٜy6�Co~��}[� ��7��� �_�^���֑f��f��O���T[�2�I��� /M���@ ���{�����:���������Zu���߸?��6�����m��
+#0��dkk�**� UU1,�>�׺�Ը_��R���8Ŭ~!nr?��0<�_~��k;��w���.���;���㽺;� ���{����u�g�=�����v�@KU[�j�#���ǿu�C��c��}��+:�p�Ӆ���?�+K��?���!��U&H��)��׺�>��
+�����#�w�>ߛGoc��z?�C��n#�7jmϳ��d(3��������np���ׇnomٞ鿎;#p��=Vq{��,gvndRm�������@W'��L
+�����'��:4_�%m����*~��E��W�>;�v��Y,�q�|������~Cr���^a�??�>��F�����n?�4�w�;����G�S�=���?�g��`���wk�q-:�!��}!���?�6~s����k����{;��?b?�?���?Ä¿a��n m����UUUׯ6��Ou����_���=���jp�մ���E_�U�=�����vv_�2[OdP��W{�^�u�7o�-�窷�;�Gd�ʯ���ت��Y��v�e�-��L�c^6�\���{�^�L��9$��sѲo!��ܗ$M��B��{�^���v>?�A��ߺ�N��׺+_9��a�|���M�}�u�յ_�G���k� |�>o:�7���Q��ߺ�Z��4s�¿��`b�r�@������C���~��}G��uH�X�_�r���ln=�u�����W;1�? �_s���ie�'��)>�;�{�k�i�n-�H5�����]U(����>�׺��|��z�b|z��U�ڹ����{�,sج�q�aq�mŻ��s��?��k��{�^��ttw'ǎ��wOR��7aŀ�����Χ�p���(�����+�6}�}�VR���=�u�����7�e������꾮��w�Rv��{��+�T�X���쌾��m����ͩWM���u��}��u�S���2���_��N|d��_�G��^��+=e��-Ù¸r{ct�;��˧{�}���e�>�IP6eUNp�րO�r}�tL���o� 1��o�m��+c�n��N��-�D�üw�|�#soݶD'j�v U&.ZUl�T_�?>��{�����ñ€¨©�wzm�{��������[�^�x��?���,�Ŗ�`iM�S7�����FOroeo�08�~��}?=�u�~������D�0��V�A�ݾ�׺�����~m��z7m�\��zKg�3���\�=���Y�EW�z�WQ��׺��O�h�Y�3z/ouOEl-��+��mx�n���Vv�tP ��f��+��?�S?�ߺ�V���{�{�^�_��R�����۰���Pv�uo���~���m���o-�C�py���b�����8�Y�))[H<���ݲ��K׺�o�O��󻮊�}�|�ڿ�*'�p||��P���5�<��oj>��׫н���fM���i��0��j���?���Lx�+7{�}��/�N�����W�N��;=����~��U�g�ߣ�7��ٙZ�?�+n^���n;��KRc��TV�1���t�k�~|2�c�G^t_��<`cE�*q5��xQ9ZMÝ¿qg(~��b/�G�ߺ�W?GGOC�����a��~��?��b�!�sl#�l ©k�P �U9�����uT_�>�>?v���|�B��w�6&��v���Uo�|�#}��5���xq���U)jR�����u�׺�u���_�"�_�_ ���n�~����!{7�=
+�����u���׺R{�^���׺�u���{�{�^넟������?~��{ߺ�^��׽�u�~��{ߺ�^���{۟�*{;�����o%��{���
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
new file mode 100644
index 000000000..1e2820886
--- /dev/null
+++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer.java
@@ -0,0 +1,116 @@
+package org.apache.fop.render.bitmap;
+
+import java.awt.image.RenderedImage;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.batik.ext.awt.image.codec.PNGEncodeParam;
+import org.apache.batik.ext.awt.image.codec.PNGImageEncoder;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.render.java2d.Java2DRenderer;
+
+/**
+ * PNG Renderer This class actually does not render itself, instead it extends
+ * <code>org.apache.fop.render.java2D.Java2DRenderer</code> and just encode
+ * rendering results into PNG format using Batik's image codec
+ */
+public class PNGRenderer extends Java2DRenderer {
+
+ /** The MIME type for png-Rendering */
+ public static final String MIME_TYPE = "image/png";
+
+ /** The file syntax prefix, eg. "page" will output "page1.png" etc */
+ private String fileSyntax;
+
+ /** The output directory where images are to be written */
+ private File outputDir;
+
+ /** The PNGEncodeParam for the image */
+ private PNGEncodeParam renderParams;
+
+ /** The OutputStream for the first Image */
+ private OutputStream firstOutputStream;
+
+ /** @see org.apache.fop.render.AbstractRenderer */
+ public String getMimeType() {
+ return MIME_TYPE;
+ }
+
+ /** default constructor */
+ public PNGRenderer() {}
+
+ /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
+ public void startRenderer(OutputStream outputStream) throws IOException {
+ getLogger().info("rendering areas to PNG");
+ setOutputDirectory();
+ this.firstOutputStream = outputStream;
+ }
+
+ /**
+ * Sets the output directory, either from the outfile specified on the
+ * command line, or from the directory specified in configuration file. Also
+ * sets the file name syntax, eg. "page"
+ */
+ private void setOutputDirectory() {
+
+ // the file provided on the command line
+ File f = getUserAgent().getOutputFile();
+
+ outputDir = f.getParentFile();
+
+ // extracting file name syntax
+ String s = f.getName();
+ int i = s.lastIndexOf(".");
+ if (s.charAt(i - 1) == '1') {
+ i--; // getting rid of the "1"
+ }
+ fileSyntax = s.substring(0, i);
+ }
+
+ public void stopRenderer() throws IOException {
+
+ super.stopRenderer();
+
+ for (int i = 0; i < pageViewportList.size(); i++) {
+
+ // Do the rendering: get the image for this page
+ RenderedImage image = (RenderedImage) getPageImage((PageViewport) pageViewportList
+ .get(i));
+
+ // Encode this image
+ getLogger().debug("Encoding Page " + (i + 1));
+ renderParams = PNGEncodeParam.getDefaultEncodeParam(image);
+ OutputStream os = getCurrentOutputStream(i);
+ PNGImageEncoder encoder = new PNGImageEncoder(os, renderParams);
+ encoder.encode(image);
+ os.flush();
+ }
+ }
+
+ /**
+ * Builds the OutputStream corresponding to this page
+ * @param 0-based pageNumber
+ * @return the corresponding OutputStream
+ */
+ private OutputStream getCurrentOutputStream(int pageNumber) {
+
+ if (pageNumber == 0) {
+ return firstOutputStream;
+ }
+
+ File f = new File(outputDir + File.separator + fileSyntax
+ + (pageNumber + 1) + ".png");
+ try {
+ OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
+ return os;
+ } catch (FileNotFoundException e) {
+ new FOPException("Can't build the OutputStream\n" + e);
+ return null;
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/render/bitmap/PNGRenderer_onthefly.java b/src/java/org/apache/fop/render/bitmap/PNGRenderer_onthefly.java
new file mode 100644
index 000000000..3a9ad74c9
--- /dev/null
+++ b/src/java/org/apache/fop/render/bitmap/PNGRenderer_onthefly.java
@@ -0,0 +1,117 @@
+package org.apache.fop.render.bitmap;
+
+import java.awt.image.RenderedImage;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.batik.ext.awt.image.codec.PNGEncodeParam;
+import org.apache.batik.ext.awt.image.codec.PNGImageEncoder;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.render.java2d.Java2DRenderer;
+
+/**
+ * PNG Renderer This class actually does not render itself, instead it extends
+ * <code>org.apache.fop.render.java2D.Java2DRenderer</code> and just encode
+ * rendering results into PNG format using Batik's image codec
+ */
+public class PNGRenderer_onthefly extends Java2DRenderer {
+
+ /** The MIME type for png-Rendering */
+ public static final String MIME_TYPE = "image/png";
+
+ /** The file syntax prefix, eg. "page" will output "page1.png" etc */
+ private String fileSyntax;
+
+ /** The output directory where images are to be written */
+ private File outputDir;
+
+ /** The PNGEncodeParam for the image */
+ private PNGEncodeParam renderParams;
+
+ /** The OutputStream for the first Image */
+ private OutputStream firstOutputStream;
+
+ /** default constructor */
+ public PNGRenderer_onthefly() {}
+
+ /** @see org.apache.fop.render.AbstractRenderer */
+ public String getMimeType() {
+ return MIME_TYPE;
+ }
+
+ public boolean supportsOutOfOrder() {
+ return true;
+ }
+
+ /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
+ public void startRenderer(OutputStream outputStream) throws IOException {
+ getLogger().info("rendering areas to PNG");
+ setOutputDirectory();
+ this.firstOutputStream = outputStream;
+ }
+
+ /**
+ * Sets the output directory, either from the outfile specified on the
+ * command line, or from the directory specified in configuration file. Also
+ * sets the file name syntax, eg. "page"
+ */
+ private void setOutputDirectory() {
+
+ // the file provided on the command line
+ File f = getUserAgent().getOutputFile();
+
+ outputDir = f.getParentFile();
+
+ // extracting file name syntax
+ String s = f.getName();
+ int i = s.lastIndexOf(".");
+ if (s.charAt(i - 1) == '1') {
+ i--; // getting rid of the "1"
+ }
+ fileSyntax = s.substring(0, i);
+ }
+
+ public void renderPage(PageViewport pageViewport) throws IOException,
+ FOPException {
+
+ // Do the rendering: get the image for this page
+ RenderedImage image = (RenderedImage) getPageImage(pageViewport);
+
+ // Encode this image
+ getLogger().debug("Encoding Page" + (getCurrentPageNumber() + 1));
+ renderParams = PNGEncodeParam.getDefaultEncodeParam(image);
+ OutputStream os = getCurrentOutputStream(getCurrentPageNumber());
+ PNGImageEncoder encoder = new PNGImageEncoder(os, renderParams);
+ encoder.encode(image);
+ os.flush();
+
+ setCurrentPageNumber(getCurrentPageNumber() + 1);
+ }
+
+ /**
+ * Builds the OutputStream corresponding to this page
+ * @param 0-based pageNumber
+ * @return the corresponding OutputStream
+ */
+ private OutputStream getCurrentOutputStream(int pageNumber) {
+
+ if (pageNumber == 0) {
+ return firstOutputStream;
+ }
+
+ File f = new File(outputDir + File.separator + fileSyntax
+ + (pageNumber + 1) + ".png");
+ try {
+ OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
+ return os;
+ } catch (FileNotFoundException e) {
+ new FOPException("Can't build the OutputStream\n" + e);
+ return null;
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
new file mode 100644
index 000000000..1e673911f
--- /dev/null
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 1999-2005 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.bitmap;
+
+// Code originaly contributed by Oleg Tkachenko of Multiconn International Ltd
+// (olegt@multiconn.com).
+
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.batik.ext.awt.image.codec.tiff.TIFFEncodeParam;
+import org.apache.batik.ext.awt.image.codec.tiff.TIFFImageEncoder;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.render.java2d.Java2DRenderer;
+
+/**
+ * <p>
+ * This class represents renderer to TIFF (Tagged Image File Format) format. It
+ * is one of the most popular and flexible of the current public domain raster
+ * file formats, which was is primarily designed for raster data interchange.
+ * Supported compression types are:
+ * <ul>
+ * <li>Raw noncompressed data</li>
+ * <li>Byte-oriented run-length encoding "PackBits" compression.</li>
+ * <li>Modified Huffman Compression (CCITT Group 3 1D facsimile compression)</li>
+ * <li>CCITT T.4 bilevel compression (CCITT Group 3 2D facsimile compression)</li>
+ * <li>CCITT T.6 bilevel compression (CCITT Group 4 facsimile compression)</li>
+ * <li>JPEG-in-TIFF compression</li>
+ * <li>DEFLATE lossless compression (also known as "Zip-in-TIFF")</li>
+ * <li>LZW compression</li>
+ * TODO
+ * <p>
+ * This class actually does not render itself, instead it extends
+ * <code>org.apache.fop.render.java2D.Java2DRenderer</code> and just encode
+ * rendering results into TIFF format using Batik's image codec
+ */
+public class TIFFRenderer extends Java2DRenderer {
+
+ /** The MIME type for tiff-Rendering */
+ public static final String MIME_TYPE = "image/tiff";
+
+ /** */
+ private TIFFEncodeParam renderParams;
+
+ private OutputStream outputStream;
+
+ /** @see org.apache.fop.render.AbstractRenderer */
+ public String getMimeType() {
+ return MIME_TYPE;
+ }
+
+ /** Creates TIFF renderer. */
+ public TIFFRenderer() {
+
+ renderParams = new TIFFEncodeParam();
+
+ }
+
+ /**
+ * Configure the TIFF renderer. Get the configuration to be used for
+ * compression
+ * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
+ */
+ public void configure(Configuration cfg) throws ConfigurationException {
+
+ String c = cfg.getChild("directory").getAttribute("value");
+ int comp = Integer.parseInt(c);
+ String name = null;
+ switch (comp) {
+ case TIFFEncodeParam.COMPRESSION_NONE:
+ name = "COMPRESSION_NONE";
+ break;
+ case TIFFEncodeParam.COMPRESSION_JPEG_TTN2:
+ name = "COMPRESSION_JPEG_TTN2";
+ break;
+ case TIFFEncodeParam.COMPRESSION_PACKBITS:
+ name = "COMPRESSION_PACKBITS";
+ break;
+ case TIFFEncodeParam.COMPRESSION_DEFLATE:
+ name = "COMPRESSION_DEFLATE";
+ break;
+ default:
+ getLogger().info("TIFF compression not supported: " + comp);
+ return;
+ }
+ getLogger().info("TIFF compression set to " + name);
+
+ renderParams.setCompression(comp);
+ }
+
+ /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
+ public void startRenderer(OutputStream outputStream) throws IOException {
+ this.outputStream = outputStream;
+ super.startRenderer(outputStream);
+ }
+
+ /** @see org.apache.fop.render.Renderer#stopRenderer() */
+ public void stopRenderer() throws IOException {
+
+ super.stopRenderer();
+ getLogger().debug("Starting Tiff encoding ...");
+
+ // Creates encoder
+ TIFFImageEncoder enc = new TIFFImageEncoder(outputStream, renderParams);
+
+ // Creates lazy iterator over generated page images
+ Iterator pageImagesItr = new LazyPageImagesIterator(getNumberOfPages());
+
+ // The first image to be passed to enc
+ RenderedImage first = (RenderedImage) pageImagesItr.next();
+
+ // The other images are set to the renderParams
+ renderParams.setExtraImages(pageImagesItr);
+
+ // Start encoding
+ enc.encode(first);
+
+ // Cleaning
+ outputStream.flush();
+ clearViewportList();
+ getLogger().debug("Tiff encoding done.");
+
+ }
+
+ /** Private inner class to lazy page rendering. */
+ private class LazyPageImagesIterator implements Iterator {
+ private int count;
+
+ private int current = 0;
+
+ public LazyPageImagesIterator(int c) {
+ count = c;
+ }
+
+ public boolean hasNext() {
+ return current < count;
+ }
+
+ public Object next() {
+ getLogger().debug("[" + (current + 1) + "]");
+
+ // Renders current page as image
+ BufferedImage pageImage = null;
+ try {
+ pageImage = getPageImage(current++);
+ } catch (FOPException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ switch (renderParams.getCompression()) { //TODO
+ // These types of compression require bilevel image
+ case TIFFEncodeParam.COMPRESSION_GROUP3_1D:
+ case TIFFEncodeParam.COMPRESSION_GROUP3_2D:
+ case TIFFEncodeParam.COMPRESSION_GROUP4:
+ default: //FIXME
+ BufferedImage faxImage = new BufferedImage(
+ pageImage.getWidth(), pageImage.getHeight(),
+ BufferedImage.TYPE_BYTE_BINARY);
+ faxImage.getGraphics().drawImage(pageImage, 0, 0, null);
+ return faxImage;
+ //default:
+ // return pageImage;
+ }
+
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "Method 'remove' is not supported.");
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/render/awt/FontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java
index 6e0df2c66..fb27bdee6 100644
--- a/src/java/org/apache/fop/render/awt/FontMetricsMapper.java
+++ b/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java
@@ -16,7 +16,7 @@
/* $Id$ */
-package org.apache.fop.render.awt;
+package org.apache.fop.render.java2d;
// Java
import java.awt.Graphics2D;
@@ -31,7 +31,7 @@ import org.apache.fop.fonts.FontType;
* This class implements org.apache.fop.layout.FontMetrics and
* is added to the hash table in FontInfo. It deferes the
* actual calculation of the metrics to
- * AWTFontMetrics. It only keeps the java name and
+ * Java2DFontMetrics. It only keeps the java name and
* style as member varibles
*/
@@ -44,10 +44,10 @@ public class FontMetricsMapper implements FontMetrics {
private static final int LAST_CHAR = 255;
/**
- * This is a AWTFontMetrics that does the real calculation.
+ * This is a Java2DFontMetrics that does the real calculation.
* It is only one class that dynamically determines the font-size.
*/
- private static AWTFontMetrics metric = null;
+ private static Java2DFontMetrics metric = null;
/**
* The java name of the font.
@@ -72,7 +72,7 @@ public class FontMetricsMapper implements FontMetrics {
this.family = family;
this.style = style;
if (metric == null) {
- metric = new AWTFontMetrics(graphics);
+ metric = new Java2DFontMetrics(graphics);
}
}
@@ -130,7 +130,7 @@ public class FontMetricsMapper implements FontMetrics {
* @see org.apache.fop.fonts.FontMetrics#getWidths()
*/
public int[] getWidths() {
- return metric.getWidths(family, style, AWTFontMetrics.FONT_SIZE);
+ return metric.getWidths(family, style, Java2DFontMetrics.FONT_SIZE);
}
/**
diff --git a/src/java/org/apache/fop/render/awt/FontSetup.java b/src/java/org/apache/fop/render/java2d/FontSetup.java
index 0c7811003..7adbfb1ac 100644
--- a/src/java/org/apache/fop/render/awt/FontSetup.java
+++ b/src/java/org/apache/fop/render/java2d/FontSetup.java
@@ -16,7 +16,7 @@
/* $Id$ */
-package org.apache.fop.render.awt;
+package org.apache.fop.render.java2d;
// FOP
import org.apache.fop.fonts.FontInfo;
diff --git a/src/java/org/apache/fop/render/awt/AWTFontMetrics.java b/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java
index fdfd8b826..2ae7b8ce3 100644
--- a/src/java/org/apache/fop/render/awt/AWTFontMetrics.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java
@@ -16,7 +16,7 @@
/* $Id$ */
-package org.apache.fop.render.awt;
+package org.apache.fop.render.java2d;
// Java
import java.awt.Font;
@@ -37,7 +37,7 @@ import java.awt.font.TextLayout;
* Since FontState and FontInfo multiply all factors by
* size, we assume a "standard" font of FONT_SIZE.
*/
-public class AWTFontMetrics {
+public class Java2DFontMetrics {
/**
* Font size standard used for metric measurements
@@ -97,7 +97,7 @@ public class AWTFontMetrics {
* @param graphics a temp graphics object - this is needed so
* that we can get an instance of java.awt.FontMetrics
*/
- public AWTFontMetrics(Graphics2D graphics) {
+ public Java2DFontMetrics(Graphics2D graphics) {
this.graphics = graphics;
}
diff --git a/src/java/org/apache/fop/render/awt/AWTGraphicsState.java b/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java
index 7dae50b78..22596ea53 100644
--- a/src/java/org/apache/fop/render/awt/AWTGraphicsState.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java
@@ -16,7 +16,7 @@
/* $Id$ */
-package org.apache.fop.render.awt;
+package org.apache.fop.render.java2d;
import java.awt.BasicStroke;
import java.awt.Color;
@@ -38,7 +38,7 @@ import org.apache.fop.fonts.FontInfo;
* <p>
* The graphics context is updated with the updateXXX() methods.
*/
-public class AWTGraphicsState implements Constants, RendererState {
+public class Java2DGraphicsState implements Constants, RendererState {
/** Holds the datas of the current state */
private Graphics2D currentGraphics;
@@ -54,10 +54,21 @@ public class AWTGraphicsState implements Constants, RendererState {
/** Font configuration, passed from AWTRenderer */
private FontInfo fontInfo;
- /** State for storing graphics state. */
- public AWTGraphicsState(Graphics2D graphics, FontInfo fontInfo) {
+ /** Initial AffinTransform passed by the renderer, includes scaling-info */
+ private AffineTransform initialTransform;
+
+ /**
+ * State for storing graphics state.
+ * @param graphics the graphics associated with the BufferedImage
+ * @param fontInfo the FontInfo from the renderer
+ * @param at the initial AffineTransform containing the scale transformation
+ */
+ public Java2DGraphicsState(Graphics2D graphics, FontInfo fontInfo,
+ AffineTransform at) {
this.fontInfo = fontInfo;
this.currentGraphics = graphics;
+ this.initialTransform = at;
+ currentGraphics.setTransform(at);
}
/**
@@ -67,13 +78,13 @@ public class AWTGraphicsState implements Constants, RendererState {
return currentGraphics;
}
- /** @see org.apache.fop.render.awt.RendererState#push() */
+ /** @see org.apache.fop.render.java2d.RendererState#push() */
public void push() {
Graphics2D tmpGraphics = (Graphics2D) currentGraphics.create();
stateStack.add(tmpGraphics);
}
- /** @see org.apache.fop.render.awt.RendererState#pop() */
+ /** @see org.apache.fop.render.java2d.RendererState#pop() */
public Graphics2D pop() {
if (getStackLevel() > 0) {
Graphics2D popped = (Graphics2D) stateStack.remove(stateStack
@@ -86,7 +97,7 @@ public class AWTGraphicsState implements Constants, RendererState {
}
}
- /** @see org.apache.fop.render.awt.RendererState#getStackLevel() */
+ /** @see org.apache.fop.render.java2d.RendererState#getStackLevel() */
public int getStackLevel() {
return stateStack.size();
}
@@ -130,7 +141,7 @@ public class AWTGraphicsState implements Constants, RendererState {
}
/**
- * @see org.apache.fop.render.awt.RendererState#updateColor(org.apache.fop.datatypes.ColorType,
+ * @see org.apache.fop.render.java2d.RendererState#updateColor(org.apache.fop.datatypes.ColorType,
* boolean, java.lang.StringBuffer)
*/
public boolean updateColor(ColorType col, boolean fill, StringBuffer pdf) {
@@ -161,7 +172,7 @@ public class AWTGraphicsState implements Constants, RendererState {
}
/**
- * @see org.apache.fop.render.awt.RendererState#updateFont(java.lang.String,
+ * @see org.apache.fop.render.java2d.RendererState#updateFont(java.lang.String,
* int, java.lang.StringBuffer)
*/
public boolean updateFont(String name, int size, StringBuffer pdf) {
@@ -190,7 +201,7 @@ public class AWTGraphicsState implements Constants, RendererState {
}
/**
- * @see org.apache.fop.render.awt.RendererState#updateStroke(float, int)
+ * @see org.apache.fop.render.java2d.RendererState#updateStroke(float, int)
*/
public boolean updateStroke(float width, int style) {
@@ -243,7 +254,7 @@ public class AWTGraphicsState implements Constants, RendererState {
return (BasicStroke) currentGraphics.getStroke();
}
- /** @see org.apache.fop.render.awt.RendererState#updatePaint(java.awt.Paint) */
+ /** @see org.apache.fop.render.java2d.RendererState#updatePaint(java.awt.Paint) */
public boolean updatePaint(Paint p) {
if (getGraph().getPaint() == null) {
if (p != null) {
@@ -257,7 +268,7 @@ public class AWTGraphicsState implements Constants, RendererState {
return false;
}
- /** @see org.apache.fop.render.awt.RendererState#checkClip(java.awt.Shape) */
+ /** @see org.apache.fop.render.java2d.RendererState#checkClip(java.awt.Shape) */
// TODO implement and test
public boolean checkClip(Shape cl) {
if (getGraph().getClip() == null) {
@@ -272,7 +283,7 @@ public class AWTGraphicsState implements Constants, RendererState {
}
/**
- * @see org.apache.fop.render.awt.RendererState#updateClip(java.awt.Shape)
+ * @see org.apache.fop.render.java2d.RendererState#updateClip(java.awt.Shape)
*/
public boolean updateClip(Shape cl) {
if (getGraph().getClip() != null) {
@@ -286,28 +297,30 @@ public class AWTGraphicsState implements Constants, RendererState {
}
/**
- * @see org.apache.fop.render.awt.RendererState#checkTransform(java.awt.geom.AffineTransform)
+ * @see org.apache.fop.render.java2d.RendererState#checkTransform(java.awt.geom.AffineTransform)
*/
public boolean checkTransform(AffineTransform tf) {
return !tf.equals(getGraph().getTransform());
}
/**
- * @see org.apache.fop.render.awt.RendererState#setTransform(java.awt.geom.AffineTransform)
+ * @see org.apache.fop.render.java2d.RendererState#setTransform(java.awt.geom.AffineTransform)
*/
public void setTransform(AffineTransform tf) {
- getGraph().setTransform(tf);
+ //apply initial transformation
+ getGraph().setTransform(initialTransform);
+ getGraph().transform(tf);
}
/**
- * @see org.apache.fop.render.awt.RendererState#transform(java.awt.geom.AffineTransform)
+ * @see org.apache.fop.render.java2d.RendererState#transform(java.awt.geom.AffineTransform)
*/
public void transform(AffineTransform tf) {
getGraph().transform(tf);
}
/**
- * @see org.apache.fop.render.awt.RendererState#getTransform()
+ * @see org.apache.fop.render.java2d.RendererState#getTransform()
*/
public AffineTransform getTransform() {
/*
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
new file mode 100644
index 000000000..24add0188
--- /dev/null
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -0,0 +1,1114 @@
+/*
+ * Copyright 1999-2005 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.java2d;
+
+// Java
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Line2D;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.PixelInterleavedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.GVTBuilder;
+import org.apache.batik.bridge.ViewBox;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.BlockViewport;
+import org.apache.fop.area.CTM;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.Trait;
+import org.apache.fop.area.inline.Character;
+import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.Image;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.Leader;
+import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.datatypes.ColorType;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontMetrics;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.image.ImageFactory;
+import org.apache.fop.image.XMLImage;
+import org.apache.fop.render.AbstractRenderer;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.pdf.CTMHelper;
+import org.apache.fop.svg.SVGUserAgent;
+import org.apache.fop.traits.BorderProps;
+import org.w3c.dom.Document;
+import org.w3c.dom.svg.SVGDocument;
+import org.w3c.dom.svg.SVGSVGElement;
+
+/**
+ * The <code>Java2DRenderer</code> class provides the abstract technical
+ * foundation for all rendering with the Java2D API. Renderers like
+ * <code>AWTRenderer</code> subclass it and provide the concrete output paths.
+ * <p>
+ * A lot of the logic is performed by <code>AbstractRenderer</code>. The
+ * class-variables <code>currentIPPosition</code> and
+ * <code>currentBPPosition</code> hold the position of the currently rendered
+ * area.
+ * <p>
+ * <code>Java2DGraphicsState state</code> holds the <code>Graphics2D</code>,
+ * which is used along the whole rendering. <code>state</code> also acts as a
+ * stack (<code>state.push()</code> and <code>state.pop()</code>).
+ * <p>
+ * The rendering process is basically always the same:
+ * <p>
+ * <code>void renderXXXXX(Area area) {
+ * //calculate the currentPosition
+ * state.updateFont(name, size, null);
+ * state.updateColor(ct, false, null);
+ * state.getGraph.draw(new Shape(args));
+ * }</code>
+ *
+ */
+public abstract class Java2DRenderer extends AbstractRenderer {
+
+ /** The MIME type for Java2D-Rendering */
+ public static final String MIME_TYPE = "application/X-Java2D";
+
+ /** The scale factor for the image size, values: ]0 ; 1] */
+ protected double scaleFactor = 1;
+
+ /** The page width in pixels */
+ protected int pageWidth = 0;
+
+ /** The page height in pixels */
+ protected int pageHeight = 0;
+
+ /** List of Viewports */
+ protected List pageViewportList = new java.util.ArrayList();
+
+ /** The 0-based current page number */
+ private int currentPageNumber = 0;
+
+ /** The 0-based total number of rendered pages */
+ private int numberOfPages;
+
+ /** true if antialiasing is set */
+ protected boolean antialiasing = true;
+
+ /** true if qualityRendering is set */
+ protected boolean qualityRendering = true;
+
+ /** The current state, holds a Graphics2D and its context */
+ protected Java2DGraphicsState state;
+
+ /** a Line2D.Float used to draw text decorations and leaders */
+ protected Line2D.Float line = new Line2D.Float();
+
+ /** Font configuration */
+ protected FontInfo fontInfo;
+
+ protected Map fontNames = new java.util.Hashtable();
+
+ protected Map fontStyles = new java.util.Hashtable();
+
+ /** true if the renderer has finished rendering all the pages */
+ public boolean renderingDone;
+
+ /** Default constructor */
+ public Java2DRenderer() {}
+
+ /**
+ * @see org.apache.fop.render.Renderer#setUserAgent(org.apache.fop.apps.FOUserAgent)
+ */
+ public void setUserAgent(FOUserAgent foUserAgent) {
+ super.setUserAgent(foUserAgent);
+ userAgent.setRendererOverride(this); // for document regeneration
+ }
+
+ /** @return the FOUserAgent */
+ public FOUserAgent getUserAgent() {
+ return userAgent;
+ }
+
+ /** @see org.apache.fop.render.AbstractRenderer */
+ public String getMimeType() {
+ return MIME_TYPE;
+ }
+
+ /**
+ * @see org.apache.fop.render.Renderer#setupFontInfo(org.apache.fop.fonts.FontInfo)
+ */
+ public void setupFontInfo(FontInfo inFontInfo) {
+ // create a temp Image to test font metrics on
+ fontInfo = inFontInfo;
+ BufferedImage fontImage = new BufferedImage(100, 100,
+ BufferedImage.TYPE_INT_RGB);
+ FontSetup.setup(fontInfo, fontImage.createGraphics());
+ }
+
+ /**
+ * Sets the new scale factor.
+ * @param newScaleFactor ]0 ; 1]
+ */
+ public void setScaleFactor(double newScaleFactor) {
+ scaleFactor = newScaleFactor;
+ }
+
+ public double getScaleFactor() {
+ return scaleFactor;
+ }
+
+ public void startRenderer(OutputStream out) throws IOException {
+ // do nothing by default
+ }
+
+ public void stopRenderer() throws IOException {
+ getLogger().debug("Java2DRenderer stopped");
+ renderingDone = true;
+ numberOfPages = currentPageNumber;
+ // TODO set all vars to null for gc
+ if (numberOfPages == 0) {
+ new FOPException("No page could be rendered");
+ }
+ }
+
+ /** @return The 0-based current page number */
+ public int getCurrentPageNumber() {
+ return currentPageNumber;
+ }
+
+ /** @param The 0-based current page number */
+ public void setCurrentPageNumber(int c) {
+ this.currentPageNumber = c;
+ }
+
+ /** @return The 0-based total number of rendered pages */
+ public int getNumberOfPages() {
+ return numberOfPages;
+ }
+
+ /** clears the ViewportList, in case the document is reloaded */
+ public void clearViewportList() {
+ pageViewportList.clear();
+ setCurrentPageNumber(0);
+ }
+
+ /**
+ * @param the 0-based pageIndex
+ * @return the corresponding PageViewport
+ */
+ public PageViewport getPageViewport(int pageIndex) {
+ return (PageViewport) pageViewportList.get(pageIndex);
+ }
+
+ /**
+ * 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
+ * desired BufferedImages by calling getPageImage(), which lazily starts the
+ * rendering process).
+ *
+ * @param pageViewport the <code>PageViewport</code> object supplied by
+ * the Area Tree
+ * @see org.apache.fop.render.Renderer
+ */
+ public void renderPage(PageViewport pageViewport) throws IOException,
+ FOPException {
+ pageViewportList.add(pageViewport.clone());// FIXME clone
+ currentPageNumber++;
+ }
+
+ /**
+ * Generates a desired page from the renderer's page viewport list.
+ *
+ * @param pageViewport the PageViewport to be rendered
+ * @return the <code>java.awt.image.BufferedImage</code> corresponding to
+ * the page or null if the page doesn't exist.
+ */
+ public BufferedImage getPageImage(PageViewport pageViewport) {
+
+ Rectangle2D bounds = pageViewport.getViewArea();
+ pageWidth = (int) Math.round(bounds.getWidth() / 1000f);
+ pageHeight = (int) Math.round(bounds.getHeight() / 1000f);
+
+ getLogger().info(
+ "Rendering Page " + pageViewport.getPageNumberString()
+ + " (pageWidth " + pageWidth + ", pageHeight "
+ + pageHeight + ")");
+
+ BufferedImage currentPageImage = new BufferedImage(
+ (int) ((pageWidth * scaleFactor)),
+ (int) ((pageHeight * scaleFactor)), BufferedImage.TYPE_INT_RGB);
+ // FIXME TYPE_BYTE_BINARY ?
+
+ Graphics2D graphics = currentPageImage.createGraphics();
+ graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ if (antialiasing) {
+ graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ }
+ if (qualityRendering) {
+ graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY);
+ }
+
+ // transform page based on scale factor supplied
+ AffineTransform at = graphics.getTransform();
+ at.scale(scaleFactor, scaleFactor);
+ graphics.setTransform(at);
+
+ // draw page frame
+ graphics.setColor(Color.white);
+ graphics.fillRect(0, 0, pageWidth, pageHeight);
+ graphics.setColor(Color.black);
+ graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2);
+ graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2);
+ graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3);
+ graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2);
+ graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3);
+
+ state = new Java2DGraphicsState(graphics, this.fontInfo, at);
+
+ // reset the current Positions
+ currentBPPosition = 0;
+ currentIPPosition = 0;
+
+ // this toggles the rendering of all areas
+ renderPageAreas(pageViewport.getPage());
+ return currentPageImage;
+ }
+
+ /**
+ * Generates a desired page from the renderer's page viewport list.
+ *
+ * @param pageNum the 0-based page number to generate
+ * @return the <code>java.awt.image.BufferedImage</code> corresponding to
+ * the page or null if the page doesn't exist.
+ * @throws FOPException
+ */
+ public BufferedImage getPageImage(int pageNum) throws FOPException {
+ if (pageNum < 0 || pageNum >= pageViewportList.size()) {
+ throw new FOPException("out-of-range page number (" + pageNum
+ + ") requested; only " + pageViewportList.size()
+ + " page(s) available.");
+ }
+ PageViewport pageViewport = (PageViewport) pageViewportList
+ .get(pageNum);
+ return getPageImage(pageViewport);
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
+ */
+ protected void startVParea(CTM ctm) {
+
+ // push (and save) the current graphics state
+ state.push();
+
+ // Set the given CTM in the graphics state
+ state.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
+
+ // TODO Set clip?
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#endVParea()
+ */
+ protected void endVParea() {
+ state.pop();
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport,
+ * List)
+ */
+ protected void renderBlockViewport(BlockViewport bv, List children) {
+ // clip and position viewport if necessary
+
+ // save positions
+ int saveIP = currentIPPosition;
+ int saveBP = currentBPPosition;
+
+ CTM ctm = bv.getCTM();
+ int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
+ int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
+ float x, y;
+ x = (float) (bv.getXOffset() + containingIPPosition) / 1000f;
+ y = (float) (bv.getYOffset() + containingBPPosition) / 1000f;
+
+ if (bv.getPositioning() == Block.ABSOLUTE
+ || bv.getPositioning() == Block.FIXED) {
+ // TODO not tested yet
+ // For FIXED, we need to break out of the current viewports to the
+ // one established by the page. We save the state stack for
+ // restoration
+ // after the block-container has been painted. See below.
+ List breakOutList = null;
+ if (bv.getPositioning() == Block.FIXED) {
+ getLogger().debug("Block.FIXED --> break out");
+ breakOutList = new java.util.ArrayList();
+ Graphics2D graph;
+ while (true) {
+ graph = state.getGraph();
+ if (state.pop() == null) {
+ break;
+ }
+ breakOutList.add(0, graph); // Insert because of
+ // stack-popping
+ getLogger().debug("Adding to break out list: " + graph);
+ }
+ }
+
+ CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
+ ctm = tempctm.multiply(ctm);
+
+ // This is the content-rect
+ float width = (float) bv.getIPD() / 1000f;
+ float height = (float) bv.getBPD() / 1000f;
+
+ // Adjust for spaces (from margin or indirectly by start-indent etc.
+ Integer spaceStart = (Integer) bv.getTrait(Trait.SPACE_START);
+ if (spaceStart != null) {
+ x += spaceStart.floatValue() / 1000;
+ }
+ Integer spaceBefore = (Integer) bv.getTrait(Trait.SPACE_BEFORE);
+ if (spaceBefore != null) {
+ y += spaceBefore.floatValue() / 1000;
+ }
+
+ float bpwidth = (borderPaddingStart + bv
+ .getBorderAndPaddingWidthEnd()) / 1000f;
+ float bpheight = (borderPaddingBefore + bv
+ .getBorderAndPaddingWidthAfter()) / 1000f;
+
+ drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight);
+
+ // Now adjust for border/padding
+ x += borderPaddingStart / 1000f;
+ y += borderPaddingBefore / 1000f;
+
+ if (bv.getClip()) {
+ // saves the graphics state in a stack
+ state.push();
+
+ clip(x, y, width, height);
+ }
+
+ startVParea(ctm);
+
+ renderBlocks(bv, children);
+ endVParea();
+
+ if (bv.getClip()) {
+ // restores the last graphics state from the stack
+ state.pop();
+ }
+
+ // clip if necessary
+
+ if (breakOutList != null) {
+ getLogger().debug(
+ "Block.FIXED --> restoring context after break-out");
+ Graphics2D graph;
+ Iterator i = breakOutList.iterator();
+ while (i.hasNext()) {
+ graph = (Graphics2D) i.next();
+ getLogger().debug("Restoring: " + graph);
+ state.push();
+ }
+ }
+
+ currentIPPosition = saveIP;
+ currentBPPosition = saveBP;
+
+ } else { // orientation = Block.STACK or RELATIVE
+
+ Integer spaceBefore = (Integer) bv.getTrait(Trait.SPACE_BEFORE);
+ if (spaceBefore != null) {
+ currentBPPosition += spaceBefore.intValue();
+ }
+
+ // borders and background in the old coordinate system
+ handleBlockTraits(bv);
+
+ CTM tempctm = new CTM(containingIPPosition, currentBPPosition
+ + containingBPPosition);
+ ctm = tempctm.multiply(ctm);
+
+ // Now adjust for border/padding
+ x += borderPaddingStart / 1000f;
+ y += borderPaddingBefore / 1000f;
+
+ // clip if necessary
+ if (bv.getClip()) {
+ // saves the graphics state in a stack
+ state.push();
+ float width = (float) bv.getIPD() / 1000f;
+ float height = (float) bv.getBPD() / 1000f;
+ clip(x, y, width, height);
+ }
+
+ if (ctm != null) {
+ startVParea(ctm);
+ }
+ renderBlocks(bv, children);
+ if (ctm != null) {
+ endVParea();
+ }
+
+ if (bv.getClip()) {
+ // restores the last graphics state from the stack
+ state.pop();
+ }
+
+ currentIPPosition = saveIP;
+ currentBPPosition = saveBP;
+
+ // Adjust BP position (alloc BPD + spaces)
+ if (spaceBefore != null) {
+ currentBPPosition += spaceBefore.intValue();
+ }
+ currentBPPosition += (int) (bv.getAllocBPD());
+ Integer spaceAfter = (Integer) bv.getTrait(Trait.SPACE_AFTER);
+ if (spaceAfter != null) {
+ currentBPPosition += spaceAfter.intValue();
+ }
+ }
+ }
+
+ /**
+ * Clip an area.
+ */
+ protected void clip() {
+ // TODO via AWTGraphicsState.updateClip();
+ // currentStream.add("W\n");
+ // currentStream.add("n\n");
+ }
+
+ /**
+ * Clip an area. write a clipping operation given coordinates in the current
+ * transform.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ protected void clip(float x, float y, float width, float height) {
+ // TODO via AWTGraphicsState.updateClip();
+ // currentStream.add(x + " " + y + " " + width + " " + height + "
+ // re ");
+ clip();
+ }
+
+ /**
+ * Draw the background and borders. This draws the background and border
+ * traits for an area given the position.
+ *
+ * @param block the area to get the traits from
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ protected void drawBackAndBorders(Area area, float startx, float starty,
+ float width, float height) {
+
+ BorderProps bpsBefore = (BorderProps) area
+ .getTrait(Trait.BORDER_BEFORE);
+ BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER);
+ BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START);
+ BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END);
+
+ // draw background
+ Trait.Background back;
+ back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
+ if (back != null) {
+
+ // Calculate padding rectangle
+ float sx = startx;
+ float sy = starty;
+ float paddRectWidth = width;
+ float paddRectHeight = height;
+
+ if (bpsStart != null) {
+ sx += bpsStart.width / 1000f;
+ paddRectWidth -= bpsStart.width / 1000f;
+ }
+ if (bpsBefore != null) {
+ sy += bpsBefore.width / 1000f;
+ paddRectHeight -= bpsBefore.width / 1000f;
+ }
+ if (bpsEnd != null) {
+ paddRectWidth -= bpsEnd.width / 1000f;
+ }
+ if (bpsAfter != null) {
+ paddRectHeight -= bpsAfter.width / 1000f;
+ }
+
+ if (back.getColor() != null) {
+ drawBackground(back, sx, sy, paddRectWidth, paddRectHeight);
+ }
+
+ // background image
+ if (back.getFopImage() != null) {
+ FopImage fopimage = back.getFopImage();
+ if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
+ clip(sx, sy, paddRectWidth, paddRectHeight);
+ int horzCount = (int) ((paddRectWidth * 1000 / fopimage
+ .getIntrinsicWidth()) + 1.0f);
+ int vertCount = (int) ((paddRectHeight * 1000 / fopimage
+ .getIntrinsicHeight()) + 1.0f);
+ if (back.getRepeat() == EN_NOREPEAT) {
+ horzCount = 1;
+ vertCount = 1;
+ } else if (back.getRepeat() == EN_REPEATX) {
+ vertCount = 1;
+ } else if (back.getRepeat() == EN_REPEATY) {
+ horzCount = 1;
+ }
+ // change from points to millipoints
+ sx *= 1000;
+ sy *= 1000;
+ if (horzCount == 1) {
+ sx += back.getHoriz();
+ }
+ if (vertCount == 1) {
+ sy += back.getVertical();
+ }
+ for (int x = 0; x < horzCount; x++) {
+ for (int y = 0; y < vertCount; y++) {
+ // place once
+ Rectangle2D pos;
+ pos = new Rectangle2D.Float(sx
+ + (x * fopimage.getIntrinsicWidth()), sy
+ + (y * fopimage.getIntrinsicHeight()),
+ fopimage.getIntrinsicWidth(), fopimage
+ .getIntrinsicHeight());
+ putImage(back.getURL(), pos); // TODO test
+ }
+ }
+
+ } else {
+ getLogger().warn(
+ "Can't find background image: " + back.getURL());
+ }
+ }
+ }
+
+ // draw border
+ // BORDER_BEFORE
+ if (bpsBefore != null) {
+ int borderWidth = (int) Math.round((bpsBefore.width / 1000f));
+ state.updateColor(bpsBefore.color);
+ state.getGraph().fillRect((int) startx, (int) starty, (int) width,
+ borderWidth);
+ }
+ // BORDER_AFTER
+ if (bpsAfter != null) {
+ int borderWidth = (int) Math.round((bpsAfter.width / 1000f));
+ float sy = starty + height;
+ state.updateColor(bpsAfter.color);
+ state.getGraph().fillRect((int) startx,
+ (int) (starty + height - borderWidth), (int) width,
+ borderWidth);
+ }
+ // BORDER_START
+ if (bpsStart != null) {
+ int borderWidth = (int) Math.round((bpsStart.width / 1000f));
+ state.updateColor(bpsStart.color);
+ state.getGraph().fillRect((int) startx, (int) starty, borderWidth,
+ (int) height);
+ }
+ // BORDER_END
+ if (bpsEnd != null) {
+ int borderWidth = (int) Math.round((bpsEnd.width / 1000f));
+ float sx = startx + width;
+ state.updateColor(bpsEnd.color);
+ state.getGraph().fillRect((int) (startx + width - borderWidth),
+ (int) starty, borderWidth, (int) height);
+ }
+ }
+
+ /**
+ * Draw the Background Rectangle of a given area.
+ *
+ * @param back the Trait.Background
+ * @param sx x coordinate of the rectangle to be filled.
+ * @param sy y the y coordinate of the rectangle to be filled.
+ * @param paddRectWidth the width of the rectangle to be filled.
+ * @param paddRectHeight the height of the rectangle to be filled.
+ */
+ protected void drawBackground(Trait.Background back, float sx, float sy,
+ float paddRectWidth, float paddRectHeight) {
+
+ state.updateColor(back.getColor());
+ state.getGraph().fillRect((int) sx, (int) sy, (int) paddRectWidth,
+ (int) paddRectHeight);
+ }
+
+ /**
+ * Handle block traits. The block could be any sort of block with any
+ * positioning so this should render the traits such as border and
+ * background in its position.
+ *
+ * @param block the block to render the traits
+ */
+ protected void handleBlockTraits(Block block) {
+ // copied from pdf
+ int borderPaddingStart = block.getBorderAndPaddingWidthStart();
+ int borderPaddingBefore = block.getBorderAndPaddingWidthBefore();
+
+ float startx = currentIPPosition / 1000f;
+ float starty = currentBPPosition / 1000f;
+ float width = block.getIPD() / 1000f;
+ float height = block.getBPD() / 1000f;
+
+ startx += block.getStartIndent() / 1000f;
+ startx -= block.getBorderAndPaddingWidthStart() / 1000f;
+ width += borderPaddingStart / 1000f;
+ width += block.getBorderAndPaddingWidthEnd() / 1000f;
+ height += borderPaddingBefore / 1000f;
+ height += block.getBorderAndPaddingWidthAfter() / 1000f;
+
+ drawBackAndBorders(block, startx, starty, width, height);
+ }
+
+ /**
+ * @see org.apache.fop.render.Renderer#renderText(TextArea)
+ */
+ public void renderText(TextArea text) {
+
+ float x = currentIPPosition;
+ float y = currentBPPosition + text.getOffset(); // baseline
+
+ String name = (String) text.getTrait(Trait.FONT_NAME);
+ int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
+ state.updateFont(name, size, null);
+
+ ColorType ct = (ColorType) text.getTrait(Trait.COLOR);
+ state.updateColor(ct, false, null);
+
+ String s = text.getTextArea();
+ state.getGraph().drawString(s, x / 1000f, y / 1000f);
+
+ // getLogger().debug("renderText(): \"" + s + "\", x: "
+ // + x + ", y: " + y + state);
+
+ // rendering text decorations
+ FontMetrics metrics = fontInfo.getMetricsFor(name);
+ Font fs = new Font(name, metrics, size);
+ renderTextDecoration(fs, text, y, x);
+
+ super.renderText(text);
+ }
+
+ /**
+ * @see org.apache.fop.render.Renderer#renderCharacter(Character)
+ */
+ public void renderCharacter(Character ch) {
+
+ float x = currentIPPosition;
+ float y = currentBPPosition + ch.getOffset(); // baseline
+
+ String name = (String) ch.getTrait(Trait.FONT_NAME);
+ int size = ((Integer) ch.getTrait(Trait.FONT_SIZE)).intValue();
+ state.updateFont(name, size, null);
+
+ ColorType ct = (ColorType) ch.getTrait(Trait.COLOR);
+ state.updateColor(ct, false, null);
+
+ String s = ch.getChar();
+ state.getGraph().drawString(s, x / 1000f, y / 1000f);
+
+ // getLogger().debug( "renderCharacter(): \"" + s + "\", x: "
+ // + x + ", y: " + y + state);
+
+ // rendering text decorations
+ FontMetrics metrics = fontInfo.getMetricsFor(name);
+ Font fs = new Font(name, metrics, size);
+ renderTextDecoration(fs, ch, y, x);
+
+ super.renderCharacter(ch);
+ }
+
+ /**
+ * Paints the text decoration marks.
+ *
+ * @param fs Current font
+ * @param inline inline area to paint the marks for
+ * @param baseline position of the baseline
+ * @param startIPD start IPD
+ */
+ protected void renderTextDecoration(Font fs, InlineArea inline,
+ float baseline, float startIPD) {
+
+ boolean hasTextDeco = inline.hasUnderline() || inline.hasOverline()
+ || inline.hasLineThrough();
+
+ if (hasTextDeco) {
+ state.updateStroke((fs.getDescender() / (-8 * 1000f)),
+ Constants.EN_SOLID);
+ float endIPD = startIPD + inline.getIPD();
+ if (inline.hasUnderline()) {
+ ColorType ct = (ColorType) inline
+ .getTrait(Trait.UNDERLINE_COLOR);
+ state.updateColor(ct, false, null);
+ float y = baseline - fs.getDescender() / 2;
+ line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f,
+ y / 1000f);
+ state.getGraph().draw(line);
+ }
+ if (inline.hasOverline()) {
+ ColorType ct = (ColorType) inline
+ .getTrait(Trait.OVERLINE_COLOR);
+ state.updateColor(ct, false, null);
+ float y = (float) (baseline - (1.1 * fs.getCapHeight()));
+ line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f,
+ y / 1000f);
+ state.getGraph().draw(line);
+ }
+ if (inline.hasLineThrough()) {
+ ColorType ct = (ColorType) inline
+ .getTrait(Trait.LINETHROUGH_COLOR);
+ state.updateColor(ct, false, null);
+ float y = (float) (baseline - (0.45 * fs.getCapHeight()));
+ line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f,
+ y / 1000f);
+ state.getGraph().draw(line);
+ }
+ }
+ }
+
+ /**
+ * Render leader area. This renders a leader area which is an area with a
+ * rule.
+ *
+ * @param area the leader area to render
+ */
+ public void renderLeader(Leader area) {
+
+ // TODO leader-length: 25%, 50%, 75%, 100% not working yet
+ // TODO Colors do not work on Leaders yet
+
+ float startx = ((float) currentIPPosition) / 1000f;
+ float starty = ((currentBPPosition + area.getOffset()) / 1000f);
+ float endx = (currentIPPosition + area.getIPD()) / 1000f;
+
+ ColorType ct = (ColorType) area.getTrait(Trait.COLOR);
+ state.updateColor(ct, true, null);
+
+ line.setLine(startx, starty, endx, starty);
+ float thickness = area.getRuleThickness() / 1000f;
+
+ int style = area.getRuleStyle();
+ switch (style) {
+ case EN_SOLID:
+ case EN_DOTTED:
+ case EN_DASHED:
+ state.updateStroke(thickness, style);
+ state.getGraph().draw(line);
+ break;
+ case EN_DOUBLE:
+
+ state.updateStroke(thickness / 3f, EN_SOLID); // only a third
+
+ // upper Leader
+ line.setLine(startx, starty, endx, starty);
+ state.getGraph().draw(line);
+ // lower Leader
+ line.setLine(startx, starty + 2 * thickness, endx, starty + 2
+ * thickness);
+ state.getGraph().draw(line);
+
+ break;
+
+ case EN_GROOVE:
+ // The rule looks as though it were carved into the canvas.
+ // (Top/left half of the rule's thickness is the
+ // color specified; the other half is white.)
+
+ state.updateStroke(thickness / 2f, EN_SOLID); // only the half
+
+ // upper Leader
+ line.setLine(startx, starty, endx, starty);
+ state.getGraph().draw(line);
+ // lower Leader
+ line.setLine(startx, starty + thickness, endx, starty + thickness);
+ state.getGraph().setColor(Color.WHITE);
+ state.getGraph().draw(line);
+
+ // TODO the implementation could be nicer, f.eg. with triangles at
+ // the tip of the lines. See also RenderX's implementation (looks
+ // like a button)
+
+ break;
+
+ case EN_RIDGE:
+ // The opposite of "groove", the rule looks as though it were
+ // coming out of the canvas. (Bottom/right half of the rule's
+ // thickness is the color specified; the other half is white.)
+
+ state.updateStroke(thickness / 2f, EN_SOLID); // only the half
+
+ // lower Leader
+ line.setLine(startx, starty + thickness, endx, starty + thickness);
+ state.getGraph().draw(line);
+ // upperLeader
+ line.setLine(startx, starty, endx, starty);
+ state.getGraph().setColor(Color.WHITE);
+ state.getGraph().draw(line);
+
+ // TODO the implementation could be nicer, f.eg. with triangles at
+ // the tip of the lines. See also RenderX's implementation (looks
+ // like a button)
+
+ break;
+
+ case EN_NONE:
+ // No rule is drawn
+ break;
+
+ } // end switch
+
+ super.renderLeader(area);
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#renderImage(Image,
+ * Rectangle2D)
+ */
+ public void renderImage(Image image, Rectangle2D pos) {
+ // endTextObject();
+ String url = image.getURL();
+ putImage(url, pos);
+ }
+
+ /**
+ * draws an image
+ *
+ * @param url URL of the bitmap
+ * @param pos Position of the bitmap
+ */
+ protected void putImage(String pUrl, Rectangle2D pos) {
+
+ int x = currentIPPosition; // TODO + area.getXOffset();
+ int y = currentBPPosition;
+ String url = ImageFactory.getURL(pUrl);
+
+ ImageFactory fact = ImageFactory.getInstance();
+ FopImage fopimage = fact.getImage(url, userAgent);
+
+ if (fopimage == null) {
+ return;
+ }
+ if (!fopimage.load(FopImage.DIMENSIONS)) {
+ return;
+ }
+ int w = fopimage.getWidth();
+ int h = fopimage.getHeight();
+ String mime = fopimage.getMimeType();
+ if ("text/xml".equals(mime)) {
+ if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
+ return;
+ }
+ Document doc = ((XMLImage) fopimage).getDocument();
+ String ns = ((XMLImage) fopimage).getNameSpace();
+ renderDocument(doc, ns, pos);
+
+ } else if ("image/svg+xml".equals(mime)) {
+ if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
+ return;
+ }
+ Document doc = ((XMLImage) fopimage).getDocument();
+ renderSVGDocument(doc, pos); // TODO check if ok.
+
+ } else if ("image/eps".equals(mime)) {
+ getLogger().warn("EPS images are not supported by this renderer");
+ currentBPPosition += (h * 1000);
+ } else if ("image/jpeg".equals(mime)) {
+ if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
+ return;
+ }
+
+ // TODO Load JPEGs rather through fopimage.load(FopImage.BITMAP),
+ // but JpegImage will need to be extended for that
+
+ // url = url.substring(7);
+ // url = "C:/eclipse/myWorkbenches/fop4/xml-fop/examples/fo" + url;
+ java.awt.Image awtImage = new javax.swing.ImageIcon(url).getImage();
+
+ state.getGraph().drawImage(awtImage, (int) (x / 1000f),
+ (int) (y / 1000f), (int) w, h, null);
+ currentBPPosition += (h * 1000);
+ } else {
+ if (!fopimage.load(FopImage.BITMAP)) {
+ getLogger().warn("Loading of bitmap failed: " + url);
+ return;
+ }
+
+ byte[] raw = fopimage.getBitmaps();
+
+ // TODO Hardcoded color and sample models, FIX ME!
+ ColorModel cm = new ComponentColorModel(ColorSpace
+ .getInstance(ColorSpace.CS_LINEAR_RGB), false, false,
+ ColorModel.OPAQUE, DataBuffer.TYPE_BYTE);
+ SampleModel sampleModel = new PixelInterleavedSampleModel(
+ DataBuffer.TYPE_BYTE, w, h, 3, w * 3, new int[] { 0, 1, 2 });
+ DataBuffer dbuf = new DataBufferByte(raw, w * h * 3);
+
+ WritableRaster raster = Raster.createWritableRaster(sampleModel,
+ dbuf, null);
+
+ java.awt.Image awtImage;
+ // Combine the color model and raster into a buffered image
+ awtImage = new BufferedImage(cm, raster, false, null);
+
+ state.getGraph().drawImage(awtImage, (int) (x / 1000f),
+ (int) (y / 1000f), (int) w, h, null);
+ currentBPPosition += (h * 1000);
+ }
+ }
+
+ /**
+ * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject,
+ * Rectangle2D)
+ */
+ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
+ Document doc = fo.getDocument();
+ String ns = fo.getNameSpace();
+ if (ns.equals("http://www.w3.org/2000/svg")) {
+ renderSVGDocument(doc, pos);
+ } else {
+ renderDocument(doc, ns, pos);
+ }
+ // this.currentXPosition += area.getContentWidth();
+ }
+
+ /**
+ * Renders an XML document (SVG for example).
+ *
+ * @param doc DOM document representing the XML document
+ * @param ns Namespace for the document
+ * @param pos Position on the page
+ */
+ public void renderDocument(Document doc, String ns, Rectangle2D pos) {
+ RendererContext context;
+ context = new RendererContext(MIME_TYPE);
+ context.setUserAgent(userAgent);
+ // TODO implement
+ /*
+ * context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc);
+ * context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream);
+ * context.setProperty(PDFXMLHandler.PDF_STATE, currentState);
+ * context.setProperty(PDFXMLHandler.PDF_PAGE, currentPage);
+ * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext == null ?
+ * currentPage : currentContext);
+ * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext);
+ * context.setProperty(PDFXMLHandler.PDF_STREAM, currentStream);
+ * context.setProperty(PDFXMLHandler.PDF_XPOS, new
+ * Integer(currentIPPosition + (int) pos.getX()));
+ * context.setProperty(PDFXMLHandler.PDF_YPOS, new
+ * Integer(currentBPPosition + (int) pos.getY()));
+ * context.setProperty(PDFXMLHandler.PDF_FONT_INFO, fontInfo);
+ * context.setProperty(PDFXMLHandler.PDF_FONT_NAME, currentFontName);
+ * context.setProperty(PDFXMLHandler.PDF_FONT_SIZE, new
+ * Integer(currentFontSize));
+ * context.setProperty(PDFXMLHandler.PDF_WIDTH, new Integer((int)
+ * pos.getWidth())); context.setProperty(PDFXMLHandler.PDF_HEIGHT, new
+ * Integer((int) pos.getHeight())); renderXML(userAgent, context, doc,
+ * ns);
+ */
+ }
+
+ protected void renderSVGDocument(Document doc, Rectangle2D pos) {
+
+ int x = currentIPPosition; // TODO + area.getXOffset();
+ int y = currentBPPosition;
+
+ RendererContext context;
+ context = new RendererContext(MIME_TYPE);
+ context.setUserAgent(userAgent);
+
+ SVGUserAgent ua = new SVGUserAgent(context.getUserAgent()
+ .getPixelUnitToMillimeter(), new AffineTransform());
+
+ GVTBuilder builder = new GVTBuilder();
+ BridgeContext ctx = new BridgeContext(ua);
+
+ GraphicsNode root;
+ try {
+ root = builder.build(ctx, doc);
+ } catch (Exception e) {
+ getLogger().error(
+ "svg graphic could not be built: " + e.getMessage(), e);
+ return;
+ }
+ float w = (float) ctx.getDocumentSize().getWidth() * 1000f;
+ float h = (float) ctx.getDocumentSize().getHeight() * 1000f;
+
+ // correct integer roundoff
+ state.getGraph().translate(x / 1000, y / 1000);
+
+ SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
+ AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
+ w / 1000f, h / 1000f);
+ AffineTransform inverse = null;
+ try {
+ inverse = at.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ getLogger().warn(e);
+ }
+ if (!at.isIdentity()) {
+ state.getGraph().transform(at);
+ }
+
+ try {
+ root.paint(state.getGraph());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (inverse != null && !inverse.isIdentity()) {
+ state.getGraph().transform(inverse);
+ }
+ // correct integer roundoff
+ // currentState.getCurrentGraphics().translate(-x / 1000f, y / 1000f -
+ // pageHeight);
+ state.getGraph().translate(-(x + 500) / 1000,
+ (y + 500) / 1000 - pageHeight);
+ }
+}
diff --git a/src/java/org/apache/fop/render/awt/RendererState.java b/src/java/org/apache/fop/render/java2d/RendererState.java
index 3fdc8690a..f89c8c531 100644
--- a/src/java/org/apache/fop/render/awt/RendererState.java
+++ b/src/java/org/apache/fop/render/java2d/RendererState.java
@@ -16,7 +16,7 @@
/* $Id$ */
-package org.apache.fop.render.awt;
+package org.apache.fop.render.java2d;
import java.awt.Graphics2D;
import java.awt.Paint;
diff --git a/src/java/org/apache/fop/render/awt/AWTPrintRenderer.java b/src/java/org/apache/fop/render/print/PrintRenderer.java
index 5b057959a..3e165ccec 100644
--- a/src/java/org/apache/fop/render/awt/AWTPrintRenderer.java
+++ b/src/java/org/apache/fop/render/print/PrintRenderer.java
@@ -1,12 +1,12 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
+ * Copyright 2005 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.
@@ -15,31 +15,51 @@
*/
/* $Id$ */
-
-package org.apache.fop.render.awt;
+package org.apache.fop.render.print;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+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.Vector;
-public class AWTPrintRenderer extends AWTRenderer {
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.render.java2d.Java2DRenderer;
+
+/**
+ * Renderer that prints through java.awt.PrintJob.
+ */
+public class PrintRenderer extends Java2DRenderer implements Pageable, Printable {
private static final int EVEN_AND_ALL = 0;
+
private static final int EVEN = 1;
+
private static final int ODD = 2;
-
+
private int startNumber;
+
private int endNumber;
+
private int mode = EVEN_AND_ALL;
+
private int copies = 1;
+
private PrinterJob printerJob;
- public AWTPrintRenderer() {
- initialize();
+ public PrintRenderer() {
+ initializePrinterJob();
}
- private void initialize() throws IllegalArgumentException {
+ private void initializePrinterJob() throws IllegalArgumentException {
// read from command-line options
copies = getIntProperty("copies", 1);
startNumber = getIntProperty("start", 1) - 1;
@@ -48,22 +68,24 @@ public class AWTPrintRenderer extends AWTRenderer {
if (str != null) {
mode = Boolean.valueOf(str).booleanValue() ? EVEN : ODD;
}
-
+
printerJob = PrinterJob.getPrinterJob();
printerJob.setJobName("FOP Document");
printerJob.setCopies(copies);
if (System.getProperty("dialog") != null) {
if (!printerJob.printDialog()) {
- throw new IllegalArgumentException("Printing cancelled by operator");
+ throw new IllegalArgumentException(
+ "Printing cancelled by operator");
}
}
printerJob.setPageable(this);
- }
+ }
public void stopRenderer() throws IOException {
super.stopRenderer();
if (endNumber == -1) {
+ // was not set on command line
endNumber = getNumberOfPages();
}
@@ -76,10 +98,10 @@ public class AWTPrintRenderer extends AWTRenderer {
printerJob.print();
} catch (PrinterException e) {
e.printStackTrace();
- throw new IOException("Unable to print: "
- + e.getClass().getName()
- + ": " + e.getMessage());
+ throw new IOException("Unable to print: " + e.getClass().getName()
+ + ": " + e.getMessage());
}
+ clearViewportList();
}
public static int getIntProperty(String name, int def) {
@@ -117,5 +139,58 @@ public class AWTPrintRenderer extends AWTRenderer {
}
return vec;
}
-} // class AWTPrintRenderer
+ public int print(Graphics g, PageFormat pageFormat, int pageIndex)
+ throws PrinterException {
+ if (pageIndex >= getNumberOfPages()){
+ return NO_SUCH_PAGE;
+ }
+
+ Graphics2D g2 = (Graphics2D) g;
+
+ BufferedImage image;
+ try {
+ image = getPageImage(pageIndex);
+ } catch (FOPException e) {
+ e.printStackTrace();
+ return NO_SUCH_PAGE;
+ }
+
+ g2.drawImage(image,null,0,0);
+
+ return PAGE_EXISTS;
+ }
+
+ public PageFormat getPageFormat(int pageIndex)
+ throws IndexOutOfBoundsException {
+ if (pageIndex >= getNumberOfPages())
+ return null;
+
+ PageFormat pageFormat = new PageFormat();
+
+ Paper paper = new Paper();
+ pageFormat.setPaper(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);
+ }
+ return pageFormat;
+ }
+
+ public Printable getPrintable(int pageIndex)
+ throws IndexOutOfBoundsException {
+ return this;
+ }
+}
diff --git a/src/java/org/apache/fop/render/svg/SVGRenderer.java b/src/java/org/apache/fop/render/svg/SVGRenderer.java
index 25ea983d6..ccf1e82f4 100644
--- a/src/java/org/apache/fop/render/svg/SVGRenderer.java
+++ b/src/java/org/apache/fop/render/svg/SVGRenderer.java
@@ -137,7 +137,7 @@ public class SVGRenderer extends AbstractRenderer implements XMLHandler {
// create a temp Image to test font metrics on
BufferedImage fontImage =
new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
- org.apache.fop.render.awt.FontSetup.setup(fontInfo,
+ org.apache.fop.render.java2d.FontSetup.setup(fontInfo,
fontImage.createGraphics());
}
diff --git a/src/java/org/apache/fop/tools/anttasks/Fop.java b/src/java/org/apache/fop/tools/anttasks/Fop.java
index c60bb9f06..a26febb40 100644
--- a/src/java/org/apache/fop/tools/anttasks/Fop.java
+++ b/src/java/org/apache/fop/tools/anttasks/Fop.java
@@ -354,6 +354,13 @@ class FOPTaskStarter {
|| format.equalsIgnoreCase("at")
|| format.equalsIgnoreCase("xml")) {
return Constants.RENDER_XML;
+ } else if (format.equalsIgnoreCase("image/tiff")
+ || format.equalsIgnoreCase("tiff")
+ || format.equalsIgnoreCase("tif")) {
+ return Constants.RENDER_TIFF;
+ } else if (format.equalsIgnoreCase("image/png")
+ || format.equalsIgnoreCase("png")) {
+ return Constants.RENDER_PNG;
} else {
String err = "Couldn't determine renderer to use: " + format;
throw new BuildException(err);
@@ -376,6 +383,10 @@ class FOPTaskStarter {
return ".txt";
case Constants.RENDER_XML:
return ".xml";
+ case Constants.RENDER_TIFF:
+ return ".tiff";
+ case Constants.RENDER_PNG:
+ return ".png";
default:
String err = "Unknown renderer: " + renderer;
throw new BuildException(err);