/*
SVGSalamanderLoader.java
(c) 2011-2016 Edward Swartz
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
*/
package v9t9.video.svg;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.net.URI;
import java.net.URL;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import com.kitfox.svg.SVGCache;
import com.kitfox.svg.SVGDiagram;
import com.kitfox.svg.SVGUniverse;
/**
* This class manages a reference to a loaded SVG document
* and provides SWT Images from it
* @author eswartz
*
*/
public class SVGSalamanderLoader implements ISVGLoader {
private static boolean DEBUG = false;
private URI uri;
private BufferedImage image;
private SVGDiagram diagram;
private Thread loaderThread;
public SVGSalamanderLoader(final URL url) {
loaderThread = new Thread() {
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
@Override
public void run() {
if (DEBUG) System.err.println("*** start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
if (DEBUG) System.err.println("*** loading");
SVGUniverse universe = SVGCache.getSVGUniverse();
URI uri = universe.loadSVG(url);
SVGDiagram diagram = universe.getDiagram(uri);
synchronized (SVGSalamanderLoader.this) {
SVGSalamanderLoader.this.uri = uri;
SVGSalamanderLoader.this.diagram = diagram;
if (DEBUG) System.err.println("*** done");
SVGSalamanderLoader.this.notifyAll();
}
}
};
loaderThread.start();
/*
this.icon = new SVGIcon();
icon.setSvgURI(url.toURI());
icon.setAntiAlias(true);
icon.setInterpolation(SVGIcon.INTERP_BICUBIC);
*/
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final SVGSalamanderLoader other = (SVGSalamanderLoader) obj;
if (uri == null) {
if (other.uri != null)
return false;
} else if (!uri.equals(other.uri))
return false;
return true;
}
/* (non-Javadoc)
* @see v9t9.emulator.clients.builtin.swt.ISVGLoader#isValid()
*/
@Override
public synchronized boolean isValid() {
return loaderThread.isAlive() || diagram != null;
}
/* (non-Javadoc)
* @see v9t9.emulator.clients.builtin.swt.ISVGLoader#isSlow()
*/
@Override
public synchronized boolean isSlow() {
return diagram == null;
}
/* (non-Javadoc)
* @see v9t9.emulator.clients.builtin.swt.ISVGLoader#getImageData(org.eclipse.swt.graphics.Point)
*/
@Override
public BufferedImage getImageData(Point size) throws SVGException {
synchronized (this) {
if (diagram == null)
throw new SVGException("Failed to read SVG image from " + uri, null);
}
try {
java.awt.Rectangle r = getNativeRect();
return load(new Rectangle(r.x, r.y, r.width, r.height), size);
} catch (Exception e) {
throw new SVGException("Failed to read SVG image from " + uri, e);
}
}
/**
* @return
*/
protected java.awt.Rectangle getNativeRect() {
synchronized (this) {
if (diagram == null)
return null;
}
Rectangle2D r = diagram.getViewRect();
return new java.awt.Rectangle((int) r.getMinX(), (int) r.getMinY(),
(int) Math.round(r.getMaxX() - r.getMinX()),
(int) Math.round(r.getMaxY() - r.getMinY()));
}
/* (non-Javadoc)
* @see v9t9.emulator.clients.builtin.swt.ISVGLoader#getImageData(org.eclipse.swt.graphics.Rectangle, org.eclipse.swt.graphics.Point)
*/
@Override
public BufferedImage getImageData(Rectangle aoi, Point size) throws SVGException {
try {
return load(aoi, size);
} catch (Exception e) {
throw new SVGException("Failed to load " + uri, e);
}
}
/* (non-Javadoc)
* @see v9t9.emulator.clients.builtin.swt.ISVGLoader#getSize()
*/
@Override
public Point getSize() {
try {
java.awt.Rectangle r = getNativeRect();
if (r == null)
return null;
return new Point(r.width, r.height);
} catch (Exception e) {
return null;
}
}
private synchronized BufferedImage load(Rectangle aoi, Point size) {
if (size.x == 0 || size.y == 0)
return null;
java.awt.Rectangle r = getNativeRect();
Rectangle scaledAoi = new Rectangle(aoi.x * size.x / r.width,
aoi.y * size.y / r.height,
aoi.width * size.x / r.width,
aoi.height * size.y / r.height);
if (image == null || image.getWidth() != size.x) {
image = new BufferedImage(size.x,
size.y,
BufferedImage.TYPE_4BYTE_ABGR);
diagram.setDeviceViewport(new java.awt.Rectangle(aoi.x, aoi.y, aoi.width, aoi.height));
Graphics2D g = image.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setClip(0, 0, r.width, r.height);
g.scale((double) size.x / r.width,
(double) size.y / r.height);
//icon.setPreferredSize(new Dimension(size.x, size.y));
//icon.setScaleToFit(true);
try {
//System.out.println("rendering...");
diagram.render(g);
} catch (com.kitfox.svg.SVGException e) {
e.printStackTrace();
return null;
}
g.dispose();
}
BufferedImage sub;
if (scaledAoi.width != image.getWidth() || scaledAoi.height != image.getHeight()) {
ColorModel cm = image.getColorModel();
WritableRaster wr = image.getRaster().createCompatibleWritableRaster(
scaledAoi.width, scaledAoi.height);
wr.setRect(-scaledAoi.x, -scaledAoi.y, image.getRaster());
sub = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
//data = imageData = ImageUtils.convertAwtImageData(sub);
} else {
sub = image;
//data = imageData;
}
return sub;
}
/* (non-Javadoc)
* @see v9t9.emulator.clients.builtin.swt.ISVGLoader#getURI()
*/
@Override
public String getURI() {
return uri.toString();
}
/* (non-Javadoc)
* @see v9t9.gui.client.swt.svg.ISVGLoader#isLoaded()
*/
@Override
public synchronized boolean isLoaded() {
return !loaderThread.isAlive();
}
}