Merge origin/master

Conflicts:
	libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java
This commit is contained in:
Jindra Petřík
2014-11-04 20:58:15 +01:00
90 changed files with 1977 additions and 2502 deletions

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.helpers.SwfHeaderStreamSearch;

View File

@@ -69,6 +69,7 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
import com.jpexs.decompiler.flash.exporters.modes.FramesExportMode;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter;
import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.FramesExportSettings;
@@ -82,8 +83,7 @@ import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.EndTag;
@@ -117,16 +117,7 @@ import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.SvgClip;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.treenodes.AS2PackageNode;
import com.jpexs.decompiler.flash.treenodes.ContainerNode;
import com.jpexs.decompiler.flash.treenodes.FrameNode;
import com.jpexs.decompiler.flash.treenodes.TagNode;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
@@ -212,7 +203,7 @@ import org.monte.media.avi.AVIWriter;
*
* @author JPEXS
*/
public final class SWF implements TreeItem, Timelined {
public final class SWF implements SWFContainerItem, Timelined {
/**
* Default version of SWF file format
@@ -278,6 +269,7 @@ public final class SWF implements TreeItem, Timelined {
private Timeline timeline;
public DumpInfoSwfNode dumpInfo;
public DefineBinaryDataTag binaryData;
public void updateCharacters() {
characters.clear();
@@ -285,10 +277,8 @@ public final class SWF implements TreeItem, Timelined {
}
public void resetTimelines(Timelined timelined) {
timelined.resetTimeline();
List<Tag> tags = timelined.getTimeline().tags;
for (int i = 0; i < tags.size(); i++) {
Tag t = tags.get(i);
timelined.getTimeline().reset();
for (Tag t : timelined.getTimeline().tags) {
if (t instanceof Timelined) {
resetTimelines((Timelined) t);
}
@@ -344,11 +334,6 @@ public final class SWF implements TreeItem, Timelined {
return timeline;
}
@Override
public void resetTimeline() {
timeline = null;
}
/**
* Gets all tags with specified id
*
@@ -619,7 +604,7 @@ public final class SWF implements TreeItem, Timelined {
ArrayList<ABCContainerTag> newAbcList = new ArrayList<>();
getABCTags(objs, newAbcList);
isAS3 = !newAbcList.isEmpty();
isAS3 = (fileAttributes != null && fileAttributes.actionScript3) || (fileAttributes == null && !newAbcList.isEmpty());
abcList = newAbcList;
}
@@ -649,8 +634,10 @@ public final class SWF implements TreeItem, Timelined {
if (t instanceof ExportAssetsTag) {
ExportAssetsTag eat = (ExportAssetsTag) t;
for (int i = 0; i < eat.tags.size(); i++) {
if ((!exportNames.containsKey(eat.tags.get(i))) && (!exportNames.containsValue(eat.names.get(i)))) {
exportNames.put(eat.tags.get(i), eat.names.get(i));
Integer tagId = eat.tags.get(i);
String name = eat.names.get(i);
if ((!exportNames.containsKey(tagId)) && (!exportNames.containsValue(name))) {
exportNames.put(tagId, name);
}
}
}
@@ -821,19 +808,10 @@ public final class SWF implements TreeItem, Timelined {
}
public boolean exportAS3Class(String className, String outdir, ScriptExportMode exportMode, boolean parallel) throws Exception {
List<ABCContainerTag> abcTags = new ArrayList<>();
for (Tag t : tags) {
if (t instanceof ABCContainerTag) {
ABCContainerTag cnt = (ABCContainerTag) t;
abcTags.add(cnt);
}
}
boolean exported = false;
for (int i = 0; i < abcTags.size(); i++) {
ABC abc = abcTags.get(i).getABC();
for (int i = 0; i < abcList.size(); i++) {
ABC abc = abcList.get(i).getABC();
List<ScriptPack> scrs = abc.findScriptPacksByPath(className);
for (int j = 0; j < scrs.size(); j++) {
ScriptPack scr = scrs.get(j);
@@ -841,10 +819,10 @@ public final class SWF implements TreeItem, Timelined {
if (scrs.size() > 1) {
cnt = "script " + (j + 1) + "/" + scrs.size() + " ";
}
String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + scr.getPath() + " ...";
String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcList.size() + " " + cnt + scr.getPath() + " ...";
informListeners("exporting", exStr);
scr.export(outdir, abcTags, exportMode, parallel);
exStr = "Exported " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + scr.getPath() + " ...";
scr.export(outdir, abcList, exportMode, parallel);
exStr = "Exported " + "tag " + (i + 1) + "/" + abcList.size() + " " + cnt + scr.getPath() + " ...";
informListeners("exported", exStr);
exported = true;
}
@@ -868,11 +846,8 @@ public final class SWF implements TreeItem, Timelined {
public List<MyEntry<ClassPath, ScriptPack>> getAS3Packs() {
List<MyEntry<ClassPath, ScriptPack>> packs = new ArrayList<>();
for (Tag t : tags) {
if (t instanceof ABCContainerTag) {
ABCContainerTag abcTag = (ABCContainerTag) t;
packs.addAll(abcTag.getABC().getScriptPacks());
}
for (ABCContainerTag abcTag : abcList) {
packs.addAll(abcTag.getABC().getScriptPacks());
}
return uniqueAS3Packs(packs);
}
@@ -932,28 +907,20 @@ public final class SWF implements TreeItem, Timelined {
}
}
public List<File> exportActionScript2(AbortRetryIgnoreHandler handler, String outdir, ScriptExportMode exportMode, boolean parallel, EventListener evl) throws IOException {
private List<File> exportActionScript2(AbortRetryIgnoreHandler handler, String outdir, ScriptExportMode exportMode, boolean parallel, EventListener evl) throws IOException {
List<File> ret = new ArrayList<>();
List<ContainerItem> list2 = new ArrayList<>();
list2.addAll(tags);
List<TreeNode> list = createASTagList(list2, this);
Map<String, ASMSource> asms = getASMs();
if (!outdir.endsWith(File.separator)) {
outdir += File.separator;
}
outdir += "scripts" + File.separator;
ret.addAll(TagNode.exportNodeAS(handler, list, list, outdir, exportMode, evl));
ret.addAll(new AS2ScriptExporter().exportAS2ScriptsTimeout(handler, outdir, asms.values(), exportMode, evl));
return ret;
}
public List<File> exportActionScript3(final AbortRetryIgnoreHandler handler, final String outdir, final ScriptExportMode exportMode, final boolean parallel) {
private List<File> exportActionScript3(final AbortRetryIgnoreHandler handler, final String outdir, final ScriptExportMode exportMode, final boolean parallel) {
final AtomicInteger cnt = new AtomicInteger(1);
final List<ABCContainerTag> abcTags = new ArrayList<>();
for (Tag t : tags) {
if (t instanceof ABCContainerTag) {
abcTags.add((ABCContainerTag) t);
}
}
final List<File> ret = new ArrayList<>();
final List<MyEntry<ClassPath, ScriptPack>> packs = getAS3Packs();
@@ -964,7 +931,7 @@ public final class SWF implements TreeItem, Timelined {
@Override
public Void call() throws Exception {
for (MyEntry<ClassPath, ScriptPack> item : packs) {
ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcTags, exportMode, parallel);
ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcList, exportMode, parallel);
ret.add(task.call());
}
return null;
@@ -979,7 +946,7 @@ public final class SWF implements TreeItem, Timelined {
ExecutorService executor = Executors.newFixedThreadPool(Configuration.parallelThreadCount.get());
List<Future<File>> futureResults = new ArrayList<>();
for (MyEntry<ClassPath, ScriptPack> item : packs) {
Future<File> future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcTags, exportMode, parallel));
Future<File> future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcList, exportMode, parallel));
futureResults.add(future);
}
@@ -1009,7 +976,6 @@ public final class SWF implements TreeItem, Timelined {
}
public List<File> exportActionScript(AbortRetryIgnoreHandler handler, String outdir, ScriptExportMode exportMode, boolean parallel) throws Exception {
boolean asV3Found = false;
List<File> ret = new ArrayList<>();
final EventListener evl = new EventListener() {
@Override
@@ -1019,13 +985,8 @@ public final class SWF implements TreeItem, Timelined {
}
}
};
for (Tag t : tags) {
if (t instanceof ABCContainerTag) {
asV3Found = true;
}
}
if (asV3Found) {
if (isAS3) {
ret.addAll(exportActionScript3(handler, outdir, exportMode, parallel));
} else {
ret.addAll(exportActionScript2(handler, outdir, exportMode, parallel, evl));
@@ -1033,160 +994,30 @@ public final class SWF implements TreeItem, Timelined {
return ret;
}
public static List<TreeNode> createASTagList(List<? extends ContainerItem> list, Timelined parent) {
List<TreeNode> ret = new ArrayList<>();
int frame = 0;
List<TreeNode> frames = new ArrayList<>();
for (ContainerItem t : list) {
TreeNode addNode = null;
if (t instanceof ShowFrameTag) {
// do not add PlaceObjects (+etc) to script nodes
FrameNode tti = new FrameNode(new FrameNodeItem(t.getSwf(), frame, parent, false), null, true);
for (int r = ret.size() - 1; r >= 0; r--) {
TreeNode node = ret.get(r);
TreeItem item = node.getItem();
if (!(item instanceof DefineSpriteTag
|| item instanceof DefineButtonTag
|| item instanceof DefineButton2Tag
|| item instanceof DoInitActionTag
|| item instanceof AS2PackageNodeItem)) {
tti.subNodes.add(node);
ret.remove(r);
}
}
frame++;
frames.add(tti);
} else if (t instanceof ASMSource) {
ContainerNode tti = new ContainerNode(t);
addNode = tti;
} else if (t instanceof Container) {
if (((Container) t).getItemCount() > 0) {
ContainerNode tti = new ContainerNode(t);
List<ContainerItem> subItems = ((Container) t).getSubItems();
Timelined timelined = t instanceof Timelined ? (Timelined) t : null;
tti.subNodes = createASTagList(subItems, timelined);
addNode = tti;
}
}
if (addNode != null) {
if (addNode.getItem() instanceof CharacterIdTag) {
CharacterIdTag cit = (CharacterIdTag) addNode.getItem();
String path = cit.getExportName();
if (path == null) {
path = "";
}
String[] pathParts = path.contains(".") ? path.split("\\.") : new String[]{path};
List<TreeNode> items = ret;
for (int pos = 0; pos < pathParts.length - 1; pos++) {
String pathPart = pathParts[pos];
TreeNode selNode = null;
for (TreeNode node : items) {
if (node.getItem() instanceof AS2PackageNodeItem) {
AS2PackageNodeItem pkg = (AS2PackageNodeItem) node.getItem();
if (pkg.packageName.equals(pathPart)) {
selNode = node;
break;
}
}
}
int pkgCount = 0;
for (; pkgCount < items.size(); pkgCount++) {
if (items.get(pkgCount).getItem() instanceof AS3PackageNodeItem) {
AS3PackageNodeItem pkg = (AS3PackageNodeItem) items.get(pkgCount).getItem();
if (pkg.packageName.compareTo(pathPart) > 0) {
break;
}
} else {
break;
}
}
if (selNode == null) {
items.add(pkgCount, selNode = new AS2PackageNode(new AS2PackageNodeItem(pathPart, t.getSwf())));
}
pos++;
items = selNode.subNodes;
}
int clsCount = 0;
String addNodeName = addNode.getItem().getClass().getName() + "_" + pathParts[pathParts.length - 1];
for (; clsCount < items.size(); clsCount++) {
if (items.get(clsCount).getItem() instanceof CharacterIdTag) {
CharacterIdTag ct = (CharacterIdTag) items.get(clsCount).getItem();
String expName = ct.getExportName();
if (expName == null) {
expName = "";
}
if (expName.contains(".")) {
expName = expName.substring(expName.lastIndexOf('.') + 1);
}
if ((ct.getClass().getName() + "_" + expName).compareTo(addNodeName) > 0) {
break;
}
}
}
items.add(clsCount, addNode);
} else {
ret.add(addNode);
}
}
}
ret.addAll(frames);
for (int i = ret.size() - 1; i >= 0; i--) {
TreeNode node = ret.get(i);
TreeItem item = node.getItem();
if (item instanceof ASMSource) {
ASMSource ass = (ASMSource) item;
if (ass.containsSource()) {
continue;
}
}
if (node.subNodes.isEmpty()) {
ret.remove(i);
}
}
return ret;
}
public Map<String, ASMSource> getASMs() {
List<TreeNode> list = createASTagList(tags, this);
Map<String, ASMSource> asms = new HashMap<>();
getASMs("", list, asms);
return asms;
Map<String, ASMSource> asms2 = new HashMap<>();
getASMs("", tags, asms2);
return asms2;
}
private static void getASMs(String path, List<TreeNode> nodes, Map<String, ASMSource> result) {
for (TreeNode n : nodes) {
String subPath = path + "/" + n.toString();
if (n.getItem() instanceof ASMSource) {
//cacheScript((ASMSource) n.tag);
private static void getASMs(String path, List<? extends ContainerItem> items, Map<String, ASMSource> asms) {
for (ContainerItem item : items) {
String subPath = path + "/" + item.toString();
if (item instanceof ASMSource) {
String npath = subPath;
int ppos = 1;
while (result.containsKey(npath)) {
while (asms.containsKey(npath)) {
ppos++;
npath = subPath + "[" + ppos + "]";
}
result.put(npath, (ASMSource) n.getItem());
asms.put(npath, (ASMSource) item);
}
if (item instanceof Container) {
getASMs(subPath, ((Container) item).getSubItems(), asms);
}
getASMs(subPath, n.subNodes, result);
}
}
public static void getTagsFromTreeNodes(List<TreeNode> treeNodes, List<Tag> result) {
for (TreeNode treeNode : treeNodes) {
TreeItem treeItem = treeNode.getItem();
if (treeItem instanceof Tag) {
result.add((Tag) treeItem);
}
getTagsFromTreeNodes(treeNode.subNodes, result);
}
}
private final HashSet<EventListener> listeners = new HashSet<>();
public final void addEventListener(EventListener listener) {
@@ -1401,7 +1232,7 @@ public final class SWF implements TreeItem, Timelined {
path = File.separator + Helper.makeFileName(characters.get(containerId).getExportFileName());
}
if (frames == null) {
int frameCnt = tim.frames.size();
int frameCnt = tim.getFrames().size();
frames = new ArrayList<>();
for (int i = 0; i < frameCnt; i++) {
frames.add(i);
@@ -2253,7 +2084,7 @@ public final class SWF implements TreeItem, Timelined {
Stack<Integer> clipDepths = new Stack<>();
for (int frame : frames) {
sb.append("\t\tcase ").append(frame).append(":\r\n");
Frame frameObj = timeline.frames.get(frame);
Frame frameObj = timeline.getFrames().get(frame);
for (int i = 1; i <= maxDepth + 1; i++) {
while (!clipDepths.isEmpty() && clipDepths.peek() <= i) {
clipDepths.pop();
@@ -2467,10 +2298,10 @@ public final class SWF implements TreeItem, Timelined {
}
public static void frameToSvg(Timeline timeline, int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level, double zoom) throws IOException {
if (timeline.frames.size() <= frame) {
if (timeline.getFrames().size() <= frame) {
return;
}
Frame frameObj = timeline.frames.get(frame);
Frame frameObj = timeline.getFrames().get(frame);
List<SvgClip> clips = new ArrayList<>();
List<String> prevClips = new ArrayList<>();
@@ -2570,7 +2401,7 @@ public final class SWF implements TreeItem, Timelined {
}
}
if (timeline.frames.isEmpty()) {
if (timeline.getFrames().isEmpty()) {
return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB);
}
@@ -2595,7 +2426,7 @@ public final class SWF implements TreeItem, Timelined {
public static void framesToImage(Timeline timeline, List<SerializableImage> ret, int startFrame, int stopFrame, DepthState stateUnderCursor, int mouseButton, RECT displayRect, int totalFrameCount, Stack<Integer> visited, Matrix transformation, ColorTransform colorTransform, double zoom) {
RECT rect = displayRect;
for (int f = 0; f < timeline.frames.size(); f++) {
for (int f = 0; f < timeline.getFrames().size(); f++) {
SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1,
(int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB);
image.fillTransparent();
@@ -2608,10 +2439,10 @@ public final class SWF implements TreeItem, Timelined {
public static void frameToImage(Timeline timeline, int frame, int time, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
double unzoom = SWF.unitDivisor;
if (timeline.frames.size() <= frame) {
if (timeline.getFrames().size() <= frame) {
return;
}
Frame frameObj = timeline.frames.get(frame);
Frame frameObj = timeline.getFrames().get(frame);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setPaint(frameObj.backgroundColor.toColor());
g.fill(new Rectangle(image.getWidth(), image.getHeight()));
@@ -2958,7 +2789,7 @@ public final class SWF implements TreeItem, Timelined {
tags = this.tags;
}
tags.remove(t);
timelined.resetTimeline();
timelined.getTimeline().reset();
} else {
// timeline should be always the swf here
if (removeDependencies) {
@@ -2971,4 +2802,9 @@ public final class SWF implements TreeItem, Timelined {
updateCharacters();
clearImageCache();
}
@Override
public String toString() {
return getShortFileName();
}
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.helpers.streams.SeekableInputStream;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
* Copyright (C) 2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -12,13 +12,16 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
package com.jpexs.decompiler.flash.treeitems;
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
/**
*
* @author JPEXS
*/
public interface TreeElementItem extends TreeItem {
public interface SWFContainerItem extends TreeItem {
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.helpers.Helper;

View File

@@ -1207,7 +1207,7 @@ public class ABC {
}
}
}
boolean isDocumentClass = documentClass.equals(pack.getPath().toString());
boolean isDocumentClass = documentClass.equals(pack.getClassPath().toString());
ScriptInfo si = script_info.get(oldIndex);
si.delete(this, true);

View File

@@ -245,7 +245,7 @@ public class ABCInputStream implements AutoCloseable {
return is.available();
}
private final long readLong() throws IOException {
private long readLong() throws IOException {
byte[] readBuffer = safeRead(8);
return (((long) readBuffer[7] << 56)
+ ((long) (readBuffer[6] & 255) << 48)

View File

@@ -26,7 +26,7 @@ import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.io.File;
@@ -46,7 +46,7 @@ import java.util.logging.Logger;
*
* @author JPEXS
*/
public class ScriptPack implements TreeElementItem {
public class ScriptPack extends AS3ClassTreeItem {
public final ABC abc;
public final int scriptIndex;
@@ -58,11 +58,12 @@ public class ScriptPack implements TreeElementItem {
return abc.swf;
}
public ClassPath getPath() {
public ClassPath getClassPath() {
return path;
}
public ScriptPack(ClassPath path, ABC abc, int scriptIndex, List<Integer> traitIndices) {
super(path.className, path.toString());
this.abc = abc;
this.scriptIndex = scriptIndex;
this.traitIndices = traitIndices;
@@ -178,7 +179,7 @@ public class ScriptPack implements TreeElementItem {
public File export(String directory, List<ABCContainerTag> abcList, ScriptExportMode exportMode, boolean parallel) throws IOException {
String scriptName = getPathScriptName();
String packageName = getPathPackage();
File outDir = new File(directory + File.separatorChar + makeDirPath(packageName));
File outDir = new File(directory + File.separatorChar + "scripts" + File.separatorChar + makeDirPath(packageName));
if (!outDir.exists()) {
if (!outDir.mkdirs()) {
if (!outDir.exists()) {

View File

@@ -44,7 +44,7 @@ public class Multiname {
public List<Integer> params; //for TypeName
public boolean deleted;
public boolean validType() {
private boolean validType() {
boolean cnt = false;
for (int i = 0; i < multinameKinds.length; i++) {
if (multinameKinds[i] == kind) {

View File

@@ -0,0 +1,218 @@
/*
* Copyright (C) 2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.script;
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.graph.TranslateException;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class AS2ScriptExporter {
public List<File> exportAS2ScriptsTimeout(final AbortRetryIgnoreHandler handler, final String outdir, final Collection<ASMSource> asms, final ScriptExportMode exportMode, final EventListener ev) throws IOException {
try {
List<File> result = CancellableWorker.call(new Callable<List<File>>() {
@Override
public List<File> call() throws Exception {
return exportAS2Scripts(handler, outdir, asms, exportMode, ev);
}
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
return result;
} catch (ExecutionException | InterruptedException | TimeoutException ex) {
}
return new ArrayList<>();
}
private List<File> exportAS2Scripts(AbortRetryIgnoreHandler handler, String outdir, Collection<ASMSource> asms, ScriptExportMode exportMode, EventListener ev) throws IOException {
List<File> ret = new ArrayList<>();
if (!outdir.endsWith(File.separator)) {
outdir += File.separator;
}
outdir += "scripts" + File.separator;
Map<String, List<String>> existingNamesMap = new HashMap<>();
AtomicInteger cnt = new AtomicInteger(1);
for (ASMSource asm : asms) {
String currentOutDir = outdir + getFilePath(asm) + File.separator;
currentOutDir = new File(currentOutDir).getParentFile().toString() + File.separator;
List<String> existingNames = existingNamesMap.get(currentOutDir);
if (existingNames == null) {
existingNames = new ArrayList<>();
existingNamesMap.put(currentOutDir, existingNames);
}
String name = Helper.makeFileName(asm.getExportFileName());
int i = 1;
String baseName = name;
while (existingNames.contains(name)) {
i++;
name = baseName + "_" + i;
}
existingNames.add(name);
File f = exportAS2Script(handler, currentOutDir, asm, exportMode, ev, cnt, asms.size(), name);
if (f != null) {
ret.add(f);
}
}
return ret;
}
private File exportAS2Script(AbortRetryIgnoreHandler handler, String outdir, ASMSource asm, ScriptExportMode exportMode, EventListener ev, AtomicInteger index, int count, String name) throws IOException {
boolean retry;
do {
retry = false;
try {
int currentIndex = index.getAndIncrement();
File dir = new File(outdir);
if (!dir.exists()) {
if (!dir.mkdirs()) {
if (!dir.exists()) {
throw new IOException("Cannot create directory " + outdir);
}
}
}
String f = outdir + name + ".as";
if (ev != null) {
ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f);
}
long startTime = System.currentTimeMillis();
File file = new File(f);
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(f))) {
if (exportMode == ScriptExportMode.HEX) {
asm.getActionSourcePrefix(writer);
asm.getActionBytesAsHex(writer);
asm.getActionSourceSuffix(writer);
} else if (exportMode != ScriptExportMode.AS) {
asm.getActionSourcePrefix(writer);
asm.getASMSource(exportMode, writer, null);
asm.getActionSourceSuffix(writer);
} else {
List<Action> as = asm.getActions();
Action.setActionsAddresses(as, 0);
Action.actionsToSource(asm, as, ""/*FIXME*/, writer);
}
}
long stopTime = System.currentTimeMillis();
if (ev != null) {
long time = stopTime - startTime;
ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
}
return file;
} catch (InterruptedException ex) {
} catch (IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
Logger.getLogger(AS2ScriptExporter.class.getName()).log(Level.SEVERE, "Decompilation error in file: " + name + ".as", ex);
if (handler != null) {
int action = handler.getNewInstance().handle(ex);
switch (action) {
case AbortRetryIgnoreHandler.ABORT:
throw ex;
case AbortRetryIgnoreHandler.RETRY:
retry = true;
break;
case AbortRetryIgnoreHandler.IGNORE:
retry = false;
break;
}
}
}
} while (retry);
return null;
}
// todo: honfika: get the path from the tree
private String getFilePath(ASMSource asm) {
if (asm instanceof DoInitActionTag) {
String exportName = ((DoInitActionTag) asm).getExportName();
if (exportName != null) {
String path = "";
StringTokenizer st = new StringTokenizer(exportName, ".");
while (st.hasMoreTokens()) {
String pathElement = st.nextToken();
if (path.length() > 0) {
path += File.separator;
}
path += Helper.makeFileName(pathElement);
}
return path;
}
}
if (!(asm instanceof Tag)) {
return Helper.makeFileName(asm.getSourceTag().getExportFileName()) + File.separator + Helper.makeFileName(asm.getExportFileName());
} else {
String result = "";
Timelined timelined = asm.getSourceTag().getTimelined();
if (timelined instanceof Tag) {
result += Helper.makeFileName(((Tag) timelined).getExportFileName()) + File.separator;
}
Timeline timeline = timelined.getTimeline();
int frame = timeline.getFrameForAction(asm);
if (frame != -1) {
result += "frame_" + (frame + 1) + File.separator;
}
return result + Helper.makeFileName(asm.getExportFileName());
}
}
}

View File

@@ -54,6 +54,12 @@ public class FileTextWriter extends GraphTextWriter implements AutoCloseable {
return this;
}
@Override
public GraphTextWriter hilightSpecial(String text, String type, int index, Map<String, String> data) {
writeToFile(text);
return this;
}
@Override
public FileTextWriter append(String str) {
writeToFile(str);

View File

@@ -12,13 +12,16 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
@@ -39,6 +42,9 @@ public class DefineBinaryDataTag extends CharacterTag {
public static final int ID = 87;
@Internal
public SWF innerSwf;
/**
* Gets data bytes
*

View File

@@ -255,13 +255,13 @@ public class DefineButton2Tag extends ButtonTag implements Container {
if (timeline != null) {
return timeline;
}
timeline = new Timeline(swf, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
int maxDepth = 0;
Frame frameUp = new Frame(timeline);
Frame frameDown = new Frame(timeline);
Frame frameOver = new Frame(timeline);
Frame frameHit = new Frame(timeline);
Frame frameUp = new Frame(timeline, 0);
Frame frameDown = new Frame(timeline, 0);
Frame frameOver = new Frame(timeline, 0);
Frame frameHit = new Frame(timeline, 0);
for (BUTTONRECORD r : this.characters) {
DepthState layer = new DepthState(swf, null);
@@ -288,24 +288,19 @@ public class DefineButton2Tag extends ButtonTag implements Container {
}
}
timeline.frames.add(frameUp);
timeline.getFrames().add(frameUp);
if (frameOver.layers.isEmpty()) {
frameOver = frameUp;
}
timeline.frames.add(frameOver);
timeline.getFrames().add(frameOver);
if (frameDown.layers.isEmpty()) {
frameDown = frameOver;
}
timeline.frames.add(frameDown);
timeline.getFrames().add(frameDown);
if (frameHit.layers.isEmpty()) {
frameHit = frameUp;
}
timeline.frames.add(frameHit);
timeline.getFrames().add(frameHit);
return timeline;
}
@Override
public void resetTimeline() {
timeline = null;
}
}

View File

@@ -326,7 +326,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
if (timeline != null) {
return timeline;
}
timeline = new Timeline(swf, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
ColorTransform clrTrans = null;
for (Tag t : swf.tags) {
@@ -336,10 +336,10 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
}
}
int maxDepth = 0;
Frame frameUp = new Frame(timeline);
Frame frameDown = new Frame(timeline);
Frame frameOver = new Frame(timeline);
Frame frameHit = new Frame(timeline);
Frame frameUp = new Frame(timeline, 0);
Frame frameDown = new Frame(timeline, 0);
Frame frameOver = new Frame(timeline, 0);
Frame frameHit = new Frame(timeline, 0);
for (BUTTONRECORD r : this.characters) {
DepthState layer = new DepthState(swf, null);
@@ -366,28 +366,23 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
}
}
timeline.frames.add(frameUp);
timeline.getFrames().add(frameUp);
if (frameOver.layers.isEmpty()) {
frameOver = frameUp;
}
timeline.frames.add(frameOver);
timeline.getFrames().add(frameOver);
if (frameDown.layers.isEmpty()) {
frameDown = frameOver;
}
timeline.frames.add(frameDown);
timeline.getFrames().add(frameDown);
if (frameHit.layers.isEmpty()) {
frameHit = frameUp;
}
timeline.frames.add(frameHit);
timeline.getFrames().add(frameHit);
return timeline;
}
@Override
public void resetTimeline() {
timeline = null;
}
@Override
public Tag getSourceTag() {
return this;

View File

@@ -263,7 +263,7 @@ public class DefineFont2Tag extends FontTag {
fontBoundsTable.add(sis.readRECT("rect"));
}
int kerningCount = sis.readUI16("kerningCount");
fontKerningTable = new ArrayList<KERNINGRECORD>();
fontKerningTable = new ArrayList<>();
for (int i = 0; i < kerningCount; i++) {
fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record"));
}

View File

@@ -168,7 +168,7 @@ public class DefineFont3Tag extends FontTag {
fontBoundsTable.add(sis.readRECT("rect"));
}
int kerningCount = sis.readUI16("kerningCount");
fontKerningTable = new ArrayList<KERNINGRECORD>();
fontKerningTable = new ArrayList<>();
for (int i = 0; i < kerningCount; i++) {
fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record"));
}

View File

@@ -84,16 +84,11 @@ public class DefineSpriteTag extends CharacterTag implements Container, Drawable
@Override
public Timeline getTimeline() {
if (timeline == null) {
timeline = new Timeline(swf, subTags, spriteId, getRect(new HashSet<BoundedTag>()));
timeline = new Timeline(swf, this, subTags, spriteId, getRect(new HashSet<BoundedTag>()));
}
return timeline;
}
@Override
public void resetTimeline() {
timeline = null;
}
@Override
public int getCharacterId() {
return spriteId;

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.DisassemblyListener;
@@ -199,5 +200,4 @@ public class DoActionTag extends Tag implements ASMSource {
public Tag getSourceTag() {
return this;
}
}
}

View File

@@ -179,7 +179,7 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource {
public String getExportFileName() {
String expName = getExportName();
if ((expName == null) || expName.isEmpty()) {
return super.toString();
return super.getExportFileName();
}
String[] pathParts;
if (expName.contains(".")) {
@@ -229,5 +229,4 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource {
public Tag getSourceTag() {
return this;
}
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.DisassemblyListener;
@@ -21,7 +22,6 @@ import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.Tag;
import java.util.List;
/**
@@ -29,7 +29,7 @@ import java.util.List;
*
* @author JPEXS
*/
*/
public interface ASMSource extends Exportable {
/**
* Converts actions to ASM source

View File

@@ -12,14 +12,17 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
/**
*
* @author JPEXS
*/
*/
public interface Exportable extends TreeItem {
public String getExportFileName();
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.util.Map;
import java.util.TreeMap;
/**
*
* @author JPEXS
*/
public class AS2Package implements TreeItem {
private final SWF swf;
private final String name;
private final AS2Package parent;
public Map<String, AS2Package> subPackages = new TreeMap<>();
public Map<String, ASMSource> scripts = new TreeMap<>();
public AS2Package(String name, AS2Package parent, SWF swf) {
this.name = name;
this.parent = parent;
this.swf = swf;
}
@Override
public SWF getSwf() {
return swf;
}
public TreeItem getChild(int index) {
if (index < subPackages.size()) {
for (AS2Package subPackage : subPackages.values()) {
if (index == 0) {
return subPackage;
}
index--;
}
}
index -= subPackages.size();
for (ASMSource pack : scripts.values()) {
if (index == 0) {
return pack;
}
index--;
}
return null;
}
public int getChildCount() {
return subPackages.size() + scripts.size();
}
public int getIndexOfChild(TreeItem child) {
int res = 0;
if (child instanceof AS2Package) {
for (AS2Package pkg : subPackages.values()) {
if (pkg.equals(child)) {
break;
}
res++;
}
return res;
}
res = subPackages.size();
for (ASMSource pack : scripts.values()) {
if (pack.equals(child)) {
break;
}
res++;
}
return res;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
import java.util.Map;
import java.util.TreeMap;
/**
*
* @author JPEXS
*/
public class AS3Package extends AS3ClassTreeItem {
private final SWF swf;
public String packageName;
public Map<String, AS3Package> subPackages = new TreeMap<>();
public Map<String, ScriptPack> scripts = new TreeMap<>();
public AS3Package(String packageName, SWF swf) {
super(packageName, null);
this.swf = swf;
this.packageName = packageName;
}
@Override
public SWF getSwf() {
return swf;
}
public AS3ClassTreeItem getChild(int index) {
if (index < subPackages.size()) {
for (AS3Package subPackage : subPackages.values()) {
if (index == 0) {
return subPackage;
}
index--;
}
}
index -= subPackages.size();
for (ScriptPack pack : scripts.values()) {
if (index == 0) {
return pack;
}
index--;
}
return null;
}
public int getChildCount() {
return subPackages.size() + scripts.size();
}
public int getIndexOfChild(AS3ClassTreeItem child) {
int res = 0;
if (child instanceof AS3Package) {
for (AS3Package pkg : subPackages.values()) {
if (pkg.equals(child)) {
break;
}
res++;
}
return res;
}
res = subPackages.size();
for (ScriptPack pack : scripts.values()) {
if (pack.equals(child)) {
break;
}
res++;
}
return res;
}
@Override
public String toString() {
return packageName;
}
}

View File

@@ -12,12 +12,15 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.RGBA;
import java.util.ArrayList;
@@ -28,22 +31,25 @@ import java.util.TreeMap;
*
* @author JPEXS
*/
*/
public class Frame implements TreeItem {
public final int frame;
public TreeMap<Integer, DepthState> layers = new TreeMap<>();
public TreeMap<Integer, DepthState> layers = new TreeMap<>();
public RGB backgroundColor = new RGBA(0, 0, 0, 0);
public Timeline timeline;
public List<Integer> sounds = new ArrayList<>();
public List<String> soundClasses = new ArrayList<>();
public List<DoActionTag> actions = new ArrayList<>();
public List<Tag> innerTags = new ArrayList<>();
public ShowFrameTag showFrameTag = null; // can be null for the last frame
public Frame(Timeline timeline, int frame) {
this.timeline = timeline;
this.frame = frame;
}
public Frame(Frame obj, int frame) {
this.frame = frame;
layers = new TreeMap<>();
backgroundColor = obj.backgroundColor;
timeline = obj.timeline;
@@ -52,4 +58,14 @@ public class Frame {
}
//Do not copy sounds
}
@Override
public SWF getSwf() {
return timeline.swf;
}
@Override
public String toString() {
return "frame " + (frame + 1);
}
}

View File

@@ -12,25 +12,31 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
package com.jpexs.decompiler.flash.treeitems;
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
/**
*
* @author JPEXS
*/
public class AS2PackageNodeItem implements TreeItem {
public class FrameScript implements TreeItem {
private final SWF swf;
public String packageName;
private final Frame frame;
public AS2PackageNodeItem(String packageName, SWF swf) {
public FrameScript(SWF swf, Frame frame) {
this.swf = swf;
this.packageName = packageName;
this.frame = frame;
}
public Frame getFrame() {
return frame;
}
@Override
public SWF getSwf() {
return swf;
@@ -38,6 +44,6 @@ public class AS2PackageNodeItem implements TreeItem {
@Override
public String toString() {
return packageName;
return frame.toString();
}
}

View File

@@ -14,49 +14,44 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treeitems;
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.util.List;
/**
*
* @author JPEXS
*/
public class FrameNodeItem implements TreeItem {
public class TagScript implements TreeItem {
private final SWF swf;
private final int frame;
private final Timelined parent;
private final boolean display;
public FrameNodeItem(SWF swf, int frame, Timelined parent, boolean display) {
private final Tag tag;
private final List<TreeItem> frames;
public TagScript(SWF swf, Tag tag, List<TreeItem> frames) {
this.swf = swf;
this.frame = frame;
this.parent = parent;
this.display = display;
this.tag = tag;
this.frames = frames;
}
public Tag getTag() {
return tag;
}
public List<TreeItem> getFrames() {
return frames;
}
@Override
public SWF getSwf() {
return swf;
}
public boolean isDisplayed() {
return display;
}
@Override
public String toString() {
return "frame " + (frame + 1);
}
public int getFrame() {
return frame;
}
public Timelined getParent() {
return parent;
return tag.toString();
}
}

View File

@@ -19,11 +19,13 @@ package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.StartSound2Tag;
import com.jpexs.decompiler.flash.tags.StartSoundTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
@@ -52,15 +54,59 @@ import java.util.Stack;
*/
public class Timeline {
public List<Frame> frames = new ArrayList<>();
public int id;
public SWF swf;
public RECT displayRect;
public int frameRate;
public Timelined timelined;
public Tag parentTag;
public List<Tag> tags;
public Map<Integer, Integer> depthMaxFrame = new HashMap<>();
public int getMaxDepth() {
private final List<Frame> frames = new ArrayList<>();
private final Map<Integer, Integer> depthMaxFrame = new HashMap<>();
private final List<ASMSource> asmSources = new ArrayList<>();
private final Map<ASMSource, Integer> actionFrames = new HashMap<>();
private AS2Package as2RootPackage;
private final List<Tag> otherTags = new ArrayList<>();
private boolean initialized = false;
private void ensureInitialized() {
if (!initialized) {
initialize();
}
}
public List<Frame> getFrames() {
ensureInitialized();
return frames;
}
public AS2Package getAS2RootPackage() {
ensureInitialized();
return as2RootPackage;
}
public Map<Integer, Integer> getDepthMaxFrame() {
ensureInitialized();
return depthMaxFrame;
}
public void reset() {
initialized = false;
frames.clear();
depthMaxFrame.clear();
asmSources.clear();
actionFrames.clear();
otherTags.clear();
as2RootPackage = new AS2Package(null, null, swf);
}
public final int getMaxDepth() {
ensureInitialized();
return getMaxDepthInternal();
}
public final int getMaxDepthInternal() {
int max_depth = 0;
for (Frame f : frames) {
for (int depth : f.layers.keySet()) {
@@ -76,39 +122,49 @@ public class Timeline {
}
public int getFrameCount() {
return frames.size();
return getFrames().size();
}
public int getFrameForAction(ASMSource asm) {
Integer frame = actionFrames.get(asm);
if (frame == null) {
return -1;
}
return frame;
}
public Timeline(SWF swf) {
this(swf, swf.tags, 0, swf.displayRect);
this(swf, null, swf.tags, 0, swf.displayRect);
}
public Timeline(SWF swf, List<Tag> tags, int id, RECT displayRect) {
public Timeline(SWF swf, Tag parentTag, List<Tag> tags, int id, RECT displayRect) {
this.id = id;
this.swf = swf;
this.displayRect = displayRect;
this.frameRate = swf.frameRate;
this.timelined = parentTag == null ? swf : (Timelined) parentTag;
this.parentTag = parentTag;
this.tags = tags;
Frame frame = new Frame(this);
as2RootPackage = new AS2Package(null, null, swf);
}
private void initialize() {
int frameIdx = 0;
Frame frame = new Frame(this, frameIdx++);
boolean tagAdded = false;
for (Tag t : tags) {
tagAdded = true;
if (ShowFrameTag.isNestedTagType(t.getId())) {
frame.innerTags.add(t);
tagAdded = true;
}
if (t instanceof StartSoundTag) {
frame.sounds.add(((StartSoundTag) t).soundId);
tagAdded = true;
}
if (t instanceof StartSound2Tag) {
} else if (t instanceof StartSound2Tag) {
frame.soundClasses.add(((StartSound2Tag) t).soundClassName);
tagAdded = true;
}
if (t instanceof SetBackgroundColorTag) {
} else if (t instanceof SetBackgroundColorTag) {
frame.backgroundColor = ((SetBackgroundColorTag) t).backgroundColor;
tagAdded = true;
}
if (t instanceof PlaceObjectTypeTag) {
} else if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag po = (PlaceObjectTypeTag) t;
int depth = po.getDepth();
if (!frame.layers.containsKey(depth)) {
@@ -168,30 +224,30 @@ public class Timeline {
fl.clipDepth = po.getClipDepth();
}
fl.key = true;
tagAdded = true;
}
if (t instanceof RemoveTag) {
} else if (t instanceof RemoveTag) {
RemoveTag r = (RemoveTag) t;
int depth = r.getDepth();
frame.layers.remove(depth);
tagAdded = true;
}
if (t instanceof DoActionTag) {
frame.action = (DoActionTag) t;
tagAdded = true;
}
if (t instanceof ShowFrameTag) {
} else if (t instanceof DoActionTag) {
frame.actions.add((DoActionTag) t);
actionFrames.put((DoActionTag) t, frame.frame);
} else if (t instanceof ShowFrameTag) {
frame.showFrameTag = (ShowFrameTag) t;
frames.add(frame);
frame = new Frame(frame);
frame = new Frame(frame, frameIdx++);
tagAdded = false;
} else if (t instanceof ASMSource) {
asmSources.add((ASMSource) t);
} else {
otherTags.add(t);
}
}
if (tagAdded) {
frames.add(frame);
}
detectTweens();
for (int d = 1; d <= getMaxDepth(); d++) {
for (int d = 1; d <= getMaxDepthInternal(); d++) {
for (int f = frames.size() - 1; f >= 0; f--) {
if (frames.get(f).layers.get(d) != null) {
depthMaxFrame.put(d, f + 1);
@@ -199,6 +255,10 @@ public class Timeline {
}
}
}
createASPackages();
initialized = true;
}
private boolean compare(int a, int b, int c, int tolerance) {
@@ -206,7 +266,7 @@ public class Timeline {
}
private void detectTweens() {
for (int d = 1; d <= getMaxDepth(); d++) {
for (int d = 1; d <= getMaxDepthInternal(); d++) {
int characterId = -1;
int len = 0;
for (int f = 0; f <= frames.size(); f++) {
@@ -237,6 +297,33 @@ public class Timeline {
}
}
private void createASPackages() {
for (ASMSource asm : asmSources) {
if (asm instanceof DoInitActionTag) {
DoInitActionTag initAction = (DoInitActionTag) asm;
String path = initAction.getExportName();
if (path == null || path.isEmpty()) {
path = initAction.getExportFileName();
}
String[] pathParts = path.contains(".") ? path.split("\\.") : new String[]{path};
AS2Package pkg = as2RootPackage;
for (int pos = 0; pos < pathParts.length - 1; pos++) {
String pathPart = pathParts[pos];
AS2Package subPkg = pkg.subPackages.get(pathPart);
if (subPkg == null) {
subPkg = new AS2Package(pathPart, pkg, swf);
pkg.subPackages.put(pathPart, subPkg);
}
pkg = subPkg;
}
pkg.scripts.put(pathParts[pathParts.length - 1], asm);
}
}
}
public void getNeededCharacters(Set<Integer> usedCharacters) {
for (int i = 0; i < getFrameCount(); i++) {
getNeededCharacters(i, usedCharacters);
@@ -244,13 +331,13 @@ public class Timeline {
}
public void getNeededCharacters(List<Integer> frames, Set<Integer> usedCharacters) {
for (int frame = 0; frame < frames.size(); frame++) {
for (int frame = 0; frame < getFrameCount(); frame++) {
getNeededCharacters(frame, usedCharacters);
}
}
public void getNeededCharacters(int frame, Set<Integer> usedCharacters) {
Frame frameObj = frames.get(frame);
Frame frameObj = getFrames().get(frame);
for (int depth : frameObj.layers.keySet()) {
DepthState layer = frameObj.layers.get(depth);
if (layer.characterId != -1) {
@@ -285,10 +372,10 @@ public class Timeline {
}
public void getSounds(int frame, int time, DepthState stateUnderCursor, int mouseButton, List<Integer> sounds, List<String> soundClasses) {
Frame fr = this.frames.get(frame);
Frame fr = getFrames().get(frame);
sounds.addAll(fr.sounds);
soundClasses.addAll(fr.soundClasses);
int maxDepth = this.getMaxDepth();
int maxDepth = getMaxDepthInternal();
for (int d = maxDepth; d >= 0; d--) {
DepthState ds = fr.layers.get(d);
if (ds != null) {
@@ -317,9 +404,9 @@ public class Timeline {
}
public void getObjectsOutlines(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation, List<DepthState> objs, List<Shape> outlines) {
Frame fr = this.frames.get(frame);
Frame fr = getFrames().get(frame);
Stack<Clip> clips = new Stack<>();
int maxDepth = this.getMaxDepth();
int maxDepth = getMaxDepthInternal();
for (int d = maxDepth; d >= 0; d--) {
Clip currentClip = null;
for (int i = clips.size() - 1; i >= 0; i--) {
@@ -386,10 +473,10 @@ public class Timeline {
}
public Shape getOutline(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) {
Frame fr = this.frames.get(frame);
Frame fr = getFrames().get(frame);
Area area = new Area();
Stack<Clip> clips = new Stack<>();
int maxDepth = this.getMaxDepth();
int maxDepth = getMaxDepthInternal();
for (int d = maxDepth; d >= 0; d--) {
Clip currentClip = null;
for (int i = clips.size() - 1; i >= 0; i--) {
@@ -448,7 +535,7 @@ public class Timeline {
}
public boolean isSingleFrame() {
for (int i = 0; i < frames.size(); i++) {
for (int i = 0; i < getFrameCount(); i++) {
if (!isSingleFrame(i)) {
return false;
}
@@ -458,7 +545,7 @@ public class Timeline {
private boolean isSingleFrame(int frame) {
Frame frameObj = frames.get(frame);
int maxDepth = this.getMaxDepth();
int maxDepth = getMaxDepthInternal();
for (int i = 1; i <= maxDepth; i++) {
if (!frameObj.layers.containsKey(i)) {
continue;

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
@@ -24,6 +25,4 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag;
public interface Timelined extends BoundedTag {
public Timeline getTimeline();
public Timeline getTimeline();
}

View File

@@ -12,32 +12,34 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.treeitems;
import com.jpexs.decompiler.flash.SWF;
/**
*
* @author JPEXS
*/
public class AS3PackageNodeItem implements TreeElementItem {
public abstract class AS3ClassTreeItem implements TreeItem {
private final String name;
private final String path;
private final SWF swf;
public String packageName;
public AS3PackageNodeItem(String packageName, SWF swf) {
this.swf = swf;
this.packageName = packageName;
public AS3ClassTreeItem(String name, String path) {
this.name = name;
this.path = path;
}
@Override
public SWF getSwf() {
return swf;
public String getName() {
return name;
}
public String getPath() {
return path;
}
@Override
public String toString() {
return packageName;
return name;
}
}

View File

@@ -12,25 +12,29 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.treeitems;
import com.jpexs.decompiler.flash.SWF;
import java.util.List;
/**
*
* @author JPEXS
*/
public class StringItem implements TreeItem {
public class FolderItem implements TreeItem {
public SWF swf;
private final String str;
private final String name;
public final List<TreeItem> subItems;
public StringItem(String str, String name, SWF swf) {
public FolderItem(String str, String name, SWF swf, List<TreeItem> subItems) {
this.swf = swf;
this.str = str;
this.name = name;
this.subItems = subItems;
}
public String getName() {

View File

@@ -41,5 +41,4 @@ public class HeaderItem implements TreeItem {
public String toString() {
return name;
}
}

View File

@@ -12,10 +12,12 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.treeitems;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFContainerItem;
import com.jpexs.decompiler.flash.SWFSourceInfo;
import java.util.ArrayList;
import java.util.Collection;
@@ -27,7 +29,7 @@ import java.util.ListIterator;
*
* @author JPEXS
*/
*/
public class SWFList implements List<SWF>, SWFContainerItem {
public String name;
public boolean isBundle;
@@ -39,6 +41,11 @@ public class SWFList implements List<SWF>, TreeItem {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public String toString() {
return name;
}
@Override
public Iterator<SWF> iterator() {
return swfs.iterator();

View File

@@ -0,0 +1,18 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.jpexs.decompiler.flash.treeitems;
import java.util.Map;
/**
*
* @author JPEXS
*/
public interface ScriptContainer {
public Map<String, TreeItem> getInnerScripts();
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.treeitems;
import com.jpexs.decompiler.flash.SWF;

View File

@@ -1,35 +0,0 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treenodes;
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
/**
*
* @author JPEXS
*/
public class AS2PackageNode extends TreeNode {
public AS2PackageNode(AS2PackageNodeItem item) {
super(item);
}
@Override
public AS2PackageNodeItem getItem() {
return (AS2PackageNodeItem) item;
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treenodes;
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
/**
*
* @author JPEXS
*/
public class ContainerNode extends TreeNode {
public ContainerNode(ContainerItem item) {
super(item);
}
@Override
public ContainerItem getItem() {
return (ContainerItem) item;
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treenodes;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
import java.util.List;
/**
*
* @author JPEXS
*/
public class FrameNode extends TreeNode {
public boolean scriptsNode = false;
public FrameNode(FrameNodeItem item, List<Tag> innerTags, boolean scriptsNode) {
super(item);
this.scriptsNode = scriptsNode;
if (innerTags != null) {
for (Tag tag : innerTags) {
subNodes.add(new TagNode(tag));
}
}
}
@Override
public FrameNodeItem getItem() {
return (FrameNodeItem) item;
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (C) 2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treenodes;
import com.jpexs.decompiler.flash.treeitems.HeaderItem;
/**
*
* @author JPEXS
*/
public class HeaderNode extends TreeNode {
public HeaderNode(HeaderItem item) {
super(item);
}
@Override
public HeaderItem getItem() {
return (HeaderItem) item;
}
}

View File

@@ -1,183 +0,0 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treenodes;
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.Exportable;
import com.jpexs.decompiler.graph.TranslateException;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TagNode extends ContainerNode {
public TagNode(Tag tag) {
super(tag);
}
@Override
public Tag getItem() {
return (Tag) item;
}
public static int getTagCountRecursive(List<TreeNode> nodeList) {
int count = 0;
for (TreeNode node : nodeList) {
if (node.item instanceof ASMSource) {
count += 1;
}
if (!node.subNodes.isEmpty()) {
count += getTagCountRecursive(node.subNodes);
}
}
return count;
}
public static List<File> exportNodeAS(final AbortRetryIgnoreHandler handler, final List<TreeNode> nodesList, final List<TreeNode> nodesToExport, final String outdir, final ScriptExportMode exportMode, final EventListener ev) throws IOException {
try {
List<File> result = CancellableWorker.call(new Callable<List<File>>() {
@Override
public List<File> call() throws Exception {
AtomicInteger cnt = new AtomicInteger(1);
int totalCount = TagNode.getTagCountRecursive(nodesToExport);
return exportNodeAS(handler, nodesList, nodesToExport, false, outdir, exportMode, cnt, totalCount, ev);
}
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
return result;
} catch (ExecutionException | InterruptedException | TimeoutException ex) {
}
return new ArrayList<>();
}
private static List<File> exportNodeAS(AbortRetryIgnoreHandler handler, List<TreeNode> nodesList, List<TreeNode> nodesToExport, boolean exportAll, String outdir, ScriptExportMode exportMode, AtomicInteger index, int count, EventListener ev) throws IOException {
File dir = new File(outdir);
List<File> ret = new ArrayList<>();
if (!outdir.endsWith(File.separator)) {
outdir += File.separator;
}
List<String> existingNames = new ArrayList<>();
for (TreeNode node : nodesList) {
String name = "";
if (node.item instanceof Exportable) {
name = Helper.makeFileName(((Exportable) node.item).getExportFileName());
} else {
name = Helper.makeFileName(node.item.toString());
}
int i = 1;
String baseName = name;
while (existingNames.contains(name)) {
i++;
name = baseName + "_" + i;
}
existingNames.add(name);
boolean exportNode = nodesToExport.contains(node);
if (node.item instanceof ASMSource && (exportAll || exportNode)) {
boolean retry;
do {
retry = false;
try {
int currentIndex = index.getAndIncrement();
if (!dir.exists()) {
if (!dir.mkdirs()) {
if (!dir.exists()) {
throw new IOException("Cannot create directory " + outdir);
}
}
}
String f = outdir + name + ".as";
if (ev != null) {
ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f);
}
long startTime = System.currentTimeMillis();
File file = new File(f);
ASMSource asm = ((ASMSource) node.item);
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(f))) {
if (exportMode == ScriptExportMode.HEX) {
asm.getActionSourcePrefix(writer);
asm.getActionBytesAsHex(writer);
asm.getActionSourceSuffix(writer);
} else if (exportMode != ScriptExportMode.AS) {
asm.getActionSourcePrefix(writer);
asm.getASMSource(exportMode, writer, null);
asm.getActionSourceSuffix(writer);
} else {
List<Action> as = asm.getActions();
Action.setActionsAddresses(as, 0);
Action.actionsToSource(asm, as, ""/*FIXME*/, writer);
}
}
long stopTime = System.currentTimeMillis();
if (ev != null) {
long time = stopTime - startTime;
ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
}
ret.add(file);
} catch (InterruptedException ex) {
} catch (IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
Logger.getLogger(TagNode.class.getName()).log(Level.SEVERE, "Decompilation error in file: " + name + ".as", ex);
if (handler != null) {
int action = handler.getNewInstance().handle(ex);
switch (action) {
case AbortRetryIgnoreHandler.ABORT:
throw ex;
case AbortRetryIgnoreHandler.RETRY:
retry = true;
break;
case AbortRetryIgnoreHandler.IGNORE:
retry = false;
break;
}
}
}
} while (retry);
}
if (!node.subNodes.isEmpty()) {
ret.addAll(exportNodeAS(handler, node.subNodes, nodesToExport, exportAll || exportNode, outdir + name, exportMode, index, count, ev));
}
}
return ret;
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.treenodes;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public abstract class TreeNode {
protected TreeItem item;
public List<TreeNode> subNodes;
public TreeNode(TreeItem item) {
if (item == null) {
throw new Error("TreeItem should not be null.");
}
this.item = item;
this.subNodes = new ArrayList<>();
}
public TreeItem getItem() {
return item;
}
@Override
public String toString() {
if (item == null) {
Logger.getLogger(TreeNode.class.getName()).log(Level.FINE, "Tree item is null");
return null;
}
return item.toString();
}
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.types;
import com.jpexs.decompiler.flash.DisassemblyListener;

View File

@@ -284,5 +284,4 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem, S
public Tag getSourceTag() {
return tag;
}
}

View File

@@ -20,7 +20,6 @@ import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.NeedsCharacters;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.types.ColorTransform;

View File

@@ -59,7 +59,7 @@ public abstract class GraphTargetItem implements Serializable {
public List<GraphSourceItemPos> moreSrc = new ArrayList<>();
public GraphPart firstPart;
public GraphTargetItem value;
protected Map<String,String> srcData = new HashMap<String, String>();
protected Map<String,String> srcData = new HashMap<>();
public GraphPart getFirstPart() {
if (value == null) {