diff --git a/CHANGELOG.md b/CHANGELOG.md index e96eb5072..c119d9551 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ All notable changes to this project will be documented in this file. - Substance LAF - Shadow in text (mostly in window titles) drawn incorrectly - Incorrect icons for `New empty` action - with dashed borders - [#2443] SVG importer - converting cubic bezier curves to quadratic +- SVG importer - improper stroke width when using width/height with viewBox ## [22.0.2] - 2025-01-17 ### Added diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgImporter.java index 6593aa90a..28f149bf2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgImporter.java @@ -103,6 +103,12 @@ public class SvgImporter { private Rectangle2D.Double viewBox; + private double width; + + private double height; + + private double unitRatio; + /** * Constructor. * @param st Shape tag @@ -273,22 +279,33 @@ public class SvgImporter { } this.viewBox = viewBox; + this.width = width; + this.height = height; Map cachedBitmaps = new HashMap<>(); SvgStyle style = new SvgStyle(this, idMap, rootElement, cachedBitmaps); Matrix transform = new Matrix(); + double ratioX = 1; + double ratioY = 1; + if (fill) { - double ratioX = rect.getWidth() / width / SWF.unitDivisor; - double ratioY = rect.getHeight() / height / SWF.unitDivisor; - transform = Matrix.getScaleInstance(ratioX, ratioY); - transform.translate(origXmin / SWF.unitDivisor / ratioX, origYmin / SWF.unitDivisor / ratioY); + ratioX = rect.getWidth() / width; + ratioY = rect.getHeight() / height; + transform = Matrix.getScaleInstance(ratioX / SWF.unitDivisor, ratioY / SWF.unitDivisor); + transform.translate(origXmin / ratioX, origYmin / ratioY); } transform = transform.preConcatenate(Matrix.getTranslateInstance(-viewBox.x, -viewBox.y)); if (viewBox.height != 0 && viewBox.width != 0) { - transform = transform.preConcatenate(Matrix.getScaleInstance(width / viewBox.width, height / viewBox.height)); + double ratio2x = width / viewBox.width; + double ratio2y = height / viewBox.height; + ratioX *= ratio2x; + ratioY *= ratio2y; + transform = transform.preConcatenate(Matrix.getScaleInstance(ratio2x, ratio2y)); } + + this.unitRatio = (ratioX + ratioY) / 2; processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape, cachedBitmaps, false); if (rootElement.hasAttribute("ffdec:objectType") @@ -327,6 +344,14 @@ public class SvgImporter { return (Tag) st; } + /** + * Gets unit ratio. + * @return Ratio value + */ + public double getUnitRatio() { + return unitRatio; + } + /** * Applies animation to the element. * @param element Element @@ -1440,6 +1465,18 @@ public class SvgImporter { processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape, false); } + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + public Rectangle2D.Double getViewBox() { + return viewBox; + } + //Stub for w3 test. TODO: refactor and move to test directory. It's here because of easy access - compiling single file private static void svgTest(String name) throws IOException, InterruptedException { System.err.println("running test " + name); @@ -2007,8 +2044,8 @@ public class SvgImporter { Color lineColor = strokeFill.toColor(); ILINESTYLE lineStyle = shapeNum <= 3 ? new LINESTYLE() : new LINESTYLE2(); - lineStyle.setColor(getRGB(shapeNum, lineColor)); - lineStyle.setWidth((int) Math.round(style.getStrokeWidth() * SWF.unitDivisor)); + lineStyle.setColor(getRGB(shapeNum, lineColor)); + lineStyle.setWidth((int) Math.round(style.getStrokeWidth() * this.unitRatio * SWF.unitDivisor)); SvgLineCap lineCap = style.getStrokeLineCap(); SvgLineJoin lineJoin = style.getStrokeLineJoin(); if (lineStyle instanceof LINESTYLE2) { @@ -2088,7 +2125,7 @@ public class SvgImporter { return parseLength(value, relativeTo); } - private double parseLength(String value, double relativeTo) { + public double parseLength(String value, double relativeTo) { if (value == null) { throw new NumberFormatException(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgStyle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgStyle.java index 73a486507..896429f04 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgStyle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/SvgStyle.java @@ -791,8 +791,12 @@ class SvgStyle { } break; case "stroke-width": { - double strokeWidth = Double.parseDouble(value); - return strokeWidth; + return importer.parseLength(value, + Math.sqrt( + importer.getViewBox().width * importer.getViewBox().width + + importer.getViewBox().height * importer.getViewBox().height + ) / Math.sqrt(2) + ); } case "stroke-opacity": { double opacity = Double.parseDouble(value);