From bddd2dd4e391ed9135efd3d36121b4e6c27df24e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 2 Nov 2022 22:10:05 +0100 Subject: [PATCH 1/9] Begin unreleased section in changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 184907ee5..c5175a41c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Change Log All notable changes to this project will be documented in this file. +## [Unreleased] + ## [16.0.3] - 2022-11-02 ### Fixed - [#1817] PDF export - now storing JPEG images without recompression to PNG From 62d24e344f3f759b3643d50c02e953d445a56972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 08:27:19 +0100 Subject: [PATCH 2/9] Fixed #1860 FLA export - EmptyStackException during exporting MorphShapes --- CHANGELOG.md | 5 ++++- .../src/com/jpexs/decompiler/flash/xfl/XFLConverter.java | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5175a41c..da405e86b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- [#1860] FLA export - EmptyStackException during exporting MorphShapes ## [16.0.3] - 2022-11-02 ### Fixed @@ -2328,7 +2329,8 @@ All notable changes to this project will be documented in this file. ### Added - Initial public release -[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.2...dev +[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.3...dev +[16.0.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.2...version16.0.3 [16.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.1...version16.0.2 [16.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.0...version16.0.1 [16.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version15.1.1...version16.0.0 @@ -2452,6 +2454,7 @@ All notable changes to this project will be documented in this file. [alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9 [alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8 [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 +[#1860]: https://www.free-decompiler.com/flash/issues/1860 [#1817]: https://www.free-decompiler.com/flash/issues/1817 [#1816]: https://www.free-decompiler.com/flash/issues/1816 [#1859]: https://www.free-decompiler.com/flash/issues/1859 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 46bf291e7..d11b7ade5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -145,6 +145,7 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.EmptyStackException; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -592,7 +593,6 @@ public class XFLConverter { if (distance(prevPoint, startPoint) <= maxDistance) { //start and end of the path near => close prevPoint.x = startPoint.x; prevPoint.y = startPoint.y; - System.err.println("CLOSED"); } } startPoint = currentPoint; @@ -991,7 +991,7 @@ public class XFLConverter { if (currentLayer.length() > 0) { currentLayer.writeEndElement(); // edges currentLayer.writeEndElement(); // DOMShape - + if (currentLayer.length() > 0 && hasEdge) { //no empty layers layers.add(currentLayer.toString()); } @@ -2392,7 +2392,7 @@ public class XFLConverter { } else if (character != null) { if (character instanceof MorphShapeTag) { MorphShapeTag m = (MorphShapeTag) character; - convertShape(characters, matrix, 3, m.getStartEdges().shapeRecords, m.getFillStyles().getStartFillStyles(), m.getLineStyles().getStartLineStyles(m.getShapeNum()), true, false, elementsWriter); + convertShape(characters, matrix, m.getShapeNum() == 1 ? 3 : 4, m.getStartEdges().shapeRecords, m.getFillStyles().getStartFillStyles(), m.getLineStyles().getStartLineStyles(m.getShapeNum()), true, false, elementsWriter); shapeTween = true; } else { shapeTween = false; From 80e557de2b8d5d18ec184866e2855e13735c2db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 08:43:03 +0100 Subject: [PATCH 3/9] Fixed #1782 FLA export - exporting from SWF files inside bundles (like binarysearch) --- CHANGELOG.md | 4 +++- .../jpexs/decompiler/flash/gui/MainPanel.java | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da405e86b..b358592c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- [#1860] FLA export - EmptyStackException during exporting MorphShapes +- [#1860] FLA export - EmptyStackException during exporting MorphShape +- [#1782] FLA export - exporting from SWF files inside bundles (like binarysearch) ## [16.0.3] - 2022-11-02 ### Fixed @@ -2455,6 +2456,7 @@ All notable changes to this project will be documented in this file. [alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8 [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 [#1860]: https://www.free-decompiler.com/flash/issues/1860 +[#1782]: https://www.free-decompiler.com/flash/issues/1782 [#1817]: https://www.free-decompiler.com/flash/issues/1817 [#1816]: https://www.free-decompiler.com/flash/issues/1816 [#1859]: https://www.free-decompiler.com/flash/issues/1859 diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 3a14f009d..63ea30b3c 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2416,9 +2416,19 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se fc.setCurrentDirectory(new File(selDir)); if (!selDir.endsWith(File.separator)) { selDir += File.separator; + } + String swfShortName = swf.getShortFileName(); + if ("".equals(swfShortName)) { + swfShortName = "untitled.swf"; } - String fileName = new File(swf.getFile()).getName(); - fileName = fileName.substring(0, fileName.length() - 4) + ".fla"; + String fileName; + if (swfShortName.contains(".")) { + fileName = swfShortName.substring(0, swfShortName.lastIndexOf(".")) + ".fla"; + } else { + fileName = swfShortName + ".fla"; + } + final String fSwfShortName = swfShortName; + fc.setSelectedFile(new File(selDir + fileName)); List flaFilters = new ArrayList<>(); List xflFilters = new ArrayList<>(); @@ -2484,9 +2494,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se try { AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); if (compressed) { - swf.exportFla(errorHandler, selfile.getAbsolutePath(), new File(swf.getFile()).getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); + swf.exportFla(errorHandler, selfile.getAbsolutePath(), fSwfShortName, ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); } else { - swf.exportXfl(errorHandler, selfile.getAbsolutePath(), new File(swf.getFile()).getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); + swf.exportXfl(errorHandler, selfile.getAbsolutePath(), fSwfShortName, ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), selectedVersion); } } catch (Exception ex) { logger.log(Level.SEVERE, "FLA export error", ex); From 3877e4ae1f0cdf5f1bf82fbf47f81188e8e03ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 08:44:30 +0100 Subject: [PATCH 4/9] Fixed Expand correct tree on SWF load --- CHANGELOG.md | 2 ++ src/com/jpexs/decompiler/flash/gui/MainPanel.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b358592c3..c48da43f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Fixed - [#1860] FLA export - EmptyStackException during exporting MorphShape - [#1782] FLA export - exporting from SWF files inside bundles (like binarysearch) +- Expand correct tree on SWF load ## [16.0.3] - 2022-11-02 ### Fixed diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 63ea30b3c..a8478f9d0 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -924,7 +924,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se public void load(SWFList newSwfs, boolean first) { View.checkAccess(); - List> expandedNodes = View.getExpandedNodes(tagTree); + List> expandedNodes = View.getExpandedNodes(getCurrentTree()); previewPanel.clear(); swfs.add(newSwfs); @@ -935,7 +935,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se doFilter(); reload(false); - View.expandTreeNodes(tagTree, expandedNodes); + View.expandTreeNodes(getCurrentTree(), expandedNodes); } public ABCPanel getABCPanel() { From 88440526d6bcf0add0729723782691349ca309b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 19:45:57 +0100 Subject: [PATCH 5/9] SWF computeDependentFrames creates timeline when null --- libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index c815f966e..9343367da 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -556,8 +556,9 @@ public final class SWF implements SWFContainerItem, Timelined { public void computeDependentFrames() { Map> dep = new HashMap<>(); - for (int i = 0; i < timeline.getFrameCount(); i++) { - Frame frame = timeline.getFrame(i); + Timeline tim = getTimeline(); + for (int i = 0; i < tim.getFrameCount(); i++) { + Frame frame = tim.getFrame(i); Set needed = new HashSet<>(); frame.getNeededCharacters(needed); for (Integer needed1 : needed) { From 6d0597eece7f3a1693c64f49931d19ebfa9afddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 19:51:43 +0100 Subject: [PATCH 6/9] Fixed #1679 FLA export - MorphShapes (shape tween) --- CHANGELOG.md | 2 + .../flash/tags/base/MorphShapeTag.java | 18 +- .../decompiler/flash/xfl/XFLConverter.java | 256 +++++++++++------- 3 files changed, 164 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c48da43f0..4bc83501a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. - [#1860] FLA export - EmptyStackException during exporting MorphShape - [#1782] FLA export - exporting from SWF files inside bundles (like binarysearch) - Expand correct tree on SWF load +- [#1679] FLA export - MorphShapes (shape tween) ## [16.0.3] - 2022-11-02 ### Fixed @@ -2459,6 +2460,7 @@ All notable changes to this project will be documented in this file. [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 [#1860]: https://www.free-decompiler.com/flash/issues/1860 [#1782]: https://www.free-decompiler.com/flash/issues/1782 +[#1679]: https://www.free-decompiler.com/flash/issues/1679 [#1817]: https://www.free-decompiler.com/flash/issues/1817 [#1816]: https://www.free-decompiler.com/flash/issues/1816 [#1859]: https://www.free-decompiler.com/flash/issues/1859 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java index 8ea363080..84bf72e52 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java @@ -230,8 +230,8 @@ public abstract class MorphShapeTag extends DrawableTag { } StyleChangeRecord scr = scr1.clone(); if (scr1.stateMoveTo || scr2.stateMoveTo) { - scr.moveDeltaX = startPosX + (endPosX - startPosX) * ratio / MAX_RATIO; - scr.moveDeltaY = startPosY + (endPosY - startPosY) * ratio / MAX_RATIO; + scr.moveDeltaX = startPosX + (int)Math.round((endPosX - startPosX) * ratio / (double)MAX_RATIO); + scr.moveDeltaY = startPosY + (int)Math.round((endPosY - startPosY) * ratio / (double)MAX_RATIO); scr.stateMoveTo = scr.moveDeltaX != posX || scr.moveDeltaY != posY; } finalRecords.add(scr); @@ -264,10 +264,10 @@ public abstract class MorphShapeTag extends DrawableTag { continue; } CurvedEdgeRecord cer = new CurvedEdgeRecord(); - cer.controlDeltaX = cer1.controlDeltaX + (cer2.controlDeltaX - cer1.controlDeltaX) * ratio / MAX_RATIO; - cer.controlDeltaY = cer1.controlDeltaY + (cer2.controlDeltaY - cer1.controlDeltaY) * ratio / MAX_RATIO; - cer.anchorDeltaX = cer1.anchorDeltaX + (cer2.anchorDeltaX - cer1.anchorDeltaX) * ratio / MAX_RATIO; - cer.anchorDeltaY = cer1.anchorDeltaY + (cer2.anchorDeltaY - cer1.anchorDeltaY) * ratio / MAX_RATIO; + cer.controlDeltaX = cer1.controlDeltaX + (int)Math.round((cer2.controlDeltaX - cer1.controlDeltaX) * ratio / (double)MAX_RATIO); + cer.controlDeltaY = cer1.controlDeltaY + (int)Math.round((cer2.controlDeltaY - cer1.controlDeltaY) * ratio / (double)MAX_RATIO); + cer.anchorDeltaX = cer1.anchorDeltaX + (int)Math.round((cer2.anchorDeltaX - cer1.anchorDeltaX) * ratio / (double)MAX_RATIO); + cer.anchorDeltaY = cer1.anchorDeltaY + (int)Math.round((cer2.anchorDeltaY - cer1.anchorDeltaY) * ratio / (double)MAX_RATIO); startPosX += cer1.controlDeltaX + cer1.anchorDeltaX; startPosY += cer1.controlDeltaY + cer1.anchorDeltaY; endPosX += cer2.controlDeltaX + cer2.anchorDeltaX; @@ -290,8 +290,8 @@ public abstract class MorphShapeTag extends DrawableTag { StraightEdgeRecord ser = new StraightEdgeRecord(); ser.generalLineFlag = true; ser.vertLineFlag = false; - ser.deltaX = ser1.deltaX + (ser2.deltaX - ser1.deltaX) * ratio / MAX_RATIO; - ser.deltaY = ser1.deltaY + (ser2.deltaY - ser1.deltaY) * ratio / MAX_RATIO; + ser.deltaX = ser1.deltaX + (int)Math.round((ser2.deltaX - ser1.deltaX) * ratio / (double)MAX_RATIO); + ser.deltaY = ser1.deltaY + (int)Math.round((ser2.deltaY - ser1.deltaY) * ratio / (double)MAX_RATIO); startPosX += ser1.deltaX; startPosY += ser1.deltaY; endPosX += ser2.deltaX; @@ -307,7 +307,7 @@ public abstract class MorphShapeTag extends DrawableTag { shape.shapeRecords = finalRecords; return shape; } - + @Override public int getUsedParameters() { return PARAMETER_RATIO; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index d11b7ade5..c79f73f73 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -137,11 +137,13 @@ import com.jpexs.helpers.SerializableImage; import com.jpexs.helpers.utf8.Utf8Helper; import java.awt.Font; import java.awt.Point; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -156,6 +158,8 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -163,11 +167,17 @@ import javax.xml.stream.XMLStreamException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -246,7 +256,7 @@ public class XFLConverter { } } if (!hasMove) { - ret.append("!").append(startX).append(" ").append(startY); + ret.append("! ").append(startX).append(" ").append(startY); } for (SHAPERECORD rec : records) { convertShapeEdge(mat, rec, x, y, ret); @@ -810,47 +820,34 @@ public class XFLConverter { strokesNewStr.writeStartElement("strokes"); if (fillStyleCount > 0 || lineStyleCount > 0) { - if ((fillStyle0 > 0) || (fillStyle1 > 0) || (strokeStyle > 0)) { - - boolean empty = false; - if ((fillStyle0 <= 0) && (fillStyle1 <= 0) && (strokeStyle > 0) && morphshape) { - if (shapeNum == 4) { - if (strokeStyleOrig > 0) { - if (actualLinestyles != null && !((LINESTYLE2) actualLinestyles.lineStyles2[strokeStyleOrig]).hasFillFlag) { - RGBA color = (RGBA) actualLinestyles.lineStyles2[strokeStyleOrig].getColor(); - if (color.alpha == 0 && color.red == 0 && color.green == 0 && color.blue == 0) { - empty = true; - } - } - } - } + if ((fillStyle0 > 0) || (fillStyle1 > 0) || (strokeStyle > 0)) { + currentLayer.writeStartElement("Edge"); + if (fillStyle0 > -1) { + currentLayer.writeAttribute("fillStyle0", fillStyle0); } - if (!empty) { - currentLayer.writeStartElement("Edge"); - if (fillStyle0 > -1) { - currentLayer.writeAttribute("fillStyle0", fillStyle0); - } - if (fillStyle1 > -1) { - currentLayer.writeAttribute("fillStyle1", fillStyle1); - } - if (strokeStyle > -1) { - currentLayer.writeAttribute("strokeStyle", strokeStyle); - } - StringBuilder edgesSb = new StringBuilder(); - convertShapeEdges(startEdgeX, startEdgeY, mat, edges, edgesSb); - currentLayer.writeAttribute("edges", edgesSb.toString()); - currentLayer.writeEndElement(); - hasEdge = true; + if (fillStyle1 > -1) { + currentLayer.writeAttribute("fillStyle1", fillStyle1); } + if (strokeStyle > -1) { + currentLayer.writeAttribute("strokeStyle", strokeStyle); + } + StringBuilder edgesSb = new StringBuilder(); + convertShapeEdges(startEdgeX, startEdgeY, mat, edges, edgesSb); + currentLayer.writeAttribute("edges", edgesSb.toString()); + currentLayer.writeEndElement(); + hasEdge = true; } - } if (currentLayer.length() > 0) { currentLayer.writeEndElement(); // edges currentLayer.writeEndElement(); // DOMShape } if (currentLayer.length() > 0 && hasEdge) { //no empty layers - layers.add(currentLayer.toString()); + String s = currentLayer.toString(); + if (morphshape) { + s = removeOnlyStrokeEdgesBeforeSameFilled(s); + } + layers.add(s); } currentLayer.setLength(0); hasEdge = false; @@ -905,43 +902,28 @@ public class XFLConverter { styleChange = true; } if (scr.stateLineStyle) { - strokeStyle = scr.lineStyle;// == 0 ? 0 : lineStyleCount - lastLineStyleCount + scr.lineStyle; + strokeStyle = scr.lineStyle; strokeStyleOrig = scr.lineStyle - 1; styleChange = true; } if (!edges.isEmpty()) { - if ((fillStyle0 > 0) || (fillStyle1 > 0) || (strokeStyle > 0)) { - boolean empty = false; - if ((fillStyle0 <= 0) && (fillStyle1 <= 0) && (strokeStyle > 0) && morphshape) { - if (shapeNum == 4) { - if (strokeStyleOrig > 0) { - if (actualLinestyles != null && !((LINESTYLE2) actualLinestyles.lineStyles2[strokeStyleOrig]).hasFillFlag) { - RGBA color = (RGBA) actualLinestyles.lineStyles2[strokeStyleOrig].getColor(); - if (color.alpha == 0 && color.red == 0 && color.green == 0 && color.blue == 0) { - empty = true; - } - } - } - } + if ((fillStyle0 > 0) || (fillStyle1 > 0) || (strokeStyle > 0)) { + currentLayer.writeStartElement("Edge"); + if (lastFillStyle0 > -1) { + currentLayer.writeAttribute("fillStyle0", lastFillStyle0); } - if (!empty) { - currentLayer.writeStartElement("Edge"); - if (lastFillStyle0 > -1) { - currentLayer.writeAttribute("fillStyle0", lastFillStyle0); - } - if (lastFillStyle1 > -1) { - currentLayer.writeAttribute("fillStyle1", lastFillStyle1); - } - if (lastStrokeStyle > -1) { - currentLayer.writeAttribute("strokeStyle", lastStrokeStyle); - } - StringBuilder edgesSb = new StringBuilder(); - convertShapeEdges(startEdgeX, startEdgeY, mat, edges, edgesSb); - currentLayer.writeAttribute("edges", edgesSb.toString()); - currentLayer.writeEndElement(); - hasEdge = true; + if (lastFillStyle1 > -1) { + currentLayer.writeAttribute("fillStyle1", lastFillStyle1); } - + if (lastStrokeStyle > -1) { + currentLayer.writeAttribute("strokeStyle", lastStrokeStyle); + } + StringBuilder edgesSb = new StringBuilder(); + convertShapeEdges(startEdgeX, startEdgeY, mat, edges, edgesSb); + currentLayer.writeAttribute("edges", edgesSb.toString()); + currentLayer.writeEndElement(); + hasEdge = true; + startEdgeX = x; startEdgeY = y; } @@ -953,38 +935,22 @@ public class XFLConverter { y = edge.changeY(y); } if (!edges.isEmpty()) { - if ((fillStyle0 > 0) || (fillStyle1 > 0) || (strokeStyle > 0)) { - - boolean empty = false; - if ((fillStyle0 <= 0) && (fillStyle1 <= 0) && (strokeStyle > 0) && morphshape) { - if (shapeNum == 4) { - if (strokeStyleOrig > 0) { - if (actualLinestyles != null && !((LINESTYLE2) actualLinestyles.lineStyles2[strokeStyleOrig]).hasFillFlag) { - RGBA color = (RGBA) actualLinestyles.lineStyles2[strokeStyleOrig].getColor(); - if (color.alpha == 0 && color.red == 0 && color.green == 0 && color.blue == 0) { - empty = true; - } - } - } - } + if ((fillStyle0 > 0) || (fillStyle1 > 0) || (strokeStyle > 0)) { + currentLayer.writeStartElement("Edge"); + if (fillStyle0 > -1) { + currentLayer.writeAttribute("fillStyle0", fillStyle0); } - if (!empty) { - currentLayer.writeStartElement("Edge"); - if (fillStyle0 > -1) { - currentLayer.writeAttribute("fillStyle0", fillStyle0); - } - if (fillStyle1 > -1) { - currentLayer.writeAttribute("fillStyle1", fillStyle1); - } - if (strokeStyle > -1) { - currentLayer.writeAttribute("strokeStyle", strokeStyle); - } - StringBuilder edgesSb = new StringBuilder(); - convertShapeEdges(startEdgeX, startEdgeY, mat, edges, edgesSb); - currentLayer.writeAttribute("edges", edgesSb.toString()); - currentLayer.writeEndElement(); - hasEdge = true; + if (fillStyle1 > -1) { + currentLayer.writeAttribute("fillStyle1", fillStyle1); } + if (strokeStyle > -1) { + currentLayer.writeAttribute("strokeStyle", strokeStyle); + } + StringBuilder edgesSb = new StringBuilder(); + convertShapeEdges(startEdgeX, startEdgeY, mat, edges, edgesSb); + currentLayer.writeAttribute("edges", edgesSb.toString()); + currentLayer.writeEndElement(); + hasEdge = true; } } edges.clear(); @@ -993,11 +959,86 @@ public class XFLConverter { currentLayer.writeEndElement(); // DOMShape if (currentLayer.length() > 0 && hasEdge) { //no empty layers - layers.add(currentLayer.toString()); + String s = currentLayer.toString(); + if (morphshape) { + s = removeOnlyStrokeEdgesBeforeSameFilled(s); + } + layers.add(s); } } return layers; } + + /** + * A hack. This will remove a stroked path with no fill which has same stroke as subsequent path. + * This happens in the morphshape edges. This needs to be cleaned up before exporting to FLA. + * + * @param layer + * @return + */ + private static String removeOnlyStrokeEdgesBeforeSameFilled(String layer) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + dbf.setNamespaceAware(false); + dbf.setValidating(false); + DocumentBuilder db; + try { + db = dbf.newDocumentBuilder(); + String docString = "" + layer + ""; + Document doc = db.parse(new ByteArrayInputStream(docString.getBytes("UTF-8"))); + NodeList edgesParentList = doc.getElementsByTagName("edges"); + String prevStrokeOnly = null; + String prevEdgesStr = ""; + for (int j = 0; j < edgesParentList.getLength(); j++) { + Node edgesParent = edgesParentList.item(j); + NodeList edges = edgesParent.getChildNodes(); + Node prevNode = null; + for (int i = 0; i < edges.getLength(); i++) { + Node edge = edges.item(i); + if (edge.getNodeType() == Node.TEXT_NODE) { + continue; + } + NamedNodeMap attributes = edge.getAttributes(); + Node strokeStyleNode = attributes.getNamedItem("strokeStyle"); + Node fillStyle0Node = attributes.getNamedItem("fillStyle0"); + Node fillStyle1Node = attributes.getNamedItem("fillStyle1"); + Node edgesNode = attributes.getNamedItem("edges"); + String edgesStr = edgesNode.getNodeValue(); + + String strokeStyle = strokeStyleNode != null ? strokeStyleNode.getNodeValue() : null; + String fillStyle0 = fillStyle0Node != null ? fillStyle0Node.getNodeValue() : null; + String fillStyle1 = fillStyle1Node != null ? fillStyle1Node.getNodeValue() : null; + + if (prevStrokeOnly != null && + strokeStyle != null && + strokeStyle.equals(prevStrokeOnly) && + prevEdgesStr.equals(edgesStr)) { + Node edgeToRemove = prevNode; + edgeToRemove.getParentNode().removeChild(edgeToRemove); + } + + prevStrokeOnly = null; + if (strokeStyle != null && fillStyle0 == null && fillStyle1 == null) { + prevStrokeOnly = strokeStyle; + } + prevNode = edge; + prevEdgesStr = edgesStr; + } + } + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + String output = writer.getBuffer().toString(); + output = output.trim(); + output = output.substring(3, output.length() - 4); + return output; + } catch (TransformerException | SAXException | IOException | ParserConfigurationException ex) { + Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, null, ex); + } + return layer; + } private static int getLayerCount(ReadOnlyTagList tags) { int maxDepth = 0; @@ -2269,8 +2310,8 @@ public class XFLConverter { int characterId = -1; int ratio = -1; boolean shapeTween = false; - boolean lastShapeTween = false; MorphShapeTag shapeTweener = null; + int lastTweenRatio = -1; //Add ShowFrameTag to the end when there is one last missing List timTags = timelineTags.toArrayList(); @@ -2360,7 +2401,8 @@ public class XFLConverter { if (shapeTween && character != null) { MorphShapeTag m = (MorphShapeTag) character; shapeTweener = m; - shapeTween = false; + shapeTween = false; + lastTweenRatio = ratio; } character = null; metadata = null; @@ -2384,7 +2426,18 @@ public class XFLConverter { if (frame + 1 <= endFrame) { lastIn = true; - if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(characterId) || shapeTweener != null)) { + if (shapeTweener != null) { + MorphShapeTag m = shapeTweener; + XFLXmlWriter addLastWriter = new XFLXmlWriter(); + SHAPEWITHSTYLE endShape = m.getShapeAtRatio(lastTweenRatio); + convertShape(characters, matrix, m.getShapeNum() == 1 ? 3 : 4, endShape.shapeRecords, m.getFillStyles().getFillStylesAt(lastTweenRatio), m.getLineStyles().getLineStylesAt(m.getShapeNum(), lastTweenRatio), true, false, addLastWriter); + duration--; + convertFrame(true, null, null, frame - duration, duration, "", lastElements, files, writer2); + duration = 1; + lastElements = addLastWriter.toString(); + shapeTweener = null; + } + if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(characterId))) { // || shapeTweener != null)) { ShapeTag shape = (ShapeTag) character; convertShape(characters, matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, false, false, elementsWriter); shapeTween = false; @@ -2409,7 +2462,7 @@ public class XFLConverter { frame++; String elements = elementsWriter.toString(); if (!elements.equals(lastElements) && frame > 0) { - convertFrame(lastShapeTween, null, null, frame - duration, duration, "", lastElements, files, writer2); + convertFrame(false, null, null, frame - duration, duration, "", lastElements, files, writer2); duration = 1; } else if (frame == 0) { duration = 1; @@ -2417,19 +2470,16 @@ public class XFLConverter { duration++; } - lastShapeTween = shapeTween; lastElements = elements; if (frame > endFrame) { if (lastIn) { lastElements = ""; - lastShapeTween = false; lastIn = false; } } } else { if (lastIn) { lastElements = ""; - lastShapeTween = false; lastIn = false; } frame++; @@ -2443,7 +2493,7 @@ public class XFLConverter { } if (!lastElements.isEmpty()) { frame++; - convertFrame(lastShapeTween, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2); + convertFrame(false, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2); } afterStr = "" + afterStr; From 0d40e84d8b024e6fb74cf4088ad6371e5899b3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 19:57:00 +0100 Subject: [PATCH 7/9] morphshape test data [ci skip] --- .../testdata/morphshape/morphshape.html | 49 +++++ .../testdata/morphshape/morphshape.swf | Bin 0 -> 1260 bytes .../morphshape/morphshape/DOMDocument.xml | 111 ++++++++++ .../morphshape/META-INF/metadata.xml | 110 ++++++++++ .../morphshape/morphshape/MobileSettings.xml | 0 .../morphshape/morphshape/PublishSettings.xml | 206 ++++++++++++++++++ .../morphshape/morphshape/bin/SymDepend.cache | Bin 0 -> 28 bytes .../morphshape/morphshape/morphshape.xfl | 1 + 8 files changed, 477 insertions(+) create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape.html create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape.swf create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape/DOMDocument.xml create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape/META-INF/metadata.xml create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape/MobileSettings.xml create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape/PublishSettings.xml create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape/bin/SymDepend.cache create mode 100644 libsrc/ffdec_lib/testdata/morphshape/morphshape/morphshape.xfl diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape.html b/libsrc/ffdec_lib/testdata/morphshape/morphshape.html new file mode 100644 index 000000000..17fe7a4a6 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/morphshape/morphshape.html @@ -0,0 +1,49 @@ + + + + morphshape + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + Get Adobe Flash player + + + + + +
+ + diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape.swf b/libsrc/ffdec_lib/testdata/morphshape/morphshape.swf new file mode 100644 index 0000000000000000000000000000000000000000..0983c22d94d0a369bfedf45e2c885f24f2aa60ee GIT binary patch literal 1260 zcmVUuF>d7n zZK9Pngj9|lC+$WV0~|;G&wsw}i~sNcbut9p-2f~f1E8iH#C&OmewW6$I1b9*HfdN6yQbW8(F#(#gbP$M*>5w;7y;D`? zX3j#9Ntrh?4n}c+a@iUA+80`!) zEKRe)h@Xz2U=cTu%u`d)4>k+xJNWKQ^&{a|D9lj~@0+MW^ zu5ow*;vnzmZXe#|QZV z=UCjm}{WQti-C`*i^#_&R4`QYp4gF-%?& zU|YNyB?6Kpvf=T!iMhWGlCzx`agWU7;=wKryMS zS-T4wuN%;EYGZA|D$6F@UshVeChngK`wO+8CN5#qO{$5D3(2R{|6|kNN|43IEcmqa zNK?)s*i3>LK0iOdb_D=+OdSR58XwxtYwaB&xk2gL7Uejmy=zM!4Nk49Kqn{$Is~Xd zk^x}Ts!Mi4d$A4k$rC&Jl&v$q(X%_Wmk#{l+dl#N%;$5yEAOAicG|FcfNu1`Rss>& zmzA0K-FfV_B=N@UY|Y`m{^_^BzIX0Z`bgEgQ^}b(KYsP8irgnhys62PGY={+@A>(a zZO?u2)wp@#r>$oIaG#sLBeVq^E)9M+{iJgD58&1d-|p$iu`Kb+=q)3sT^o*p;GrK! zX5KsS>kIoU=k}coue~UEm#1bY$8fnFtUu$OJTdm=!KoI{T;%rA*<~Y7{666se+PVc z7w{gvI(||;df#~3wYU3n>e(xwpLKnQ!BS)R$1s;0Rq-z8K_F} zk`hBFia`~lvSL(epEan%h9>jFWhr$)f-zarJllJAL&5asx8ZTC96D*CUI6sUVTG+i>`>POhevZ}6Sj0~^A#i6?zt1hW= zRTH3$z+43GCNK|CQcB=u1YSyX!!fJ`189MjmAi8EW@{5G zukhsPTpK_u90AJi$Hf7L}JnjB%^29d}90cpnk+@8L Wbm;!d$>XEWd?2%0kj$SD2CP-#%5awe literal 0 HcmV?d00001 diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape/DOMDocument.xml b/libsrc/ffdec_lib/testdata/morphshape/morphshape/DOMDocument.xml new file mode 100644 index 000000000..c7560f614 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/morphshape/morphshape/DOMDocument.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape/META-INF/metadata.xml b/libsrc/ffdec_lib/testdata/morphshape/morphshape/META-INF/metadata.xml new file mode 100644 index 000000000..acad0faf0 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/morphshape/morphshape/META-INF/metadata.xml @@ -0,0 +1,110 @@ + + + + + Adobe Flash Professional CS6 - build 481 + 2021-11-29T21:00:28-08:00 + 2022-11-03T11:43:33-07:00 + 2022-11-03T11:43:33-07:00 + + + application/vnd.adobe.fla + + + xmp.iid:6A6D3EE1675BED11AEA5D18306A6F790 + xmp.did:6A6D3EE1675BED11AEA5D18306A6F790 + xmp.did:C5BAF59A1F51EC118EC6DBA80AAFBA90 + + + + created + xmp.iid:C5BAF59A1F51EC118EC6DBA80AAFBA90 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + created + xmp.iid:DB01969D1058EC11B0BD896CDB4C1F9F + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + created + xmp.iid:FCCDB50C4558EC11A79581A4DE002270 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + created + xmp.iid:CBDFDAC26B53ED11A79581A4DE002270 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + created + xmp.iid:7DAC1B2F7E56ED11AEA5D18306A6F790 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + created + xmp.iid:83AC1B2F7E56ED11AEA5D18306A6F790 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + created + xmp.iid:676D3EE1675BED11AEA5D18306A6F790 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + saved + xmp.iid:696D3EE1675BED11AEA5D18306A6F790 + 2022-11-03T08:49:07-07:00 + Adobe Flash Professional CS6 - build 481 + / + + + created + xmp.iid:6A6D3EE1675BED11AEA5D18306A6F790 + 2021-11-29T21:00:28-08:00 + Adobe Flash Professional CS6 - build 481 + + + + + xmp.iid:696D3EE1675BED11AEA5D18306A6F790 + xmp.did:696D3EE1675BED11AEA5D18306A6F790 + xmp.did:C5BAF59A1F51EC118EC6DBA80AAFBA90 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape/MobileSettings.xml b/libsrc/ffdec_lib/testdata/morphshape/morphshape/MobileSettings.xml new file mode 100644 index 000000000..e69de29bb diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape/PublishSettings.xml b/libsrc/ffdec_lib/testdata/morphshape/morphshape/PublishSettings.xml new file mode 100644 index 000000000..39e2502ca --- /dev/null +++ b/libsrc/ffdec_lib/testdata/morphshape/morphshape/PublishSettings.xml @@ -0,0 +1,206 @@ + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + Untitledas3.swf + Untitledas3.exe + Untitledas3.app + Untitledas3.html + Untitledas3.gif + Untitledas3.jpg + Untitledas3.png + Untitledas3.mov + Untitledas3.smil + Untitledas3.swc + + + 0 + 12,0,0,0;11,2,0,0;11,1,0,0;10,3,0,0;10,2,153,0;10,1,52,0;9,0,124,0;8,0,24,0;7,0,14,0;6,0,79,0;5,0,58,0;4,0,32,0;3,0,8,0;2,0,1,12;1,0,0,1; + 1 + 1 + Untitledas3.xfl_content.html + Untitledas3.xfl_alternate.html + 0 + + 550 + 400 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 4 + 0 + 0 + 1 + 0 + C:\Users\MyUser\AppData\Local\Adobe\Flash CS6\en_US\Configuration\HTML\Default.html + 1 + + + + + 0 + 0 + 0 + 80 + 0 + 0 + 7 + 0 + 7 + 0 + 15 + FlashPlayer11.2 + 3 + 1 + + . + CONFIG::FLASH_AUTHORING="true"; + 1 + + 1 + 0 + 1 + 0 + 0 + 0 + 0 + MainClass + 2 + 4 + 4096 + AS3 + 1 + 1 + 0 + 15 + 1 + 0 + 4102 + rsl + wrap + $(AppConfig)/ActionScript 3.0/rsls/loader_animation.swf + + + $(AppConfig)/ActionScript 3.0/libs + merge + + + $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc + rsl + http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz + http://fpdownload.adobe.com/pub/swz/crossdomain.xml + textLayout_2.0.0.232.swz + + + + + $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc + + http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz + http://fpdownload.adobe.com/pub/swz/crossdomain.xml + textLayout_2.0.0.232.swz + + + + + 550 + 400 + 0 + 4718592 + 0 + 80 + 1 + + + 1 + 0 + 1 + 0 + 0 + 100000 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + + + 550 + 400 + 0 + 1 + 1 + 0 + 1 + 0 + 1 + 0 + 0 + + 128 + + + 255 + + + + 550 + 400 + 1 + 0 + 0 + 1 + 0 + 0 + 1 + + + + 24-bit with Alpha + 255 + + + + 550 + 400 + 1 + 0 + + + 00000000 + 0 + 0 + 0 + 0 + 1 + + + \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape/bin/SymDepend.cache b/libsrc/ffdec_lib/testdata/morphshape/morphshape/bin/SymDepend.cache new file mode 100644 index 0000000000000000000000000000000000000000..87dc366b16e8509cb16fa36918ad50a7418acf4f GIT binary patch literal 28 fcmYdiU|@L0&dtEWz|6qSpv|BN`? literal 0 HcmV?d00001 diff --git a/libsrc/ffdec_lib/testdata/morphshape/morphshape/morphshape.xfl b/libsrc/ffdec_lib/testdata/morphshape/morphshape/morphshape.xfl new file mode 100644 index 000000000..860a820ec --- /dev/null +++ b/libsrc/ffdec_lib/testdata/morphshape/morphshape/morphshape.xfl @@ -0,0 +1 @@ +PROXY-CS5 \ No newline at end of file From 9f1970fdfabedb96c629495a06c284bb8881c4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 21:33:00 +0100 Subject: [PATCH 8/9] Fixed #1860, #1732, #1837 FLA export - AS3 - missing framescripts on the timeline --- CHANGELOG.md | 3 +++ .../flash/abc/types/traits/TraitClass.java | 6 ++++- .../decompiler/flash/xfl/XFLConverter.java | 22 ++++++++++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bc83501a..1b296042d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. - [#1782] FLA export - exporting from SWF files inside bundles (like binarysearch) - Expand correct tree on SWF load - [#1679] FLA export - MorphShapes (shape tween) +- [#1860], [#1732], [#1837] FLA export - AS3 - missing framescripts on the timeline ## [16.0.3] - 2022-11-02 ### Fixed @@ -2461,6 +2462,8 @@ All notable changes to this project will be documented in this file. [#1860]: https://www.free-decompiler.com/flash/issues/1860 [#1782]: https://www.free-decompiler.com/flash/issues/1782 [#1679]: https://www.free-decompiler.com/flash/issues/1679 +[#1732]: https://www.free-decompiler.com/flash/issues/1732 +[#1837]: https://www.free-decompiler.com/flash/issues/1837 [#1817]: https://www.free-decompiler.com/flash/issues/1817 [#1816]: https://www.free-decompiler.com/flash/issues/1816 [#1859]: https://www.free-decompiler.com/flash/issues/1859 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 50d81a903..076559427 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.model.CallPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item; @@ -282,7 +283,10 @@ public class TraitClass extends Trait implements TraitWithSlot { if ("addFrameScript".equals(propName.resolvedMultinameName)) { for (int i = 0; i < callProp.arguments.size(); i += 2) { if (callProp.arguments.get(i) instanceof IntegerValueAVM2Item) { - if (callProp.arguments.get(i + 1) instanceof GetPropertyAVM2Item) { + if (callProp.arguments.get(i + 1) instanceof GetLexAVM2Item) { + GetLexAVM2Item lex = (GetLexAVM2Item) callProp.arguments.get(i + 1); + frameTraitNames.add(abc.constants.getMultinameId(lex.propertyName, false)); + } else if (callProp.arguments.get(i + 1) instanceof GetPropertyAVM2Item) { GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) callProp.arguments.get(i + 1); if (getProp.object instanceof ThisAVM2Item) { if (getProp.propertyName instanceof FullMultinameAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index c79f73f73..75840ce2d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -26,12 +26,14 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.avm2.model.CallPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -2629,7 +2631,7 @@ public class XFLConverter { try { constructorBody.convert(new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); - Map frameToTraitMultiname = new HashMap<>(); + Map frameToTraitMultiname = new HashMap<>(); //find all addFrameScript(xx,this.method) in constructor /* @@ -2657,13 +2659,16 @@ public class XFLConverter { if (callProp.arguments.get(i) instanceof IntegerValueAVM2Item) { IntegerValueAVM2Item frameItem = (IntegerValueAVM2Item) callProp.arguments.get(i); int frame = frameItem.intValue(); - if (callProp.arguments.get(i + 1) instanceof GetPropertyAVM2Item) { + if (callProp.arguments.get(i + 1) instanceof GetLexAVM2Item) { + GetLexAVM2Item lex = (GetLexAVM2Item) callProp.arguments.get(i + 1); + frameToTraitMultiname.put(frame, lex.propertyName); + } else if (callProp.arguments.get(i + 1) instanceof GetPropertyAVM2Item) { GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) callProp.arguments.get(i + 1); if (getProp.object instanceof ThisAVM2Item) { if (getProp.propertyName instanceof FullMultinameAVM2Item) { FullMultinameAVM2Item framePropName = (FullMultinameAVM2Item) getProp.propertyName; int multinameIndex = framePropName.multinameIndex; - frameToTraitMultiname.put(frame, multinameIndex); + frameToTraitMultiname.put(frame, abc.constants.getMultiname(multinameIndex)); } } } @@ -2674,15 +2679,16 @@ public class XFLConverter { } } } - Map multinameToMethodTrait = new HashMap<>(); + Map multinameToMethodTrait = new HashMap<>(); for (Trait trait : instanceInfo.instance_traits.traits) { if (trait instanceof TraitMethodGetterSetter) { - multinameToMethodTrait.put(trait.name_index, (TraitMethodGetterSetter) trait); + Multiname m = abc.constants.getMultiname(trait.name_index); + multinameToMethodTrait.put(abc.constants.getMultiname(trait.name_index), (TraitMethodGetterSetter) trait); } } for (int frame : frameToTraitMultiname.keySet()) { - int multiName = frameToTraitMultiname.get(frame); + Multiname multiName = frameToTraitMultiname.get(frame); if (multinameToMethodTrait.containsKey(multiName)) { TraitMethodGetterSetter methodTrait = multinameToMethodTrait.get(multiName); int methodIndex = methodTrait.method_info; @@ -2722,6 +2728,10 @@ public class XFLConverter { if (!script.isEmpty()) { script = "#initclip\r\n" + script + "#endinitclip\r\n"; } + + if (spriteId == 320) { + System.err.println("xxx"); + } Map frameToScriptMap = new HashMap<>(); From b712fd4b440e41acc8d06fb94604d60798302418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 3 Nov 2022 22:16:44 +0100 Subject: [PATCH 9/9] Fixed Flash viewer - dropshadow filter hideobject(compositeSource) parameter --- CHANGELOG.md | 1 + .../flash/types/filters/DROPSHADOWFILTER.java | 2 +- .../flash/types/filters/Filtering.java | 30 ++++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b296042d..ba8b43d51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Expand correct tree on SWF load - [#1679] FLA export - MorphShapes (shape tween) - [#1860], [#1732], [#1837] FLA export - AS3 - missing framescripts on the timeline +- Flash viewer - dropshadow filter hideobject(compositeSource) parameter ## [16.0.3] - 2022-11-02 ### Fixed diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java index 12ade420e..1b33b3002 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/DROPSHADOWFILTER.java @@ -93,7 +93,7 @@ public class DROPSHADOWFILTER extends FILTER { @Override public SerializableImage apply(SerializableImage src, double zoom) { - return Filtering.dropShadow(src, (int) Math.round(blurX * zoom), (int) Math.round(blurY * zoom), (int) (angle * 180 / Math.PI), distance * zoom, dropShadowColor.toColor(), innerShadow, passes, strength, knockout); + return Filtering.dropShadow(src, (int) Math.round(blurX * zoom), (int) Math.round(blurY * zoom), (int) (angle * 180 / Math.PI), distance * zoom, dropShadowColor.toColor(), innerShadow, passes, strength, knockout, compositeSource); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/Filtering.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/Filtering.java index 538861eb5..4235c7c87 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/Filtering.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/Filtering.java @@ -286,8 +286,8 @@ public class Filtering { BufferedImage shadowInner = null; BufferedImage hilightInner = null; if (type != OUTER) { - BufferedImage hilightIm = dropShadow(src, 0, 0, angle, distance, Color.red, true, iterations, strength, true);//new DropShadowFilter(blurX, blurY, strength, inner ? highlightColor : shadowColor, angle, distance, inner, true, iterations).filter(src - BufferedImage shadowIm = dropShadow(src, 0, 0, angle + 180, distance, Color.blue, true, iterations, strength, true); //new DropShadowFilter(blurX, blurY, strength, inner ? shadowColor : highlightColor, angle + 180, distance, inner, true, iterations).filter(src); + BufferedImage hilightIm = dropShadow(src, 0, 0, angle, distance, Color.red, true, iterations, strength, true, true);//new DropShadowFilter(blurX, blurY, strength, inner ? highlightColor : shadowColor, angle, distance, inner, true, iterations).filter(src + BufferedImage shadowIm = dropShadow(src, 0, 0, angle + 180, distance, Color.blue, true, iterations, strength, true, true); //new DropShadowFilter(blurX, blurY, strength, inner ? shadowColor : highlightColor, angle + 180, distance, inner, true, iterations).filter(src); BufferedImage h2 = new BufferedImage(width, height, src.getType()); BufferedImage s2 = new BufferedImage(width, height, src.getType()); Graphics2D hc = h2.createGraphics(); @@ -306,8 +306,8 @@ public class Filtering { BufferedImage shadowOuter = null; BufferedImage hilightOuter = null; if (type != INNER) { - BufferedImage hilightIm = dropShadow(src, 0, 0, angle + 180, distance, Color.red, false, iterations, strength, true);//new DropShadowFilter(blurX, blurY, strength, inner ? highlightColor : shadowColor, angle, distance, inner, true, iterations).filter(src - BufferedImage shadowIm = dropShadow(src, 0, 0, angle, distance, Color.blue, false, iterations, strength, true); //new DropShadowFilter(blurX, blurY, strength, inner ? shadowColor : highlightColor, angle + 180, distance, inner, true, iterations).filter(src); + BufferedImage hilightIm = dropShadow(src, 0, 0, angle + 180, distance, Color.red, false, iterations, strength, true, true);//new DropShadowFilter(blurX, blurY, strength, inner ? highlightColor : shadowColor, angle, distance, inner, true, iterations).filter(src + BufferedImage shadowIm = dropShadow(src, 0, 0, angle, distance, Color.blue, false, iterations, strength, true, true); //new DropShadowFilter(blurX, blurY, strength, inner ? shadowColor : highlightColor, angle + 180, distance, inner, true, iterations).filter(src); BufferedImage h2 = new BufferedImage(width, height, src.getType()); BufferedImage s2 = new BufferedImage(width, height, src.getType()); Graphics2D hc = h2.createGraphics(); @@ -382,11 +382,11 @@ public class Filtering { } public static SerializableImage glow(SerializableImage src, int blurX, int blurY, float strength, Color color, boolean inner, boolean knockout, int iterations) { - return new SerializableImage(dropShadow(src.getBufferedImage(), blurX, blurY, 45, 0, color, inner, iterations, strength, knockout)); + return new SerializableImage(dropShadow(src.getBufferedImage(), blurX, blurY, 45, 0, color, inner, iterations, strength, knockout, true)); } - public static SerializableImage dropShadow(SerializableImage src, int blurX, int blurY, float angle, double distance, Color color, boolean inner, int iterations, float strength, boolean knockout) { - return new SerializableImage(dropShadow(src.getBufferedImage(), blurX, blurY, angle, distance, color, inner, iterations, strength, knockout)); + public static SerializableImage dropShadow(SerializableImage src, int blurX, int blurY, float angle, double distance, Color color, boolean inner, int iterations, float strength, boolean knockout, boolean compositeSource) { + return new SerializableImage(dropShadow(src.getBufferedImage(), blurX, blurY, angle, distance, color, inner, iterations, strength, knockout, compositeSource)); } private static int cut(int val, int min, int max) { @@ -399,7 +399,7 @@ public class Filtering { return val; } - private static BufferedImage dropShadow(BufferedImage src, int blurX, int blurY, float angle, double distance, Color color, boolean inner, int iterations, float strength, boolean knockout) { + private static BufferedImage dropShadow(BufferedImage src, int blurX, int blurY, float angle, double distance, Color color, boolean inner, int iterations, float strength, boolean knockout, boolean compositeSource) { int width = src.getWidth(); int height = src.getHeight(); int[] srcPixels = getRGB(src); @@ -424,18 +424,20 @@ public class Filtering { blur(shadow, width, height, blurX, blurY, iterations, null); } - for (int i = 0; i < shadow.length; i++) { - int mask = (srcPixels[i] >> 24) & 0xff; - if (!inner) { - mask = 255 - mask; + if (compositeSource) { + for (int i = 0; i < shadow.length; i++) { + int mask = (srcPixels[i] >> 24) & 0xff; + if (!inner) { + mask = 255 - mask; + } + shadow[i] = shadow[i] & 0xffffff + ((mask * ((shadow[i] >> 24) & 0xff) / 255) << 24); } - shadow[i] = shadow[i] & 0xffffff + ((mask * ((shadow[i] >> 24) & 0xff) / 255) << 24); } BufferedImage retCanvas = new BufferedImage(width, height, src.getType()); setRGB(retCanvas, width, height, shadow); - if (!knockout) { + if (!knockout && compositeSource) { Graphics2D g = retCanvas.createGraphics(); g.setComposite(AlphaComposite.DstOver); g.drawImage(src, 0, 0, null);