Merge pull request #522 from Schmidor/svg_size

#518 Parsing SVG width/height attributes
This commit is contained in:
Harald Kuhr 2020-01-31 15:50:24 +01:00 committed by GitHub
commit a1047edddb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 15 deletions

View File

@ -33,9 +33,11 @@ package com.twelvemonkeys.imageio.plugins.svg;
import com.twelvemonkeys.image.ImageUtil; import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase; import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.util.IIOUtil; import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.lang.StringUtil;
import org.apache.batik.anim.dom.SVGDOMImplementation; import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.anim.dom.SVGOMDocument; import org.apache.batik.anim.dom.SVGOMDocument;
import org.apache.batik.bridge.*; import org.apache.batik.bridge.*;
import org.apache.batik.css.parser.CSSLexicalUnit;
import org.apache.batik.dom.util.DOMUtilities; import org.apache.batik.dom.util.DOMUtilities;
import org.apache.batik.ext.awt.image.GraphicsUtil; import org.apache.batik.ext.awt.image.GraphicsUtil;
import org.apache.batik.gvt.CanvasGraphicsNode; import org.apache.batik.gvt.CanvasGraphicsNode;
@ -47,6 +49,7 @@ import org.apache.batik.transcoder.*;
import org.apache.batik.transcoder.image.ImageTranscoder; import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.ParsedURL; import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.SVGConstants; import org.apache.batik.util.SVGConstants;
import org.apache.batik.xml.LexicalUnits;
import org.w3c.dom.DOMImplementation; import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGSVGElement; import org.w3c.dom.svg.SVGSVGElement;
@ -324,24 +327,54 @@ public class SVGImageReader extends ImageReaderBase {
} }
// ---- // ----
SVGSVGElement rootElement = svgDoc.getRootElement();
// get the 'width' and 'height' attributes of the SVG document // get the 'width' and 'height' attributes of the SVG document
Dimension2D docSize = ctx.getDocumentSize(); UnitProcessor.Context uctx
if (docSize != null) { = UnitProcessor.createContext(ctx, rootElement);
defaultWidth = (float) docSize.getWidth(); String widthStr = rootElement.getAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE);
defaultHeight = (float) docSize.getHeight(); String heightStr = rootElement.getAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE);
if (!StringUtil.isEmpty(widthStr)) {
defaultWidth = UnitProcessor.svgToUserSpace(widthStr, SVGConstants.SVG_WIDTH_ATTRIBUTE, UnitProcessor.HORIZONTAL_LENGTH, uctx);
} }
else { if(!StringUtil.isEmpty(heightStr)){
defaultWidth = 200; defaultHeight = UnitProcessor.svgToUserSpace(heightStr, SVGConstants.SVG_HEIGHT_ATTRIBUTE, UnitProcessor.VERTICAL_LENGTH, uctx);
defaultHeight = 200;
} }
SVGSVGElement rootElement = svgDoc.getRootElement();
String viewBoxStr = rootElement.getAttributeNS boolean hasWidth = defaultWidth > 0.0;
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE); boolean hasHeight = defaultHeight > 0.0;
if (viewBoxStr.length() != 0) {
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null); if (!hasWidth || !hasHeight) {
defaultWidth = rect[2]; String viewBoxStr = rootElement.getAttributeNS
defaultHeight = rect[3]; (null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
if (viewBoxStr.length() != 0) {
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
// if one dimension is given, calculate other by aspect ratio in viewBox
// or use viewBox if no dimension is given
if (hasWidth) {
defaultHeight = defaultWidth * rect[3] / rect[2];
}
else if (hasHeight) {
defaultWidth = defaultHeight * rect[2] / rect[3];
}
else {
defaultWidth = rect[2];
defaultHeight = rect[3];
}
}
else {
if (hasHeight) {
defaultWidth = defaultHeight;
}
else if (hasWidth) {
defaultHeight = defaultWidth;
}
else {
// fallback to batik default sizes
defaultWidth = 400;
defaultHeight = 400;
}
}
} }
// Hack to work around exception above // Hack to work around exception above

View File

@ -74,7 +74,11 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
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/red-square.svg"), new Dimension(100, 100)),
new TestData(getClassLoaderResource("/svg/blue-square.svg"), new Dimension(100, 100)), new TestData(getClassLoaderResource("/svg/blue-square.svg"), new Dimension(100, 100)),
new TestData(getClassLoaderResource("/svg/Android_robot.svg"), new Dimension(294, 345)) new TestData(getClassLoaderResource("/svg/Android_robot.svg"), new Dimension(294, 345)),
new TestData(getClassLoaderResource("/svg/sizes/w50h50.svg"), new Dimension(50, 50)),
new TestData(getClassLoaderResource("/svg/sizes/w50_1to2.svg"), new Dimension(25, 50)),
new TestData(getClassLoaderResource("/svg/sizes/h50_1to2.svg"), new Dimension(50, 100)),
new TestData(getClassLoaderResource("/svg/sizes/w50noview.svg"), new Dimension(50, 50))
); );
} }

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="50" viewBox="0 0 100 200" version="1.1">
<g id="layer1">
<rect id="rect2985" width="50" height="50" x="0" y="0"
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 427 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" height="50" viewBox="0 0 100 200" version="1.1">
<g id="layer1">
<rect id="rect2985" width="50" height="50" x="0" y="0"
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 200" version="1.1">
<g id="layer1">
<rect id="rect2985" width="50" height="50" x="0" y="0"
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 439 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="50" version="1.1">
<g id="layer1">
<rect id="rect2985" width="50" height="50" x="0" y="0"
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 405 B