From d2504e5e711ba54a55e2a4fd051c9cd205af925a Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sat, 1 Apr 2017 17:25:49 +0200 Subject: [PATCH] SVG importer rounding problem fixed --- .../flash/exporters/commonshape/Matrix.java | 13 ++++ .../flash/importers/svg/SvgImporter.java | 69 ++++++++++--------- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java index bef21beee..a14a53279 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/Matrix.java @@ -43,6 +43,12 @@ public final class Matrix implements Cloneable { return mat; } + public static Matrix getScaleInstance(double scaleX, double scaleY) { + Matrix mat = new Matrix(); + mat.scale(scaleX, scaleY); + return mat; + } + public static Matrix getTranslateInstance(double x, double y) { Matrix mat = new Matrix(); mat.translate(x, y); @@ -200,6 +206,13 @@ public final class Matrix implements Cloneable { rotateSkew1 *= factor; } + public void scale(double factorX, double factorY) { + scaleX *= factorX; + scaleY *= factorY; + rotateSkew0 *= factorX; + rotateSkew1 *= factorY; + } + public Matrix concatenate(Matrix m) { Matrix result = new Matrix(); result.scaleX = scaleX * m.scaleX + rotateSkew1 * m.rotateSkew0; 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 26c1bc5f0..5f6b5adbb 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 @@ -100,6 +100,14 @@ public class SvgImporter { shapes.lineStyles.lineStyles = new LINESTYLE[0]; int shapeNum = st.getShapeNum(); + RECT rect = st.getRect(); + int origXmin = rect.Xmin; + int origYmin = rect.Ymin; + rect.Xmin -= origXmin; + rect.Xmax -= origXmin; + rect.Ymin -= origYmin; + rect.Ymax -= origYmin; + shapes.shapeRecords = new ArrayList<>(); Rectangle2D.Double viewBox = null; @@ -165,6 +173,18 @@ public class SvgImporter { SvgStyle style = new SvgStyle(this, idMap, rootElement); Matrix transform = new Matrix(); + + if (!fill) { + rect.Xmin = (int) Math.round(viewBox.x * SWF.unitDivisor); + rect.Ymin = (int) Math.round(viewBox.y * SWF.unitDivisor); + rect.Xmax = (int) Math.round((viewBox.x + viewBox.width) * SWF.unitDivisor); + rect.Ymax = (int) Math.round((viewBox.y + viewBox.height) * SWF.unitDivisor); + } else { + double ratioX = rect.getWidth() / width / SWF.unitDivisor; + double ratioY = rect.getHeight() / height / SWF.unitDivisor; + transform = Matrix.getScaleInstance(ratioX, ratioY); + } + processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style); } catch (SAXException | IOException | ParserConfigurationException ex) { Logger.getLogger(ShapeImporter.class.getName()).log(Level.SEVERE, null, ex); @@ -172,27 +192,6 @@ public class SvgImporter { shapes.shapeRecords.add(new EndShapeRecord()); - RECT rect = st.getRect(); - int origXmin = rect.Xmin; - int origYmin = rect.Ymin; - rect.Xmin -= origXmin; - rect.Xmax -= origXmin; - rect.Ymin -= origYmin; - rect.Ymax -= origYmin; - - if (!fill && viewBox != null) { - rect.Xmin = (int) Math.round(viewBox.x * SWF.unitDivisor); - rect.Ymin = (int) Math.round(viewBox.y * SWF.unitDivisor); - rect.Xmax = (int) Math.round((viewBox.x + viewBox.width) * SWF.unitDivisor); - rect.Ymax = (int) Math.round((viewBox.y + viewBox.height) * SWF.unitDivisor); - } else if (viewBox != null) { - double width = viewBox.width * SWF.unitDivisor; - double height = viewBox.height * SWF.unitDivisor; - double radioX = rect.getWidth() / width; - double radioY = rect.getHeight() / height; - shapes = shapes.resize(radioX, radioY); - } - st.shapes = shapes; st.setModified(true); @@ -279,7 +278,13 @@ public class SvgImporter { double x = x0; double y = y0; Point p; - char cmd = Character.toUpperCase(command.command); + + boolean isRelative = Character.isLowerCase(command.command); + if (isRelative) { + throw new Error("processCommands is called with relative command"); + } + + char cmd = command.command; switch (cmd) { case 'M': StyleChangeRecord scr = new StyleChangeRecord(); @@ -298,18 +303,18 @@ public class SvgImporter { p = transform2.transform(x, y); scr.moveDeltaX = (int) Math.round(p.x); scr.moveDeltaY = (int) Math.round(p.y); - prevPoint = p; + prevPoint = new Point(scr.moveDeltaX, scr.moveDeltaY); scr.stateMoveTo = true; newRecords.add(scr); - startPoint = p; + startPoint = prevPoint; break; case 'Z': StraightEdgeRecord serz = new StraightEdgeRecord(); p = startPoint; serz.deltaX = (int) Math.round(p.x - prevPoint.x); serz.deltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x + serz.deltaX, prevPoint.y + serz.deltaY); serz.generalLineFlag = true; newRecords.add(serz); if (lineStyle2Obj != null) { @@ -324,7 +329,7 @@ public class SvgImporter { p = transform2.transform(x, y); serl.deltaX = (int) Math.round(p.x - prevPoint.x); serl.deltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x + serl.deltaX, prevPoint.y + serl.deltaY); serl.generalLineFlag = true; serl.simplify(); newRecords.add(serl); @@ -335,7 +340,7 @@ public class SvgImporter { p = transform2.transform(x, y); serh.deltaX = (int) Math.round(p.x - prevPoint.x); - prevPoint = p; + prevPoint = new Point(prevPoint.x + serh.deltaX, prevPoint.y/* + serh.deltaY*/); newRecords.add(serh); break; case 'V': @@ -344,7 +349,7 @@ public class SvgImporter { p = transform2.transform(x, y); serv.deltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x/* + serv.deltaX*/, prevPoint.y + serv.deltaY); serv.vertLineFlag = true; newRecords.add(serv); break; @@ -356,7 +361,7 @@ public class SvgImporter { p = transform2.transform(x, y); cer.controlDeltaX = (int) Math.round(p.x - prevPoint.x); cer.controlDeltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x + cer.controlDeltaX, prevPoint.y + cer.controlDeltaY); x = command.params[2]; y = command.params[3]; @@ -364,7 +369,7 @@ public class SvgImporter { p = transform2.transform(x, y); cer.anchorDeltaX = (int) Math.round(p.x - prevPoint.x); cer.anchorDeltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x + cer.anchorDeltaX, prevPoint.y + cer.anchorDeltaY); newRecords.add(cer); break; case 'C': @@ -400,12 +405,12 @@ public class SvgImporter { p = new Point(quadCoordinates.get(i++), quadCoordinates.get(i++)); cerc.controlDeltaX = (int) Math.round(p.x - prevPoint.x); cerc.controlDeltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x + cerc.controlDeltaX, prevPoint.y + cerc.controlDeltaY); p = new Point(quadCoordinates.get(i++), quadCoordinates.get(i++)); cerc.anchorDeltaX = (int) Math.round(p.x - prevPoint.x); cerc.anchorDeltaY = (int) Math.round(p.y - prevPoint.y); - prevPoint = p; + prevPoint = new Point(prevPoint.x + cerc.anchorDeltaX, prevPoint.y + cerc.anchorDeltaY); newRecords.add(cerc); }