| /****************************************************************************** |
| * Copyright (c) 2003, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| ****************************************************************************/ |
| |
| package org.eclipse.gmf.tests.runtime.draw2d.ui.render.internal.svg; |
| |
| import java.awt.image.BufferedImage; |
| import java.io.ByteArrayInputStream; |
| import java.io.InputStream; |
| import java.net.URL; |
| |
| import junit.framework.TestCase; |
| |
| import org.apache.batik.transcoder.TranscoderException; |
| import org.apache.batik.transcoder.TranscoderInput; |
| import org.apache.batik.transcoder.TranscoderOutput; |
| import org.eclipse.core.runtime.FileLocator; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.SWTGraphics; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.RenderInfo; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.RenderedImage; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.image.ImageConverter; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.ImageTranscoderEx; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg.SVGImage; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.factory.RenderedImageFactory; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.internal.RenderHelper; |
| import org.eclipse.gmf.runtime.draw2d.ui.render.internal.RenderingListener; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.PlatformUI; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * @author sshaw |
| * |
| * To change the template for this generated type comment go to |
| * Window>Preferences>Java>Code Generation>Code and Comments |
| */ |
| public class SVGImageTest |
| extends TestCase { |
| |
| /** |
| * The icons root directory. |
| */ |
| private static final String PREFIX_ROOT = "resources/svg/"; //$NON-NLS-1$ |
| |
| private static final String SVG_BLACKWHITE = PREFIX_ROOT + "blackwhite.svg"; //$NON-NLS-1$ |
| private static final String SVG_SHAPES = PREFIX_ROOT + "shapes.svg";//$NON-NLS-1$ |
| private static final String SVG_UMLSHAPES = PREFIX_ROOT + "uml.svg";//$NON-NLS-1$ |
| private static final String SVG_TRANSPARENCY_TEST = PREFIX_ROOT + "presenter.svg";//$NON-NLS-1$ |
| |
| private final int WIDTH = 200; |
| |
| private final int HEIGHT = 200; |
| |
| private final int NEW_WIDTH = 120; |
| |
| private final int NEW_HEIGHT = 140; |
| |
| private final RGB NEW_FILL = new RGB(255, 0, 0); |
| |
| private final RGB NEW_OUTLINE = new RGB(0, 255, 0); |
| |
| private RenderedImage fixture1; |
| |
| private RenderedImage fixture2; |
| |
| private RenderedImage fixture3; |
| |
| private RenderedImage fixture4; |
| |
| public SVGImageTest(String name) { |
| super(name); |
| } |
| |
| private RenderedImage getFixture1() { |
| return fixture1; |
| } |
| |
| private RenderedImage getFixture2() { |
| return fixture2; |
| } |
| |
| private RenderedImage getFixture3() { |
| return fixture3; |
| } |
| |
| private RenderedImage getFixture4() { |
| return fixture4; |
| } |
| |
| protected void setUp() { |
| try { |
| |
| // Initialize the path the the resources. |
| Bundle bundle = Platform.getBundle("org.eclipse.gmf.tests.runtime.draw2d.ui.render" ); //$NON-NLS-1$ |
| |
| URL url = FileLocator.find(bundle, new Path(SVG_UMLSHAPES), null); |
| fixture1 = RenderedImageFactory.getInstance(url); |
| |
| assertNotNull("Fixture1 shouldn't be null", fixture1); //$NON-NLS-1$ |
| |
| RenderInfo info = RenderedImageFactory.createInfo(WIDTH, HEIGHT, |
| false, false, (RGB) null, (RGB) null); |
| url = FileLocator.find(bundle, new Path(SVG_SHAPES), null); |
| fixture2 = RenderedImageFactory.getInstance(url, info); |
| assertNotNull("Fixture2 shouldn't be null", fixture2); //$NON-NLS-1$ |
| |
| url = FileLocator.find(bundle, new Path(SVG_BLACKWHITE), null); |
| fixture3 = RenderedImageFactory.getInstance(url); |
| assertNotNull("Fixture3 shouldn't be null", fixture3); //$NON-NLS-1$ |
| |
| url = FileLocator.find(bundle, new Path(SVG_TRANSPARENCY_TEST), null); |
| fixture4 = RenderedImageFactory.getInstance(url); |
| assertNotNull("Fixture3 shouldn't be null", fixture4); //$NON-NLS-1$ |
| |
| } catch (Exception e) { |
| fail("The SVGImageTest.setUp method caught an exception - " + e); //$NON-NLS-1$ |
| } |
| } |
| |
| public void testGetRenderInfo() { |
| |
| RenderInfo info = getFixture1().getRenderInfo(); |
| assertTrue("getRenderInfo fixture 1 return null", info != null); //$NON-NLS-1$ |
| |
| info = getFixture2().getRenderInfo(); |
| assertTrue("getRenderInfo fixture 2 return null", info != null); //$NON-NLS-1$ |
| assertTrue("getRenderInfo fixture 2 width / height not correct", //$NON-NLS-1$ |
| info.getWidth() == WIDTH && info.getHeight() == HEIGHT); |
| } |
| |
| public void testGetNewRenderedImage() { |
| |
| RenderInfo info = RenderedImageFactory.createInfo(NEW_WIDTH, |
| NEW_HEIGHT, true, true, NEW_FILL, NEW_OUTLINE); |
| assertTrue(info != null); |
| info = RenderedImageFactory.createInfo(NEW_WIDTH, NEW_HEIGHT, false, false, null, |
| NEW_OUTLINE); |
| assertTrue(info != null); |
| } |
| |
| private void performBatikRendering(SVGImage svg1, int width, int height) { |
| InputStream in = new ByteArrayInputStream(svg1.getBuffer()); |
| RenderInfo info = svg1.getRenderInfo(); |
| ImageTranscoderEx transcoder = new ImageTranscoderEx(); |
| |
| if (width > 0) |
| transcoder.addTranscodingHint(ImageTranscoderEx.KEY_WIDTH, |
| new Float(width)); |
| if (height > 0) |
| transcoder.addTranscodingHint(ImageTranscoderEx.KEY_HEIGHT, |
| new Float(height)); |
| |
| transcoder.addTranscodingHint( |
| ImageTranscoderEx.KEY_MAINTAIN_ASPECT_RATIO, Boolean.valueOf(info |
| .shouldMaintainAspectRatio())); |
| |
| transcoder.addTranscodingHint(ImageTranscoderEx.KEY_ANTI_ALIASING, |
| Boolean.valueOf(info.shouldAntiAlias())); |
| |
| if (info.getBackgroundColor() != null) { |
| transcoder |
| .addTranscodingHint(ImageTranscoderEx.KEY_FILL_COLOR, new RGB( |
| info.getBackgroundColor().red, |
| info.getBackgroundColor().green, |
| info.getBackgroundColor().blue)); |
| } |
| |
| if (info.getForegroundColor() != null) { |
| transcoder |
| .addTranscodingHint(ImageTranscoderEx.KEY_OUTLINE_COLOR, |
| new RGB(info.getForegroundColor().red, info |
| .getForegroundColor().green, |
| info.getForegroundColor().blue)); |
| } |
| |
| TranscoderInput input = new TranscoderInput(in); |
| TranscoderOutput output = new TranscoderOutput(); |
| |
| try { |
| transcoder.transcode(input, output); |
| } catch (TranscoderException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| |
| BufferedImage bufImg = transcoder.getBufferedImage(); |
| Image swtImage = ImageConverter.convert(bufImg); |
| assertNotNull("swtImage fixture 1 Image invalid", swtImage); //$NON-NLS-1$ |
| } |
| |
| private void performRenderedImageRendering(SVGImage svg1, int width, |
| int height) { |
| RenderInfo info = svg1.getRenderInfo(); |
| |
| info.setValues(width, height, true, true, info.getBackgroundColor(), info |
| .getForegroundColor()); |
| |
| RenderedImage ri = svg1.getNewRenderedImage(info); |
| Image img = ri.getSWTImage(); |
| assertNotNull("getSWTImage fixture 1 Image invalid", img); //$NON-NLS-1$ |
| } |
| |
| final static int START_DIM = 100; |
| |
| final static int END_DIM = 1000; |
| |
| final static int INC_DIM = 10; |
| |
| public void testRenderedImagePerformance() { |
| |
| SVGImage svg1 = (SVGImage) getFixture1(); |
| |
| int width = START_DIM; |
| int height = START_DIM; |
| long batikTime = 0; |
| long renderTime = 0; |
| |
| // do one rendering outside to initialize Batik; |
| performBatikRendering(svg1, width, height); |
| |
| long startTime = System.currentTimeMillis(); |
| |
| while (width < END_DIM && height < END_DIM) { |
| performBatikRendering(svg1, width, height); |
| width += INC_DIM; |
| height += INC_DIM; |
| } |
| |
| long endTime = System.currentTimeMillis(); |
| batikTime = endTime - startTime; |
| |
| startTime = System.currentTimeMillis(); |
| |
| width = START_DIM; |
| height = START_DIM; |
| while (width < END_DIM && height < END_DIM) { |
| performRenderedImageRendering(svg1, width, height); |
| width += INC_DIM; |
| height += INC_DIM; |
| } |
| |
| endTime = System.currentTimeMillis(); |
| renderTime = endTime - startTime; |
| |
| System.out.println("Batik rendering time was: " + batikTime); //$NON-NLS-1$ |
| System.out.println("RenderedImage rendering time was: " + renderTime); //$NON-NLS-1$ |
| System.out |
| .println("Percentage difference: " + (renderTime - batikTime) / (float) batikTime * 100 + "%"); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| assertTrue(renderTime < batikTime); |
| } |
| |
| static private class RenderingListenerImpl |
| implements RenderingListener { |
| |
| boolean done = false; |
| |
| public RenderingListenerImpl() { |
| super(); |
| } |
| |
| boolean isDone() { |
| return done; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.gmf.runtime.draw2d.ui.render.internal.RenderingListener#paintFigureWhileRendering(org.eclipse.draw2d.Graphics) |
| */ |
| public void paintFigureWhileRendering(Graphics g) { |
| // do nothing |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gmf.runtime.draw2d.ui.render.RenderingListener#imageRendered(org.eclipse.gmf.runtime.draw2d.ui.render.RenderedImage) |
| */ |
| synchronized public void imageRendered(RenderedImage rndImg) { |
| done = true; |
| assertTrue(rndImg.isRendered()); |
| assertTrue(rndImg.getSWTImage() != null); |
| } |
| } |
| |
| public void testRenderHelper() { |
| |
| Display display = Display.getDefault(); |
| |
| Image image = new Image(display, new Rectangle(0, 0, 500, 500)); |
| GC gc = new GC(image); |
| SWTGraphics swtG = new SWTGraphics(gc); |
| |
| org.eclipse.draw2d.geometry.Rectangle target = new org.eclipse.draw2d.geometry.Rectangle( |
| 50, 50, 94, 94); |
| RenderInfo info = getFixture1().getRenderInfo(); |
| info.setValues(target.width, target.height, true, true, info.getBackgroundColor(), |
| info.getForegroundColor()); |
| |
| RenderedImage ri = getFixture1().getNewRenderedImage(info); |
| |
| // first test with delay render turned off |
| RenderHelper renderHelper = RenderHelper.getInstance(1.0, false, false, |
| null); |
| RenderingListenerImpl listener = new RenderingListenerImpl(); |
| RenderedImage retImage = renderHelper.drawRenderedImage(swtG, ri, |
| target, listener); |
| assertTrue(retImage.isRendered()); |
| assertTrue(retImage.getSWTImage() != null); |
| |
| // second test with delay render turned on |
| target.width -= 10; |
| target.height -= 10; |
| listener = new RenderingListenerImpl(); |
| renderHelper = RenderHelper.getInstance(1.0, false, true, null); |
| |
| retImage = renderHelper.drawRenderedImage(swtG, retImage, target, |
| listener); |
| |
| int i = 0; |
| while (!retImage.isRendered() && i < 100) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| |
| i++; |
| } |
| |
| assertTrue(retImage.isRendered() && i < 100); |
| } |
| |
| static final private Dimension MAX_RENDER_SIZE = new Dimension(200, 200); |
| |
| public void testRenderMaxSize() { |
| Display display = PlatformUI.getWorkbench().getDisplay(); |
| |
| Image image = new Image(display, new Rectangle(0, 0, 500, 500)); |
| GC gc = new GC(image); |
| SWTGraphics swtG = new SWTGraphics(gc); |
| |
| org.eclipse.draw2d.geometry.Rectangle target = new org.eclipse.draw2d.geometry.Rectangle( |
| 0, 0, MAX_RENDER_SIZE.width * 2, MAX_RENDER_SIZE.height * 2); |
| RenderInfo info = getFixture1().getRenderInfo(); |
| info.setValues(MAX_RENDER_SIZE.width * 2, MAX_RENDER_SIZE.height * 2, |
| false, true, info.getBackgroundColor(), info.getForegroundColor()); |
| |
| RenderedImage ri = getFixture1().getNewRenderedImage(info); |
| |
| // first test with no maximum render size |
| RenderHelper renderHelper = RenderHelper.getInstance(1.0, false, false, |
| null); |
| RenderingListenerImpl listener = new RenderingListenerImpl(); |
| RenderedImage retImage = renderHelper.drawRenderedImage(swtG, ri, |
| target, listener); |
| assertTrue(retImage.isRendered()); |
| assertTrue(retImage.getSWTImage() != null); |
| assertTrue(Math.abs(retImage.getSWTImage().getBounds().width - (MAX_RENDER_SIZE.width * 2)) <= 5); |
| assertTrue(Math.abs(retImage.getSWTImage().getBounds().height - (MAX_RENDER_SIZE.height * 2)) <=5); |
| |
| // now test with maximum render size |
| renderHelper = RenderHelper.getInstance(1.0, false, false, |
| MAX_RENDER_SIZE); |
| retImage = renderHelper.drawRenderedImage(swtG, ri, |
| target, listener); |
| assertTrue(retImage.isRendered()); |
| assertTrue(retImage.getSWTImage() != null); |
| assertTrue(retImage.getSWTImage().getBounds().width <= MAX_RENDER_SIZE.width); |
| assertTrue(retImage.getSWTImage().getBounds().height <= MAX_RENDER_SIZE.height); |
| } |
| |
| private boolean findColor(Image srcImage, RGB colorToFind) { |
| BufferedImage bufImg = ImageConverter.convert(srcImage); |
| |
| int width = bufImg.getWidth(); |
| int height = bufImg.getHeight(); |
| |
| // loop over the imagedata and set each pixel in the BufferedImage to |
| // the appropriate color. |
| for (int y = 0; y < height; y++) { |
| for (int x = 0; x < width; x++) { |
| int color = bufImg.getRGB(x, y); |
| Color swtColor = integerToColor(color); |
| RGB checkColor = new RGB(swtColor.getRed(), |
| swtColor.getGreen(), swtColor.getBlue()); |
| swtColor.dispose(); |
| if (checkColor.equals(colorToFind)) |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Method integerToColor. converts from an int (from BufferedImage) to a |
| * Color representation |
| * |
| * Note: Normally, colors should be instantiated using the |
| * AbstractResourceManager. |
| * |
| * @param i |
| * @return Color |
| */ |
| private Color integerToColor(int color) { |
| return new Color(null, (color & 0x00FF0000) >> 16, |
| (color & 0x0000FF00) >> 8, (color & 0x000000FF)); |
| } |
| |
| private static RGB BLACK = new RGB(0, 0, 0); |
| |
| private static RGB WHITE = new RGB(255, 255, 255); |
| |
| private static RGB RED = new RGB(255, 0, 0); |
| |
| private static RGB GREEN = new RGB(0, 255, 0); |
| |
| public void testChangeColors() { |
| RenderedImage fixture = getFixture3(); |
| RenderInfo info = fixture.getRenderInfo(); |
| Image swtImg1 = fixture.getSWTImage(); |
| assertTrue(findColor(swtImg1, BLACK)); |
| assertTrue(findColor(swtImg1, WHITE)); |
| assertFalse(findColor(swtImg1, RED)); |
| assertFalse(findColor(swtImg1, GREEN)); |
| |
| // ImageLoader imageLoader = new ImageLoader(); |
| // imageLoader.data = new ImageData[] {swtImg1.getImageData()}; |
| // imageLoader.logicalScreenHeight = swtImg1.getBounds().width; |
| // imageLoader.logicalScreenHeight = swtImg1.getBounds().height; |
| // imageLoader.save("C:\\originalImg.bmp", SWT.IMAGE_BMP); |
| |
| // set color first time - red fill, red outline |
| info.setValues(info.getWidth(), info.getHeight(), true, true, RED, RED); |
| RenderedImage colorImg1 = fixture.getNewRenderedImage(info); |
| Image swtImg2 = colorImg1.getSWTImage(); |
| assertNotNull("getSWTImage colorImg1 Image invalid", swtImg1); //$NON-NLS-1$ |
| |
| // imageLoader = new ImageLoader(); |
| // imageLoader.data = new ImageData[] {swtImg2.getImageData()}; |
| // imageLoader.logicalScreenHeight = swtImg2.getBounds().width; |
| // imageLoader.logicalScreenHeight = swtImg2.getBounds().height; |
| // imageLoader.save("C:\\redImg.bmp", SWT.IMAGE_BMP); |
| |
| assertTrue(findColor(swtImg2, RED)); |
| assertFalse(findColor(swtImg2, GREEN)); |
| |
| // set color second time - green fill, green outline |
| info.setValues(info.getWidth(), info.getHeight(), true, |
| true, GREEN, GREEN); |
| RenderedImage colorImg2 = fixture.getNewRenderedImage(info); |
| Image swtImg3 = colorImg2.getSWTImage(); |
| assertNotNull("getSWTImage colorImg1 Image invalid", swtImg1); //$NON-NLS-1$ |
| assertNotNull("getSWTImage colorImg2 Image invalid", swtImg2); //$NON-NLS-1$ |
| |
| // imageLoader = new ImageLoader(); |
| // imageLoader.data = new ImageData[] {swtImg3.getImageData()}; |
| // imageLoader.logicalScreenHeight = swtImg3.getBounds().width; |
| // imageLoader.logicalScreenHeight = swtImg3.getBounds().height; |
| // imageLoader.save("C:\\greenImg.bmp", SWT.IMAGE_BMP); |
| |
| assertTrue(colorImg1 != colorImg2); |
| assertTrue(findColor(swtImg3, GREEN)); |
| assertFalse(findColor(swtImg3, RED)); |
| } |
| |
| // cropping not supported yet |
| |
| // static final int SHRINK_EXT = 50; |
| // static final int CROPTEST_START_SIZE = 400; |
| // |
| // public void testCroppedImage() { |
| // org.eclipse.draw2d.geometry.Rectangle target = new |
| // org.eclipse.draw2d.geometry.Rectangle(0, 0, CROPTEST_START_SIZE, |
| // CROPTEST_START_SIZE); |
| // RenderInfo info = getFixture1().getRenderInfo(); |
| // info.setValues(target.width, target.height, info.getBackgroundColor(), |
| // info.getForegroundColor(), false, true); |
| // |
| // RenderedImage first = getFixture1().getNewRenderedImage(info); |
| // Image firstImage = first.getSWTImage(); |
| // Rectangle firstBounds = firstImage.getBounds(); |
| // assertTrue(firstBounds.width == CROPTEST_START_SIZE && firstBounds.height |
| // == CROPTEST_START_SIZE); |
| // ImageLoader imageLoader = new ImageLoader(); |
| // imageLoader.data = new ImageData[] {firstImage.getImageData()}; |
| // imageLoader.logicalScreenHeight = firstImage.getBounds().width; |
| // imageLoader.logicalScreenHeight = firstImage.getBounds().height; |
| // imageLoader.save("C:\\originalImg.bmp", SWT.IMAGE_BMP); |
| // |
| // RenderedImage cropped = first.getCroppedImage(target.shrink(SHRINK_EXT, |
| // SHRINK_EXT)); |
| // |
| // Image croppedImage = cropped.getSWTImage(); |
| // Rectangle croppedBounds = croppedImage.getBounds(); |
| // //assertTrue(croppedBounds.width == CROPTEST_START_SIZE - (SHRINK_EXT * |
| // 2) |
| // // && croppedBounds.height == CROPTEST_START_SIZE - (SHRINK_EXT * 2)); |
| // |
| // imageLoader = new ImageLoader(); |
| // imageLoader.data = new ImageData[] {croppedImage.getImageData()}; |
| // imageLoader.logicalScreenHeight = croppedImage.getBounds().width; |
| // imageLoader.logicalScreenHeight = croppedImage.getBounds().height; |
| // imageLoader.save("C:\\croppedImg.bmp", SWT.IMAGE_BMP); |
| // } |
| |
| public void testGetSWTImage() { |
| Image img = getFixture1().getSWTImage(); |
| assertNotNull("getSWTImage fixture 1 Image invalid", img); //$NON-NLS-1$ |
| |
| img = getFixture2().getSWTImage(); |
| assertNotNull("getSWTImage fixture 2 Image invalid", img); //$NON-NLS-1$ |
| } |
| |
| public void testTransparency() { |
| Image img = getFixture4().getSWTImage(); |
| ImageData imgData = img.getImageData(); |
| Rectangle bounds = img.getBounds(); |
| |
| // check 4 corners |
| assertTrue(isTransparentAt(imgData, bounds.x + 1, bounds.y + 1)); |
| assertTrue(isTransparentAt(imgData, bounds.x + bounds.width - 2, bounds.y + 1)); |
| assertTrue(isTransparentAt(imgData, bounds.x + 1, bounds.y + bounds.height - 2)); |
| assertTrue(isTransparentAt(imgData, bounds.x + bounds.width - 2, bounds.y + bounds.height - 2)); |
| } |
| |
| protected boolean isTransparentAt(ImageData data, int x, int y) { |
| // boundary checking |
| if (x < 0 || x >= data.width || y < 0 |
| || y >= data.height) |
| return true; |
| |
| ImageData transMaskData = data.getTransparencyMask(); |
| // check for alpha channel |
| int transValue = 255; |
| // check for transparency mask |
| if (transMaskData != null) { |
| transValue = transMaskData.getPixel(x, y) == 0 ? 0 |
| : 255; |
| } |
| |
| if (transValue != 0) { |
| if (data.alphaData != null) { |
| transValue = data.getAlpha(x, y); |
| } |
| } |
| |
| // use a tolerance |
| boolean trans = false; |
| if (transValue < 10) { |
| trans = true; |
| } |
| |
| return trans; |
| } |
| } |