diff options
author | Jeremias Maerki <jeremias@apache.org> | 2005-06-09 08:49:27 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2005-06-09 08:49:27 +0000 |
commit | 4aa0eca9779c3baf8ed3a21d6fd9e06fa2d71af9 (patch) | |
tree | e573b7bc321d90ea2d40719ec0e855557c56180e | |
parent | dd08f131b250a44f7b900b895deadf70981114fa (diff) | |
download | xmlgraphics-fop-4aa0eca9779c3baf8ed3a21d6fd9e06fa2d71af9.tar.gz xmlgraphics-fop-4aa0eca9779c3baf8ed3a21d6fd9e06fa2d71af9.zip |
Bugzilla: #33760
Resurrected Java2D/AWT Renderer (including bitmap output to PNG and TIFF using the Batik codecs and print capability).
Submitted by: Renaud Richardet <renaud.richardet.at.gmail.com>
Changes on the original patch:
- PageViewport: isResolved() caused a NPE which I fixed.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198725 13f79535-47bb-0310-9956-ffa450edef68
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������6J�����ӌ-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�.�??TV 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!æˆ ï¿½ï¿½Ä³ï¿½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 longLeftlongBtomlongARghtlongxslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenumESliceOrigin
+autoGeneratedTypeenum
+ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongARghtlongxurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefaultbgColorTypeenumESliceBGColorTypeNone topOutsetlong
+leftOutsetlongbottomOutsetlongrightOutsetlong8BIM8BIM8BIM�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��nm����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); |