From ff5f56081090a486965e0c766b1a5119dc6ed884 Mon Sep 17 00:00:00 2001 From: fotis Date: Thu, 16 Nov 2000 15:37:01 +0000 Subject: [PATCH] AWTRenderer uses now system fonts and not pdf fonts. All (error) messages are handled in the Gui [Dorothea Wiarda] git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193823 13f79535-47bb-0310-9956-ffa450edef68 --- src/org/apache/fop/apps/AWTCommandLine.java | 308 +-- src/org/apache/fop/apps/CommandLine.java | 334 ++- src/org/apache/fop/apps/Driver.java | 525 ++-- src/org/apache/fop/apps/XalanCommandLine.java | 318 +-- src/org/apache/fop/layout/FontMetric.java | 12 +- src/org/apache/fop/layout/FontState.java | 10 +- src/org/apache/fop/pdf/PDFDocument.java | 2 +- .../apache/fop/render/awt/AWTFontMetrics.java | 304 +++ .../apache/fop/render/awt/AWTRenderer.java | 2241 +++++++++-------- .../fop/render/awt/FontMetricsMapper.java | 182 ++ src/org/apache/fop/render/awt/FontSetup.java | 228 ++ src/org/apache/fop/render/pdf/Font.java | 3 + src/org/apache/fop/viewer/PreviewDialog.java | 201 +- 13 files changed, 2823 insertions(+), 1845 deletions(-) create mode 100644 src/org/apache/fop/render/awt/AWTFontMetrics.java create mode 100644 src/org/apache/fop/render/awt/FontMetricsMapper.java create mode 100644 src/org/apache/fop/render/awt/FontSetup.java diff --git a/src/org/apache/fop/apps/AWTCommandLine.java b/src/org/apache/fop/apps/AWTCommandLine.java index 7a7236baa..c82023cb9 100644 --- a/src/org/apache/fop/apps/AWTCommandLine.java +++ b/src/org/apache/fop/apps/AWTCommandLine.java @@ -43,191 +43,201 @@ import java.util.*; public class AWTCommandLine { - public static String TRANSLATION_PATH = "/org/apache/fop/viewer/resources/"; + public static String TRANSLATION_PATH = "/org/apache/fop/viewer/resources/"; - private Translator resource; + private Translator resource; - public AWTCommandLine(String srcFile, String language) { + public AWTCommandLine(String srcFile, String language) { - if (language == null) - language = System.getProperty("user.language"); + if (language == null) + language = System.getProperty("user.language"); - resource = getResourceBundle(TRANSLATION_PATH + "resources." + language); + resource = getResourceBundle(TRANSLATION_PATH + "resources." + + language); - UserMessage.setTranslator(getResourceBundle(TRANSLATION_PATH + "messages." + language)); + UserMessage.setTranslator( + getResourceBundle(TRANSLATION_PATH + "messages." + + language)); - resource.setMissingEmphasized(false); - AWTRenderer renderer = new AWTRenderer(resource); - PreviewDialog frame = createPreviewDialog(renderer, resource); - renderer.setProgressListener(frame); + resource.setMissingEmphasized(false); + AWTRenderer renderer = new AWTRenderer(resource); + PreviewDialog frame = createPreviewDialog(renderer, resource); + renderer.setProgressListener(frame); + renderer.setComponent(frame); + MessageHandler.setOutputMethod(MessageHandler.EVENT); + MessageHandler.addListener(frame); + //init parser + frame.progress(resource.getString("Init parser") + " ..."); + XMLReader parser = createParser(); -//init parser - frame.progress(resource.getString("Init parser") + " ..."); - XMLReader parser = createParser(); + if (parser == null) { + MessageHandler.errorln("ERROR: Unable to create SAX parser"); + System.exit(1); + } - if (parser == null) { - MessageHandler.errorln("ERROR: Unable to create SAX parser"); - System.exit(1); - } + // setting the necessary parser features + try { + parser.setFeature("http://xml.org/sax/features/namespace-prefixes", + true); + } catch (SAXException e) { + MessageHandler.errorln("Error in setting up parser feature namespace-prefixes"); + MessageHandler.errorln("You need a parser which supports SAX version 2"); + System.exit(1); + } - // setting the necessary parser features - try { - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true); - } catch (SAXException e) { - MessageHandler.errorln("Error in setting up parser feature namespace-prefixes"); - MessageHandler.errorln("You need a parser which supports SAX version 2"); - System.exit(1); - } + try { + Driver driver = new Driver(); + driver.setRenderer(renderer); - try { - Driver driver = new Driver(); - driver.setRenderer(renderer); + // init mappings: time + frame.progress(resource.getString("Init mappings") + " ..."); -// init mappings: time - frame.progress(resource.getString("Init mappings") + " ..."); + driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); + driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); + driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); + driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); + // build FO tree: time + frame.progress(resource.getString("Build FO tree") + " ..."); + driver.buildFOTree(parser, fileInputSource(srcFile)); -// build FO tree: time - frame.progress(resource.getString("Build FO tree") + " ..."); - driver.buildFOTree(parser, fileInputSource(srcFile)); + // layout FO tree: time + frame.progress(resource.getString("Layout FO tree") + " ..."); + driver.format(); -// layout FO tree: time - frame.progress(resource.getString("Layout FO tree") + " ..."); - driver.format(); + // render: time + frame.progress(resource.getString("Render") + " ..."); + driver.render(); -// render: time - frame.progress(resource.getString("Render") + " ..."); - driver.render(); + frame.progress(resource.getString("Show")); + frame.showPage(); - frame.progress(resource.getString("Show")); - frame.showPage(); - - } catch (Exception e) { - MessageHandler.errorln("FATAL ERROR: " + e.getMessage()); - e.printStackTrace(); - System.exit(1); - } - } + } catch (Exception e) { + MessageHandler.errorln("FATAL ERROR: " + e.getMessage()); + e.printStackTrace(); + System.exit(1); + } + } static XMLReader createParser() { - String parserClassName = - System.getProperty("org.xml.sax.parser"); - if (parserClassName == null) { - parserClassName = "org.apache.xerces.parsers.SAXParser"; - } - MessageHandler.errorln("using SAX parser " + parserClassName); - - try { - return (XMLReader) - Class.forName(parserClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + parserClassName); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + parserClassName); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + parserClassName); - } catch (ClassCastException e) { - MessageHandler.errorln(parserClassName + " is not a SAX driver"); - } - return null; + String parserClassName = System.getProperty("org.xml.sax.parser"); + if (parserClassName == null) { + parserClassName = "org.apache.xerces.parsers.SAXParser"; + } + MessageHandler.logln("using SAX parser " + parserClassName); + + try { + return (XMLReader) Class.forName( + parserClassName).newInstance(); + } catch (ClassNotFoundException e) { + MessageHandler.errorln("Could not find " + parserClassName); + } + catch (InstantiationException e) { + MessageHandler.errorln("Could not instantiate " + + parserClassName); + } + catch (IllegalAccessException e) { + MessageHandler.errorln("Could not access " + parserClassName); + } + catch (ClassCastException e) { + MessageHandler.errorln(parserClassName + " is not a SAX driver"); + } + return null; } - protected PreviewDialog createPreviewDialog(AWTRenderer renderer, Translator res) { - PreviewDialog frame = new PreviewDialog(renderer, res); - frame.validate(); - - // center window - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - Dimension frameSize = frame.getSize(); - if (frameSize.height > screenSize.height) - frameSize.height = screenSize.height; - if (frameSize.width > screenSize.width) - frameSize.width = screenSize.width; - frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); - frame.setVisible(true); - return frame; - } - - - - /** - * create an InputSource from a file name - * - * @param filename the name of the file - * @return the InputSource created - */ - protected static InputSource fileInputSource(String filename) { - /* this code adapted from James Clark's in XT */ - File file = new File(filename); - String path = file.getAbsolutePath(); - String fSep = System.getProperty("file.separator"); - if (fSep != null && fSep.length() == 1) - path = path.replace(fSep.charAt(0), '/'); - if (path.length() > 0 && path.charAt(0) != '/') - path = '/' + path; - try { - return new InputSource(new URL("file", null, - path).toString()); - } - catch (java.net.MalformedURLException e) { - throw new Error("unexpected MalformedURLException"); - } - } - - - private SecureResourceBundle getResourceBundle(String path) { - InputStream in = null; - - try { - URL url = getClass().getResource(path); - in = url.openStream(); - } catch(Exception ex) { - MessageHandler.logln("Can't find URL to: <" + path + "> " + ex.getMessage()); + protected PreviewDialog createPreviewDialog(AWTRenderer renderer, + Translator res) { + PreviewDialog frame = new PreviewDialog(renderer, res); + frame.validate(); + + // center window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = frame.getSize(); + if (frameSize.height > screenSize.height) + frameSize.height = screenSize.height; + if (frameSize.width > screenSize.width) + frameSize.width = screenSize.width; + frame.setLocation((screenSize.width - frameSize.width) / 2, + (screenSize.height - frameSize.height) / 2); + frame.setVisible(true); + return frame; } - return new SecureResourceBundle(in); - } - /* main - */ - public static void main(String[] args) { - try { - UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel()); - } catch (Exception e) { - e.printStackTrace(); + + /** + * create an InputSource from a file name + * + * @param filename the name of the file + * @return the InputSource created + */ + protected static InputSource fileInputSource(String filename) { + /* this code adapted from James Clark's in XT */ + File file = new File(filename); + String path = file.getAbsolutePath(); + String fSep = System.getProperty("file.separator"); + if (fSep != null && fSep.length() == 1) + path = path.replace(fSep.charAt(0), '/'); + if (path.length() > 0 && path.charAt(0) != '/') + path = '/' + path; + try { + return new InputSource(new URL("file", null, path).toString()); + } catch (java.net.MalformedURLException e) { + throw new Error("unexpected MalformedURLException"); + } } - String srcPath = null; - String language = null; - String imageDir = null; - MessageHandler.errorln(Version.getVersion()); - if (args.length < 1 || args.length > 3) { - MessageHandler.errorln("usage: java AWTCommandLine " + - "formatting-object-file [language] "); - System.exit(1); - } + private SecureResourceBundle getResourceBundle(String path) { + InputStream in = null; - srcPath = args[0]; - if (args.length > 1) { - language = args[1]; + try { + URL url = getClass().getResource(path); + in = url.openStream(); + } catch (Exception ex) { + MessageHandler.logln("Can't find URL to: <" + path + "> " + + ex.getMessage()); + } + return new SecureResourceBundle(in); } - new AWTCommandLine(srcPath, language); - } // main -} // AWTCommandLine + /* main + */ + public static void main(String[] args) { + try { + UIManager.setLookAndFeel( + new javax.swing.plaf.metal.MetalLookAndFeel()); + } catch (Exception e) { + e.printStackTrace(); + } + + String srcPath = null; + String language = null; + String imageDir = null; + + MessageHandler.errorln(Version.getVersion()); + if (args.length < 1 || args.length > 3) { + MessageHandler.errorln("usage: java AWTCommandLine " + "formatting-object-file [language] "); + System.exit(1); + } + + srcPath = args[0]; + if (args.length > 1) { + language = args[1]; + } + + new AWTCommandLine(srcPath, language); + + } // main +} // AWTCommandLine + diff --git a/src/org/apache/fop/apps/CommandLine.java b/src/org/apache/fop/apps/CommandLine.java index 11cf71d33..d817f2587 100644 --- a/src/org/apache/fop/apps/CommandLine.java +++ b/src/org/apache/fop/apps/CommandLine.java @@ -1,36 +1,36 @@ -/*-- $Id$ -- +/*-- $Id$ -- ============================================================================ The Apache Software License, Version 1.1 ============================================================================ - + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. - + Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. - + 4. The names "Fop" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. - + 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. - + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE @@ -41,12 +41,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by - James Tauber . For more information on the Apache + James Tauber . For more information on the Apache Software Foundation, please see . - + */ @@ -67,7 +67,7 @@ import java.io.IOException; import java.io.FileNotFoundException; import java.net.URL; -// FOP +// FOP import org.apache.fop.messaging.MessageHandler; @@ -76,180 +76,178 @@ import org.apache.fop.messaging.MessageHandler; * * Gets input and output filenames from the command line. * Creates a SAX Parser (defaulting to Xerces). - * + * */ public class CommandLine { private String foFile = null; private String pdfFile = null; - + /** show a full dump on error */ private static boolean errorDump = false; - - public CommandLine(String[] args) - { - for (int i=0; i 0 && path.charAt(0) != '/') - path = '/' + path; - try { - return new InputSource(new URL("file", null, - path).toString()); - } - catch (java.net.MalformedURLException e) { - throw new Error("unexpected MalformedURLException"); - } + + /* this code adapted from James Clark's in XT */ + File file = new File(filename); + String path = file.getAbsolutePath(); + String fSep = System.getProperty("file.separator"); + if (fSep != null && fSep.length() == 1) + path = path.replace(fSep.charAt(0), '/'); + if (path.length() > 0 && path.charAt(0) != '/') + path = '/' + path; + try { + return new InputSource(new URL("file", null, path).toString()); + } catch (java.net.MalformedURLException e) { + throw new Error("unexpected MalformedURLException"); + } } /** - * mainline method - * - * first command line argument is input file - * second command line argument is output file - * - * @param command line arguments - */ + * mainline method + * + * first command line argument is input file + * second command line argument is output file + * + * @param command line arguments + */ public static void main(String[] args) { - String version = Version.getVersion(); - MessageHandler.errorln(version); - - CommandLine cmdLine = new CommandLine(args); - cmdLine.run(); - + String version = Version.getVersion(); + MessageHandler.errorln(version); + + CommandLine cmdLine = new CommandLine(args); + cmdLine.run(); + } - + } diff --git a/src/org/apache/fop/apps/Driver.java b/src/org/apache/fop/apps/Driver.java index ff2ad79bc..46b922970 100644 --- a/src/org/apache/fop/apps/Driver.java +++ b/src/org/apache/fop/apps/Driver.java @@ -1,36 +1,36 @@ -/*-- $Id$ -- +/*-- $Id$ -- ============================================================================ The Apache Software License, Version 1.1 ============================================================================ - + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. - + Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. - + 4. The names "FOP" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. - + 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. - + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE @@ -41,12 +41,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by - James Tauber . For more information on the Apache + James Tauber . For more information on the Apache Software Foundation, please see . - + */ package org.apache.fop.apps; @@ -131,307 +131,316 @@ public class Driver { /** If true, full error stacks are reported */ protected boolean errorDump; - + /** create a new Driver */ public Driver() { - this.treeBuilder = new FOTreeBuilder(); + this.treeBuilder = new FOTreeBuilder(); } - + /** Set the error dump option - * @param dump if true, full stacks will be reported to the error log - */ - public void setErrorDump(boolean dump) - { - errorDump = dump; + * @param dump if true, full stacks will be reported to the error log + */ + public void setErrorDump(boolean dump) { + errorDump = dump; } - + /** set the Renderer to use */ public void setRenderer(Renderer renderer) { - this.renderer = renderer; + this.renderer = renderer; } /** - * set the class name of the Renderer to use as well as the - * producer string for those renderers that can make use of it - */ + * set the class name of the Renderer to use as well as the + * producer string for those renderers that can make use of it + */ public void setRenderer(String rendererClassName, String producer) { - this.renderer = createRenderer(rendererClassName); - this.renderer.setProducer(producer); + this.renderer = createRenderer(rendererClassName); + this.renderer.setProducer(producer); } /** - * protected method used by setRenderer(String, String) to - * instantiate the Renderer class - */ + * protected method used by setRenderer(String, String) to + * instantiate the Renderer class + */ protected Renderer createRenderer(String rendererClassName) { - MessageHandler.logln("using renderer " + rendererClassName); - - try { - return (Renderer) - Class.forName(rendererClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + rendererClassName); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + rendererClassName); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + rendererClassName); - } catch (ClassCastException e) { - MessageHandler.errorln(rendererClassName + " is not a renderer"); - } - return null; + MessageHandler.logln("using renderer " + rendererClassName); + + try { + return (Renderer) Class.forName( + rendererClassName).newInstance(); + } catch (ClassNotFoundException e) { + MessageHandler.errorln("Could not find " + rendererClassName); + } + catch (InstantiationException e) { + MessageHandler.errorln("Could not instantiate " + + rendererClassName); + } + catch (IllegalAccessException e) { + MessageHandler.errorln("Could not access " + rendererClassName); + } + catch (ClassCastException e) { + MessageHandler.errorln(rendererClassName + " is not a renderer"); + } + return null; } - + /** - * add the given element mapping. - * - * an element mapping maps element names to Java classes - */ + * add the given element mapping. + * + * an element mapping maps element names to Java classes + */ public void addElementMapping(ElementMapping mapping) { - mapping.addToBuilder(this.treeBuilder); + mapping.addToBuilder(this.treeBuilder); } - + /** - * add the element mapping with the given class name - */ + * add the element mapping with the given class name + */ public void addElementMapping(String mappingClassName) { - createElementMapping(mappingClassName).addToBuilder(this.treeBuilder); + createElementMapping(mappingClassName).addToBuilder( + this.treeBuilder); } /** - * protected method used by addElementMapping(String) to - * instantiate element mapping class - */ - protected ElementMapping createElementMapping(String mappingClassName) { - MessageHandler.logln("using element mapping " + mappingClassName); - - try { - return (ElementMapping) - Class.forName(mappingClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + mappingClassName); - dumpError(e); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + mappingClassName); - dumpError(e); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + mappingClassName); - dumpError(e); - } catch (ClassCastException e) { - MessageHandler.errorln(mappingClassName + " is not an element mapping"); - dumpError(e); - } - return null; + * protected method used by addElementMapping(String) to + * instantiate element mapping class + */ + protected ElementMapping createElementMapping( + String mappingClassName) { + MessageHandler.logln("using element mapping " + mappingClassName); + + try { + return (ElementMapping) Class.forName( + mappingClassName).newInstance(); + } catch (ClassNotFoundException e) { + MessageHandler.errorln("Could not find " + mappingClassName); + dumpError(e); + } + catch (InstantiationException e) { + MessageHandler.errorln("Could not instantiate " + + mappingClassName); + dumpError(e); + } + catch (IllegalAccessException e) { + MessageHandler.errorln("Could not access " + mappingClassName); + dumpError(e); + } + catch (ClassCastException e) { + MessageHandler.errorln(mappingClassName + " is not an element mapping"); + dumpError(e); + } + return null; } /** - * add the element mapping with the given class name - */ + * add the element mapping with the given class name + */ public void addPropertyList(String listClassName) { - createPropertyList(listClassName).addToBuilder(this.treeBuilder); + createPropertyList(listClassName).addToBuilder(this.treeBuilder); } /** - * protected method used by addPropertyList(String) to - * instantiate list mapping class - */ - protected PropertyListMapping createPropertyList(String listClassName) { - MessageHandler.logln("using property list mapping " + listClassName); - - try { - return (PropertyListMapping) - Class.forName(listClassName).newInstance(); - } catch (ClassNotFoundException e) { - MessageHandler.errorln("Could not find " + listClassName); - dumpError(e); - } catch (InstantiationException e) { - MessageHandler.errorln("Could not instantiate " - + listClassName); - dumpError(e); - } catch (IllegalAccessException e) { - MessageHandler.errorln("Could not access " + listClassName); - dumpError(e); - } catch (ClassCastException e) { - MessageHandler.errorln(listClassName + " is not an property list"); - dumpError(e); - } - return null; + * protected method used by addPropertyList(String) to + * instantiate list mapping class + */ + protected PropertyListMapping createPropertyList( + String listClassName) { + MessageHandler.logln("using property list mapping " + + listClassName); + + try { + return (PropertyListMapping) Class.forName( + listClassName).newInstance(); + } catch (ClassNotFoundException e) { + MessageHandler.errorln("Could not find " + listClassName); + dumpError(e); + } + catch (InstantiationException e) { + MessageHandler.errorln("Could not instantiate " + + listClassName); + dumpError(e); + } + catch (IllegalAccessException e) { + MessageHandler.errorln("Could not access " + listClassName); + dumpError(e); + } + catch (ClassCastException e) { + MessageHandler.errorln(listClassName + " is not an property list"); + dumpError(e); + } + return null; } /** - * return the tree builder (a SAX DocumentHandler). - * - * used in situations where SAX is used but not via a FOP-invoked - * SAX parser. A good example is an XSLT engine that fires SAX - * events but isn't a SAX Parser itself. - */ + * return the tree builder (a SAX DocumentHandler). + * + * used in situations where SAX is used but not via a FOP-invoked + * SAX parser. A good example is an XSLT engine that fires SAX + * events but isn't a SAX Parser itself. + */ public ContentHandler getContentHandler() { - return this.treeBuilder; + return this.treeBuilder; } /** - * build the formatting object tree using the given SAX Parser and - * SAX InputSource - */ - public void buildFOTree(XMLReader parser, InputSource source) - throws FOPException { - - parser.setContentHandler(this.treeBuilder); - try { - parser.parse(source); - } catch (SAXException e) { - if (e.getException() instanceof FOPException) { - dumpError(e.getException()); - throw (FOPException) e.getException(); - } - else { - dumpError(e); - throw new FOPException(e.getMessage()); - } - } catch (IOException e) { - dumpError(e); - throw new FOPException(e.getMessage()); - } + * build the formatting object tree using the given SAX Parser and + * SAX InputSource + */ + public void buildFOTree(XMLReader parser, + InputSource source) throws FOPException { + + parser.setContentHandler(this.treeBuilder); + try { + parser.parse(source); + } catch (SAXException e) { + if (e.getException() instanceof FOPException) { + dumpError(e.getException()); + throw (FOPException) e.getException(); + } else { + dumpError(e); + throw new FOPException(e.getMessage()); + } + } + catch (IOException e) { + dumpError(e); + throw new FOPException(e.getMessage()); + } } /** - * build the formatting object tree using the given DOM Document - */ - public void buildFOTree(Document document) - throws FOPException { - - /* most of this code is modified from John Cowan's */ - - Node currentNode; - AttributesImpl currentAtts; - - /* temporary array for making Strings into character arrays */ - char[] array = null; - - currentAtts = new AttributesImpl(); - - /* start at the document element */ - currentNode = document; - - try { - while (currentNode != null) { - switch (currentNode.getNodeType()) { - case Node.DOCUMENT_NODE: - this.treeBuilder.startDocument(); - break; - case Node.CDATA_SECTION_NODE: - case Node.TEXT_NODE: - String data = currentNode.getNodeValue(); - int datalen = data.length(); - if (array == null || array.length < datalen) { - /* if the array isn't big enough, make a new - one */ - array = new char[datalen]; - } - data.getChars(0, datalen, array, 0); - this.treeBuilder.characters(array, 0, datalen); - break; - case Node.PROCESSING_INSTRUCTION_NODE: - this.treeBuilder.processingInstruction( - currentNode.getNodeName(), - currentNode.getNodeValue()); - break; - case Node.ELEMENT_NODE: - NamedNodeMap map = currentNode.getAttributes(); - currentAtts.clear(); - for (int i = map.getLength() - 1; i >= 0; i--) { - Attr att = (Attr)map.item(i); - currentAtts.addAttribute(att.getNamespaceURI(), - att.getLocalName(), - att.getName(), - "CDATA", - att.getValue()); - } - this.treeBuilder.startElement( - currentNode.getNamespaceURI(), currentNode.getLocalName(), currentNode.getNodeName(), currentAtts); - break; - } - - Node nextNode = currentNode.getFirstChild(); - if (nextNode != null) { - currentNode = nextNode; - continue; - } - - while (currentNode != null) { - switch (currentNode.getNodeType()) { - case Node.DOCUMENT_NODE: - this.treeBuilder.endDocument(); - break; - case Node.ELEMENT_NODE: - this.treeBuilder.endElement( - currentNode.getNamespaceURI(), currentNode.getLocalName(), currentNode.getNodeName()); - break; - } - - nextNode = currentNode.getNextSibling(); - if (nextNode != null) { - currentNode = nextNode; - break; - } - - currentNode = currentNode.getParentNode(); - } - } - } catch (SAXException e) { - dumpError(e); - throw new FOPException(e.getMessage()); - } + * build the formatting object tree using the given DOM Document + */ + public void buildFOTree(Document document) throws FOPException { + + /* most of this code is modified from John Cowan's */ + + Node currentNode; + AttributesImpl currentAtts; + + /* temporary array for making Strings into character arrays */ + char[] array = null; + + currentAtts = new AttributesImpl(); + + /* start at the document element */ + currentNode = document; + + try { + while (currentNode != null) { + switch (currentNode.getNodeType()) { + case Node.DOCUMENT_NODE: + this.treeBuilder.startDocument(); + break; + case Node.CDATA_SECTION_NODE: + case Node.TEXT_NODE: + String data = currentNode.getNodeValue(); + int datalen = data.length(); + if (array == null || array.length < datalen) { + /* if the array isn't big enough, make a new + one */ + array = new char[datalen]; + } + data.getChars(0, datalen, array, 0); + this.treeBuilder.characters(array, 0, datalen); + break; + case Node.PROCESSING_INSTRUCTION_NODE: + this.treeBuilder.processingInstruction( + currentNode.getNodeName(), + currentNode.getNodeValue()); + break; + case Node.ELEMENT_NODE: + NamedNodeMap map = currentNode.getAttributes(); + currentAtts.clear(); + for (int i = map.getLength() - 1; i >= 0; i--) { + Attr att = (Attr) map.item(i); + currentAtts.addAttribute( att.getNamespaceURI(), + att.getLocalName(), att.getName(), + "CDATA", att.getValue()); + } + this.treeBuilder.startElement( + currentNode.getNamespaceURI(), + currentNode.getLocalName(), + currentNode.getNodeName(), currentAtts); + break; + } + + Node nextNode = currentNode.getFirstChild(); + if (nextNode != null) { + currentNode = nextNode; + continue; + } + + while (currentNode != null) { + switch (currentNode.getNodeType()) { + case Node.DOCUMENT_NODE: + this.treeBuilder.endDocument(); + break; + case Node.ELEMENT_NODE: + this.treeBuilder.endElement( + currentNode.getNamespaceURI(), + currentNode.getLocalName(), + currentNode.getNodeName()); + break; + } + + nextNode = currentNode.getNextSibling(); + if (nextNode != null) { + currentNode = nextNode; + break; + } + + currentNode = currentNode.getParentNode(); + } + } + } catch (SAXException e) { + dumpError(e); + throw new FOPException(e.getMessage()); + } } /** - * Dumps an error - */ - public void dumpError(Exception e) - { - if (errorDump) { - if (e instanceof SAXException) { - e.printStackTrace(); - if (((SAXException)e).getException() != null) { - ((SAXException)e).getException().printStackTrace(); - } - } - else { - e.printStackTrace(); - } - } - + * Dumps an error + */ + public void dumpError(Exception e) { + if (errorDump) { + if (e instanceof SAXException) { + e.printStackTrace(); + if (((SAXException) e).getException() != null) { + ((SAXException) e).getException().printStackTrace(); + } + } else { + e.printStackTrace(); + } + } + } - + /** - * set the PrintWriter to use to output the result of the Renderer - * (if applicable) - */ + * set the PrintWriter to use to output the result of the Renderer + * (if applicable) + */ public void setWriter(PrintWriter writer) { - this.writer = writer; + this.writer = writer; } /** - * format the formatting object tree into an area tree - */ - public void format() - throws FOPException { - FontInfo fontInfo = new FontInfo(); - this.renderer.setupFontInfo(fontInfo); + * format the formatting object tree into an area tree + */ + public void format() throws FOPException { + FontInfo fontInfo = new FontInfo(); + this.renderer.setupFontInfo(fontInfo); - this.areaTree = new AreaTree(); - this.areaTree.setFontInfo(fontInfo); + this.areaTree = new AreaTree(); + this.areaTree.setFontInfo(fontInfo); - this.treeBuilder.format(areaTree); + this.treeBuilder.format(areaTree); } /** - * render the area tree to the output form - */ - public void render() - throws IOException, FOPException { - this.renderer.render(areaTree, this.writer); + * render the area tree to the output form + */ + public void render() throws IOException, FOPException { + this.renderer.render(areaTree, this.writer); } } diff --git a/src/org/apache/fop/apps/XalanCommandLine.java b/src/org/apache/fop/apps/XalanCommandLine.java index 7df56cf18..0981dfe7e 100644 --- a/src/org/apache/fop/apps/XalanCommandLine.java +++ b/src/org/apache/fop/apps/XalanCommandLine.java @@ -90,164 +90,172 @@ import org.apache.fop.messaging.MessageHandler; */ public class XalanCommandLine { - /** - * creates a SAX parser, using the value of org.xml.sax.parser - * defaulting to org.apache.xerces.parsers.SAXParser - * - * @return the created SAX parser - */ - static XMLReader createParser() { - String parserClassName = - System.getProperty("org.xml.sax.parser"); - if (parserClassName == null) { - parserClassName = "org.apache.xerces.parsers.SAXParser"; - } - org.apache.fop.messaging.MessageHandler.logln("using SAX parser " + parserClassName); - - try { - return (XMLReader) - Class.forName(parserClassName).newInstance(); - } catch (ClassNotFoundException e) { - org.apache.fop.messaging.MessageHandler.errorln("Could not find " + parserClassName); - } catch (InstantiationException e) { - org.apache.fop.messaging.MessageHandler.errorln("Could not instantiate " - + parserClassName); - } catch (IllegalAccessException e) { - org.apache.fop.messaging.MessageHandler.errorln("Could not access " + parserClassName); - } catch (ClassCastException e) { - org.apache.fop.messaging.MessageHandler.errorln(parserClassName + " is not a SAX driver"); - } - return null; - } - - /** - * create an InputSource from a file name - * - * @param filename the name of the file - * @return the InputSource created - */ - protected static InputSource fileInputSource(String filename) { - - /* this code adapted from James Clark's in XT */ - File file = new File(filename); - String path = file.getAbsolutePath(); - String fSep = System.getProperty("file.separator"); - if (fSep != null && fSep.length() == 1) - path = path.replace(fSep.charAt(0), '/'); - if (path.length() > 0 && path.charAt(0) != '/') - path = '/' + path; - try { - return new InputSource(new URL("file", null, - path).toString()); - } - catch (java.net.MalformedURLException e) { - throw new Error("unexpected MalformedURLException"); - } - } - - /** - * mainline method - * - * first command line argument is xml input file - * second command line argument is xslt file which commands the conversion from xml to xsl:fo - * third command line argument is the output file - * - * @param command line arguments - */ - public static void main(String[] args) { - String version = Version.getVersion(); - MessageHandler.logln(version); - - - if (args.length != 3) { - MessageHandler.errorln("usage: java " - + "org.apache.fop.apps.XalanCommandLine " - + "xml-file xslt-file pdf-file"); - System.exit(1); + /** + * creates a SAX parser, using the value of org.xml.sax.parser + * defaulting to org.apache.xerces.parsers.SAXParser + * + * @return the created SAX parser + */ + static XMLReader createParser() { + String parserClassName = System.getProperty("org.xml.sax.parser"); + if (parserClassName == null) { + parserClassName = "org.apache.xerces.parsers.SAXParser"; + } + org.apache.fop.messaging.MessageHandler.logln( + "using SAX parser " + parserClassName); + + try { + return (XMLReader) Class.forName( + parserClassName).newInstance(); + } catch (ClassNotFoundException e) { + org.apache.fop.messaging.MessageHandler.errorln( + "Could not find " + parserClassName); + } + catch (InstantiationException e) { + org.apache.fop.messaging.MessageHandler.errorln( + "Could not instantiate " + parserClassName); + } + catch (IllegalAccessException e) { + org.apache.fop.messaging.MessageHandler.errorln( + "Could not access " + parserClassName); + } + catch (ClassCastException e) { + org.apache.fop.messaging.MessageHandler.errorln( + parserClassName + " is not a SAX driver"); + } + return null; } - XMLReader parser = createParser(); - - if (parser == null) { - MessageHandler.errorln("ERROR: Unable to create SAX parser"); - System.exit(1); - } - - // setting the parser features - try { - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", true); - } catch (SAXException e) { - MessageHandler.errorln("Error in setting up parser feature namespace-prefixes"); - MessageHandler.errorln("You need a parser which supports SAX version 2"); - System.exit(1); + /** + * create an InputSource from a file name + * + * @param filename the name of the file + * @return the InputSource created + */ + protected static InputSource fileInputSource(String filename) { + + /* this code adapted from James Clark's in XT */ + File file = new File(filename); + String path = file.getAbsolutePath(); + String fSep = System.getProperty("file.separator"); + if (fSep != null && fSep.length() == 1) + path = path.replace(fSep.charAt(0), '/'); + if (path.length() > 0 && path.charAt(0) != '/') + path = '/' + path; + try { + return new InputSource(new URL("file", null, path).toString()); + } catch (java.net.MalformedURLException e) { + throw new Error("unexpected MalformedURLException"); + } } - - try { - java.io.Writer writer; - java.io.Reader reader; - boolean usefile = false; - - MessageHandler.logln("transforming to xsl:fo markup"); - - - // create a Writer - // the following is an ugly hack to allow processing of larger files - // if xml file size is larger than 700 kb write the fo:file to disk - if ((new File(args[0]).length()) > 500000) { - writer = new FileWriter(args[2]+".tmp"); - usefile = true; - } else { - writer = new StringWriter(); - } - - // Use XSLTProcessorFactory to instantiate an XSLTProcessor. - XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); - - // Create the 3 objects the XSLTProcessor needs to perform the transformation. - // Fix up the args... - XMLParserLiaison xmlPL = processor.getXMLProcessorLiaison(); - URL urlTmp = xmlPL.getURLFromString(args[0], null); - System.err.println("XML File: " + args[0]); - System.err.println("URL: " + urlTmp); - XSLTInputSource xmlSource = new XSLTInputSource (urlTmp.toString()); - urlTmp = xmlPL.getURLFromString(args[1], null); - System.err.println("XSL File: " + args[1]); - System.err.println("URL: " + urlTmp); - XSLTInputSource xslSheet = new XSLTInputSource (urlTmp.toString()); - - XSLTResultTarget xmlResult = new XSLTResultTarget (writer); - - // Perform the transformation. - processor.process(xmlSource, xslSheet, xmlResult); - - if (usefile) { - reader = new FileReader(args[2]+".tmp"); - } else { - // create a input source containing the xsl:fo file which can be fed to Fop - reader = new StringReader(writer.toString()); - } - writer.flush(); - writer.close(); - - //set Driver methods to start Fop processing - Driver driver = new Driver(); - driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", version); - driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); - driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); - driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); - driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); - driver.setWriter(new PrintWriter(new FileWriter(args[2]))); - driver.buildFOTree(parser, new InputSource(reader)); - reader.close(); - driver.format(); - driver.render(); - if (usefile) { - new File (args[2]+".tmp").delete(); - } - } catch (Exception e) { - MessageHandler.errorln("FATAL ERROR: " + e.getMessage()); - System.exit(1); + /** + * mainline method + * + * first command line argument is xml input file + * second command line argument is xslt file which commands the conversion from xml to xsl:fo + * third command line argument is the output file + * + * @param command line arguments + */ + public static void main(String[] args) { + String version = Version.getVersion(); + MessageHandler.logln(version); + + + if (args.length != 3) { + MessageHandler.errorln("usage: java " + + "org.apache.fop.apps.XalanCommandLine " + "xml-file xslt-file pdf-file"); + System.exit(1); + } + + XMLReader parser = createParser(); + + if (parser == null) { + MessageHandler.errorln("ERROR: Unable to create SAX parser"); + System.exit(1); + } + + // setting the parser features + try { + parser.setFeature("http://xml.org/sax/features/namespace-prefixes", + true); + } catch (SAXException e) { + MessageHandler.errorln("Error in setting up parser feature namespace-prefixes"); + MessageHandler.errorln("You need a parser which supports SAX version 2"); + System.exit(1); + } + + + try { + java.io.Writer writer; + java.io.Reader reader; + boolean usefile = false; + + MessageHandler.logln("transforming to xsl:fo markup"); + + + // create a Writer + // the following is an ugly hack to allow processing of larger files + // if xml file size is larger than 700 kb write the fo:file to disk + if ((new File(args[0]).length()) > 500000) { + writer = new FileWriter(args[2] + ".tmp"); + usefile = true; + } else { + writer = new StringWriter(); + } + + // Use XSLTProcessorFactory to instantiate an XSLTProcessor. + XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); + + // Create the 3 objects the XSLTProcessor needs to perform the transformation. + // Fix up the args... + XMLParserLiaison xmlPL = processor.getXMLProcessorLiaison(); + URL urlTmp = xmlPL.getURLFromString(args[0], null); + System.err.println("XML File: " + args[0]); + System.err.println("URL: " + urlTmp); + XSLTInputSource xmlSource = + new XSLTInputSource (urlTmp.toString()); + urlTmp = xmlPL.getURLFromString(args[1], null); + System.err.println("XSL File: " + args[1]); + System.err.println("URL: " + urlTmp); + XSLTInputSource xslSheet = + new XSLTInputSource (urlTmp.toString()); + + XSLTResultTarget xmlResult = new XSLTResultTarget (writer); + + // Perform the transformation. + processor.process(xmlSource, xslSheet, xmlResult); + + if (usefile) { + reader = new FileReader(args[2] + ".tmp"); + } else { + // create a input source containing the xsl:fo file which can be fed to Fop + reader = new StringReader(writer.toString()); + } + writer.flush(); + writer.close(); + + //set Driver methods to start Fop processing + Driver driver = new Driver(); + driver.setRenderer("org.apache.fop.render.pdf.PDFRenderer", + version); + driver.addElementMapping("org.apache.fop.fo.StandardElementMapping"); + driver.addElementMapping("org.apache.fop.svg.SVGElementMapping"); + driver.addPropertyList("org.apache.fop.fo.StandardPropertyListMapping"); + driver.addPropertyList("org.apache.fop.svg.SVGPropertyListMapping"); + driver.setWriter(new PrintWriter(new FileWriter(args[2]))); + driver.buildFOTree(parser, new InputSource(reader)); + reader.close(); + driver.format(); + driver.render(); + if (usefile) { + new File (args[2] + ".tmp").delete(); + } + } + catch (Exception e) { + MessageHandler.errorln("FATAL ERROR: " + e.getMessage()); + System.exit(1); + } } - } } diff --git a/src/org/apache/fop/layout/FontMetric.java b/src/org/apache/fop/layout/FontMetric.java index 426702f8e..e203d3103 100644 --- a/src/org/apache/fop/layout/FontMetric.java +++ b/src/org/apache/fop/layout/FontMetric.java @@ -55,10 +55,10 @@ package org.apache.fop.layout; */ public interface FontMetric { - public int getAscender(); - public int getCapHeight(); - public int getDescender(); - public int getXHeight(); + public int getAscender(int size); + public int getCapHeight(int size); + public int getDescender(int size); + public int getXHeight(int size); public int getFirstChar(); public int getLastChar(); @@ -67,6 +67,6 @@ public interface FontMetric { * return width (in 1/1000ths of point size) of character at * code point i */ - public int width(int i); - public int[] getWidths(); + public int width(int i, int size); + public int[] getWidths(int size); } diff --git a/src/org/apache/fop/layout/FontState.java b/src/org/apache/fop/layout/FontState.java index c9dcbbbc4..55508dc70 100644 --- a/src/org/apache/fop/layout/FontState.java +++ b/src/org/apache/fop/layout/FontState.java @@ -73,15 +73,15 @@ public class FontState { } public int getAscender() { - return fontSize * metric.getAscender() / 1000; + return metric.getAscender(fontSize) / 1000; } public int getCapHeight() { - return fontSize * metric.getCapHeight() / 1000; + return metric.getCapHeight(fontSize) / 1000; } public int getDescender() { - return fontSize * metric.getDescender() / 1000; + return metric.getDescender(fontSize) / 1000; } public String getFontName() { @@ -109,11 +109,11 @@ public class FontState { } public int getXHeight() { - return fontSize * metric.getXHeight() / 1000; + return metric.getXHeight(fontSize) / 1000; } public int width(int charnum) { // returns width of given character number in millipoints - return (fontSize * metric.width(charnum) / 1000); + return (metric.width(charnum, fontSize) / 1000); } } diff --git a/src/org/apache/fop/pdf/PDFDocument.java b/src/org/apache/fop/pdf/PDFDocument.java index d93367faa..a259238a2 100644 --- a/src/org/apache/fop/pdf/PDFDocument.java +++ b/src/org/apache/fop/pdf/PDFDocument.java @@ -763,7 +763,7 @@ public class PDFDocument { PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor); font.setDescriptor(pdfdesc); font.setWidthMetrics(metrics.getFirstChar(), metrics.getLastChar(), - makeArray(metrics.getWidths())); + makeArray(metrics.getWidths(1))); return font; } } diff --git a/src/org/apache/fop/render/awt/AWTFontMetrics.java b/src/org/apache/fop/render/awt/AWTFontMetrics.java new file mode 100644 index 000000000..5ddeb9fc0 --- /dev/null +++ b/src/org/apache/fop/render/awt/AWTFontMetrics.java @@ -0,0 +1,304 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package org.apache.fop.render.awt; + +//FOP +import org.apache.fop.messaging.MessageHandler; +import org.apache.fop.layout.FontInfo; +import org.apache.fop.layout.FontDescriptor; +import org.apache.fop.layout.FontState; + +// Java +import java.util.Enumeration; +import java.util.Hashtable; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.awt.FontMetrics; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; + +/** +* This is a FontMetrics to be used for AWT rendering. +* It instanciates a font, depening on famil and style +* values. The java.awt.FontMetrics for this font is then +* created to be used for the actual measurement. +* Since layout is word by word and since it is expected that +* two subsequent words often share the same style, the +* Font and FontMetrics is buffered and only changed if needed. +*

+* Since FontState and FontInfo multiply all factors by +* size, we assume a "standard" font of FONT_SIZE. +*/ + +public class AWTFontMetrics { + /** + * Font size standard used for metric measurements + */ + public static final int FONT_SIZE = 1; + + /** + * This factor multiplies the calculated values to scale + * to FOP internal measurements + */ + public static final int FONT_FACTOR = (1000 * 1000) / FONT_SIZE; + + + /** + * The width of all 256 character, if requested + */ + private int width[] = null; + + /** + * The typical height of a small cap latter + */ + private int xHeight = 0; + + /** + * Buffered font. + * f1 is bufferd for metric measurements during layout. + * fSized is buffered for display purposes + */ + private Font f1 = null; //, fSized = null; + + /** + * The family type of the font last used + */ + private String family = ""; + + /** + * The style of the font last used + */ + private int style = 0; + + /** + * The size of the font last used + */ + private float size = 0; + + /** + * The FontMetrics object used to calculate character width etc. + */ + private FontMetrics fmt = null; + + /** + * Component parent is needed to have an AWT reference from which to get + * the font metrics + */ + Component parent; + + /** + * Constructs a new Font-metrics. + * @param parent an AWT component - this is needed so + * that we can get an instance of + * java.awt.FontMetrics + */ + public AWTFontMetrics(Component parent) { + this.parent = parent; + } + + /** + * Determines the font ascent of the Font described by this + * FontMetrics object + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + * @return ascent in milliponts + */ + public int getAscender(String family, int style, int size) { + setFont(family, style, size); + return (FONT_FACTOR * fmt.getAscent()); + } + + + /** + * The size of a capital letter measured from the font's baseline + */ + public int getCapHeight(String family, int style, int size) { + setFont(family, style, size); + return (FONT_FACTOR * fmt.getAscent()); + } + + /** + * Determines the font descent of the Font described by this + * FontMetrics object + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + * @return descent in milliponts + */ + public int getDescender(String family, int style, int size) { + setFont(family, style, size); + return (-1 * FONT_FACTOR * fmt.getDescent()); + } + + /** + * Determines the typical font height of a small cap letter + * FontMetrics object + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + * @return font height in milliponts + */ + public int getXHeight(String family, int style, int size) { + setFont(family, style, size); + return (int)(FONT_FACTOR * xHeight); + } + + /** + * Returns width (in 1/1000ths of point size) of character at + * code point i + * @param i the character for which to get the width + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + * @param size the of the font + */ + public int width(int i, String family, int style, int size) { + int w; + setFont(family, style, size); + // the output seems to look a little better if the + // space is rendered larger than given by + // the FontMetrics object + if (i <= 32) + w = (int)(1.4 * fmt.charWidth(i) * FONT_FACTOR); + else + w = (int)(fmt.charWidth(i) * FONT_FACTOR); + return w; + } + + /** + * Return widths (in 1/1000ths of point size) of all + * characters + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + */ + public int[] getWidths(String family, int style, int size) { + int i; + + if (width == null) { + width = new int[256]; + } + setFont(family, style, size); + for (i = 0 ; i < 256 ; i++) { + width[i] = FONT_FACTOR * fmt.charWidth(i); + } + return width; + } + + /** + * Checks whether the font for which values are + * requested is the one used immediately before or + * whether it is a new one + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + * @return true if the font was changed, false otherwise + */ + private boolean setFont(String family, int style, int size) { + boolean changed = false; + Rectangle2D rect; + TextLayout layout; + int s = (int)(size / 1000f); + Graphics2D g; + + if (f1 == null) { + f1 = new Font(family, style, s); + fmt = parent.getFontMetrics(f1); + changed = true; + } else { + if ((this.style != style) || !this.family.equals(family) || + this.size != s) { + if (family.equals(this.family)) { + f1 = f1.deriveFont(style, (float) s); + } else + f1 = new Font(family, style, s); + fmt = parent.getFontMetrics(f1); + changed = true; + } + // else the font is unchanged from last time + } + if (changed) { + g = (Graphics2D) parent.getGraphics(); + layout = new TextLayout("m", f1, g.getFontRenderContext()); + rect = layout.getBounds(); + xHeight = (int) rect.getHeight(); + } + // save the family and style for later comparison + this.family = family; + this.style = style; + this.size = s; + return changed; + } + + + /** + * Returns a java.awt.Font instance for the desired + * family, style and size type. + * This is here, so that the font-mapping + * of FOP-defined fonts to java-fonts can be done + * in one place and does not need to occur in + *AWTFontRenderer. + * @param family font family (jave name) to use + * @param style font style (jave def.) to use + * @param size font size + * @return font with the desired characeristics. + */ + public java.awt.Font getFont(String family, int style, int size) { + Font f; + + setFont(family, style, size); + return f1; + /*if( setFont(family,style, size) ) fSized = null; + if( fSized == null || this.size != size ) { + fSized = f1.deriveFont( size / 1000f ); + } + this.size = size; + return fSized;*/ + } +} + + + + + + diff --git a/src/org/apache/fop/render/awt/AWTRenderer.java b/src/org/apache/fop/render/awt/AWTRenderer.java index e098d6fc4..809bcff7f 100644 --- a/src/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/org/apache/fop/render/awt/AWTRenderer.java @@ -35,25 +35,23 @@ import java.beans.*; import javax.swing.*; import java.awt.print.*; import java.awt.image.BufferedImage; +import java.text.*; import org.apache.fop.render.Renderer; public class AWTRenderer implements Renderer, Printable, Pageable { - protected int pageWidth = 0; - protected int pageHeight = 0; - protected double scaleFactor = 100.0; - protected int pageNumber = 0; - protected AreaTree tree; - protected ProgressListener progressListener = null; - protected Translator res = null; + protected int pageWidth = 0; + protected int pageHeight = 0; + protected double scaleFactor = 100.0; + protected int pageNumber = 0; + protected AreaTree tree; + protected ProgressListener progressListener = null; + protected Translator res = null; - protected Hashtable fontNames = new Hashtable(); - protected Hashtable fontStyles = new Hashtable(); - protected Color saveColor; - - // Key - Font name, Value - java Font name. - protected static Hashtable JAVA_FONT_NAMES; + protected Hashtable fontNames = new Hashtable(); + protected Hashtable fontStyles = new Hashtable(); + protected Color saveColor = null; /** * Image Object and Graphics Object. The Graphics Object is the Graphics @@ -65,1148 +63,1231 @@ public class AWTRenderer implements Renderer, Printable, Pageable { /** * The current (internal) font name */ - protected String currentFontName; + protected String currentFontName; + + + /** + * The parent component, used to set up the font. + * This is needed as FontSetup needs a live AWT component + * in order to generate valid font measures. + */ + protected Component parent; + + /** * The current font size in millipoints */ - protected int currentFontSize; + protected int currentFontSize; /** * The current colour's red, green and blue component */ - protected float currentRed = 0; - protected float currentGreen = 0; - protected float currentBlue = 0; + protected float currentRed = 0; + protected float currentGreen = 0; + protected float currentBlue = 0; /** * The current vertical position in millipoints from bottom */ - protected int currentYPosition = 0; + protected int currentYPosition = 0; /** * The current horizontal position in millipoints from left */ - protected int currentXPosition = 0; + protected int currentXPosition = 0; /** * The horizontal position of the current area container */ - private int currentAreaContainerXPosition = 0; + private int currentAreaContainerXPosition = 0; - static { - JAVA_FONT_NAMES = new Hashtable(); - JAVA_FONT_NAMES.put("Times", "serif"); - JAVA_FONT_NAMES.put("Times-Roman", "serif"); - JAVA_FONT_NAMES.put("Courier", "monospaced"); - JAVA_FONT_NAMES.put("Helvetica", "sansserif"); - // JAVA_FONT_NAMES.put("Serif", "sansserif"); - } + public AWTRenderer(Translator aRes) { + res = aRes; + } - public AWTRenderer(Translator aRes) { - res = aRes; - } + /** + * Sets parent component which is used to set up the font. + * This is needed as FontSetup needs a live AWT component + * in order to generate valid font measures. + * @param parent the live AWT component reference + */ + public void setComponent(Component parent) { + this.parent = parent; + } - public int getPageNumber() { - return pageNumber; - } + public int getPageNumber() { + return pageNumber; + } - public void setPageNumber(int aValue) { - pageNumber = aValue; - } + public void setPageNumber(int aValue) { + pageNumber = aValue; + } - public void setScaleFactor(double newScaleFactor) { - scaleFactor = newScaleFactor; - } + public void setScaleFactor(double newScaleFactor) { + scaleFactor = newScaleFactor; + } - public double getScaleFactor() { - return scaleFactor; - } + public double getScaleFactor() { + return scaleFactor; + } public BufferedImage getLastRenderedPage() { - return pageImage; + return pageImage; } /** - * add a line to the current stream - * - * @param x1 the start x location in millipoints - * @param y1 the start y location in millipoints - * @param x2 the end x location in millipoints - * @param y2 the end y location in millipoints - * @param th the thickness in millipoints - * @param r the red component - * @param g the green component - * @param b the blue component - */ + * add a line to the current stream + * + * @param x1 the start x location in millipoints + * @param y1 the start y location in millipoints + * @param x2 the end x location in millipoints + * @param y2 the end y location in millipoints + * @param th the thickness in millipoints + * @param r the red component + * @param g the green component + * @param b the blue component + */ protected void addLine(int x1, int y1, int x2, int y2, int th, - float r, float g, float b) { - graphics.setColor(new Color (r,g,b)); - // graphics.setColor(Color.red); - graphics.drawLine((int)(x1/1000f), pageHeight - (int)(y1/1000f), - (int)(x2/1000f), pageHeight - (int)(y2/1000f)); + float r, float g, float b) { + graphics.setColor(new Color (r, g, b)); + // graphics.setColor(Color.red); + graphics.drawLine((int)(x1 / 1000f), + pageHeight - (int)(y1 / 1000f), (int)(x2 / 1000f), + pageHeight - (int)(y2 / 1000f)); } /** - * draw a filled rectangle - * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param r the red component - * @param g the green component - * @param b the blue component - */ - protected void addRect(int x, int y, int w, int h, - float r, float g, float b) { - graphics.setColor(new Color (r,g,b)); - // graphics.setColor(Color.green); - graphics.drawRect((int) (x/1000f), pageHeight - (int) (y/1000f), - (int) (w/1000f), -(int) (h/1000f)); + * draw a filled rectangle + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param r the red component + * @param g the green component + * @param b the blue component + */ + protected void addRect(int x, int y, int w, int h, float r, + float g, float b) { + graphics.setColor(new Color (r, g, b)); + // graphics.setColor(Color.green); + graphics.drawRect((int)(x / 1000f), + pageHeight - (int)(y / 1000f), (int)(w / 1000f), + -(int)(h / 1000f)); } /** - * draw a filled rectangle - * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param r the red component of edges - * @param g the green component of edges - * @param b the blue component of edges - * @param fr the red component of the fill - * @param fg the green component of the fill - * @param fb the blue component of the fill - */ - protected void addRect(int x, int y, int w, int h, - float r, float g, float b, - float fr, float fg, float fb) { - graphics.setColor(new Color (r,g,b)); - graphics.fill3DRect((int) (x/1000f), pageHeight - (int) (y/1000f), - (int) (w/1000f), -(int) (h/1000f),true); + * draw a filled rectangle + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param r the red component of edges + * @param g the green component of edges + * @param b the blue component of edges + * @param fr the red component of the fill + * @param fg the green component of the fill + * @param fb the blue component of the fill + */ + protected void addRect(int x, int y, int w, int h, float r, + float g, float b, float fr, float fg, float fb) { + graphics.setColor(new Color (r, g, b)); + graphics.fill3DRect((int)(x / 1000f), + pageHeight - (int)(y / 1000f), (int)(w / 1000f), + -(int)(h / 1000f), true); } - /** - * To configure before print. - * - * Choose pages - * Zoom factor - * Page format / Landscape or Portrait - **/ - public void transform(Graphics2D g2d, double zoomPercent, double angle) { - AffineTransform at = g2d.getTransform(); - at.rotate(angle); - at.scale(zoomPercent/100.0, zoomPercent/100.0); - g2d.setTransform(at); - } - - protected void drawFrame() { - - int width = pageWidth; - int height = pageHeight; - - graphics.setColor(Color.white); - graphics.fillRect(0, 0, width, height); - graphics.setColor(Color.black); - graphics.drawRect(-1, -1, width+2, height+2); - graphics.drawLine(width+2, 0, width+2, height+2); - graphics.drawLine(width+3, 1, width+3, height+3); - - graphics.drawLine(0, height+2, width+2, height+2); - graphics.drawLine(1, height+3, width+3, height+3); - } - /** - * Retrieve the number of pages in this document. - * - * @return the number of pages - */ - public int getPageCount() - { - if (tree == null) { - return 0; - } + * To configure before print. + * + * Choose pages + * Zoom factor + * Page format / Landscape or Portrait + **/ + public void transform(Graphics2D g2d, double zoomPercent, + double angle) { + AffineTransform at = g2d.getTransform(); + at.rotate(angle); + at.scale(zoomPercent / 100.0, zoomPercent / 100.0); + g2d.setTransform(at); + } + + protected void drawFrame() { + + int width = pageWidth; + int height = pageHeight; + + graphics.setColor(Color.white); + graphics.fillRect(0, 0, width, height); + graphics.setColor(Color.black); + graphics.drawRect(-1, -1, width + 2, height + 2); + graphics.drawLine(width + 2, 0, width + 2, height + 2); + graphics.drawLine(width + 3, 1, width + 3, height + 3); + + graphics.drawLine(0, height + 2, width + 2, height + 2); + graphics.drawLine(1, height + 3, width + 3, height + 3); + } - return tree.getPages().size(); + /** + * Retrieve the number of pages in this document. + * + * @return the number of pages + */ + public int getPageCount() { + if (tree == null) { + return 0; + } + + return tree.getPages().size(); } public void render(int aPageNumber) { - if (tree != null) { + if (tree != null) { try { - render(tree, aPageNumber); - } catch (IOException e) { + render(tree, aPageNumber); + } catch (IOException e) { e.printStackTrace(); - // This exception can't occur because we are not dealing with - // any files. - } - } + // This exception can't occur because we are not dealing with + // any files. + } + } } - public void render(AreaTree areaTree, PrintWriter writer) - throws IOException { - tree = areaTree; - render(areaTree, 0); + public void render(AreaTree areaTree, + PrintWriter writer) throws IOException { + tree = areaTree; + render(areaTree, 0); } - public void render(AreaTree areaTree, int aPageNumber) - throws IOException { - tree = areaTree; - Page page = (Page)areaTree.getPages().elementAt(aPageNumber); + public void render(AreaTree areaTree, + int aPageNumber) throws IOException { + tree = areaTree; + Page page = (Page) areaTree.getPages().elementAt(aPageNumber); + + pageWidth = (int)((float) page.getWidth() / 1000f); + pageHeight = (int)((float) page.getHeight() / 1000f); - pageWidth = (int)((float)page.getWidth() / 1000f); - pageHeight = (int)((float)page.getHeight() / 1000f); + pageImage = new BufferedImage( + (int)((pageWidth * (int) scaleFactor) / 100), + (int)((pageHeight * (int) scaleFactor) / 100), + BufferedImage.TYPE_INT_RGB); - pageImage = new BufferedImage((int)((pageWidth * (int)scaleFactor)/100), - (int)((pageHeight * (int)scaleFactor)/100), - BufferedImage.TYPE_INT_RGB); + graphics = pageImage.createGraphics(); - graphics = pageImage.createGraphics(); + transform(graphics, scaleFactor, 0); + drawFrame(); - transform(graphics, scaleFactor, 0); - drawFrame(); + renderPage(page); + } - renderPage(page); - } + public void renderPage(Page page) { + AreaContainer body, before, after; - public void renderPage(Page page) { - AreaContainer body, before, after; + body = page.getBody(); + before = page.getBefore(); + after = page.getAfter(); - body = page.getBody(); - before = page.getBefore(); - after = page.getAfter(); + this.currentFontName = ""; + this.currentFontSize = 0; - this.currentFontName = ""; - this.currentFontSize = 0; + renderAreaContainer(body); - renderAreaContainer(body); + if (before != null) { + renderAreaContainer(before); + } - if (before != null) { - renderAreaContainer(before); + if (after != null) { + renderAreaContainer(after); + } + + // SG: Wollen wir Links abbilden? + /* + if (page.hasLinks()) { + .... + } + */ } - if (after != null) { - renderAreaContainer(after); + public void renderAreaContainer(AreaContainer area) { + + int saveY = this.currentYPosition; + int saveX = this.currentAreaContainerXPosition; + + if (area.getPosition() == + org.apache.fop.fo.properties.Position.ABSOLUTE) { + // Y position is computed assuming positive Y axis, adjust + //for negative postscript one + this.currentYPosition = + area.getYPosition() - 2 * area.getPaddingTop() - + 2 * area.borderWidthTop; + this.currentAreaContainerXPosition = area.getXPosition(); + } else if (area.getPosition() == + org.apache.fop.fo.properties.Position.RELATIVE) { + this.currentYPosition -= area.getYPosition(); + this.currentAreaContainerXPosition += area.getXPosition(); + } else if (area.getPosition() == + org.apache.fop.fo.properties.Position.STATIC) { + this.currentYPosition -= + area.getPaddingTop() + area.borderWidthTop; + this.currentAreaContainerXPosition += + area.getPaddingLeft() + area.borderWidthLeft; + } + + doFrame(area); + + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + org.apache.fop.layout.Box b = + (org.apache.fop.layout.Box) e.nextElement(); + b.render(this); + } + + if (area.getPosition() != + org.apache.fop.fo.properties.Position.STATIC) { + this.currentYPosition = saveY; + this.currentAreaContainerXPosition = saveX; + } else { + this.currentYPosition -= area.getHeight(); + } } - // SG: Wollen wir Links abbilden? - /* - if (page.hasLinks()) { - .... + private void doFrame(org.apache.fop.layout.Area area) { + int w, h; + int rx = this.currentAreaContainerXPosition; + w = area.getContentWidth(); + + if (area instanceof BlockArea) { + rx += ((BlockArea) area).getStartIndent(); + } + + h = area.getContentHeight(); + int ry = this.currentYPosition; + ColorType bg = area.getBackgroundColor(); + + rx = rx - area.getPaddingLeft(); + ry = ry + area.getPaddingTop(); + w = w + area.getPaddingLeft() + area.getPaddingRight(); + h = h + area.getPaddingTop() + area.getPaddingBottom(); + + // I'm not sure I should have to check for bg being null + // but I do + if ((bg != null) && (bg.alpha() == 0)) { + this.addRect(rx, ry, w, -h, bg.red(), bg.green(), + bg.blue(), bg.red(), bg.green(), bg.blue()); + } + + rx = rx - area.borderWidthLeft; + ry = ry + area.borderWidthTop; + w = w + area.borderWidthLeft + area.borderWidthRight; + h = h + area.borderWidthTop + area.borderWidthBottom; + + if (area.borderWidthTop != 0) { + addLine(rx, ry, rx + w, ry, area.borderWidthTop, + area.borderColorTop.red(), area.borderColorTop.green(), + area.borderColorTop.blue()); + } + + if (area.borderWidthLeft != 0) { + addLine(rx, ry, rx, ry - h, area.borderWidthLeft, + area.borderColorLeft.red(), + area.borderColorLeft.green(), + area.borderColorLeft.blue()); + } + + if (area.borderWidthRight != 0) { + addLine(rx + w, ry, rx + w, ry - h, area.borderWidthRight, + area.borderColorRight.red(), + area.borderColorRight.green(), + area.borderColorRight.blue()); + } + + if (area.borderWidthBottom != 0) { + addLine(rx, ry - h, rx + w, ry - h, area.borderWidthBottom, + area.borderColorBottom.red(), + area.borderColorBottom.green(), + area.borderColorBottom.blue()); + } } - */ - } - - public void renderAreaContainer(AreaContainer area) { - - int saveY = this.currentYPosition; - int saveX = this.currentAreaContainerXPosition; - - if (area.getPosition() == - org.apache.fop.fo.properties.Position.ABSOLUTE) { - // Y position is computed assuming positive Y axis, adjust - //for negative postscript one - this.currentYPosition = area.getYPosition() - - 2 * area.getPaddingTop() - - 2 * area.borderWidthTop; - this.currentAreaContainerXPosition = area.getXPosition(); - } else if (area.getPosition() == - org.apache.fop.fo.properties.Position.RELATIVE) { - this.currentYPosition -= area.getYPosition(); - this.currentAreaContainerXPosition += area.getXPosition(); - } else if (area.getPosition() == - org.apache.fop.fo.properties.Position.STATIC) { - this.currentYPosition -= area.getPaddingTop() + area.borderWidthTop; - this.currentAreaContainerXPosition += area.getPaddingLeft() + - area.borderWidthLeft; - } - - doFrame(area); - - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { - org.apache.fop.layout.Box b = - (org.apache.fop.layout.Box) e.nextElement(); - b.render(this); - } - - if (area.getPosition() != - org.apache.fop.fo.properties.Position.STATIC) { - this.currentYPosition = saveY; - this.currentAreaContainerXPosition = saveX; - } else { - this.currentYPosition -= area.getHeight(); + + + + protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { + return new Rectangle2D.Double(currentAreaContainerXPosition, + currentYPosition, a.getAllocationWidth(), a.getHeight()); } - } - - private void doFrame(org.apache.fop.layout.Area area) { - int w, h; - int rx = this.currentAreaContainerXPosition; - w = area.getContentWidth(); - - if (area instanceof BlockArea) { - rx += ((BlockArea)area).getStartIndent(); - } - - h = area.getContentHeight(); - int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); - - rx = rx - area.getPaddingLeft(); - ry = ry + area.getPaddingTop(); - w = w + area.getPaddingLeft() + area.getPaddingRight(); - h = h + area.getPaddingTop() + area.getPaddingBottom(); - - // I'm not sure I should have to check for bg being null - // but I do - if ((bg != null) && (bg.alpha() == 0)) { - this.addRect(rx, ry, w, -h, - bg.red(), bg.green(), bg.blue(), - bg.red(), bg.green(), bg.blue()); + + public void renderBlockArea(BlockArea area) { + doFrame(area); + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + org.apache.fop.layout.Box b = + (org.apache.fop.layout.Box) e.nextElement(); + b.render(this); + } } - rx = rx - area.borderWidthLeft; - ry = ry + area.borderWidthTop; - w = w + area.borderWidthLeft + area.borderWidthRight; - h = h + area.borderWidthTop + area.borderWidthBottom; - - if (area.borderWidthTop != 0) { - addLine(rx, ry, rx + w, ry, - area.borderWidthTop, - area.borderColorTop.red(), area.borderColorTop.green(), - area.borderColorTop.blue()); - } - - if (area.borderWidthLeft != 0) { - addLine(rx, ry, rx, ry - h, - area.borderWidthLeft, - area.borderColorLeft.red(), area.borderColorLeft.green(), - area.borderColorLeft.blue()); - } - - if (area.borderWidthRight != 0) { - addLine(rx + w, ry, rx + w, ry - h, - area.borderWidthRight, - area.borderColorRight.red(), area.borderColorRight.green(), - area.borderColorRight.blue()); - } - - if (area.borderWidthBottom != 0) { - addLine(rx, ry - h, rx + w, ry - h, - area.borderWidthBottom, - area.borderColorBottom.red(), area.borderColorBottom.green(), - area.borderColorBottom.blue()); - } - } - - - - protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { - return new Rectangle2D.Double(currentAreaContainerXPosition, - currentYPosition, - a.getAllocationWidth(), - a.getHeight()); - } - - public void renderBlockArea(BlockArea area) { - doFrame(area); - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { - org.apache.fop.layout.Box b = - (org.apache.fop.layout.Box) e.nextElement(); - b.render(this); + public void setupFontInfo(FontInfo fontInfo) { + FontSetup.setup(fontInfo, parent); } - } - - public void setupFontInfo(FontInfo fontInfo) { - FontSetup.setup(fontInfo); - Hashtable hash = fontInfo.getFonts(); - org.apache.fop.render.pdf.Font f; - String name; - Object key; - int fontStyle; - - for (Enumeration e = hash.keys(); e.hasMoreElements();) { - fontStyle = java.awt.Font.PLAIN; - key = e.nextElement(); - f = (org.apache.fop.render.pdf.Font)hash.get(key); - name = f.fontName(); - - if (name.toUpperCase().indexOf("BOLD") > 0) { - fontStyle += java.awt.Font.BOLD; - } - if (name.toUpperCase().indexOf("ITALIC") > 0 || - name.toUpperCase().indexOf("OBLIQUE") > 0) { - fontStyle += java.awt.Font.ITALIC; - } - - int hyphenIndex = name.indexOf("-"); - - hyphenIndex = (hyphenIndex < 0) ? name.length() : hyphenIndex; - fontNames.put(key, name.substring(0, hyphenIndex)); - fontStyles.put(key, new Integer(fontStyle)); + + public void renderDisplaySpace(DisplaySpace space) { + int d = space.getSize(); + this.currentYPosition -= d; } - } - - public void renderDisplaySpace(DisplaySpace space) { - int d = space.getSize(); - this.currentYPosition -= d; - } - - - public void renderImageArea(ImageArea area) { - int x = currentAreaContainerXPosition + - area.getXOffset(); - int y = currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - - FopImage img = area.getImage(); - - if (img == null) { - MessageHandler.logln("Error while loading image : area.getImage() is null"); - graphics.drawRect(x / 1000, - pageHeight - y / 1000, - w / 1000, - h / 1000); - java.awt.Font f = graphics.getFont(); - java.awt.Font smallFont = new java.awt.Font(f.getFontName(),f.getStyle(),8); - graphics.setFont(smallFont); - graphics.drawString("area.getImage() is null", x / 1000, pageHeight - y / 1000); - graphics.setFont(f); - } else { - - String urlString = img.getURL(); - try { - URL url = new URL(urlString); - - ImageIcon icon = new ImageIcon(url); - Image image = icon.getImage(); - - graphics.drawImage(image, x / 1000, - pageHeight - y / 1000, - w / 1000, - h / 1000, - null); - } catch(MalformedURLException mue) { - // cannot normally occur because, if URL is wrong, constructing FopImage - // will already have failed earlier on - } - } - - currentYPosition -= h; - } - - public void renderInlineArea(InlineArea area) { - char ch; - StringBuffer pdf = new StringBuffer(); - - String name = area.getFontState().getFontName(); - int size = area.getFontState().getFontSize(); - - float red = area.getRed(); - float green = area.getGreen(); - float blue = area.getBlue(); - - if ((!name.equals(this.currentFontName)) - || (size != this.currentFontSize)) { - this.currentFontName = name; - this.currentFontSize = size; - } - - if ((red != this.currentRed) - || (green != this.currentGreen) - || (blue != this.currentBlue)) { - this.currentRed = red; - this.currentGreen = green; - this.currentBlue = blue; - } - - int rx = this.currentXPosition; - int bl = this.currentYPosition; - - - String s = area.getText(); - Color oldColor = graphics.getColor(); - java.awt.Font oldFont = graphics.getFont(); - String aFontName = fontNames.get(name).toString(); - - aFontName = getJavaFontName(aFontName); - - java.awt.Font f = - new java.awt.Font(aFontName, - ((Integer)fontStyles.get(name)).intValue(), - (int)(size / 1000f)); - - graphics.setColor(new Color(red, green, blue)); - - /* - Die KLasse TextLayout nimmt für die Ausgabe eigenen Schriftsatz, - der i.R. breiter ist. Deshalb wird bis diese Tatsache sich geklärt/ - geregelt hat weniger schöne Ausgabe über Graphics benutzt. - */ - - // Fonts in bold still have trouble displaying! - FontRenderContext newContext = new FontRenderContext(null, true, true); - TextLayout layout = new TextLayout(s, f, newContext); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, - RenderingHints.VALUE_RENDER_QUALITY); - layout.draw(graphics, rx / 1000f, (int)(pageHeight - bl / 1000f)); - - graphics.setColor(oldColor); - this.currentXPosition += area.getContentWidth(); - } - - public void renderInlineSpace(InlineSpace space) { - this.currentXPosition += space.getSize(); - } - - public void renderLineArea(LineArea area) { - int rx = this.currentAreaContainerXPosition - + area.getStartIndent(); - int ry = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - - this.currentYPosition -= area.getPlacementOffset(); - this.currentXPosition = rx; - - int bl = this.currentYPosition; - - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { - org.apache.fop.layout.Box b = - (org.apache.fop.layout.Box) e.nextElement(); - b.render(this); - } - - this.currentYPosition = ry-h; - } - - /** - * render rule area into PDF - * - * @param area area to render - */ - public void renderRuleArea(RuleArea area) { - int rx = this.currentAreaContainerXPosition - + area.getStartIndent(); - int ry = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - int th = area.getRuleThickness(); - float r = area.getRed(); - float g = area.getGreen(); - float b = area.getBlue(); - Color oldColor = graphics.getColor(); - - graphics.setColor(new Color(r, g, b)); - graphics.fillRect((int)(rx / 1000f), (int)(pageHeight - ry / 1000f), - (int)(w / 1000f), (int)(th / 1000f)); - graphics.setColor(oldColor); - - } - - public void renderSVGArea(SVGArea area) { - - int x = this.currentAreaContainerXPosition; - int y = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { - Object o = e.nextElement(); - if(o instanceof GraphicImpl) { - renderElement(area, (GraphicImpl)o, x, y, null); - } - } - - this.currentYPosition -= h; - - } - - - protected String getJavaFontName(String aName) { - if (aName == null) - return null; - - Object o = JAVA_FONT_NAMES.get(aName); - - return (o == null) ? aName : o.toString(); - } - - public void setProducer(String producer) { - // defined in Renderer Interface - } - - public int print(Graphics g, PageFormat pageFormat, int pageIndex) - throws PrinterException { - if (pageIndex >= tree.getPages().size()) - return NO_SUCH_PAGE; - - Graphics2D oldGraphics = graphics; - int oldPageNumber = pageNumber; - - graphics = (Graphics2D)g; - Page aPage = (Page)tree.getPages().elementAt(pageIndex); - renderPage(aPage); - graphics = oldGraphics; - - return PAGE_EXISTS; - } - - public int getNumberOfPages() { - return tree.getPages().size(); - } - - public PageFormat getPageFormat(int pageIndex) - throws IndexOutOfBoundsException { - if (pageIndex >= tree.getPages().size()) - return null; - - Page page = (Page)tree.getPages().elementAt(pageIndex); - PageFormat pageFormat = new PageFormat(); - Paper paper = new Paper(); - paper.setImageableArea(0, 0, - page.getWidth() / 1000d, page.getHeight() / 1000d); - paper.setSize(page.getWidth() / 1000d, page.getHeight() / 1000d); - pageFormat.setPaper(paper); - - return pageFormat; - } - - public Printable getPrintable(int pageIndex) - throws IndexOutOfBoundsException { - return this; - } - - public void setProgressListener(ProgressListener l) { - progressListener = l; - } - - public static Color colorType2Color(ColorType ct) { - if (ct == null) { - return null; - } - return new Color(ct.red(), ct.green(), ct.blue()); - } - - - - /** - * Draws an image. - * TODO: protect other image formats (JIMI) - */ - public void renderImage(String href, float x, float y, float width, float height, Vector transform) { - // What is with transformations? - try { - URL url = new URL(href); - ImageIcon imageIcon = new ImageIcon(url); - - AffineTransform fullTransform = new AffineTransform(); - AffineTransform aTransform; - - transform = (transform == null) ? new Vector() : transform; - for (int i = 0; i < transform.size(); i++) { - org.w3c.dom.svg.SVGTransform t = (org.w3c.dom.svg.SVGTransform)transform.elementAt(i); - SVGMatrix matrix = t.getMatrix(); - aTransform = new AffineTransform(matrix.getA(), matrix.getB(), matrix.getC(), - matrix.getD(), matrix.getE(), matrix.getF()); - fullTransform.concatenate(aTransform); - } - - BufferedImage bi = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = bi.createGraphics(); - BufferedImageOp bop = new AffineTransformOp(fullTransform, - AffineTransformOp.TYPE_NEAREST_NEIGHBOR); - g2d.drawImage(imageIcon.getImage(), 0, 0, (int) width, (int) height, imageIcon.getImageObserver()); - graphics.drawImage(bi, bop, (int) x, (int) y); - } catch (Exception ex) { - MessageHandler.errorln("AWTRenderer: renderImage(): " + ex.getMessage()); - } - } - - - - public void renderElement(SVGArea svgarea, GraphicImpl area, int posx, int posy, - Vector parentTransforms) { - int x = posx; - int y = posy; - Hashtable style = area.oldgetStyle(); - DrawingInstruction di = createInstruction(area, style); - - Object o = null; - Vector v = area.oldgetTransform(); - v = (v == null) ? new Vector() : v; - Vector trans = new Vector(v); - parentTransforms = (parentTransforms == null) ? new Vector() : parentTransforms; - - if (parentTransforms != null) { - trans.addAll(0, parentTransforms); - } - - float red = (float) graphics.getColor().getRed(); - float green = (float) graphics.getColor().getGreen(); - float blue = (float) graphics.getColor().getBlue(); - Color c = null; - - ColorType ct = null; - try { - o = style.get("fill"); - if (o != null && o instanceof ColorType) { - ct = (ColorType) o; - c = new Color((int) (ct.red() * 255f), (int) (ct.green() * 255f), (int) (ct.blue() * 255f)); - } - o = style.get("stroke"); - if (c == null && o != null && o instanceof ColorType) { - ct = (ColorType) o; - c = new Color((int) (ct.red() * 255f), (int) (ct.green() * 255f), (int) (ct.blue() * 255f)); - } - } catch (Exception ex) { - MessageHandler.errorln("Can't set color: R G B : " + (int) (ct.red() * 255f) + " " + (int) (ct.green() * 255f) + " " + (int) (ct.blue() * 255f)); - c = Color.pink; - } - - if (c == null) { - c = new Color((int) red, (int) green, (int) blue); - } - Color oldColor = graphics.getColor(); - - if (area instanceof SVGLineElement) { - graphics.setColor(c); - SVGLineElementImpl lg = (SVGLineElementImpl) area; - - float x1 = lg.getX1().getBaseVal().getValue() * 1000 + posx; - float y1 = posy - lg.getY1().getBaseVal().getValue() * 1000 ; - float x2 = lg.getX2().getBaseVal().getValue() * 1000 + posx; - float y2 = posy - lg.getY2().getBaseVal().getValue() * 1000; - // TODO: - // The thickness of contour protect. - int th = 1; - o = style.get("stroke-width"); - if (o != null) - th = (int)((SVGLengthImpl)o).getValue(); - Line2D.Double aLine = new Line2D.Double(x1 / 1000f, pageHeight - y1 / 1000f, - x2 / 1000f, pageHeight - y2 / 1000f); - drawShape(transformShape(trans, aLine), di); - graphics.setColor(oldColor); - } else if (area instanceof SVGRectElement) { - graphics.setColor(c); - SVGRectElement rg = (SVGRectElement)area; - float rectx = rg.getX().getBaseVal().getValue() * 1000 + posx; - float recty = posy - rg.getY().getBaseVal().getValue() * 1000; - float rx = rg.getRx().getBaseVal().getValue() * 1000; - float ry = rg.getRy().getBaseVal().getValue() * 1000; - float rw = rg.getWidth().getBaseVal().getValue() * 1000; - float rh = rg.getHeight().getBaseVal().getValue() * 1000; - - // TODO: - // rx and ry are roundings. - // RoundRectangle2D.Double - Rectangle aRectangle = new Rectangle(); - aRectangle.setRect(rectx / 1000d, pageHeight - recty / 1000d, rw / 1000d, rh / 1000d); - drawShape(transformShape(trans, aRectangle), di); - graphics.setColor(oldColor); - } else if (area instanceof SVGCircleElement) { - graphics.setColor(c); - SVGCircleElement cg = (SVGCircleElement)area; - float cx = cg.getCx().getBaseVal().getValue() * 1000 + posx; - float cy = posy - cg.getCy().getBaseVal().getValue() * 1000; - float r = cg.getR().getBaseVal().getValue(); - Ellipse2D.Double anEllipse = new Ellipse2D.Double(cx / 1000d - r, - pageHeight - cy / 1000d - r, - r * 2d, r * 2d); - drawShape(transformShape(trans, anEllipse), di); - graphics.setColor(oldColor); - } else if (area instanceof SVGEllipseElement) { - graphics.setColor(c); - SVGEllipseElement cg = (SVGEllipseElement)area; - float cx = cg.getCx().getBaseVal().getValue() * 1000 + posx; - float cy = posy - cg.getCy().getBaseVal().getValue() * 1000; - float rx = cg.getRx().getBaseVal().getValue(); - float ry = cg.getRy().getBaseVal().getValue(); - Ellipse2D.Double anEllipse = new Ellipse2D.Double(cx / 1000d - rx, - pageHeight - cy / 1000d - ry, - rx * 2d, ry * 2d); - drawShape(transformShape(trans, anEllipse), di); - graphics.setColor(oldColor); - } else if (area instanceof SVGImageElementImpl) { - SVGImageElementImpl ig = (SVGImageElementImpl)area; - renderImage(ig.link, ig.x + posx / 1000f, pageHeight - (posy / 1000f - ig.y), ig.width, ig.height, trans); - } else if(area instanceof SVGUseElementImpl) { - SVGUseElementImpl ug = (SVGUseElementImpl)area; - String ref = ug.link; - ref = ref.substring(1, ref.length()); - GraphicImpl graph = null; -// graph = area.locateDef(ref); - if(graph != null) { - // probably not the best way to do this, should be able - // to render without the style being set. -// GraphicImpl parent = graph.getGraphicParent(); -// graph.setParent(area); - // need to clip (if necessary) to the use area - // the style of the linked element is as if is was - // a direct descendant of the use element. - - renderElement(svgarea, graph, posx, posy, trans); -// graph.setParent(parent); - } - } else if (area instanceof SVGPolylineElementImpl) { - graphics.setColor(c); - Vector points = ((SVGPolylineElementImpl)area).points; - PathPoint p = null; - Point2D.Double p1 = null; - Point2D.Double p2 = null; - if (points.size() > 0) { - p = (PathPoint) points.elementAt(0); - double xc = p.x * 1000f + posx; - double yc = posy - p.y * 1000f; - p1 = new Point2D.Double(xc / 1000f, pageHeight - yc / 1000f); - - int[] xarr = {(int) xc}; - int[] yarr = {(int) yc}; - graphics.drawPolyline(xarr, yarr, 1); - } - Line2D.Double aLine; - for (int i = 1; i< points.size(); i++) { - p = (PathPoint) points.elementAt(i); - p2 = new Point2D.Double(p.x + posx / 1000f, pageHeight - (posy - p.y * 1000f) / 1000f); - aLine = new Line2D.Double(p1, p2); - graphics.draw(transformShape(trans, aLine)); - p1 = p2; - } - graphics.setColor(oldColor); - } else if (area instanceof SVGPolygonElementImpl) { - graphics.setColor(c); - java.awt.Polygon aPolygon = convertPolygon(((SVGPolygonElementImpl)area), posx, posy); - drawShape(transformShape(trans, aPolygon), di); - graphics.setColor(oldColor); - } else if (area instanceof SVGGElementImpl) { - renderGArea(svgarea, (SVGGElementImpl)area, x, y, parentTransforms); - } else if (area instanceof SVGPathElementImpl) { - graphics.setColor(c); - GeneralPath path = convertPath((SVGPathElementImpl) area, posx, posy); - drawShape(transformShape(trans, path), di); - graphics.setColor(oldColor); - } else if (area instanceof SVGTextElementImpl) { - MessageHandler.errorln("SVGTextElementImpl is not implemented yet."); - // renderText(svgarea, (SVGTextElementImpl)area, 0, 0, di); - } else if (area instanceof SVGArea) { - // the x and y pos will be wrong! - Enumeration e = ((SVGArea)area).getChildren().elements(); - while (e.hasMoreElements()) { - Object el = e.nextElement(); - if(o instanceof GraphicImpl) { - renderElement((SVGArea)area, (GraphicImpl)el, x, y, parentTransforms); - } - } - } - - // should be done with some cleanup code, so only - // required values are reset. - } // renderElement - - - public void renderGArea(SVGArea svgarea, SVGGElementImpl area, int posx, int posy, Vector v) { - - - Vector trans = null; -// trans = new Vector(area.oldgetTransform()); -// trans.addAll(0, v); -/* Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { - Object o = e.nextElement(); - if(o instanceof GraphicImpl) { - renderElement(svgarea, (GraphicImpl)o, posx, posy, trans); - } - }*/ - } - public void renderGArea(SVGArea svgarea, SVGGElementImpl area, int posx, int posy) - { - renderGArea(svgarea, area, posx, posy, new Vector()); - } - - - /** - * Applies SVGTransform to the shape and gets the transformed shape. - * The type of the new shape may be different to the original type. - */ - public Shape transformShape(Vector trans, Shape shape) { - if (trans == null || trans.size() == 0) { - return shape; - } - - AffineTransform at; - for(int i = trans.size() - 1; i >= 0; i--) { - org.w3c.dom.svg.SVGTransform t = (org.w3c.dom.svg.SVGTransform)trans.elementAt(i); - SVGMatrix matrix = t.getMatrix(); - at = new AffineTransform(matrix.getA(), matrix.getB(), matrix.getC(), - matrix.getD(), matrix.getE(), matrix.getF()); - shape = at.createTransformedShape(shape); - } - return shape; - } - - - /** - * Mapps a SVG-Polygon to a AWT-Polygon. - */ - public java.awt.Polygon convertPolygon(SVGPolygonElementImpl svgpl, int x, int y) { - java.awt.Polygon aPolygon = new java.awt.Polygon(); - Vector points = svgpl.points; - - PathPoint p; - for (int i = 0; i < points.size(); i++) { - p = (PathPoint) points.elementAt(i); - aPolygon.addPoint((int) (x / 1000f + p.x), pageHeight - (int) (y / 1000f - p.y)); - } - - return aPolygon; - } - - // TODO: other attributes of DrawingInstruction protect too. - protected DrawingInstruction createInstruction(GraphicImpl area, Hashtable style) { - DrawingInstruction di = new DrawingInstruction(); - Object sp; - sp = style.get("fill"); - if(sp != null && !(sp instanceof String && sp.equals("none"))) { - di.fill = true; - } - // ... - return di; - } - - // Draws a shape. - // TODO: other attributes of DrawingInstruction protect too. - protected void drawShape(Shape s, DrawingInstruction di) { - if (di.fill) { - graphics.fill(s); - } else { - graphics.draw(s); - } - } - - /** - * Mapps a SVG-Path to a AWT-GeneralPath. - */ - public GeneralPath convertPath(SVGPathElementImpl svgpath, float x, float y) { - Vector points = svgpath.pathElements; - GeneralPath path = new GeneralPath(); - - float lastx = 0; - float lasty = 0; - SVGPathSegImpl pathmoveto = null; - - for(Enumeration e = points.elements(); e.hasMoreElements(); ) { - SVGPathSegImpl pc = (SVGPathSegImpl)e.nextElement(); - float[] vals = pc.getValues(); - float lastcx = 0; - float lastcy = 0; - switch(pc.getPathSegType()) { - case SVGPathSeg.PATHSEG_MOVETO_ABS: - lastx = vals[0]; - lasty = vals[1]; - pathmoveto = pc; - path.moveTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_MOVETO_REL: - if (pathmoveto == null) { - lastx = vals[0]; - lasty = vals[1]; - path.moveTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - pathmoveto = pc; - } else { - lastx += vals[0]; - lasty += vals[1]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - - } - break; - case SVGPathSeg.PATHSEG_LINETO_ABS: - lastx = vals[0]; - lasty = vals[1]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_LINETO_REL: - lastx += vals[0]; - lasty += vals[1]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS: - lasty = vals[0]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL: - lasty += vals[0]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS: - lastx = vals[0]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL: - lastx += vals[0]; - path.lineTo(lastx + x / 1000f, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: - lastx = vals[4]; - lasty = vals[5]; - lastcx = vals[2]; - lastcy = vals[3]; - path.curveTo(x / 1000f + vals[0], pageHeight - y / 1000f + vals[1], - x / 1000f + lastcx, pageHeight - y / 1000f + lastcy, - x / 1000f + lastx, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: - path.curveTo(x / 1000f + vals[0] + lastx, pageHeight - y / 1000f + vals[1] + lasty, - x / 1000f + lastx + vals[2], pageHeight - y / 1000f + lasty + vals[3], - x / 1000f + lastx + vals[4], pageHeight - y / 1000f + lasty + vals[5]); - lastcx = vals[2] + lastx; - lastcy = vals[3] + lasty; - lastx += vals[4]; - lasty += vals[5]; - break; - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: - if (lastcx == 0) - lastcx = lastx; - if (lastcy == 0) - lastcy = lasty; - lastx = vals[2]; - lasty = vals[3]; - path.curveTo(x / 1000f + lastcx, pageHeight - y / 1000f + lastcy, - x / 1000f + vals[0], pageHeight - y / 1000f + vals[1], - x / 1000f + lastx, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: - if (lastcx == 0) - lastcx = lastx; - if (lastcy == 0) - lastcy = lasty; - path.curveTo(x / 1000f + lastcx, pageHeight - y / 1000f + lastcy, - x / 1000f + lastx + vals[0], pageHeight - y / 1000f + lasty + vals[1], - x / 1000f + lastx + vals[2], pageHeight - y / 1000f + lasty + vals[3]); - lastx += vals[2]; - lasty += vals[3]; - break; - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: - if (lastcx == 0) - lastcx = lastx; - if (lastcy == 0) - lastcy = lasty; - lastx = vals[0]; - lasty = vals[1]; - lastcx = 0; - lastcy = 0; - path.quadTo(x / 1000f + lastcx, pageHeight - y / 1000f + lastcy, - x / 1000f + lastx, pageHeight - y / 1000f + lasty); - break; - case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: - if (lastcx == 0) - lastcx = lastx; - if (lastcy == 0) - lastcy = lasty; - - path.quadTo(x / 1000f + lastcx , pageHeight - y / 1000f + lastcy, - x / 1000f + lastx + vals[0], pageHeight - y / 1000f + lasty + vals[1]); - - lastx += vals[0]; - lasty += vals[1]; - lastcx = 0; - lastcy = 0; - break; - case SVGPathSeg.PATHSEG_ARC_ABS: { - // Arc2D.Double arc = new Arc2D.Double(); - // arc.setAngles(current point, end point); .... - double rx = vals[0]; - double ry = vals[1]; - double theta = vals[2]; - boolean largearcflag = (vals[3] == 1.0); - boolean sweepflag = (vals[4] == 1.0); - - double cx = lastx; - double cy = lasty; - - path.curveTo(x / 1000f + lastx, pageHeight - y / 1000f + lasty, - x / 1000f + vals[0], pageHeight - y / 1000f + vals[1], - x / 1000f + vals[5], pageHeight - y / 1000f + vals[6]); - - lastcx = 0; //?? - lastcy = 0; //?? - lastx = vals[5]; - lasty = vals[6]; - } - break; - case SVGPathSeg.PATHSEG_ARC_REL: { - double rx = vals[0]; - double ry = vals[1]; - double theta = vals[2]; - boolean largearcflag = (vals[3] == 1.0); - boolean sweepflag = (vals[4] == 1.0); - - path.curveTo(x / 1000f + lastx, pageHeight - y / 1000f + lasty, - x / 1000f + (vals[0] + lastx), pageHeight - y / 1000f + (vals[1] + lasty), - x / 1000f + (vals[5] + lastx) , pageHeight - y / 1000f + (vals[6] + lasty)); - lastcx = 0; //?? - lastcy = 0; //?? - lastx += vals[5]; - lasty += vals[6]; - } - break; - case SVGPathSeg.PATHSEG_CLOSEPATH: - path.closePath(); - break; - - - } // switch - } // for points.elements() - - return path; - } // convertPath -/* - if(di == null) { - currentStream.add("S\n"); - } else { - if(di.fill) { - if(di.stroke) { - if(!di.nonzero) - currentStream.add("B*\n"); - else - currentStream.add("B\n"); - } else { - if(!di.nonzero) - currentStream.add("f*\n"); - else - currentStream.add("f\n"); - } - } else { -// if(di.stroke) - currentStream.add("S\n"); - } - } -*/ - - /* - * by pdfrenderer übernommen. - * - */ - class DrawingInstruction { - boolean stroke = false; - boolean nonzero = false; // non-zero fill rule "f*", "B*" operator - boolean fill = false; - int linecap = 0; // butt - int linejoin = 0; // miter - int miterwidth = 8; - } - - public void renderForeignObjectArea(ForeignObjectArea area) { - area.getObject().render(this); - } + + public void renderImageArea(ImageArea area) { + + int x = currentAreaContainerXPosition + + area.getXOffset(); + + int y = currentYPosition; + + int w = area.getContentWidth(); + + int h = area.getHeight(); + + + + FopImage img = area.getImage(); + + + + if (img == null) { + + MessageHandler.logln("Error while loading image : area.getImage() is null"); + + graphics.drawRect(x / 1000, + pageHeight - y / 1000, + w / 1000, + h / 1000); + + java.awt.Font f = graphics.getFont(); + + java.awt.Font smallFont = + new java.awt.Font(f.getFontName(), f.getStyle(), 8); + + graphics.setFont(smallFont); + + graphics.drawString("area.getImage() is null", x / 1000, + pageHeight - y / 1000); + + graphics.setFont(f); + + } else { + + + + String urlString = img.getURL(); + + try { + + URL url = new URL(urlString); + + + + ImageIcon icon = new ImageIcon(url); + + Image image = icon.getImage(); + + + + graphics.drawImage(image, x / 1000, + pageHeight - y / 1000, + w / 1000, + h / 1000, + null); + + } catch (MalformedURLException mue) { + + // cannot normally occur because, if URL is wrong, constructing FopImage + + // will already have failed earlier on + + } + + } + + + + currentYPosition -= h; + + } + + public void renderInlineArea(InlineArea area) { + char ch; + StringBuffer pdf = new StringBuffer(); + + String name = area.getFontState().getFontName(); + int size = area.getFontState().getFontSize(); + boolean underlined = area.getUnderlined(); + + float red = area.getRed(); + float green = area.getGreen(); + float blue = area.getBlue(); + + FontMetricsMapper mapper; + try { + mapper = (FontMetricsMapper) + area.getFontState().getFontInfo().getMetricsFor(name); + } catch (FOPException iox) { + mapper = new FontMetricsMapper("MonoSpaced", + java.awt.Font.PLAIN, parent); + } + + if ((!name.equals(this.currentFontName)) || + (size != this.currentFontSize)) { + this.currentFontName = name; + this.currentFontSize = size; + } + + if ((red != this.currentRed) || (green != this.currentGreen) || + (blue != this.currentBlue)) { + this.currentRed = red; + this.currentGreen = green; + this.currentBlue = blue; + } + + int rx = this.currentXPosition; + int bl = this.currentYPosition; + + + String s = area.getText(); + Color oldColor = graphics.getColor(); + java.awt.Font oldFont = graphics.getFont(); + java.awt.Font f = mapper.getFont(size); + + if (saveColor != null) { + if (saveColor.getRed() != red || + saveColor.getGreen() != green || + saveColor.getBlue() != blue) { + saveColor = new Color(red, green, blue); + } + } else { + saveColor = new Color(red, green, blue); + } + graphics.setColor(saveColor); + + FontRenderContext newContext = graphics.getFontRenderContext(); + AttributedString ats = new AttributedString(s); + ats.addAttribute(TextAttribute.FONT, f); + if (underlined) { + ats.addAttribute(TextAttribute.UNDERLINE, + TextAttribute.UNDERLINE_ON); + } + AttributedCharacterIterator iter = ats.getIterator(); + graphics.drawString(iter, rx / 1000f, + (int)(pageHeight - bl / 1000f)); + + graphics.setColor(oldColor); + this.currentXPosition += area.getContentWidth(); + } + + public void renderInlineSpace(InlineSpace space) { + this.currentXPosition += space.getSize(); + } + + public void renderLineArea(LineArea area) { + int rx = this.currentAreaContainerXPosition + area.getStartIndent(); + int ry = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + + this.currentYPosition -= area.getPlacementOffset(); + this.currentXPosition = rx; + + int bl = this.currentYPosition; + + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + org.apache.fop.layout.Box b = + (org.apache.fop.layout.Box) e.nextElement(); + b.render(this); + } + + this.currentYPosition = ry - h; + } + + /** + * render rule area into PDF + * + * @param area area to render + */ + public void renderRuleArea(RuleArea area) { + int rx = this.currentAreaContainerXPosition + area.getStartIndent(); + int ry = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + int th = area.getRuleThickness(); + float r = area.getRed(); + float g = area.getGreen(); + float b = area.getBlue(); + Color oldColor = graphics.getColor(); + + graphics.setColor(new Color(r, g, b)); + graphics.fillRect((int)(rx / 1000f), + (int)(pageHeight - ry / 1000f), (int)(w / 1000f), + (int)(th / 1000f)); + graphics.setColor(oldColor); + + } + + public void renderSVGArea(SVGArea area) { + + int x = this.currentAreaContainerXPosition; + int y = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Object o = e.nextElement(); + if (o instanceof GraphicImpl) { + renderElement(area, (GraphicImpl) o, x, y, null); + } + } + + this.currentYPosition -= h; + + } + + + + public void setProducer(String producer) { + // defined in Renderer Interface + } + + public int print(Graphics g, PageFormat pageFormat, + int pageIndex) throws PrinterException { + if (pageIndex >= tree.getPages().size()) + return NO_SUCH_PAGE; + + Graphics2D oldGraphics = graphics; + int oldPageNumber = pageNumber; + + graphics = (Graphics2D) g; + Page aPage = (Page) tree.getPages().elementAt(pageIndex); + renderPage(aPage); + graphics = oldGraphics; + + return PAGE_EXISTS; + } + + public int getNumberOfPages() { + return tree.getPages().size(); + } + + public PageFormat getPageFormat(int pageIndex) + throws IndexOutOfBoundsException { + if (pageIndex >= tree.getPages().size()) + return null; + + Page page = (Page) tree.getPages().elementAt(pageIndex); + PageFormat pageFormat = new PageFormat(); + Paper paper = new Paper(); + paper.setImageableArea(0, 0, page.getWidth() / 1000d, + page.getHeight() / 1000d); + paper.setSize(page.getWidth() / 1000d, page.getHeight() / 1000d); + pageFormat.setPaper(paper); + + return pageFormat; + } + + public Printable getPrintable(int pageIndex) + throws IndexOutOfBoundsException { + return this; + } + + public void setProgressListener(ProgressListener l) { + progressListener = l; + } + + public static Color colorType2Color(ColorType ct) { + if (ct == null) { + return null; + } + return new Color(ct.red(), ct.green(), ct.blue()); + } + + + + /** + * Draws an image. + * TODO: protect other image formats (JIMI) + */ + public void renderImage(String href, float x, float y, float width, + float height, Vector transform) { + // What is with transformations? + try { + URL url = new URL(href); + ImageIcon imageIcon = new ImageIcon(url); + + AffineTransform fullTransform = new AffineTransform(); + AffineTransform aTransform; + + transform = (transform == null) ? new Vector() : transform; + for (int i = 0; i < transform.size(); i++) { + org.w3c.dom.svg.SVGTransform t = + (org.w3c.dom.svg.SVGTransform) + transform.elementAt(i); + SVGMatrix matrix = t.getMatrix(); + aTransform = new AffineTransform(matrix.getA(), + matrix.getB(), matrix.getC(), matrix.getD(), + matrix.getE(), matrix.getF()); + fullTransform.concatenate(aTransform); + } + + BufferedImage bi = new BufferedImage((int) width, (int) height, + BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bi.createGraphics(); + BufferedImageOp bop = new AffineTransformOp(fullTransform, + AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + g2d.drawImage(imageIcon.getImage(), 0, 0, (int) width, + (int) height, imageIcon.getImageObserver()); + graphics.drawImage(bi, bop, (int) x, (int) y); + } catch (Exception ex) { + MessageHandler.errorln("AWTRenderer: renderImage(): " + + ex.getMessage()); + } + } + + + + public void renderElement(SVGArea svgarea, GraphicImpl area, + int posx, int posy, Vector parentTransforms) { + int x = posx; + int y = posy; + Hashtable style = area.oldgetStyle(); + DrawingInstruction di = createInstruction(area, style); + + Object o = null; + Vector v = area.oldgetTransform(); + v = (v == null) ? new Vector() : v; + Vector trans = new Vector(v); + parentTransforms = (parentTransforms == null) ? new Vector() : + parentTransforms; + + if (parentTransforms != null) { + trans.addAll(0, parentTransforms); + } + + float red = (float) graphics.getColor().getRed(); + float green = (float) graphics.getColor().getGreen(); + float blue = (float) graphics.getColor().getBlue(); + Color c = null; + + ColorType ct = null; + try { + o = style.get("fill"); + if (o != null && o instanceof ColorType) { + ct = (ColorType) o; + c = new Color((int)(ct.red() * 255f), + (int)(ct.green() * 255f), (int)(ct.blue() * 255f)); + } + o = style.get("stroke"); + if (c == null && o != null && o instanceof ColorType) { + ct = (ColorType) o; + c = new Color((int)(ct.red() * 255f), + (int)(ct.green() * 255f), (int)(ct.blue() * 255f)); + } + } catch (Exception ex) { + MessageHandler.errorln("Can't set color: R G B : " + + (int)(ct.red() * 255f) + " " + + (int)(ct.green() * 255f) + " " + + (int)(ct.blue() * 255f)); + c = Color.pink; + } + + if (c == null) { + c = new Color((int) red, (int) green, (int) blue); + } + Color oldColor = graphics.getColor(); + + if (area instanceof SVGLineElement) { + graphics.setColor(c); + SVGLineElementImpl lg = (SVGLineElementImpl) area; + + float x1 = lg.getX1().getBaseVal().getValue() * 1000 + posx; + float y1 = posy - lg.getY1().getBaseVal().getValue() * 1000 ; + float x2 = lg.getX2().getBaseVal().getValue() * 1000 + posx; + float y2 = posy - lg.getY2().getBaseVal().getValue() * 1000; + // TODO: + // The thickness of contour protect. + int th = 1; + o = style.get("stroke-width"); + if (o != null) + th = (int)((SVGLengthImpl) o).getValue(); + Line2D.Double aLine = new Line2D.Double(x1 / 1000f, + pageHeight - y1 / 1000f, x2 / 1000f, + pageHeight - y2 / 1000f); + drawShape(transformShape(trans, aLine), di); + graphics.setColor(oldColor); + } else if (area instanceof SVGRectElement) { + graphics.setColor(c); + SVGRectElement rg = (SVGRectElement) area; + float rectx = rg.getX().getBaseVal().getValue() * 1000 + posx; + float recty = posy - rg.getY().getBaseVal().getValue() * 1000; + float rx = rg.getRx().getBaseVal().getValue() * 1000; + float ry = rg.getRy().getBaseVal().getValue() * 1000; + float rw = rg.getWidth().getBaseVal().getValue() * 1000; + float rh = rg.getHeight().getBaseVal().getValue() * 1000; + + // TODO: + // rx and ry are roundings. + // RoundRectangle2D.Double + Rectangle aRectangle = new Rectangle(); + aRectangle.setRect(rectx / 1000d, + pageHeight - recty / 1000d, rw / 1000d, rh / 1000d); + drawShape(transformShape(trans, aRectangle), di); + graphics.setColor(oldColor); + } else if (area instanceof SVGCircleElement) { + graphics.setColor(c); + SVGCircleElement cg = (SVGCircleElement) area; + float cx = cg.getCx().getBaseVal().getValue() * 1000 + posx; + float cy = posy - cg.getCy().getBaseVal().getValue() * 1000; + float r = cg.getR().getBaseVal().getValue(); + Ellipse2D.Double anEllipse = + new Ellipse2D.Double(cx / 1000d - r, + pageHeight - cy / 1000d - r, r * 2d, r * 2d); + drawShape(transformShape(trans, anEllipse), di); + graphics.setColor(oldColor); + } else if (area instanceof SVGEllipseElement) { + graphics.setColor(c); + SVGEllipseElement cg = (SVGEllipseElement) area; + float cx = cg.getCx().getBaseVal().getValue() * 1000 + posx; + float cy = posy - cg.getCy().getBaseVal().getValue() * 1000; + float rx = cg.getRx().getBaseVal().getValue(); + float ry = cg.getRy().getBaseVal().getValue(); + Ellipse2D.Double anEllipse = + new Ellipse2D.Double(cx / 1000d - rx, + pageHeight - cy / 1000d - ry, rx * 2d, ry * 2d); + drawShape(transformShape(trans, anEllipse), di); + graphics.setColor(oldColor); + } else if (area instanceof SVGImageElementImpl) { + SVGImageElementImpl ig = (SVGImageElementImpl) area; + renderImage(ig.link, ig.x + posx / 1000f, + pageHeight - (posy / 1000f - ig.y), ig.width, + ig.height, trans); + } else if (area instanceof SVGUseElementImpl) { + SVGUseElementImpl ug = (SVGUseElementImpl) area; + String ref = ug.link; + ref = ref.substring(1, ref.length()); + GraphicImpl graph = null; + // graph = area.locateDef(ref); + if (graph != null) { + // probably not the best way to do this, should be able + // to render without the style being set. + // GraphicImpl parent = graph.getGraphicParent(); + // graph.setParent(area); + // need to clip (if necessary) to the use area + // the style of the linked element is as if is was + // a direct descendant of the use element. + + renderElement(svgarea, graph, posx, posy, trans); + // graph.setParent(parent); + } + } else if (area instanceof SVGPolylineElementImpl) { + graphics.setColor(c); + Vector points = ((SVGPolylineElementImpl) area).points; + PathPoint p = null; + Point2D.Double p1 = null; + Point2D.Double p2 = null; + if (points.size() > 0) { + p = (PathPoint) points.elementAt(0); + double xc = p.x * 1000f + posx; + double yc = posy - p.y * 1000f; + p1 = new Point2D.Double(xc / 1000f, + pageHeight - yc / 1000f); + + int[] xarr = {(int) xc}; + int[] yarr = {(int) yc}; + graphics.drawPolyline(xarr, yarr, 1); + } + Line2D.Double aLine; + for (int i = 1; i < points.size(); i++) { + p = (PathPoint) points.elementAt(i); + p2 = new Point2D.Double(p.x + posx / 1000f, + pageHeight - (posy - p.y * 1000f) / 1000f); + aLine = new Line2D.Double(p1, p2); + graphics.draw(transformShape(trans, aLine)); + p1 = p2; + } + graphics.setColor(oldColor); + } else if (area instanceof SVGPolygonElementImpl) { + graphics.setColor(c); + java.awt.Polygon aPolygon = + convertPolygon(((SVGPolygonElementImpl) area), + posx, posy); + drawShape(transformShape(trans, aPolygon), di); + graphics.setColor(oldColor); + } else if (area instanceof SVGGElementImpl) { + renderGArea(svgarea, (SVGGElementImpl) area, x, y, + parentTransforms); + } else if (area instanceof SVGPathElementImpl) { + graphics.setColor(c); + GeneralPath path = + convertPath((SVGPathElementImpl) area, posx, posy); + drawShape(transformShape(trans, path), di); + graphics.setColor(oldColor); + } else if (area instanceof SVGTextElementImpl) { + MessageHandler.errorln("SVGTextElementImpl is not implemented yet."); + // renderText(svgarea, (SVGTextElementImpl)area, 0, 0, di); + } else if (area instanceof SVGArea) { + // the x and y pos will be wrong! + Enumeration e = ((SVGArea) area).getChildren().elements(); + while (e.hasMoreElements()) { + Object el = e.nextElement(); + if (o instanceof GraphicImpl) { + renderElement((SVGArea) area, (GraphicImpl) el, x, + y, parentTransforms); + } + } + } + + // should be done with some cleanup code, so only + // required values are reset. + } // renderElement + + + public void renderGArea(SVGArea svgarea, SVGGElementImpl area, + int posx, int posy, Vector v) { + + + Vector trans = null; + // trans = new Vector(area.oldgetTransform()); + // trans.addAll(0, v); + /* Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Object o = e.nextElement(); + if(o instanceof GraphicImpl) { + renderElement(svgarea, (GraphicImpl)o, posx, posy, trans); + } + }*/ + } + public void renderGArea(SVGArea svgarea, SVGGElementImpl area, + int posx, int posy) { + renderGArea(svgarea, area, posx, posy, new Vector()); + } + + + /** + * Applies SVGTransform to the shape and gets the transformed shape. + * The type of the new shape may be different to the original type. + */ + public Shape transformShape(Vector trans, Shape shape) { + if (trans == null || trans.size() == 0) { + return shape; + } + + AffineTransform at; + for (int i = trans.size() - 1; i >= 0; i--) { + org.w3c.dom.svg.SVGTransform t = + (org.w3c.dom.svg.SVGTransform) trans.elementAt(i); + SVGMatrix matrix = t.getMatrix(); + at = new AffineTransform(matrix.getA(), matrix.getB(), + matrix.getC(), matrix.getD(), matrix.getE(), + matrix.getF()); + shape = at.createTransformedShape(shape); + } + return shape; + } + + + /** + * Mapps a SVG-Polygon to a AWT-Polygon. + */ + public java.awt.Polygon convertPolygon(SVGPolygonElementImpl svgpl, + int x, int y) { + java.awt.Polygon aPolygon = new java.awt.Polygon(); + Vector points = svgpl.points; + + PathPoint p; + for (int i = 0; i < points.size(); i++) { + p = (PathPoint) points.elementAt(i); + aPolygon.addPoint((int)(x / 1000f + p.x), + pageHeight - (int)(y / 1000f - p.y)); + } + + return aPolygon; + } + + // TODO: other attributes of DrawingInstruction protect too. + protected DrawingInstruction createInstruction(GraphicImpl area, + Hashtable style) { + DrawingInstruction di = new DrawingInstruction(); + Object sp; + sp = style.get("fill"); + if (sp != null && !(sp instanceof String && sp.equals("none"))) { + di.fill = true; + } + // ... + return di; + } + + // Draws a shape. + // TODO: other attributes of DrawingInstruction protect too. + protected void drawShape(Shape s, DrawingInstruction di) { + if (di.fill) { + graphics.fill(s); + } else { + graphics.draw(s); + } + } + + /** + * Mapps a SVG-Path to a AWT-GeneralPath. + */ + public GeneralPath convertPath(SVGPathElementImpl svgpath, float x, + float y) { + Vector points = svgpath.pathElements; + GeneralPath path = new GeneralPath(); + + float lastx = 0; + float lasty = 0; + SVGPathSegImpl pathmoveto = null; + + for (Enumeration e = points.elements(); e.hasMoreElements();) { + SVGPathSegImpl pc = (SVGPathSegImpl) e.nextElement(); + float[] vals = pc.getValues(); + float lastcx = 0; + float lastcy = 0; + switch (pc.getPathSegType()) { + case SVGPathSeg.PATHSEG_MOVETO_ABS: + lastx = vals[0]; + lasty = vals[1]; + pathmoveto = pc; + path.moveTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_MOVETO_REL: + if (pathmoveto == null) { + lastx = vals[0]; + lasty = vals[1]; + path.moveTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + pathmoveto = pc; + } else { + lastx += vals[0]; + lasty += vals[1]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + + } + break; + case SVGPathSeg.PATHSEG_LINETO_ABS: + lastx = vals[0]; + lasty = vals[1]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_LINETO_REL: + lastx += vals[0]; + lasty += vals[1]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS: + lasty = vals[0]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL: + lasty += vals[0]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS: + lastx = vals[0]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL: + lastx += vals[0]; + path.lineTo(lastx + x / 1000f, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS: + lastx = vals[4]; + lasty = vals[5]; + lastcx = vals[2]; + lastcy = vals[3]; + path.curveTo(x / 1000f + vals[0], + pageHeight - y / 1000f + vals[1], + x / 1000f + lastcx, + pageHeight - y / 1000f + lastcy, + x / 1000f + lastx, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: + path.curveTo(x / 1000f + vals[0] + lastx, + pageHeight - y / 1000f + vals[1] + lasty, + x / 1000f + lastx + vals[2], + pageHeight - y / 1000f + lasty + vals[3], + x / 1000f + lastx + vals[4], + pageHeight - y / 1000f + lasty + vals[5]); + lastcx = vals[2] + lastx; + lastcy = vals[3] + lasty; + lastx += vals[4]; + lasty += vals[5]; + break; + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: + if (lastcx == 0) + lastcx = lastx; + if (lastcy == 0) + lastcy = lasty; + lastx = vals[2]; + lasty = vals[3]; + path.curveTo(x / 1000f + lastcx, + pageHeight - y / 1000f + lastcy, + x / 1000f + vals[0], + pageHeight - y / 1000f + vals[1], + x / 1000f + lastx, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: + if (lastcx == 0) + lastcx = lastx; + if (lastcy == 0) + lastcy = lasty; + path.curveTo(x / 1000f + lastcx, + pageHeight - y / 1000f + lastcy, + x / 1000f + lastx + vals[0], + pageHeight - y / 1000f + lasty + vals[1], + x / 1000f + lastx + vals[2], + pageHeight - y / 1000f + lasty + vals[3]); + lastx += vals[2]; + lasty += vals[3]; + break; + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS: + if (lastcx == 0) + lastcx = lastx; + if (lastcy == 0) + lastcy = lasty; + lastx = vals[0]; + lasty = vals[1]; + lastcx = 0; + lastcy = 0; + path.quadTo(x / 1000f + lastcx, + pageHeight - y / 1000f + lastcy, + x / 1000f + lastx, + pageHeight - y / 1000f + lasty); + break; + case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: + if (lastcx == 0) + lastcx = lastx; + if (lastcy == 0) + lastcy = lasty; + + path.quadTo(x / 1000f + lastcx , + pageHeight - y / 1000f + lastcy, + x / 1000f + lastx + vals[0], + pageHeight - y / 1000f + lasty + vals[1]); + + lastx += vals[0]; + lasty += vals[1]; + lastcx = 0; + lastcy = 0; + break; + case SVGPathSeg.PATHSEG_ARC_ABS: + { + // Arc2D.Double arc = new Arc2D.Double(); + // arc.setAngles(current point, end point); .... + double rx = vals[0]; + double ry = vals[1]; + double theta = vals[2]; + boolean largearcflag = (vals[3] == 1.0); + boolean sweepflag = (vals[4] == 1.0); + + double cx = lastx; + double cy = lasty; + + path.curveTo(x / 1000f + lastx, + pageHeight - y / 1000f + lasty, + x / 1000f + vals[0], + pageHeight - y / 1000f + vals[1], + x / 1000f + vals[5], + pageHeight - y / 1000f + vals[6]); + + lastcx = 0; //?? + lastcy = 0; //?? + lastx = vals[5]; + lasty = vals[6]; + } + break; + case SVGPathSeg.PATHSEG_ARC_REL: + { + double rx = vals[0]; + double ry = vals[1]; + double theta = vals[2]; + boolean largearcflag = (vals[3] == 1.0); + boolean sweepflag = (vals[4] == 1.0); + + path.curveTo(x / 1000f + lastx, + pageHeight - y / 1000f + lasty, + x / 1000f + (vals[0] + lastx), + pageHeight - y / 1000f + (vals[1] + lasty), + x / 1000f + (vals[5] + lastx), + pageHeight - y / 1000f + (vals[6] + lasty)); + lastcx = 0; //?? + lastcy = 0; //?? + lastx += vals[5]; + lasty += vals[6]; + } + break; + case SVGPathSeg.PATHSEG_CLOSEPATH: + path.closePath(); + break; + + + } // switch + } // for points.elements() + + return path; + } // convertPath + /* + if(di == null) { + currentStream.add("S\n"); + } else { + if(di.fill) { + if(di.stroke) { + if(!di.nonzero) + currentStream.add("B*\n"); + else + currentStream.add("B\n"); + } else { + if(!di.nonzero) + currentStream.add("f*\n"); + else + currentStream.add("f\n"); + } + } else { + // if(di.stroke) + currentStream.add("S\n"); + } + } + */ + + /* + * by pdfrenderer übernommen. + * + */ + class DrawingInstruction { + boolean stroke = false; + boolean nonzero = false; // non-zero fill rule "f*", "B*" operator + boolean fill = false; + int linecap = 0; // butt + int linejoin = 0; // miter + int miterwidth = 8; + } + + public void renderForeignObjectArea(ForeignObjectArea area) { + area.getObject().render(this); + } } diff --git a/src/org/apache/fop/render/awt/FontMetricsMapper.java b/src/org/apache/fop/render/awt/FontMetricsMapper.java new file mode 100644 index 000000000..ee7f519d1 --- /dev/null +++ b/src/org/apache/fop/render/awt/FontMetricsMapper.java @@ -0,0 +1,182 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package org.apache.fop.render.awt; + +//FOP +import org.apache.fop.messaging.MessageHandler; +import org.apache.fop.layout.FontInfo; +import org.apache.fop.layout.FontDescriptor; +import org.apache.fop.layout.FontState; + +// Java +import java.util.Enumeration; +import java.util.Hashtable; +import java.awt.Component; +import java.awt.Font; + + +/** +* This class implements org.apache.fop.layout.FontMetric 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 +* style as member varibles +*/ + +public class FontMetricsMapper implements org.apache.fop.layout.FontMetric { + /** + * The first and last non space-character + */ + private final static int FIRST_CHAR = 32; + private final static int LAST_CHAR = 255; + + /** + * This is a AWTFontMetrics that does the real calculation. + * It is only one class that dynamically determines the font-size. + */ + private static AWTFontMetrics metric = null; + + /** + * The java name of the font. + # Make the family name immutable. + */ + private final String family; + + /** + * The java style of the font. + # Make the style immutable. + */ + private final int style; + + /** + * Constructs a new Font-metrics. + * @param family the family name of the font (java value) + * @param style the java type style value of the font + * @param parent an AWT component - this is needed so + * that we can get an instance of + * java.awt.FontMetrics + */ + public FontMetricsMapper(String family, int style, Component parent) { + this.family = family; + this.style = style; + if (metric == null) + metric = new AWTFontMetrics(parent); + } + + /** + * Determines the font ascent of the Font described by this + * FontMetrics object + * @return ascent in milliponts + */ + public int getAscender(int size) { + return metric.getAscender(family, style, size); + } + + + /** + * The size of a capital letter measured from the font's baseline + */ + public int getCapHeight(int size) { + return metric.getCapHeight(family, style, size); + } + + /** + * Determines the font descent of the Font described by this + * FontMetrics object + * @return descent in milliponts + */ + public int getDescender(int size) { + return metric.getDescender(family, style, size); + } + + /** + * Determines the typical font height of this + * FontMetrics object + * @return font height in milliponts + */ + public int getXHeight(int size) { + return metric.getXHeight(family, style, size); + } + + + public int getFirstChar() { + return FIRST_CHAR; + } + + public int getLastChar() { + return LAST_CHAR; + } + + /** + * return width (in 1/1000ths of point size) of character at + * code point i. + */ + public int width(int i, int size) { + return metric.width(i, family, style, size); + } + + + /** + * return width (in 1/1000ths of point size) of all character + */ + public int[] getWidths(int size) { + return metric.getWidths(family, style, size); + } + + /** + * Gets a Font instance of the Font that this + * FontMetrics describes in the desired size. + * @return font with the desired characeristics. + */ + public Font getFont(int size) { + return metric.getFont(family, style, size); + } +} + + + + + diff --git a/src/org/apache/fop/render/awt/FontSetup.java b/src/org/apache/fop/render/awt/FontSetup.java new file mode 100644 index 000000000..2d24f55bd --- /dev/null +++ b/src/org/apache/fop/render/awt/FontSetup.java @@ -0,0 +1,228 @@ +/*-- $Id: FontSetup.java -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber . For more information on the Apache + Software Foundation, please see . + + */ +package org.apache.fop.render.awt; + +// FOP +import org.apache.fop.messaging.MessageHandler; +import org.apache.fop.layout.FontInfo; +import org.apache.fop.layout.FontDescriptor; + +// Java +import java.util.Enumeration; +import java.util.Hashtable; +import java.awt.Font; +import java.awt.Component; + +/** + * sets up the AWT fonts. It is similar to + * org.apache.fop.render.pdf.FontSetup. + * Assigns the font (with metrics) to internal names like "F1" and + * assigns family-style-weight triplets to the fonts + */ +public class FontSetup { + + + /** sets up the font info object. + * + * adds metrics for basic fonts and useful family-style-weight + * triplets for lookup + * + * @param fontInfo the font info object to set up + * @param parent needed, since a live AWT component is needed + * to get a valid java.awt.FontMetrics object + */ + public static void setup(FontInfo fontInfo, Component parent) { + FontMetricsMapper metric; + int normal, bold, bolditalic, italic; + + MessageHandler.logln("setting up fonts"); + + /* available java fonts are: + Serif - bold, normal, italic, bold-italic + SansSerif - bold, normal, italic, bold-italic + MonoSpaced - bold, normal, italic, bold-italic + */ + normal = java.awt.Font.PLAIN; + bold = java.awt.Font.BOLD; + italic = java.awt.Font.ITALIC; + bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; + + metric = new FontMetricsMapper("SansSerif", normal, parent); + // --> goes to F1 + fontInfo.addMetrics("F1", metric); + metric = new FontMetricsMapper("SansSerif",italic, parent); + // --> goes to F2 + fontInfo.addMetrics("F2", metric); + metric = new FontMetricsMapper("SansSerif", bold, parent); + // --> goes to F3 + fontInfo.addMetrics("F3", metric); + metric = new FontMetricsMapper("SansSerif", bolditalic, parent); + // --> goes to F4 + fontInfo.addMetrics("F4", metric); + + + metric = new FontMetricsMapper("Serif", normal, parent); + // --> goes to F5 + fontInfo.addMetrics("F5", metric); + metric = new FontMetricsMapper("Serif", italic, parent); + // --> goes to F6 + fontInfo.addMetrics("F6", metric); + metric = new FontMetricsMapper("Serif", bold, parent); + // --> goes to F7 + fontInfo.addMetrics("F7", metric); + metric = new FontMetricsMapper("Serif", bolditalic, parent); + // --> goes to F8 + fontInfo.addMetrics("F8", metric); + + metric = new FontMetricsMapper("MonoSpaced", normal, parent); + // --> goes to F9 + fontInfo.addMetrics("F9", metric); + metric = new FontMetricsMapper("MonoSpaced", italic, parent); + // --> goes to F10 + fontInfo.addMetrics("F10", metric); + metric = new FontMetricsMapper("MonoSpaced", bold, parent); + // --> goes to F11 + fontInfo.addMetrics("F11", metric); + metric = new FontMetricsMapper("MonoSpaced", bolditalic, parent); + // --> goes to F12 + fontInfo.addMetrics("F12", metric); + + metric = new FontMetricsMapper("Symbol", bolditalic, parent); + // --> goes to F13 and F14 + fontInfo.addMetrics("F13", metric); + fontInfo.addMetrics("F14", metric); + + //Custom type 1 fonts step 1/2 + // fontInfo.addMetrics("F15", new OMEP()); + // fontInfo.addMetrics("F16", new GaramondLightCondensed()); + // fontInfo.addMetrics("F17", new BauerBodoniBoldItalic()); + + /* any is treated as serif */ + fontInfo.addFontProperties("F5", "any", "normal", "normal"); + fontInfo.addFontProperties("F6", "any", "italic", "normal"); + fontInfo.addFontProperties("F6", "any", "oblique", "normal"); + fontInfo.addFontProperties("F7", "any", "normal", "bold"); + fontInfo.addFontProperties("F8", "any", "italic", "bold"); + fontInfo.addFontProperties("F8", "any", "oblique", "bold"); + + fontInfo.addFontProperties("F1", "sans-serif", "normal", "normal"); + fontInfo.addFontProperties("F2", "sans-serif", "oblique", "normal"); + fontInfo.addFontProperties("F2", "sans-serif", "italic", "normal"); + fontInfo.addFontProperties("F3", "sans-serif", "normal", "bold"); + fontInfo.addFontProperties("F4", "sans-serif", "oblique", "bold"); + fontInfo.addFontProperties("F4", "sans-serif", "italic", "bold"); + fontInfo.addFontProperties("F5", "serif", "normal", "normal"); + fontInfo.addFontProperties("F6", "serif", "oblique", "normal"); + fontInfo.addFontProperties("F6", "serif", "italic", "normal"); + fontInfo.addFontProperties("F7", "serif", "normal", "bold"); + fontInfo.addFontProperties("F8", "serif", "oblique", "bold"); + fontInfo.addFontProperties("F8", "serif", "italic", "bold"); + fontInfo.addFontProperties("F9", "monospace", "normal", "normal"); + fontInfo.addFontProperties("F10", "monospace", "oblique", "normal"); + fontInfo.addFontProperties("F10", "monospace", "italic", "normal"); + fontInfo.addFontProperties("F11", "monospace", "normal", "bold"); + fontInfo.addFontProperties("F12", "monospace", "oblique", "bold"); + fontInfo.addFontProperties("F12", "monospace", "italic", "bold"); + + fontInfo.addFontProperties("F1", "Helvetica", "normal", "normal"); + fontInfo.addFontProperties("F2", "Helvetica", "oblique", "normal"); + fontInfo.addFontProperties("F2", "Helvetica", "italic", "normal"); + fontInfo.addFontProperties("F3", "Helvetica", "normal", "bold"); + fontInfo.addFontProperties("F4", "Helvetica", "oblique", "bold"); + fontInfo.addFontProperties("F4", "Helvetica", "italic", "bold"); + fontInfo.addFontProperties("F5", "Times", "normal", "normal"); + fontInfo.addFontProperties("F6", "Times", "oblique", "normal"); + fontInfo.addFontProperties("F6", "Times", "italic", "normal"); + fontInfo.addFontProperties("F7", "Times", "normal", "bold"); + fontInfo.addFontProperties("F8", "Times", "oblique", "bold"); + fontInfo.addFontProperties("F8", "Times", "italic", "bold"); + fontInfo.addFontProperties("F9", "Courier", "normal", "normal"); + fontInfo.addFontProperties("F10", "Courier", "oblique", "normal"); + fontInfo.addFontProperties("F10", "Courier", "italic", "normal"); + fontInfo.addFontProperties("F11", "Courier", "normal", "bold"); + fontInfo.addFontProperties("F12", "Courier", "oblique", "bold"); + fontInfo.addFontProperties("F12", "Courier", "italic", "bold"); + fontInfo.addFontProperties("F13", "Symbol", "normal", "normal"); + fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", "normal"); + + //Custom type 1 fonts step 2/2 + // fontInfo.addFontProperties("F15", "OMEP", "normal", "normal"); + // fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", "normal"); + // fontInfo.addFontProperties("F17", "BauerBodoni", "italic", "bold"); + + /* for compatibility with PassiveTex */ + fontInfo.addFontProperties("F5", "Times-Roman", "normal", "normal"); + fontInfo.addFontProperties("F6", "Times-Roman", "oblique", "normal"); + fontInfo.addFontProperties("F6", "Times-Roman", "italic", "normal"); + fontInfo.addFontProperties("F7", "Times-Roman", "normal", "bold"); + fontInfo.addFontProperties("F8", "Times-Roman", "oblique", "bold"); + fontInfo.addFontProperties("F8", "Times-Roman", "italic", "bold"); + fontInfo.addFontProperties("F5", "Times Roman", "normal", "normal"); + fontInfo.addFontProperties("F6", "Times Roman", "oblique", "normal"); + fontInfo.addFontProperties("F6", "Times Roman", "italic", "normal"); + fontInfo.addFontProperties("F7", "Times Roman", "normal", "bold"); + fontInfo.addFontProperties("F8", "Times Roman", "oblique", "bold"); + fontInfo.addFontProperties("F8", "Times Roman", "italic", "bold"); + fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", + "normal", "normal"); + } + +} + + + + + + + + + + diff --git a/src/org/apache/fop/render/pdf/Font.java b/src/org/apache/fop/render/pdf/Font.java index 5717a62ad..88e677cd1 100644 --- a/src/org/apache/fop/render/pdf/Font.java +++ b/src/org/apache/fop/render/pdf/Font.java @@ -68,3 +68,6 @@ public abstract class Font implements FontMetric { */ public abstract String fontName(); } + + + diff --git a/src/org/apache/fop/viewer/PreviewDialog.java b/src/org/apache/fop/viewer/PreviewDialog.java index 8aeb7325c..15ca7390a 100644 --- a/src/org/apache/fop/viewer/PreviewDialog.java +++ b/src/org/apache/fop/viewer/PreviewDialog.java @@ -5,22 +5,34 @@ package org.apache.fop.viewer; Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com, Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com, Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com + + Doro Wiarda (wiarda@dwiarda.com: + added MessageListener support and made + the showing of the progress and error + messages Swing thread safe. + This is needed as xml parse errors do not + necessarily occur in the + EventDispatchThread. */ import java.awt.*; import java.awt.print.*; import java.awt.event.*; import java.awt.image.BufferedImage; +import java.util.StringTokenizer; +import java.util.Vector; import javax.swing.*; import org.apache.fop.layout.*; import org.apache.fop.render.awt.*; +import org.apache.fop.messaging.*; /** * Frame and User Interface for Preview */ -public class PreviewDialog extends JFrame implements ProgressListener { +public class PreviewDialog extends JFrame implements ProgressListener, + MessageListener { protected Translator res; @@ -346,43 +358,186 @@ public class PreviewDialog extends JFrame implements ProgressListener { } public void progress(int percentage) { - processStatus.setText(percentage + "%"); + progress(new String(percentage + "%")); } public void progress(int percentage, String message) { - processStatus.setText(message + " " + percentage + "%"); + progress(new String(message + " " + percentage + "%")); } + + /** + * Setting the text of a JLabel is not thread save, it + * needs to be done in the EventThread. Here we make sure + * it is done. + */ public void progress(String message) { - processStatus.setText(message); + SwingUtilities.invokeLater( new showProgress( message, false ) ); } - public void showPage() { - BufferedImage pageImage = null; - Graphics graphics = null; + /** + * This class is used to show status and error messages in + * a thread safe way. + */ + class showProgress implements Runnable{ + /** + * The message to display + */ + Object message; + + /** + * Is this an errorMessage, i.e. should it be shown in + * an JOptionPane or in the status bar. + */ + boolean isErrorMessage = false; + + /** + * Constructs showProgress thread + * @param message message to display + * @param isErrorMessage show in status bar or in JOptionPane + */ + public showProgress(Object message, boolean isErrorMessage){ + this.message = message; + this.isErrorMessage = isErrorMessage; + } + + public void run(){ + if( isErrorMessage ){ + JOptionPane.showMessageDialog(null, message, "Error", + JOptionPane.ERROR_MESSAGE); + } + else processStatus.setText(message.toString()); + } + } + + public void showPage(){ + showPageImage viewer = new showPageImage(); + + if( SwingUtilities.isEventDispatchThread() ){ + viewer.run(); + } + else SwingUtilities.invokeLater(viewer); + } - renderer.render(currentPage); - pageImage = renderer.getLastRenderedPage(); - if (pageImage == null) - return; - graphics = pageImage.getGraphics(); - graphics.setColor(Color.black); - graphics.drawRect(0, 0, pageImage.getWidth() - 1, - pageImage.getHeight() -1 ); - - previewImageLabel.setIcon(new ImageIcon(pageImage)); - pageCount = renderer.getPageCount(); + /** + * This class is used to update the page image + * in a thread safe way. + */ + class showPageImage implements Runnable{ + + /** + * The run method that does the actuall updating + */ + public void run() { + BufferedImage pageImage = null; + Graphics graphics = null; + + renderer.render(currentPage); + pageImage = renderer.getLastRenderedPage(); + if (pageImage == null) + return; + graphics = pageImage.getGraphics(); + graphics.setColor(Color.black); + graphics.drawRect(0, 0, pageImage.getWidth() - 1, + pageImage.getHeight() -1 ); + + previewImageLabel.setIcon(new ImageIcon(pageImage)); + + pageCount = renderer.getPageCount(); + + statisticsStatus.setText(res.getString("Page") + " " + + (currentPage + 1) + " " + + res.getString("of") + " " + + pageCount); + } + } + + + /** + * Called by MessageHandler if an error message or a + * log message is received. + */ + public void processMessage ( MessageEvent event ){ + String error = event.getMessage(); + String text = processStatus.getText(); + FontMetrics fmt = processStatus.getFontMetrics( + processStatus.getFont()); + int width = processStatus.getWidth()-fmt.stringWidth("..."); + showProgress showIt; + + if( event.getMessageType() == event.LOG){ + if( !text.endsWith("\n") ) { + text = text + error; + while ( fmt.stringWidth(text) > width){ + text = text.substring(1); + width = processStatus.getWidth()-fmt.stringWidth("..."); + } + } + else text = error; + progress( text ); + } + else{ + error = error.trim(); + if( error.equals(">") ){ + text = text + error; + while ( fmt.stringWidth(text) > width){ + text = text.substring(1); + width = processStatus.getWidth()-fmt.stringWidth("..."); + } + progress( processStatus.getText() + error ); + return; + } + if( error.equals("") ) return; + if( error.length() < 60) { + showIt = new showProgress( error, true ); + } + else{ + StringTokenizer tok = new StringTokenizer(error," "); + Vector labels = new Vector(); + StringBuffer buffer = new StringBuffer(); + String tmp,list[]; + + while(tok.hasMoreTokens()){ + tmp = tok.nextToken(); + if( (buffer.length()+tmp.length() +1) < 60 ){ + buffer.append(" ").append(tmp); + } + else{ + labels.add(buffer.toString()); + buffer = new StringBuffer(); + buffer.append(tmp); + } + } + labels.add(buffer.toString()); + list = new String[ labels.size() ]; + for( int i = 0 ; i < labels.size() ; i++) { + list[i] = labels.elementAt(i).toString(); + } + showIt = new showProgress( list, true ); + } + if( SwingUtilities.isEventDispatchThread() ){ + showIt.run(); + } + else { + try{ + SwingUtilities.invokeAndWait( showIt ); + } + catch( Exception e){ + e.printStackTrace(); + progress( event.getMessage() ); + } + } + } + } - statisticsStatus.setText(res.getString("Page") + " " + - (currentPage + 1) + " " + - res.getString("of") + " " + - pageCount); - } public void dispose() { System.exit(0); } } // class PreviewDialog + + + -- 2.39.5