IDEA-204822 [followup] indexing svg files can be slow

This commit is contained in:
Anton Tarasov
2018-12-28 17:12:34 +03:00
parent 26a2e7e4dd
commit d9eb8d68b6
3 changed files with 37 additions and 3 deletions
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- follow the white rabbit -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="10">
<rect fill="lime" width="100%" height="100%"/>
</svg>

After

Width:  |  Height:  |  Size: 291 B

@@ -10,6 +10,7 @@ import org.junit.Test;
import org.junit.rules.ExternalResource;
import java.awt.*;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
@@ -50,6 +51,22 @@ public class SvgIconSizeTest {
image = ImageUtil.toBufferedImage(image);
assertEquals("wrong image width", pixScale * 25, (double)image.getWidth(null));
assertEquals("wrong image height", pixScale * 15, (double)image.getHeight(null));
/*
* Test SVGLoader.getDocumentSize for SVG starting with <svg.
*/
url = new File(getSvgIconPath("20x10")).toURI().toURL();
Dimension2D size = SVGLoader.getDocumentSize(url, url.openStream(), 1);
assertEquals("wrong svg doc width", 20d, size.getWidth());
assertEquals("wrong svg doc height", 10d, size.getHeight());
/*
* Test SVGLoader.getDocumentSize for SVG starting with <?xml.
*/
url = new File(getSvgIconPath("xml_20x10")).toURI().toURL();
size = SVGLoader.getDocumentSize(url, url.openStream(), 1);
assertEquals("wrong svg doc width", 20d, size.getWidth());
assertEquals("wrong svg doc height", 10d, size.getHeight());
}
private static void test(ScaleContext ctx) {
@@ -31,6 +31,7 @@ import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import static com.intellij.util.ui.JBUI.ScaleType.PIX_SCALE;
@@ -151,15 +152,25 @@ public class SVGLoader {
return (T)ImageUtil.ensureHiDPI(image, ctx);
}
@SuppressWarnings("SSBasedInspection")
public static Dimension2D getDocumentSize(@Nullable URL url, @NotNull InputStream stream , double scale) throws IOException {
// In order to get the size we parse the whole document and build a tree ("GVT"), what might be too expensive.
// So, to optimize we extract the svg header and parse only it.
// So, to optimize we extract the svg header (possibly prepended with <?xml> header) and parse only it.
StringBuilder builder = new StringBuilder(100);
byte[] bytes = new byte[3];
boolean checkClosingBracket = false;
int ch;
while((ch = stream.read()) != -1) {
builder.append((char)ch);
if (ch == '>') {
//noinspection SSBasedInspection
if (ch == '<') {
if (stream.read(bytes, 0, 3) == -1) {
break;
}
String str = new String(bytes);
builder.append(str);
checkClosingBracket = "svg".equals(str);
}
else if (checkClosingBracket && ch == '>') {
return new SVGLoader(url, new ByteArrayInputStream(builder.append("</svg>").toString().getBytes()), scale).getDocumentSize();
}
}