TMI-125: Clean up after merge + fix Spi issue.

This commit is contained in:
Harald Kuhr 2015-04-07 11:05:14 +02:00
parent 4219ca437c
commit 2c8f0f5add
3 changed files with 93 additions and 88 deletions

View File

@ -74,18 +74,19 @@ import java.util.Map;
* @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A> * @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A>
*/ */
public class SVGImageReader extends ImageReaderBase { public class SVGImageReader extends ImageReaderBase {
private Rasterizer rasterizer = null; private Rasterizer rasterizer;
/** /**
* Creates an {@code SVGImageReader}. * Creates an {@code SVGImageReader}.
* *
* @param pProvider the provider * @param pProvider the provider
*/ */
public SVGImageReader(ImageReaderSpi pProvider) { public SVGImageReader(final ImageReaderSpi pProvider) {
super(pProvider); super(pProvider);
} }
protected void resetMembers() { protected void resetMembers() {
rasterizer = new Rasterizer();
} }
@Override @Override
@ -100,7 +101,6 @@ public class SVGImageReader extends ImageReaderBase {
if (imageInput != null) { if (imageInput != null) {
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput)); TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
rasterizer = new Rasterizer();
rasterizer.setInput(input); rasterizer.setInput(input);
} }
} }
@ -135,7 +135,7 @@ public class SVGImageReader extends ImageReaderBase {
try { try {
processImageStarted(pIndex); processImageStarted(pIndex);
rasterizer.mTranscoderInput.setURI(baseURI); rasterizer.transcoderInput.setURI(baseURI);
BufferedImage image = rasterizer.getImage(); BufferedImage image = rasterizer.getImage();
Graphics2D g = destination.createGraphics(); Graphics2D g = destination.createGraphics();
@ -253,31 +253,29 @@ public class SVGImageReader extends ImageReaderBase {
*/ */
private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ { private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ {
BufferedImage mImage = null; BufferedImage image = null;
private TranscoderInput mTranscoderInput; private TranscoderInput transcoderInput;
private float mDefaultWidth; private float defaultWidth;
private float mDefaultHeight; private float defaultHeight;
private boolean mInit = false; private boolean initialized = false;
private SVGOMDocument mDocument; private SVGOMDocument document;
private String mURI; private String uri;
private GraphicsNode mGVTRoot; private GraphicsNode gvtRoot;
private TranscoderException mException; private TranscoderException exception;
private BridgeContext mContext; private BridgeContext context;
public BufferedImage createImage(int w, int h) { public BufferedImage createImage(final int width, final int height) {
return ImageUtil.createTransparent(w, h);//, BufferedImage.TYPE_INT_ARGB); return ImageUtil.createTransparent(width, height);//, BufferedImage.TYPE_INT_ARGB);
} }
// This is cheating... We don't fully transcode after all // This is cheating... We don't fully transcode after all
protected void transcode(Document document, String uri, TranscoderOutput output) throws TranscoderException { protected void transcode(Document document, final String uri, final TranscoderOutput output) throws TranscoderException {
// Sets up root, curTxf & curAoi // Sets up root, curTxf & curAoi
// ---- // ----
if ((document != null) && if ((document != null) && !(document.getImplementation() instanceof SVGDOMImplementation)) {
!(document.getImplementation() instanceof SVGDOMImplementation)) { DOMImplementation impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION);
DOMImplementation impl;
impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION);
// impl = ExtensibleSVGDOMImplementation.getDOMImplementation();
document = DOMUtilities.deepCloneDocument(document, impl); document = DOMUtilities.deepCloneDocument(document, impl);
if (uri != null) { if (uri != null) {
try { try {
URL url = new URL(uri); URL url = new URL(uri);
@ -290,7 +288,6 @@ public class SVGImageReader extends ImageReaderBase {
ctx = createBridgeContext(); ctx = createBridgeContext();
SVGOMDocument svgDoc = (SVGOMDocument) document; SVGOMDocument svgDoc = (SVGOMDocument) document;
//SVGSVGElement root = svgDoc.getRootElement();
// build the GVT tree // build the GVT tree
builder = new GVTBuilder(); builder = new GVTBuilder();
@ -298,7 +295,7 @@ public class SVGImageReader extends ImageReaderBase {
boolean isDynamic = boolean isDynamic =
(hints.containsKey(KEY_EXECUTE_ONLOAD) && (hints.containsKey(KEY_EXECUTE_ONLOAD) &&
(Boolean) hints.get(KEY_EXECUTE_ONLOAD) && (Boolean) hints.get(KEY_EXECUTE_ONLOAD) &&
BaseScriptingEnvironment.isDynamicDocument(ctx, svgDoc)); BaseScriptingEnvironment.isDynamicDocument(ctx, svgDoc));
if (isDynamic) { if (isDynamic) {
ctx.setDynamicState(BridgeContext.DYNAMIC); ctx.setDynamicState(BridgeContext.DYNAMIC);
@ -312,8 +309,7 @@ public class SVGImageReader extends ImageReaderBase {
catch (BridgeException ex) { catch (BridgeException ex) {
// Note: This might fail, but we STILL have the dimensions we need // Note: This might fail, but we STILL have the dimensions we need
// However, we need to reparse later... // However, we need to reparse later...
//throw new TranscoderException(ex); exception = new TranscoderException(ex);
mException = new TranscoderException(ex);
} }
// ---- // ----
@ -321,24 +317,23 @@ public class SVGImageReader extends ImageReaderBase {
// get the 'width' and 'height' attributes of the SVG document // get the 'width' and 'height' attributes of the SVG document
Dimension2D docSize = ctx.getDocumentSize(); Dimension2D docSize = ctx.getDocumentSize();
if (docSize != null) { if (docSize != null) {
mDefaultWidth = (float) docSize.getWidth(); defaultWidth = (float) docSize.getWidth();
mDefaultHeight = (float) docSize.getHeight(); defaultHeight = (float) docSize.getHeight();
} }
else { else {
mDefaultWidth = 200; defaultWidth = 200;
mDefaultHeight = 200; defaultHeight = 200;
} }
// Hack to work around exception above // Hack to work around exception above
if (root != null) { if (root != null) {
mGVTRoot = root; gvtRoot = root;
} }
mDocument = svgDoc; this.document = svgDoc;
mURI = uri; this.uri = uri;
//ctx.dispose();
// Hack to avoid the transcode method wacking my context... // Hack to avoid the transcode method wacking my context...
mContext = ctx; context = ctx;
ctx = null; ctx = null;
} }
@ -353,24 +348,24 @@ public class SVGImageReader extends ImageReaderBase {
// Hacky workaround below... // Hacky workaround below...
if (mGVTRoot == null) { if (gvtRoot == null) {
// Try to reparse, if we had no URI last time... // Try to reparse, if we had no URI last time...
if (mURI != mTranscoderInput.getURI()) { if (uri != transcoderInput.getURI()) {
try { try {
mContext.dispose(); context.dispose();
mDocument.setURLObject(new URL(mTranscoderInput.getURI())); document.setURLObject(new URL(transcoderInput.getURI()));
transcode(mDocument, mTranscoderInput.getURI(), null); transcode(document, transcoderInput.getURI(), null);
} }
catch (MalformedURLException ignore) { catch (MalformedURLException ignore) {
// Ignored // Ignored
} }
} }
if (mGVTRoot == null) { if (gvtRoot == null) {
throw mException; throw exception;
} }
} }
ctx = mContext; ctx = context;
// /Hacky // /Hacky
if (abortRequested()) { if (abortRequested()) {
processReadAborted(); processReadAborted();
@ -378,13 +373,13 @@ public class SVGImageReader extends ImageReaderBase {
} }
processImageProgress(20f); processImageProgress(20f);
// -- -- // ----
SVGSVGElement root = mDocument.getRootElement(); SVGSVGElement root = document.getRootElement();
// ---- // ----
// ---- // ----
setImageSize(mDefaultWidth, mDefaultHeight); setImageSize(defaultWidth, defaultHeight);
if (abortRequested()) { if (abortRequested()) {
processReadAborted(); processReadAborted();
@ -394,7 +389,7 @@ public class SVGImageReader extends ImageReaderBase {
// compute the preserveAspectRatio matrix // compute the preserveAspectRatio matrix
AffineTransform Px; AffineTransform Px;
String ref = new ParsedURL(mURI).getRef(); String ref = new ParsedURL(uri).getRef();
try { try {
Px = ViewBox.getViewTransform(ref, root, width, height); Px = ViewBox.getViewTransform(ref, root, width, height);
@ -404,12 +399,12 @@ public class SVGImageReader extends ImageReaderBase {
throw new TranscoderException(ex); throw new TranscoderException(ex);
} }
if (Px.isIdentity() && (width != mDefaultWidth || height != mDefaultHeight)) { if (Px.isIdentity() && (width != defaultWidth || height != defaultHeight)) {
// The document has no viewBox, we need to resize it by hand. // The document has no viewBox, we need to resize it by hand.
// we want to keep the document size ratio // we want to keep the document size ratio
float xscale, yscale; float xscale, yscale;
xscale = width / mDefaultWidth; xscale = width / defaultWidth;
yscale = height / mDefaultHeight; yscale = height / defaultHeight;
float scale = Math.min(xscale, yscale); float scale = Math.min(xscale, yscale);
Px = AffineTransform.getScaleInstance(scale, scale); Px = AffineTransform.getScaleInstance(scale, scale);
} }
@ -440,7 +435,7 @@ public class SVGImageReader extends ImageReaderBase {
} }
processImageProgress(50f); processImageProgress(50f);
CanvasGraphicsNode cgn = getCanvasGraphicsNode(mGVTRoot); CanvasGraphicsNode cgn = getCanvasGraphicsNode(gvtRoot);
if (cgn != null) { if (cgn != null) {
cgn.setViewingTransform(Px); cgn.setViewingTransform(Px);
curTxf = new AffineTransform(); curTxf = new AffineTransform();
@ -462,7 +457,7 @@ public class SVGImageReader extends ImageReaderBase {
throw new TranscoderException(ex); throw new TranscoderException(ex);
} }
this.root = mGVTRoot; this.root = gvtRoot;
// ---- // ----
// NOTE: The code below is copied and pasted from the Batik // NOTE: The code below is copied and pasted from the Batik
@ -510,6 +505,7 @@ public class SVGImageReader extends ImageReaderBase {
g2d.setPaint(bgcolor); g2d.setPaint(bgcolor);
g2d.fillRect(0, 0, w, h); g2d.fillRect(0, 0, w, h);
} }
if (rend != null) { // might be null if the svg document is empty if (rend != null) { // might be null if the svg document is empty
g2d.drawRenderedImage(rend, new AffineTransform()); g2d.drawRenderedImage(rend, new AffineTransform());
} }
@ -534,43 +530,44 @@ public class SVGImageReader extends ImageReaderBase {
throw exception; throw exception;
} }
finally { finally {
if (mContext != null) { if (context != null) {
mContext.dispose(); context.dispose();
} }
} }
} }
private synchronized void init() throws TranscoderException { private synchronized void init() throws TranscoderException {
if (!mInit) { if (!initialized) {
if (mTranscoderInput == null) { if (transcoderInput == null) {
throw new IllegalStateException("input == null"); throw new IllegalStateException("input == null");
} }
mInit = true; initialized = true;
super.transcode(mTranscoderInput, null); super.transcode(transcoderInput, null);
} }
} }
private BufferedImage getImage() throws TranscoderException { private BufferedImage getImage() throws TranscoderException {
if (mImage == null) { if (image == null) {
mImage = readImage(); image = readImage();
} }
return mImage;
return image;
} }
protected int getDefaultWidth() throws TranscoderException { protected int getDefaultWidth() throws TranscoderException {
init(); init();
return (int) (mDefaultWidth + 0.5); return (int) (defaultWidth + 0.5);
} }
protected int getDefaultHeight() throws TranscoderException { protected int getDefaultHeight() throws TranscoderException {
init(); init();
return (int) (mDefaultHeight + 0.5); return (int) (defaultHeight + 0.5);
} }
public void setInput(TranscoderInput pInput) { public void setInput(final TranscoderInput pInput) {
mTranscoderInput = pInput; transcoderInput = pInput;
} }
} }
} }

View File

@ -29,8 +29,8 @@
package com.twelvemonkeys.imageio.plugins.svg; package com.twelvemonkeys.imageio.plugins.svg;
import com.twelvemonkeys.imageio.spi.ProviderInfo; import com.twelvemonkeys.imageio.spi.ProviderInfo;
import com.twelvemonkeys.lang.SystemUtil;
import com.twelvemonkeys.imageio.util.IIOUtil; import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.lang.SystemUtil;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageReaderSpi;
@ -80,18 +80,18 @@ public class SVGImageReaderSpi extends ImageReaderSpi {
); );
} }
public boolean canDecodeInput(Object pSource) throws IOException { public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && SVG_READER_AVAILABLE && canDecode((ImageInputStream) pSource); return pSource instanceof ImageInputStream && SVG_READER_AVAILABLE && canDecode((ImageInputStream) pSource);
} }
private static boolean canDecode(ImageInputStream pInput) throws IOException { private static boolean canDecode(final ImageInputStream pInput) throws IOException {
// NOTE: This test is quite quick as it does not involve any parsing, // NOTE: This test is quite quick as it does not involve any parsing,
// however it requires the doctype to be "svg", which may not be correct // however it requires the doctype to be "svg", which may not be correct
// in all cases... // in all cases...
try { try {
pInput.mark(); pInput.mark();
// TODO: This is may not be ok for non-UTF/iso-latin encodings... // TODO: This is not ok for UTF-16 and other wide encodings
// TODO: Use an XML (encoding) aware Reader instance instead // TODO: Use an XML (encoding) aware Reader instance instead
// Need to figure out pretty fast if this is XML or not // Need to figure out pretty fast if this is XML or not
int b; int b;
@ -111,9 +111,14 @@ public class SVGImageReaderSpi extends ImageReaderSpi {
// Skip over, until begin tag // Skip over, until begin tag
} }
// If this is not a comment, or the DOCTYPE declaration, the doc if ((b = pInput.read()) != '!') {
// has no DOCTYPE and it can't be svg if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g'
if (pInput.read() != '!') { && (Character.isWhitespace((char) (b = pInput.read())) || b == ':')) {
// TODO: Support svg with prefix + recognize namespace (http://www.w3.org/2000/svg)!
return true;
}
// If this is not a comment, or the DOCTYPE declaration, the doc has no DOCTYPE and it can't be svg
return false; return false;
} }
@ -126,19 +131,19 @@ public class SVGImageReaderSpi extends ImageReaderSpi {
} }
// If we are lucky, this is DOCTYPE declaration // If we are lucky, this is DOCTYPE declaration
if (b == 'D' && pInput.read() == 'O' && pInput.read() == 'C' if (b == 'D' && pInput.read() == 'O' && pInput.read() == 'C' && pInput.read() == 'T'
&& pInput.read() == 'T' && pInput.read() == 'Y' && pInput.read() == 'P' && pInput.read() == 'Y' && pInput.read() == 'P' && pInput.read() == 'E') {
&& pInput.read() == 'E') {
docTypeFound = true; docTypeFound = true;
while (Character.isWhitespace((char) (b = pInput.read()))) { while (Character.isWhitespace((char) (b = pInput.read()))) {
// Skip over WS // Skip over WS
} }
if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') { if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') {
//System.out.println("It's svg!");
return true; return true;
} }
} }
} }
return false; return false;
} }
finally { finally {
@ -147,17 +152,17 @@ public class SVGImageReaderSpi extends ImageReaderSpi {
} }
public ImageReader createReaderInstance(Object extension) throws IOException { public ImageReader createReaderInstance(final Object extension) throws IOException {
return new SVGImageReader(this); return new SVGImageReader(this);
} }
public String getDescription(Locale locale) { public String getDescription(final Locale locale) {
return "Scaleable Vector Graphics (SVG) format image reader"; return "Scaleable Vector Graphics (SVG) format image reader";
} }
@SuppressWarnings({"deprecation"}) @SuppressWarnings({"deprecation"})
@Override @Override
public void onRegistration(ServiceRegistry registry, Class<?> category) { public void onRegistration(final ServiceRegistry registry, final Class<?> category) {
if (!SVG_READER_AVAILABLE) { if (!SVG_READER_AVAILABLE) {
try { try {
// NOTE: This will break, but it gives us some useful debug info // NOTE: This will break, but it gives us some useful debug info

View File

@ -31,7 +31,6 @@ package com.twelvemonkeys.imageio.plugins.svg;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertEquals;
import javax.imageio.ImageReadParam; import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
@ -43,6 +42,8 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.junit.Assert.assertEquals;
/** /**
* SVGImageReaderTestCase * SVGImageReaderTestCase
* *
@ -55,7 +56,9 @@ public class SVGImageReaderTestCase extends ImageReaderAbstractTestCase<SVGImage
protected List<TestData> getTestData() { protected List<TestData> getTestData() {
return Arrays.asList( return Arrays.asList(
new TestData(getClassLoaderResource("/svg/batikLogo.svg"), new Dimension(450, 500)) new TestData(getClassLoaderResource("/svg/batikLogo.svg"), new Dimension(450, 500)),
new TestData(getClassLoaderResource("/svg/red-square.svg"), new Dimension(100, 100)),
new TestData(getClassLoaderResource("/svg/blue-square.svg"), new Dimension(100, 100))
); );
} }
@ -117,12 +120,12 @@ public class SVGImageReaderTestCase extends ImageReaderAbstractTestCase<SVGImage
@Test @Test
public void testRepeatedRead() throws IOException { public void testRepeatedRead() throws IOException {
Dimension dim = new Dimension(100, 100); Dimension dim = new Dimension(100, 100);
ImageReader reader = createReader(); ImageReader reader = createReader();
ImageReadParam param = reader.getDefaultReadParam(); ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRenderSize(dim); param.setSourceRenderSize(dim);
TestData redSquare = new TestData(getClassLoaderResource("/svg/red-square.svg"), dim); TestData redSquare = new TestData(getClassLoaderResource("/svg/red-square.svg"), dim);
reader.setInput(redSquare.getInputStream()); reader.setInput(redSquare.getInputStream());
BufferedImage imageRed = reader.read(0, param); BufferedImage imageRed = reader.read(0, param);
assertEquals(0xFF0000, imageRed.getRGB(50, 50) & 0xFFFFFF); assertEquals(0xFF0000, imageRed.getRGB(50, 50) & 0xFFFFFF);