mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-04-30 00:00:01 -04:00
Fix #1211 - SVG: support namespace prefix
This commit is contained in:
committed by
Harald Kuhr
parent
8af219e669
commit
6c8b0cdc2f
+48
-1
@@ -36,9 +36,11 @@ import com.twelvemonkeys.lang.SystemUtil;
|
|||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.spi.ServiceRegistry;
|
import javax.imageio.spi.ServiceRegistry;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
|
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
|
||||||
|
|
||||||
@@ -134,10 +136,40 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
|
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
|
||||||
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
|
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
|
||||||
// It's SVG, identified by root tag
|
// It's SVG, identified by root tag
|
||||||
// TODO: Support svg with prefix + recognize namespace (http://www.w3.org/2000/svg)!
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the full tag name (may contain a prefix of any length)
|
||||||
|
ByteArrayOutputStream nameBuf = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
// We already have 4 bytes in 'buffer' (from input.readFully(buffer))
|
||||||
|
int consumedFromBuffer = 0;
|
||||||
|
for (; consumedFromBuffer < buffer.length; consumedFromBuffer++) {
|
||||||
|
byte bb = buffer[consumedFromBuffer];
|
||||||
|
if (bb == '>' || Character.isWhitespace((char) bb) || bb == '/') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nameBuf.write(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tag name not terminated yet, keep reading bytes (within limit)
|
||||||
|
final int MAX_TAG_NAME = 256;
|
||||||
|
final boolean incompleteTagName = consumedFromBuffer == buffer.length;
|
||||||
|
readBuffer(input, nameBuf, x -> incompleteTagName && x.size() < MAX_TAG_NAME,
|
||||||
|
bb -> bb == '>' || Character.isWhitespace(bb) || bb == '/');
|
||||||
|
|
||||||
|
if (nameBuf.toString("US-ASCII").toLowerCase(Locale.ENGLISH).endsWith(":svg")) {
|
||||||
|
// Scan the rest of the tag attributes until '>' to find the SVG namespace URI
|
||||||
|
ByteArrayOutputStream attrBuf = new ByteArrayOutputStream();
|
||||||
|
final int MAX_ATTR_SCAN = 1024; // safe upper bound to keep it fast
|
||||||
|
readBuffer(input, attrBuf, x -> x.size() < MAX_ATTR_SCAN, bb -> bb == '>');
|
||||||
|
|
||||||
|
// If the tag contains the SVG namespace, it's SVG.
|
||||||
|
if (attrBuf.toString("US-ASCII").contains("http://www.w3.org/2000/svg")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the tag is not "svg", this isn't SVG
|
// If the tag is not "svg", this isn't SVG
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -157,6 +189,21 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void readBuffer(final ImageInputStream input, final ByteArrayOutputStream buffer,
|
||||||
|
final Predicate<ByteArrayOutputStream> loopCondition, Predicate<Byte> breakCondition) throws IOException {
|
||||||
|
while (loopCondition.test(buffer)) {
|
||||||
|
int r = input.read();
|
||||||
|
if (r == -1) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
byte bb = (byte) r;
|
||||||
|
if (breakCondition.test(bb)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer.write(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ImageReader createReaderInstance(final Object extension) throws IOException {
|
public ImageReader createReaderInstance(final Object extension) throws IOException {
|
||||||
return new SVGImageReader(this);
|
return new SVGImageReader(this);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ public class SVGImageReaderSpiTest {
|
|||||||
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
|
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
|
||||||
"/svg/batikLogo.svg", // xml dec, comments, namespace
|
"/svg/batikLogo.svg", // xml dec, comments, namespace
|
||||||
"/svg/blue-square.svg", // xml dec, namespace
|
"/svg/blue-square.svg", // xml dec, namespace
|
||||||
"/svg/red-square.svg",
|
"/svg/red-square.svg", // prefixed namespace
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String[] INVALID_INPUTS = {
|
private static final String[] INVALID_INPUTS = {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
|
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
|
||||||
<g id="layer1">
|
<ns0:g id="layer1">
|
||||||
<rect id="rect2985" width="100" height="100" x="0" y="0"
|
<ns0:rect id="rect2985" width="100" height="100" x="0" y="0"
|
||||||
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||||
</g>
|
</ns0:g>
|
||||||
</svg>
|
</ns0:svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 465 B |
Reference in New Issue
Block a user