deweese 2003/07/01 02:34:18 Modified: sources/org/apache/batik/bridge BaseScriptingEnvironment.java BridgeContext.java SVGAElementBridge.java ScriptingEnvironment.java sources/org/apache/batik/css/engine/sac CSSClassCondition.java sources/org/apache/batik/dom/util DOMUtilities.java sources/org/apache/batik/ext/awt/image/codec PNGImageEncoder.java sources/org/apache/batik/script Window.java sources/org/apache/batik/util Service.java test-sources/org/apache/batik/test/svg SVGRenderingAccuracyTest.java Added: test-sources/org/apache/batik/test/svg AbstractRenderingAccuracyTest.java Log: 1) parseXML now returns a Document when no 'host' Document provided. 2) BridgeContext now uses a Set rather than a list for event mementos and synchronizes acccess between the cleaner thread and the update thread. 3) CSSClass checks no longer throw exceptions for non-stylable elements (just fails). 4) DOMUtilities.writeNode now properly writes Processing Instructions. 5) SVG 'a' element bridge now derives off SVG 'g' element bridge so it properly tacks children that are added. 6) Service class no longer throws an exception when it can't get a class loader (just finds nothing). 7) SVGRenderingAccuracyTest now derives off a new Abstract baseclass AbstractRenderingAccuracyTest which defers output image creation to an 'encode' method. Revision Changes Path 1.20 +5 -5 xml-batik/sources/org/apache/batik/bridge/BaseScriptingEnvironment.java Index: BaseScriptingEnvironment.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BaseScriptingEnvironment.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- BaseScriptingEnvironment.java 11 Jun 2003 22:07:24 -0000 1.19 +++ BaseScriptingEnvironment.java 1 Jul 2003 09:34:17 -0000 1.20 @@ -26,7 +26,6 @@ import org.apache.batik.util.ParsedURL; import org.apache.batik.util.SVGConstants; import org.w3c.dom.Document; -import org.w3c.dom.DocumentFragment; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -594,10 +593,11 @@ /** * Parses the given XML string into a DocumentFragment of the - * given document. - * @return The document fragment or null on error. + * given document or a new document if 'doc' is null. + * The implementation in this class always returns 'null' + * @return The document/document fragment or null on error. */ - public DocumentFragment parseXML(String text, Document doc) { + public Node parseXML(String text, Document doc) { return null; } 1.64 +22 -14 xml-batik/sources/org/apache/batik/bridge/BridgeContext.java Index: BridgeContext.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BridgeContext.java,v retrieving revision 1.63 retrieving revision 1.64 diff -u -r1.63 -r1.64 --- BridgeContext.java 19 Jun 2003 11:51:34 -0000 1.63 +++ BridgeContext.java 1 Jul 2003 09:34:17 -0000 1.64 @@ -16,11 +16,13 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Set; import org.apache.batik.css.engine.CSSContext; import org.apache.batik.css.engine.CSSEngine; @@ -769,7 +771,7 @@ * The list of all EventListener attached by bridges that need to * be removed on a dispose() call. */ - protected List eventListenerList = new LinkedList(); + protected Set eventListenerSet = new HashSet(); /** * The DOM EventListener to receive 'DOMCharacterDataModified' event. @@ -878,30 +880,34 @@ } /** - * Adds to the eventListenerList the specified event listener + * Adds to the eventListenerSet the specified event listener * registration. */ protected void storeEventListener(EventTarget t, String s, EventListener l, boolean b) { - eventListenerList.add(new EventListenerMememto(t, s, l, b, this)); + synchronized (eventListenerSet) { + eventListenerSet.add(new EventListenerMememto(t, s, l, b, this)); + } } public static class SoftReferenceMememto extends CleanerThread.SoftReferenceCleared { Object mememto; - List list; - SoftReferenceMememto(Object ref, Object mememto, List list) { + Set set; + SoftReferenceMememto(Object ref, Object mememto, Set set) { super(ref); this.mememto = mememto; - this.list = list; + this.set = set; } public void cleared() { - list.remove(mememto); - mememto = null; - list = null; + synchronized (set) { + set.remove(mememto); + mememto = null; + set = null; + } } } @@ -920,9 +926,9 @@ EventListener l, boolean b, BridgeContext ctx) { - List list = ctx.eventListenerList; - target = new SoftReferenceMememto(t, this, list); - listener = new SoftReferenceMememto(l, this, list); + Set set = ctx.eventListenerSet; + target = new SoftReferenceMememto(t, this, set); + listener = new SoftReferenceMememto(l, this, set); eventType = s; useCapture = b; } @@ -947,8 +953,9 @@ */ public void dispose() { + synchronized (eventListenerSet) { // remove all listeners added by Bridges - Iterator iter = eventListenerList.iterator(); + Iterator iter = eventListenerSet.iterator(); while (iter.hasNext()) { EventListenerMememto m = (EventListenerMememto)iter.next(); EventTarget et = m.getTarget(); @@ -958,6 +965,7 @@ if ((et == null) || (el == null) || (t == null)) continue; et.removeEventListener(t, el, uc); + } } EventTarget evtTarget = (EventTarget)document; 1.23 +2 -9 xml-batik/sources/org/apache/batik/bridge/SVGAElementBridge.java Index: SVGAElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGAElementBridge.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- SVGAElementBridge.java 11 Jun 2003 22:07:24 -0000 1.22 +++ SVGAElementBridge.java 1 Jul 2003 09:34:17 -0000 1.23 @@ -25,7 +25,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Thierry Kormann</a> * @version $Id$ */ -public class SVGAElementBridge extends AbstractGraphicsNodeBridge { +public class SVGAElementBridge extends SVGGElementBridge { /** * Constructs a new bridge for the <a> element. @@ -44,13 +44,6 @@ */ public Bridge getInstance() { return new SVGAElementBridge(); - } - - /** - * Creates a <tt>CompositeGraphicsNode</tt>. - */ - protected GraphicsNode instantiateGraphicsNode() { - return new CompositeGraphicsNode(); } /** 1.38 +52 -18 xml-batik/sources/org/apache/batik/bridge/ScriptingEnvironment.java Index: ScriptingEnvironment.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/ScriptingEnvironment.java,v retrieving revision 1.37 retrieving revision 1.38 diff -u -r1.37 -r1.38 --- ScriptingEnvironment.java 11 Jun 2003 22:07:25 -0000 1.37 +++ ScriptingEnvironment.java 1 Jul 2003 09:34:17 -0000 1.38 @@ -54,6 +54,9 @@ XLinkSupport.XLINK_NAMESPACE_URI + "'>"; + protected final static String FRAGMENT_SUFFIX = + "</svg>"; + /** * The timer for periodic or delayed tasks. */ @@ -670,55 +673,86 @@ * Implements [EMAIL PROTECTED] * org.apache.batik.script.Window#parseXML(String,Document)}. */ - public DocumentFragment parseXML(String text, Document doc) { + public Node parseXML(String text, Document doc) { // System.out.println("Text: " + text); + // Try and parse it as an SVGDocument SAXSVGDocumentFactory df = new SAXSVGDocumentFactory (XMLResourceDescriptor.getXMLParserClassName()); - String uri = ((SVGOMDocument)bridgeContext.getDocument()). - getURLObject().toString(); - DocumentFragment result = null; + URL urlObj = null; + if ((doc != null) && (doc instanceof SVGOMDocument)) + urlObj = ((SVGOMDocument)doc).getURLObject(); + if (urlObj == null) { + urlObj = ((SVGOMDocument)bridgeContext.getDocument()). + getURLObject(); + } + String uri = (urlObj==null)?"":urlObj.toString(); try { Document d = df.createDocument(uri, new StringReader(text)); - result = doc.createDocumentFragment(); + if (doc == null) + return d; + + Node result = doc.createDocumentFragment(); result.appendChild(doc.importNode(d.getDocumentElement(), true)); + return result; } catch (Exception ex) { - StringBuffer sb = new StringBuffer(text.length() + - FRAGMENT_PREFIX.length() + - "</svg>".length()); + /* nothing */ + } + + if ((doc != null) && (doc instanceof SVGOMDocument)) { + // Try and parse with an 'svg' element wrapper - for + // things like '<rect ../>' - ensure that rect ends up + // in SVG namespace - xlink namespace is declared etc... + + // Only do this when generating a doc fragment, since + // a 'rect' element can not be root of SVG Document + // (only an svg element can be). + StringBuffer sb = new StringBuffer(FRAGMENT_PREFIX.length() + + text.length() + + FRAGMENT_SUFFIX.length()); sb.append(FRAGMENT_PREFIX); sb.append(text); - sb.append("</svg>"); + sb.append(FRAGMENT_SUFFIX); String newText = sb.toString(); try { Document d = df.createDocument (uri, new StringReader(newText)); + // No document given so make doc fragment from our + // new Document. + if (doc == null) doc = d; for (Node n = d.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling()) { if (n.getNodeType() == n.ELEMENT_NODE) { n = doc.importNode(n, true); - result = doc.createDocumentFragment(); + Node result = doc.createDocumentFragment(); result.appendChild(n); - break; + return result; } } } catch (Exception exc) { + /* nothing */ + } + } + + // Parse as a generic XML document. SAXDocumentFactory sdf = new SAXDocumentFactory (doc.getImplementation(), XMLResourceDescriptor.getXMLParserClassName()); try { - Document d = sdf.createDocument - (uri, new StringReader(text)); - result = doc.createDocumentFragment(); + Document d = sdf.createDocument(uri, new StringReader(text)); + if (doc == null) + return d; + + Node result = doc.createDocumentFragment(); result.appendChild(doc.importNode(d.getDocumentElement(), true)); + return result; } catch (Exception ext) { if (userAgent != null) userAgent.displayError(ext); } - } - } - return result; + + return null; } /** 1.4 +3 -1 xml-batik/sources/org/apache/batik/css/engine/sac/CSSClassCondition.java Index: CSSClassCondition.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/css/engine/sac/CSSClassCondition.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- CSSClassCondition.java 11 Apr 2003 13:55:31 -0000 1.3 +++ CSSClassCondition.java 1 Jul 2003 09:34:17 -0000 1.4 @@ -41,6 +41,8 @@ * Tests whether this condition matches the given element. */ public boolean match(Element e, String pseudoE) { + if (!(e instanceof CSSStylableElement)) + return false; // Can't match an unstylable element. String attr = ((CSSStylableElement)e).getCSSClass(); String val = getValue(); int i = attr.indexOf(val); 1.8 +3 -1 xml-batik/sources/org/apache/batik/dom/util/DOMUtilities.java Index: DOMUtilities.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/util/DOMUtilities.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- DOMUtilities.java 11 Apr 2003 13:57:10 -0000 1.7 +++ DOMUtilities.java 1 Jul 2003 09:34:17 -0000 1.8 @@ -96,6 +96,8 @@ case Node.PROCESSING_INSTRUCTION_NODE: w.write("<?"); w.write(n.getNodeName()); + // TD: Bug #19392 + w.write(" "); w.write(n.getNodeValue()); w.write("?>"); break; 1.6 +3 -2 xml-batik/sources/org/apache/batik/ext/awt/image/codec/PNGImageEncoder.java Index: PNGImageEncoder.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/codec/PNGImageEncoder.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- PNGImageEncoder.java 11 Apr 2003 13:57:36 -0000 1.5 +++ PNGImageEncoder.java 1 Jul 2003 09:34:17 -0000 1.6 @@ -509,8 +509,9 @@ } else { gamma = 1.0F/2.2F; // SRGB gamma } - - cs.writeInt((int)(gamma*100000)); + // TD should include the .5 but causes regard to say + // everything is different. + cs.writeInt((int)(gamma*100000/*+0.5*/)); cs.writeToStream(dataOutput); } } 1.7 +4 -4 xml-batik/sources/org/apache/batik/script/Window.java Index: Window.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/script/Window.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- Window.java 11 Apr 2003 13:58:54 -0000 1.6 +++ Window.java 1 Jul 2003 09:34:17 -0000 1.7 @@ -10,7 +10,7 @@ import org.apache.batik.bridge.BridgeContext; import org.w3c.dom.Document; -import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Node; /** * This interface represents the 'window' object defined in the global @@ -65,10 +65,10 @@ /** * Parses the given XML string into a DocumentFragment of the - * given document. + * given document or a new document if 'doc' is null. * @return The document fragment or null on error. */ - DocumentFragment parseXML(String text, Document doc); + Node parseXML(String text, Document doc); /** * Gets data from the given URI. 1.4 +12 -2 xml-batik/sources/org/apache/batik/util/Service.java Index: Service.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/Service.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- Service.java 11 Apr 2003 13:59:29 -0000 1.3 +++ Service.java 1 Jul 2003 09:34:17 -0000 1.4 @@ -47,7 +47,15 @@ * @param cls The class/interface to search for providers of. */ public static synchronized Iterator providers(Class cls) { - ClassLoader cl = cls.getClassLoader(); + ClassLoader cl = null; + try { + cl = cls.getClassLoader(); + } catch (SecurityException se) { + // Ooops! can't get his class loader. + } + // Can always request your own class loader. But it might be 'null'. + if (cl == null) cl = Service.class.getClassLoader(); + String serviceFile = "META-INF/services/"+cls.getName(); // System.out.println("File: " + serviceFile); @@ -58,6 +66,8 @@ v = new Vector(); providerMap.put(serviceFile, v); + // No class loader so we can't find 'serviceFile'. + if (cl == null) return v.iterator(); Enumeration e; try { 1.33 +36 -800 xml-batik/test-sources/org/apache/batik/test/svg/SVGRenderingAccuracyTest.java Index: SVGRenderingAccuracyTest.java =================================================================== RCS file: /home/cvs/xml-batik/test-sources/org/apache/batik/test/svg/SVGRenderingAccuracyTest.java,v retrieving revision 1.32 retrieving revision 1.33 diff -u -r1.32 -r1.33 --- SVGRenderingAccuracyTest.java 5 Mar 2003 22:12:44 -0000 1.32 +++ SVGRenderingAccuracyTest.java 1 Jul 2003 09:34:17 -0000 1.33 @@ -69,22 +69,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Vincent Hardy</a> * @version $Id$ */ -public class SVGRenderingAccuracyTest extends AbstractTest { - /** - * Error when temp file cannot be created - * {0} = IOException message - */ - public static final String ERROR_CANNOT_CREATE_TEMP_FILE - = "SVGRenderingAccuracyTest.error.cannot.create.temp.file"; - - /** - * Error when temp file stream cannot be created - * {0} = temp file's cannonical path - * {1} = IOException message - */ - public static final String ERROR_CANNOT_CREATE_TEMP_FILE_STREAM - = "SVGRenderingAccuracyTest.error.cannot.create.temp.file.stream"; - +public class SVGRenderingAccuracyTest extends AbstractRenderingAccuracyTest { /** * Error when transcoding the SVG document generates an error * {0} = URI of the transcoded SVG file @@ -96,210 +81,30 @@ = "SVGRenderingAccuracyTest.error.cannot.transcode.svg"; /** - * Error when the reference image cannot be opened - * {0} = URI of the reference image - * {1} = IOException message - */ - public static final String ERROR_CANNOT_OPEN_REFERENCE_IMAGE - = "SVGRenderingAccuracyTest.error.cannot.open.reference.image"; - - /** - * Error when the generated image cannot be read - * {0} = Cannonical path of the temp generated image - * {1} = IOException message - */ - public static final String ERROR_CANNOT_OPEN_GENERATED_IMAGE - = "SVGRenderingAccuracyTest.error.cannot.open.genereted.image"; - - /** - * Error when there is an IOException while comparing the - * two reference raster image with the new raster image built - * from the SVG. - * {0} = URI of the reference image - * {1} = Connical path for the temp generated image - * {2} = IOException message. - */ - public static final String ERROR_ERROR_WHILE_COMPARING_FILES - = "SVGRenderingAccuracyTest.error.while.comparing.files"; - - /** - * Error when the generated image from the SVG file differs from - * the reference image. - */ - public static final String ERROR_SVG_RENDERING_NOT_ACCURATE - = "SVGRenderingAccuracyTest.error.svg.rendering.not.accurate"; - - /** - * Entry describing the error - */ - public static final String ENTRY_KEY_ERROR_DESCRIPTION - = "SVGRenderingAccuracyTest.entry.key.error.description"; - - /** - * Entry describing the reference/generated image file - */ - public static final String ENTRY_KEY_REFERENCE_GENERATED_IMAGE_URI - = "SVGRenderingAccuracyTest.entry.key.reference.generated.image.file"; - - /** - * Entry describing the generated difference image - */ - public static final String ENTRY_KEY_DIFFERENCE_IMAGE - = "SVGRenderingAccuracyTest.entry.key.difference.image"; - - /** - * Entry describing that an internal error occured while - * generating the test failure description - */ - public static final String ENTRY_KEY_INTERNAL_ERROR - = "SVGRenderingAccuracyTest.entry.key.internal.error"; - - /** - * Messages expressing that comparison images could not be - * created: - * {0} : exception class - * {1} : exception message - * {2} : exception stack trace. - */ - public static final String COULD_NOT_GENERATE_COMPARISON_IMAGES - = "SVGRenderingAccuracyTest.message.error.could.not.generate.comparison.images"; - - /** - * Messages expressing that an image could not be loaded. - * {0} : URL for the reference image. - */ - public static final String COULD_NOT_LOAD_IMAGE - = "SVGRenderingAccuracyTest.message.error.could.not.load.image"; - - /** - * Message expressing that the variation URL could not be open - * {0} : URL - */ - public static final String COULD_NOT_OPEN_VARIATION_URL - = "SVGRenderingAccuracyTest.message.warning.could.not.open.variation.url"; - - /** - * The gui resources file name - */ - public final static String CONFIGURATION_RESOURCES = - "org.apache.batik.test.svg.resources.Configuration"; - - /** - * Suffix used for comparison images - */ - public final static String IMAGE_TYPE_COMPARISON = "_cmp"; - - /** - * Suffix used for diff images - */ - public final static String IMAGE_TYPE_DIFF = "_diff"; - - /** - * Suffix used for saved images (e.g., comparison and diff images) - */ - public final static String IMAGE_FILE_EXTENSION = ".png"; - - /** - * The configuration resource bundle - */ - protected static ResourceBundle configuration; - static { - configuration = ResourceBundle.getBundle(CONFIGURATION_RESOURCES, - Locale.getDefault()); - } - - /** - * Prefix for the temporary files created by Tests - * of this class - */ - public static final String TEMP_FILE_PREFIX - = configuration.getString("temp.file.prefix"); - - /** - * Suffix for the temporary files created by - * Tests of this class - */ - public static final String TEMP_FILE_SUFFIX - = configuration.getString("temp.file.suffix"); - - /** * Validating parser class name */ public static final String VALIDATING_PARSER = configuration.getString("validating.parser"); /** - * The URL where the SVG can be found. - */ - protected URL svgURL; - - /** - * The URL for the reference image - */ - protected URL refImgURL; - - /** - * The URL of a file containing an 'accepted' - * variation from the reference image. - */ - protected URL variationURL; - - /** - * The File where the newly computed variation - * should be saved if different from the - * variationURL - */ - protected File saveVariation; - - /** - * The File where the candidate reference - * should be saved if there is not candidate reference - * or if it cannot be opened. - */ - protected File candidateReference; - - /** * Controls whether or not the SVG file should be * validated. By default, no validation is used. */ protected boolean validate = false; /** - * Temporary directory - */ - protected static File tempDirectory; - - /** * The userLanguage for which the document should be tested. */ protected String userLanguage; /** - * Returns the temporary directory - */ - public static File getTempDirectory(){ - if(tempDirectory == null){ - String tmpDir = System.getProperty("java.io.tmpdir"); - if(tmpDir == null){ - throw new Error(); - } - - tempDirectory = new File(tmpDir); - if(!tempDirectory.exists()){ - throw new Error(); - } - } - return tempDirectory; - } - - /** * Constructor. * @param svgURL the URL String for the SVG document being tested. * @param refImgURL the URL for the reference image. */ public SVGRenderingAccuracyTest(String svgURL, String refImgURL){ - setConfig(svgURL, refImgURL); + super(svgURL, refImgURL); } /** @@ -309,47 +114,17 @@ } /** - * Sets this test's config. + * If true, this test will use validation */ - public void setConfig(String svgURL, - String refImgURL){ - if(svgURL == null){ - throw new IllegalArgumentException(); - } - - if(refImgURL == null){ - throw new IllegalArgumentException(); - } - - this.svgURL = resolveURL(svgURL); - this.refImgURL = resolveURL(refImgURL); + public void setValidating(Boolean validate){ + if (validate == null){ + throw new IllegalArgumentException(); + } + this.validate = validate.booleanValue(); } - - /** - * Resolves the input string as follows. - * + First, the string is interpreted as a file description. - * If the file exists, then the file name is turned into - * a URL. - * + Otherwise, the string is supposed to be a URL. If it - * is an invalid URL, an IllegalArgumentException is thrown. - */ - protected URL resolveURL(String url){ - // Is url a file? - File f = (new File(url)).getAbsoluteFile(); - if(f.getParentFile().exists()){ - try{ - return f.toURL(); - }catch(MalformedURLException e){ - throw new IllegalArgumentException(); - } - } - - // url is not a file. It must be a regular URL... - try{ - return new URL(url); - }catch(MalformedURLException e){ - throw new IllegalArgumentException(url); - } + + public boolean getValidating(){ + return validate; } /** @@ -364,52 +139,6 @@ } /** - * Sets the File where the variation from the reference image should be - * stored - */ - public void setSaveVariation(File saveVariation){ - this.saveVariation = saveVariation; - } - - public File getSaveVariation(){ - return saveVariation; - } - - public String getVariationURL(){ - return variationURL.toString(); - } - - /** - * Sets the URL where an acceptable variation fron the reference - * image can be found. - */ - public void setVariationURL(String variationURL){ - this.variationURL = resolveURL(variationURL); - } - - /** - * See [EMAIL PROTECTED] #candidateReference} - */ - public void setCandidateReference(File candidateReference){ - this.candidateReference = candidateReference; - } - - public File getCandidateReference(){ - return candidateReference; - } - - /** - * Returns this <tt>Test</tt>'s name. The name is the - * URL of the SVG being rendered. - */ - public String getName(){ - if(this.name == null){ - return svgURL.toString(); - } - return name; - } - - /** * Template method which subclasses can override if they * need to manipulate the DOM in some way before running * the accuracy test. For example, this can be useful to @@ -419,528 +148,49 @@ return doc; } - - - /** - * Requests this <tt>Test</tt> to run and produce a - * report. - * - */ - public TestReport run(){ - DefaultTestReport report - = new DefaultTestReport(this); - - // - // First, do clean-up - // - if (candidateReference != null){ - if (candidateReference.exists()){ - candidateReference.delete(); - } - } - - - // - // Render the SVG image into a raster. We use the - // ImageTranscoder to convert the SVG into a raster in - // a temporary file. - // - File tmpFile = null; - - try{ - if (candidateReference != null) - tmpFile = candidateReference; - else - tmpFile = File.createTempFile(TEMP_FILE_PREFIX, - TEMP_FILE_SUFFIX, - null); - }catch(IOException e){ - report.setErrorCode(ERROR_CANNOT_CREATE_TEMP_FILE); - report.setDescription(new TestReport.Entry[] { - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_CANNOT_CREATE_TEMP_FILE, - new Object[]{e.getMessage()})) - }); - report.setPassed(false); - return report; - } - - - FileOutputStream tmpFileOS = null; - - try{ - tmpFileOS = new FileOutputStream(tmpFile); - }catch(IOException e){ - report.setErrorCode(ERROR_CANNOT_CREATE_TEMP_FILE_STREAM); - report.setDescription(new TestReport.Entry[] { - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_CANNOT_CREATE_TEMP_FILE_STREAM, - new String[]{tmpFile.getAbsolutePath(), - e.getMessage()})) }); - report.setPassed(false); - tmpFile.deleteOnExit(); - return report; - } - - ImageTranscoder transcoder = getTestImageTranscoder(); - TranscoderInput src = new TranscoderInput(svgURL.toString()); - TranscoderOutput dst = new TranscoderOutput(tmpFileOS); - + + public TestReport encode(URL srcURL, FileOutputStream fos) { + DefaultTestReport report = new DefaultTestReport(this); try{ + ImageTranscoder transcoder = getTestImageTranscoder(); + TranscoderInput src = new TranscoderInput(svgURL.toString()); + TranscoderOutput dst = new TranscoderOutput(fos); transcoder.transcode(src, dst); + return null; }catch(TranscoderException e){ StringWriter trace = new StringWriter(); e.printStackTrace(new PrintWriter(trace)); report.setErrorCode(ERROR_CANNOT_TRANSCODE_SVG); report.setDescription(new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_CANNOT_TRANSCODE_SVG, - new String[]{svgURL.toString(), - e.getClass().getName(), - e.getMessage(), - trace.toString() - })) }); - report.setPassed(false); - tmpFile.deleteOnExit(); - return report; + new TestReport.Entry + (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), + Messages.formatMessage(ERROR_CANNOT_TRANSCODE_SVG, + new String[]{svgURL.toString(), + e.getClass().getName(), + e.getMessage(), + trace.toString() + })) }); }catch(Exception e){ StringWriter trace = new StringWriter(); e.printStackTrace(new PrintWriter(trace)); report.setErrorCode(ERROR_CANNOT_TRANSCODE_SVG); report.setDescription(new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_CANNOT_TRANSCODE_SVG, - new String[]{svgURL.toString(), - e.getClass().getName(), - e.getMessage(), - trace.toString() - })) }); - report.setPassed(false); - tmpFile.deleteOnExit(); - return report; - } - - // - // Do a binary comparison of the encoded images. - // - InputStream refStream = null; - InputStream newStream = null; - try { - refStream = - new BufferedInputStream(refImgURL.openStream()); - }catch(IOException e){ - report.setErrorCode(ERROR_CANNOT_OPEN_REFERENCE_IMAGE); - report.setDescription( new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_CANNOT_OPEN_REFERENCE_IMAGE, - new Object[]{refImgURL.toString(), - e.getMessage()})) }); - report.setPassed(false); - // Try and save tmp file as a candidate variation - if (candidateReference == null){ - tmpFile.delete(); - } - return report; - } - - try{ - newStream = - new BufferedInputStream(new FileInputStream(tmpFile)); - }catch(IOException e){ - report.setErrorCode(ERROR_CANNOT_OPEN_GENERATED_IMAGE); - report.setDescription(new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_CANNOT_OPEN_GENERATED_IMAGE, - new Object[]{tmpFile.getAbsolutePath(), - e.getMessage()}))}); - report.setPassed(false); - tmpFile.delete(); - return report; - } - - - boolean accurate = false; - try{ - accurate = compare(refStream, newStream); - } catch(IOException e) { - report.setErrorCode(ERROR_ERROR_WHILE_COMPARING_FILES); - report.setDescription(new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_ERROR_WHILE_COMPARING_FILES, - new Object[]{refImgURL.toString(), - tmpFile.getAbsolutePath(), - e.getMessage()}))}); - report.setPassed(false); - if (candidateReference == null){ - tmpFile.delete(); - } - return report; - } - - - // - // If the files differ here, it means that even the variation does - // not account for the difference return an error - // - if(!accurate){ - try{ - BufferedImage ref = getImage(refImgURL); - BufferedImage gen = getImage(tmpFile); - BufferedImage diff = buildDiffImage(ref, gen); - - // - // If there is an accepted variation, check if it equals the - // computed difference. - // - if(variationURL != null){ - File tmpDiff = imageToFile(diff, IMAGE_TYPE_DIFF); - - InputStream variationURLStream = null; - try{ - variationURLStream = variationURL.openStream(); - }catch(IOException e){ - // Could not open variationURL stream. Just trace that - System.err.println(Messages.formatMessage(COULD_NOT_OPEN_VARIATION_URL, - new Object[]{variationURL.toString()})); - } - - if(variationURLStream != null){ - InputStream refDiffStream = - new BufferedInputStream(variationURLStream); - - InputStream tmpDiffStream = - new BufferedInputStream(new FileInputStream(tmpDiff)); - - if(compare(refDiffStream, tmpDiffStream)){ - // We accept the generated result. - accurate = true; - } - } - } - - if(!accurate){ - System.err.println(">>>>>>>>>>>>>>>>>>>>>> Rendering is not accurate"); - if(saveVariation != null){ - // There is a computed variation different from the - // referenced variation and there is a place where the new - // variation should be saved. - saveImage(diff, saveVariation); - } - - // Build two images: - // a. One with the reference image and the newly generated image - // b. One with the difference between the two images and the set of - // different pixels. - BufferedImage cmp = makeCompareImage(ref, gen); - File cmpFile = imageToFile(cmp, IMAGE_TYPE_COMPARISON); - File diffFile = imageToFile(diff, IMAGE_TYPE_DIFF); - - report.setErrorCode(ERROR_SVG_RENDERING_NOT_ACCURATE); - - report.setDescription(new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_SVG_RENDERING_NOT_ACCURATE, null)), - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_REFERENCE_GENERATED_IMAGE_URI, null), - cmpFile), - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_DIFFERENCE_IMAGE, null), - diffFile) }); - - if (candidateReference == null){ - tmpFile.delete(); - } - - report.setPassed(false); - return report; - } - }catch(Exception e){ - report.setErrorCode(ERROR_SVG_RENDERING_NOT_ACCURATE); - StringWriter trace = new StringWriter(); - e.printStackTrace(new PrintWriter(trace)); - - report.setDescription(new TestReport.Entry[]{ - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), - Messages.formatMessage(ERROR_SVG_RENDERING_NOT_ACCURATE, null)), - new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_INTERNAL_ERROR, null), - Messages.formatMessage(COULD_NOT_GENERATE_COMPARISON_IMAGES, - new Object[]{e.getClass().getName(), - e.getMessage(), - trace.toString()})) }); - - if (candidateReference == null){ - tmpFile.delete(); - } - - report.setPassed(false); - return report; - } + new TestReport.Entry + (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), + Messages.formatMessage(ERROR_CANNOT_TRANSCODE_SVG, + new String[]{svgURL.toString(), + e.getClass().getName(), + e.getMessage(), + trace.toString() + })) }); } - - - // - // Yahooooooo! everything worked out well. - // - report.setPassed(true); - tmpFile.delete(); + report.setPassed(false); return report; } /** - * Compare the two input streams - */ - protected boolean compare(InputStream refStream, - InputStream newStream) - throws IOException{ - int b, nb; - boolean accurate; - do { - b = refStream.read(); - nb = newStream.read(); - } while (b != -1 && nb != -1 && b == nb); - refStream.close(); - newStream.close(); - return (b == nb); - } - - /** - * Saves an image in a given File - */ - protected void saveImage(BufferedImage img, File imgFile) - throws IOException { - if(!imgFile.exists()){ - imgFile.createNewFile(); - } - - PNGImageEncoder encoder - = new PNGImageEncoder(new FileOutputStream(imgFile), - PNGEncodeParam.getDefaultEncodeParam(img)); - - encoder.encode(img); - } - - /** - * Builds a new BufferedImage that is the difference between the two input images - */ - public static BufferedImage buildDiffImage(BufferedImage ref, - BufferedImage gen){ - BufferedImage diff = new BufferedImage(ref.getWidth(), - ref.getHeight(), - BufferedImage.TYPE_INT_ARGB); - WritableRaster refWR = ref.getRaster(); - WritableRaster genWR = gen.getRaster(); - WritableRaster dstWR = diff.getRaster(); - - boolean refPre = ref.isAlphaPremultiplied(); - if (!refPre) { - ColorModel cm = ref.getColorModel(); - cm = GraphicsUtil.coerceData(refWR, cm, true); - ref = new BufferedImage(cm, refWR, true, null); - } - boolean genPre = gen.isAlphaPremultiplied(); - if (!genPre) { - ColorModel cm = gen.getColorModel(); - cm = GraphicsUtil.coerceData(genWR, cm, true); - gen = new BufferedImage(cm, genWR, true, null); - } - - - int w=ref.getWidth(); - int h=ref.getHeight(); - int nb = ref.getSampleModel().getNumBands(); - - int y, i,val; - int [] refPix = null; - int [] genPix = null; - for (y=0; y<h; y++) { - refPix = refWR.getPixels (0, y, w, 1, refPix); - genPix = genWR.getPixels (0, y, w, 1, genPix); - for (i=0; i<refPix.length; i++) { - val = ((genPix[i]-refPix[i])*10)+128; - if ((val & 0xFFFFFF00) != 0) - if ((val & 0x80000000) != 0) val = 0; - else val = 255; - genPix[i] = val; - } - dstWR.setPixels(0, y, w, 1, genPix); - } - - if (!genPre) { - ColorModel cm = gen.getColorModel(); - cm = GraphicsUtil.coerceData(genWR, cm, false); - } - - if (!refPre) { - ColorModel cm = ref.getColorModel(); - cm = GraphicsUtil.coerceData(refWR, cm, false); - } - - return diff; - } - - /** - * Loads an image from a File - */ - protected BufferedImage getImage(File file) - throws Exception { - return getImage(file.toURL()); - } - - /** - * Loads an image from a URL - */ - protected BufferedImage getImage(URL url) - throws IOException { - ImageTagRegistry reg = ImageTagRegistry.getRegistry(); - Filter filt = reg.readURL(new ParsedURL(url)); - if(filt == null) - throw new IOException(Messages.formatMessage - (COULD_NOT_LOAD_IMAGE, - new Object[]{url.toString()})); - - RenderedImage red = filt.createDefaultRendering(); - if(red == null) - throw new IOException(Messages.formatMessage - (COULD_NOT_LOAD_IMAGE, - new Object[]{url.toString()})); - - BufferedImage img = new BufferedImage(red.getWidth(), - red.getHeight(), - BufferedImage.TYPE_INT_ARGB); - red.copyData(img.getRaster()); - - return img; - } - - /** - * - */ - protected BufferedImage makeCompareImage(BufferedImage ref, - BufferedImage gen){ - BufferedImage cmp = new BufferedImage(ref.getWidth()*2, - ref.getHeight(), - BufferedImage.TYPE_INT_ARGB); - - Graphics2D g = cmp.createGraphics(); - g.setPaint(Color.white); - g.fillRect(0, 0, cmp.getWidth(), cmp.getHeight()); - g.drawImage(ref, 0, 0, null); - g.translate(ref.getWidth(), 0); - g.drawImage(gen, 0, 0, null); - g.dispose(); - - return cmp; - } - - /** - * Creates a File into which the input image is - * saved. - * If there is a "file" component in the SVG url, - * then a temporary file is created with that - * name and the imageType suffix in the temp - * directory of the test-reports directory. - */ - protected File imageToFile(BufferedImage img, - String imageType) - throws IOException { - String file = getURLFile(svgURL); - - File imageFile = null; - if( !"".equals(file) ){ - imageFile = makeTempFileName(file, imageType); - } - else{ - imageFile = makeRandomFileName(imageType); - } - - imageFile.deleteOnExit(); - - PNGImageEncoder encoder - = new PNGImageEncoder(new FileOutputStream(imageFile), - PNGEncodeParam.getDefaultEncodeParam(img)); - - encoder.encode(img); - - return imageFile; - - } - - /** - * Extracts the file portion of the URL - */ - protected String getURLFile(URL url){ - String path = url.getPath(); - int n = path.lastIndexOf('/'); - if(n == -1){ - return path; - } - else{ - if(n<path.length()){ - return path.substring(n+1, path.length()); - } - else{ - return ""; - } - } - } - - protected File makeTempFileName(String svgFileName, - String imageType){ - int dotIndex = svgFileName.lastIndexOf('.'); - if( dotIndex == -1){ - return getNextTempFileName(svgFileName + imageType); - } - else{ - return getNextTempFileName - (svgFileName.substring(0, dotIndex) + - imageType + IMAGE_FILE_EXTENSION); - } - } - - protected File getNextTempFileName(String fileName){ - File f = new File(getTempDirectory(), fileName); - if(!f.exists()){ - return f; - } - else{ - return getNextTempFileName(fileName, - 1); - } - } - - protected File getNextTempFileName(String fileName, - int instance){ - // First, create a 'versioned' file name - int n = fileName.lastIndexOf('.'); - String iFileName = fileName + instance; - if(n != -1){ - iFileName = fileName.substring(0, n) + instance - + fileName.substring(n, fileName.length()); - } - - File r = new File(getTempDirectory(), iFileName); - if(!r.exists()){ - return r; - } - else{ - return getNextTempFileName(fileName, - instance + 1); - } - } - - /** - * Creates a temporary File into which the input image is - * saved. - */ - protected File makeRandomFileName(String imageType) - throws IOException { - - return File.createTempFile(TEMP_FILE_PREFIX, - TEMP_FILE_SUFFIX + imageType, - null); - } - - /** * Returns the <tt>ImageTranscoder</tt> the Test should * use */ @@ -965,20 +215,6 @@ userLanguage); } return t; - } - - /** - * If true, this test will use validation - */ - public void setValidating(Boolean validate){ - if (validate == null){ - throw new IllegalArgumentException(); - } - this.validate = validate.booleanValue(); - } - - public boolean getValidating(){ - return validate; } /** 1.1 xml-batik/test-sources/org/apache/batik/test/svg/AbstractRenderingAccuracyTest.java Index: AbstractRenderingAccuracyTest.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.test.svg; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.IOException; import java.io.StringWriter; import java.io.PrintWriter; import java.net.URL; import java.net.MalformedURLException; import java.util.Locale; import java.util.ResourceBundle; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.awt.image.ColorModel; import org.apache.batik.ext.awt.image.GraphicsUtil; import org.apache.batik.ext.awt.image.spi.ImageTagRegistry; import org.apache.batik.ext.awt.image.renderable.Filter; import org.apache.batik.ext.awt.image.codec.PNGImageEncoder; import org.apache.batik.ext.awt.image.codec.PNGEncodeParam; import org.apache.batik.util.ParsedURL; import org.apache.batik.test.AbstractTest; import org.apache.batik.test.DefaultTestReport; import org.apache.batik.test.TestReport; /** * Checks for regressions in rendering a specific SVG document. * The <tt>Test</tt> will rasterize and SVG document and * compare it to a reference image. The test passes if the * rasterized SVG and the reference image match exactly (i.e., * all pixel values are the same). * * @author <a href="mailto:[EMAIL PROTECTED]">Vincent Hardy</a> * @version $Id: AbstractRenderingAccuracyTest.java,v 1.1 2003/07/01 09:34:17 deweese Exp $ */ public abstract class AbstractRenderingAccuracyTest extends AbstractTest { /** * Error when temp file cannot be created * {0} = IOException message */ public static final String ERROR_CANNOT_CREATE_TEMP_FILE = "SVGRenderingAccuracyTest.error.cannot.create.temp.file"; /** * Error when temp file stream cannot be created * {0} = temp file's cannonical path * {1} = IOException message */ public static final String ERROR_CANNOT_CREATE_TEMP_FILE_STREAM = "SVGRenderingAccuracyTest.error.cannot.create.temp.file.stream"; /** * Error when the reference image cannot be opened * {0} = URI of the reference image * {1} = IOException message */ public static final String ERROR_CANNOT_OPEN_REFERENCE_IMAGE = "SVGRenderingAccuracyTest.error.cannot.open.reference.image"; /** * Error when the generated image cannot be read * {0} = Cannonical path of the temp generated image * {1} = IOException message */ public static final String ERROR_CANNOT_OPEN_GENERATED_IMAGE = "SVGRenderingAccuracyTest.error.cannot.open.genereted.image"; /** * Error when there is an IOException while comparing the * two reference raster image with the new raster image built * from the SVG. * {0} = URI of the reference image * {1} = Connical path for the temp generated image * {2} = IOException message. */ public static final String ERROR_ERROR_WHILE_COMPARING_FILES = "SVGRenderingAccuracyTest.error.while.comparing.files"; /** * Error when the generated image from the SVG file differs from * the reference image. */ public static final String ERROR_SVG_RENDERING_NOT_ACCURATE = "SVGRenderingAccuracyTest.error.svg.rendering.not.accurate"; /** * Entry describing the error */ public static final String ENTRY_KEY_ERROR_DESCRIPTION = "SVGRenderingAccuracyTest.entry.key.error.description"; /** * Entry describing the reference/generated image file */ public static final String ENTRY_KEY_REFERENCE_GENERATED_IMAGE_URI = "SVGRenderingAccuracyTest.entry.key.reference.generated.image.file"; /** * Entry describing the generated difference image */ public static final String ENTRY_KEY_DIFFERENCE_IMAGE = "SVGRenderingAccuracyTest.entry.key.difference.image"; /** * Entry describing that an internal error occured while * generating the test failure description */ public static final String ENTRY_KEY_INTERNAL_ERROR = "SVGRenderingAccuracyTest.entry.key.internal.error"; /** * Messages expressing that comparison images could not be * created: * {0} : exception class * {1} : exception message * {2} : exception stack trace. */ public static final String COULD_NOT_GENERATE_COMPARISON_IMAGES = "SVGRenderingAccuracyTest.message.error.could.not.generate.comparison.images"; /** * Messages expressing that an image could not be loaded. * {0} : URL for the reference image. */ public static final String COULD_NOT_LOAD_IMAGE = "SVGRenderingAccuracyTest.message.error.could.not.load.image"; /** * Message expressing that the variation URL could not be open * {0} : URL */ public static final String COULD_NOT_OPEN_VARIATION_URL = "SVGRenderingAccuracyTest.message.warning.could.not.open.variation.url"; /** * The gui resources file name */ public final static String CONFIGURATION_RESOURCES = "org.apache.batik.test.svg.resources.Configuration"; /** * Suffix used for comparison images */ public final static String IMAGE_TYPE_COMPARISON = "_cmp"; /** * Suffix used for diff images */ public final static String IMAGE_TYPE_DIFF = "_diff"; /** * Suffix used for saved images (e.g., comparison and diff images) */ public final static String IMAGE_FILE_EXTENSION = ".png"; /** * The configuration resource bundle */ protected static ResourceBundle configuration; static { configuration = ResourceBundle.getBundle(CONFIGURATION_RESOURCES, Locale.getDefault()); } /** * Prefix for the temporary files created by Tests * of this class */ public static final String TEMP_FILE_PREFIX = configuration.getString("temp.file.prefix"); /** * Suffix for the temporary files created by * Tests of this class */ public static final String TEMP_FILE_SUFFIX = configuration.getString("temp.file.suffix"); /** * The URL where the SVG can be found. */ protected URL svgURL; /** * The URL for the reference image */ protected URL refImgURL; /** * The URL of a file containing an 'accepted' * variation from the reference image. */ protected URL variationURL; /** * The File where the newly computed variation * should be saved if different from the * variationURL */ protected File saveVariation; /** * The File where the candidate reference * should be saved if there is not candidate reference * or if it cannot be opened. */ protected File candidateReference; /** * Temporary directory */ protected static File tempDirectory; /** * Returns the temporary directory */ public static File getTempDirectory(){ if(tempDirectory == null){ String tmpDir = System.getProperty("java.io.tmpdir"); if(tmpDir == null){ throw new Error(); } tempDirectory = new File(tmpDir); if(!tempDirectory.exists()){ throw new Error(); } } return tempDirectory; } /** * Constructor. * @param svgURL the URL String for the SVG document being tested. * @param refImgURL the URL for the reference image. */ public AbstractRenderingAccuracyTest(String svgURL, String refImgURL){ setConfig(svgURL, refImgURL); } /** * For subclasses */ protected AbstractRenderingAccuracyTest(){ } /** * Sets this test's config. */ public void setConfig(String svgURL, String refImgURL){ if(svgURL == null){ throw new IllegalArgumentException(); } if(refImgURL == null){ throw new IllegalArgumentException(); } this.svgURL = resolveURL(svgURL); this.refImgURL = resolveURL(refImgURL); } /** * Resolves the input string as follows. * + First, the string is interpreted as a file description. * If the file exists, then the file name is turned into * a URL. * + Otherwise, the string is supposed to be a URL. If it * is an invalid URL, an IllegalArgumentException is thrown. */ protected URL resolveURL(String url){ // Is url a file? File f = (new File(url)).getAbsoluteFile(); if(f.getParentFile().exists()){ try{ return f.toURL(); }catch(MalformedURLException e){ throw new IllegalArgumentException(); } } // url is not a file. It must be a regular URL... try{ return new URL(url); }catch(MalformedURLException e){ throw new IllegalArgumentException(url); } } /** * Sets the File where the variation from the reference image should be * stored */ public void setSaveVariation(File saveVariation){ this.saveVariation = saveVariation; } public File getSaveVariation(){ return saveVariation; } public String getVariationURL(){ return variationURL.toString(); } /** * Sets the URL where an acceptable variation fron the reference * image can be found. */ public void setVariationURL(String variationURL){ this.variationURL = resolveURL(variationURL); } /** * See [EMAIL PROTECTED] #candidateReference} */ public void setCandidateReference(File candidateReference){ this.candidateReference = candidateReference; } public File getCandidateReference(){ return candidateReference; } /** * Returns this <tt>Test</tt>'s name. The name is the * URL of the SVG being rendered. */ public String getName(){ if(this.name == null){ return svgURL.toString(); } return name; } /** * Requests this <tt>Test</tt> to run and produce a * report. * */ public TestReport run() { DefaultTestReport report = new DefaultTestReport(this); // // First, do clean-up // if (candidateReference != null){ if (candidateReference.exists()){ candidateReference.delete(); } } // // Render the SVG image into a raster. We call an // abstract method to convert the src into a raster in // a temporary file. File tmpFile = null; try{ if (candidateReference != null) tmpFile = candidateReference; else tmpFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX, null); }catch(IOException e){ report.setErrorCode(ERROR_CANNOT_CREATE_TEMP_FILE); report.setDescription(new TestReport.Entry[] { new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_CANNOT_CREATE_TEMP_FILE, new Object[]{e.getMessage()})) }); report.setPassed(false); return report; } FileOutputStream tmpFileOS = null; try{ tmpFileOS = new FileOutputStream(tmpFile); }catch(IOException e){ report.setErrorCode(ERROR_CANNOT_CREATE_TEMP_FILE_STREAM); report.setDescription(new TestReport.Entry[] { new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_CANNOT_CREATE_TEMP_FILE_STREAM, new String[]{tmpFile.getAbsolutePath(), e.getMessage()})) }); report.setPassed(false); tmpFile.deleteOnExit(); return report; } // Call abstract method to encode svgURL to tmpFileOS as a // raster. If this returns a non-null test report then the // encoding failed and we should return that report. { TestReport encodeTR = encode(svgURL, tmpFileOS); if (encodeTR != null) { tmpFile.deleteOnExit(); return encodeTR; } } // // Do a binary comparison of the encoded images. // InputStream refStream = null; InputStream newStream = null; try { refStream = new BufferedInputStream(refImgURL.openStream()); }catch(IOException e){ report.setErrorCode(ERROR_CANNOT_OPEN_REFERENCE_IMAGE); report.setDescription(new TestReport.Entry[]{ new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_CANNOT_OPEN_REFERENCE_IMAGE, new Object[]{refImgURL.toString(), e.getMessage()})) }); report.setPassed(false); // Try and save tmp file as a candidate variation if (candidateReference == null){ tmpFile.delete(); } return report; } try{ newStream = new BufferedInputStream(new FileInputStream(tmpFile)); }catch(IOException e){ report.setErrorCode(ERROR_CANNOT_OPEN_GENERATED_IMAGE); report.setDescription(new TestReport.Entry[]{ new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_CANNOT_OPEN_GENERATED_IMAGE, new Object[]{tmpFile.getAbsolutePath(), e.getMessage()}))}); report.setPassed(false); tmpFile.delete(); return report; } boolean accurate = false; try{ accurate = compare(refStream, newStream); } catch(IOException e) { report.setErrorCode(ERROR_ERROR_WHILE_COMPARING_FILES); report.setDescription(new TestReport.Entry[]{ new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_ERROR_WHILE_COMPARING_FILES, new Object[]{refImgURL.toString(), tmpFile.getAbsolutePath(), e.getMessage()}))}); report.setPassed(false); if (candidateReference == null){ tmpFile.delete(); } return report; } if(accurate){ // // Yahooooooo! everything worked out well. // report.setPassed(true); tmpFile.delete(); return report; } // // If the files still differ here, it means that even the // variation does not account for the difference return an // error // try { BufferedImage ref = getImage(refImgURL); BufferedImage gen = getImage(tmpFile); BufferedImage diff = buildDiffImage(ref, gen); // // If there is an accepted variation, check if it equals the // computed difference. // if(variationURL != null) { File tmpDiff = imageToFile(diff, IMAGE_TYPE_DIFF); InputStream variationURLStream = null; try{ variationURLStream = variationURL.openStream(); }catch(IOException e){ // Could not open variationURL stream. Just trace that System.err.println(Messages.formatMessage(COULD_NOT_OPEN_VARIATION_URL, new Object[]{variationURL.toString()})); } if(variationURLStream != null){ InputStream refDiffStream = new BufferedInputStream(variationURLStream); InputStream tmpDiffStream = new BufferedInputStream(new FileInputStream(tmpDiff)); if(compare(refDiffStream, tmpDiffStream)){ // We accept the generated result. accurate = true; } } } if (accurate) { // // Yahooooooo! everything worked out well, at least // with variation. report.setPassed(true); tmpFile.delete(); return report; } System.err.println(">>>>>>>>>>>>>>>>>>>>>> "+ "Rendering is not accurate"); if(saveVariation != null){ // There is a computed variation different from the // referenced variation and there is a place where the new // variation should be saved. saveImage(diff, saveVariation); } // Build two images: // a. One with the reference image and the newly generated image // b. One with the difference between the two images and the set // of different pixels. BufferedImage cmp = makeCompareImage(ref, gen); File cmpFile = imageToFile(cmp, IMAGE_TYPE_COMPARISON); File diffFile = imageToFile(diff, IMAGE_TYPE_DIFF); report.setErrorCode(ERROR_SVG_RENDERING_NOT_ACCURATE); report.setDescription(new TestReport.Entry[]{ new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_SVG_RENDERING_NOT_ACCURATE, null)), new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_REFERENCE_GENERATED_IMAGE_URI, null), cmpFile), new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_DIFFERENCE_IMAGE, null), diffFile) }); }catch(Exception e){ report.setErrorCode(ERROR_SVG_RENDERING_NOT_ACCURATE); StringWriter trace = new StringWriter(); e.printStackTrace(new PrintWriter(trace)); report.setDescription(new TestReport.Entry[]{ new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_ERROR_DESCRIPTION, null), Messages.formatMessage(ERROR_SVG_RENDERING_NOT_ACCURATE, null)), new TestReport.Entry (Messages.formatMessage(ENTRY_KEY_INTERNAL_ERROR, null), Messages.formatMessage(COULD_NOT_GENERATE_COMPARISON_IMAGES, new Object[]{e.getClass().getName(), e.getMessage(), trace.toString()})) }); } if (candidateReference == null){ tmpFile.delete(); } report.setPassed(false); return report; } public abstract TestReport encode(URL srcURL, FileOutputStream fos); /** * Compare the two input streams */ protected boolean compare(InputStream refStream, InputStream newStream) throws IOException{ int b, nb; boolean accurate; do { b = refStream.read(); nb = newStream.read(); } while (b != -1 && nb != -1 && b == nb); refStream.close(); newStream.close(); return (b == nb); } /** * Saves an image in a given File */ protected void saveImage(BufferedImage img, File imgFile) throws IOException { if(!imgFile.exists()){ imgFile.createNewFile(); } PNGImageEncoder encoder = new PNGImageEncoder (new FileOutputStream(imgFile), PNGEncodeParam.getDefaultEncodeParam(img)); encoder.encode(img); } /** * Builds a new BufferedImage that is the difference between the * two input images */ public static BufferedImage buildDiffImage(BufferedImage ref, BufferedImage gen) { BufferedImage diff = new BufferedImage(ref.getWidth(), ref.getHeight(), BufferedImage.TYPE_INT_ARGB); WritableRaster refWR = ref.getRaster(); WritableRaster genWR = gen.getRaster(); WritableRaster dstWR = diff.getRaster(); boolean refPre = ref.isAlphaPremultiplied(); if (!refPre) { ColorModel cm = ref.getColorModel(); cm = GraphicsUtil.coerceData(refWR, cm, true); ref = new BufferedImage(cm, refWR, true, null); } boolean genPre = gen.isAlphaPremultiplied(); if (!genPre) { ColorModel cm = gen.getColorModel(); cm = GraphicsUtil.coerceData(genWR, cm, true); gen = new BufferedImage(cm, genWR, true, null); } int w=ref.getWidth(); int h=ref.getHeight(); int nb = ref.getSampleModel().getNumBands(); int y, i,val; int [] refPix = null; int [] genPix = null; for (y=0; y<h; y++) { refPix = refWR.getPixels (0, y, w, 1, refPix); genPix = genWR.getPixels (0, y, w, 1, genPix); for (i=0; i<refPix.length; i++) { val = ((genPix[i]-refPix[i])*10)+128; if ((val & 0xFFFFFF00) != 0) if ((val & 0x80000000) != 0) val = 0; else val = 255; genPix[i] = val; } dstWR.setPixels(0, y, w, 1, genPix); } if (!genPre) { ColorModel cm = gen.getColorModel(); cm = GraphicsUtil.coerceData(genWR, cm, false); } if (!refPre) { ColorModel cm = ref.getColorModel(); cm = GraphicsUtil.coerceData(refWR, cm, false); } return diff; } /** * Loads an image from a File */ protected BufferedImage getImage(File file) throws Exception { return getImage(file.toURL()); } /** * Loads an image from a URL */ protected BufferedImage getImage(URL url) throws IOException { ImageTagRegistry reg = ImageTagRegistry.getRegistry(); Filter filt = reg.readURL(new ParsedURL(url)); if(filt == null) throw new IOException(Messages.formatMessage (COULD_NOT_LOAD_IMAGE, new Object[]{url.toString()})); RenderedImage red = filt.createDefaultRendering(); if(red == null) throw new IOException(Messages.formatMessage (COULD_NOT_LOAD_IMAGE, new Object[]{url.toString()})); BufferedImage img = new BufferedImage(red.getWidth(), red.getHeight(), BufferedImage.TYPE_INT_ARGB); red.copyData(img.getRaster()); return img; } /** * */ protected BufferedImage makeCompareImage(BufferedImage ref, BufferedImage gen){ BufferedImage cmp = new BufferedImage(ref.getWidth()*2, ref.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g = cmp.createGraphics(); g.setPaint(Color.white); g.fillRect(0, 0, cmp.getWidth(), cmp.getHeight()); g.drawImage(ref, 0, 0, null); g.translate(ref.getWidth(), 0); g.drawImage(gen, 0, 0, null); g.dispose(); return cmp; } /** * Creates a File into which the input image is * saved. * If there is a "file" component in the SVG url, * then a temporary file is created with that * name and the imageType suffix in the temp * directory of the test-reports directory. */ protected File imageToFile(BufferedImage img, String imageType) throws IOException { String file = getURLFile(svgURL); File imageFile = null; if( !"".equals(file) ){ imageFile = makeTempFileName(file, imageType); } else{ imageFile = makeRandomFileName(imageType); } imageFile.deleteOnExit(); PNGImageEncoder encoder = new PNGImageEncoder (new FileOutputStream(imageFile), PNGEncodeParam.getDefaultEncodeParam(img)); encoder.encode(img); return imageFile; } /** * Extracts the file portion of the URL */ protected String getURLFile(URL url){ String path = url.getPath(); int n = path.lastIndexOf('/'); if(n == -1){ return path; } else{ if(n<path.length()){ return path.substring(n+1, path.length()); } else{ return ""; } } } protected File makeTempFileName(String svgFileName, String imageType){ int dotIndex = svgFileName.lastIndexOf('.'); if( dotIndex == -1){ return getNextTempFileName(svgFileName + imageType); } else{ return getNextTempFileName (svgFileName.substring(0, dotIndex) + imageType + IMAGE_FILE_EXTENSION); } } protected File getNextTempFileName(String fileName){ File f = new File(getTempDirectory(), fileName); if(!f.exists()){ return f; } else{ return getNextTempFileName(fileName, 1); } } protected File getNextTempFileName(String fileName, int instance){ // First, create a 'versioned' file name int n = fileName.lastIndexOf('.'); String iFileName = fileName + instance; if(n != -1){ iFileName = fileName.substring(0, n) + instance + fileName.substring(n, fileName.length()); } File r = new File(getTempDirectory(), iFileName); if(!r.exists()){ return r; } else{ return getNextTempFileName(fileName, instance + 1); } } /** * Creates a temporary File into which the input image is * saved. */ protected File makeRandomFileName(String imageType) throws IOException { return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX + imageType, null); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]