allow to create swf from code only / export SWF to "Java code", which generates the SWF

This commit is contained in:
2015-01-17 12:17:03 +01:00
parent 30a3bc1e3e
commit 07eaafdc55
64 changed files with 841 additions and 259 deletions
@@ -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 SevenZip.Compression.LZMA.Decoder;
@@ -128,6 +129,7 @@ import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.filters.BEVELFILTER;
import com.jpexs.decompiler.flash.types.filters.BlendComposite;
import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER;
@@ -250,46 +252,98 @@ public final class SWF implements SWFContainerItem, Timelined {
* LZMA Properties
*/
public byte[] lzmaProperties;
@Internal
public byte[] uncompressedData;
@Internal
public byte[] originalUncompressedData;
public FileAttributesTag fileAttributes;
/**
* ScaleForm GFx
*/
public boolean gfx = false;
@Internal
public SWFList swfList;
@Internal
public String file;
@Internal
public String fileTitle;
public boolean readOnly;
public boolean isAS3;
public Map<Integer, CharacterTag> characters = new HashMap<>();
public List<ABCContainerTag> abcList;
@Internal
private Map<Integer, CharacterTag> characters;
@Internal
private List<ABCContainerTag> abcList;
@Internal
private JPEGTablesTag jtt;
@Internal
public Map<Integer, String> sourceFontNamesMap = new HashMap<>();
public static final double unitDivisor = 20;
private static final Logger logger = Logger.getLogger(SWF.class.getName());
@Internal
private Timeline timeline;
@Internal
public DumpInfoSwfNode dumpInfo;
@Internal
public DefineBinaryDataTag binaryData;
@Internal
private final HashMap<String, String> deobfuscated = new HashMap<>();
@Internal
private final IdentifiersDeobfuscation deobfuscation = new IdentifiersDeobfuscation();
@Internal
private static Cache<String, SerializableImage> frameCache = Cache.getInstance(false, "frame");
@Internal
private final Cache<ASMSource, CachedScript> as2Cache = Cache.getInstance(true, "as2");
@Internal
private final Cache<ScriptPack, CachedDecompilation> as3Cache = Cache.getInstance(true, "as3");
public void updateCharacters() {
characters.clear();
parseCharacters(tags);
characters = null;
}
public Map<Integer, CharacterTag> getCharacters() {
if (characters == null) {
Map<Integer, CharacterTag> chars = new HashMap<>();
parseCharacters(tags, chars);
characters = chars;
}
return characters;
}
public CharacterTag getCharacter(int characterId) {
return getCharacters().get(characterId);
}
public List<ABCContainerTag> getAbcList() {
if (abcList == null) {
ArrayList<ABCContainerTag> newAbcList = new ArrayList<>();
getAbcTags(tags, newAbcList);
abcList = newAbcList;
}
return abcList;
}
public boolean isAS3() {
FileAttributesTag fileAttributes = getFileAttributes();
return (fileAttributes != null && fileAttributes.actionScript3) || (fileAttributes == null && !getAbcList().isEmpty());
}
public FileAttributesTag getFileAttributes() {
for (Tag t : tags) {
if (t instanceof FileAttributesTag) {
return (FileAttributesTag) t;
}
}
return null;
}
public int getNextCharacterId() {
int max = -1;
for (int characterId : characters.keySet()) {
for (int characterId : getCharacters().keySet()) {
if (characterId > max) {
max = characterId;
}
@@ -326,7 +380,7 @@ public final class SWF implements SWFContainerItem, Timelined {
boolean moved = false;
for (Integer id : needed) {
if (!addedCharacterIds.contains(id)) {
CharacterTag neededCharacter = characters.get(id);
CharacterTag neededCharacter = getCharacter(id);
if (neededCharacter == null) {
continue;
}
@@ -364,13 +418,13 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
private void parseCharacters(List<Tag> list) {
private void parseCharacters(List<Tag> list, Map<Integer, CharacterTag> characters) {
for (Tag t : list) {
if (t instanceof CharacterTag) {
characters.put(((CharacterTag) t).getCharacterId(), (CharacterTag) t);
}
if (t instanceof DefineSpriteTag) {
parseCharacters(((DefineSpriteTag) t).getSubTags());
parseCharacters(((DefineSpriteTag) t).getSubTags(), characters);
}
}
}
@@ -573,6 +627,10 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
public SWF() {
}
public SWF(InputStream is, boolean parallelRead) throws IOException, InterruptedException {
this(is, null, parallelRead, false);
}
@@ -643,11 +701,8 @@ public final class SWF implements SWFContainerItem, Timelined {
this.tags = tags;
if (!checkOnly) {
checkInvalidSprites();
updateCharacters();
assignExportNamesToSymbols();
assignClassesToSymbols();
findFileAttributes();
findABCTags();
SWFDecompilerPlugin.fireSwfParsed(this);
} else {
@@ -695,18 +750,10 @@ public final class SWF implements SWFContainerItem, Timelined {
return new File(title).getName();
}
private void findABCTags() {
ArrayList<ABCContainerTag> newAbcList = new ArrayList<>();
getABCTags(tags, newAbcList);
isAS3 = (fileAttributes != null && fileAttributes.actionScript3) || (fileAttributes == null && !newAbcList.isEmpty());
abcList = newAbcList;
}
private static void getABCTags(List<Tag> list, List<ABCContainerTag> actionScripts) {
private static void getAbcTags(List<Tag> list, List<ABCContainerTag> actionScripts) {
for (Tag t : list) {
if (t instanceof DefineSpriteTag) {
getABCTags(((DefineSpriteTag) t).getSubTags(), actionScripts);
getAbcTags(((DefineSpriteTag) t).getSubTags(), actionScripts);
}
if (t instanceof ABCContainerTag) {
actionScripts.add((ABCContainerTag) t);
@@ -714,15 +761,6 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
private void findFileAttributes() {
for (Tag t : tags) {
if (t instanceof FileAttributesTag) {
fileAttributes = (FileAttributesTag) t;
break;
}
}
}
public void assignExportNamesToSymbols() {
HashMap<Integer, String> exportNames = new HashMap<>();
for (Tag t : tags) {
@@ -905,6 +943,7 @@ public final class SWF implements SWFContainerItem, Timelined {
public boolean exportAS3Class(String className, String outdir, ScriptExportMode exportMode, boolean parallel) throws Exception {
boolean exported = false;
List<ABCContainerTag> abcList = getAbcList();
for (int i = 0; i < abcList.size(); i++) {
ABC abc = abcList.get(i).getABC();
List<ScriptPack> scrs = abc.findScriptPacksByPath(className);
@@ -941,7 +980,7 @@ public final class SWF implements SWFContainerItem, Timelined {
public List<MyEntry<ClassPath, ScriptPack>> getAS3Packs() {
List<MyEntry<ClassPath, ScriptPack>> packs = new ArrayList<>();
for (ABCContainerTag abcTag : abcList) {
for (ABCContainerTag abcTag : getAbcList()) {
packs.addAll(abcTag.getABC().getScriptPacks());
}
return uniqueAS3Packs(packs);
@@ -1025,7 +1064,7 @@ public final class SWF implements SWFContainerItem, 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, abcList, exportMode, parallel);
ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, getAbcList(), exportMode, parallel);
ret.add(task.call());
}
return null;
@@ -1040,7 +1079,7 @@ public final class SWF implements SWFContainerItem, 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, abcList, exportMode, parallel));
Future<File> future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, getAbcList(), exportMode, parallel));
futureResults.add(future);
}
@@ -1080,7 +1119,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
};
if (isAS3) {
if (isAS3()) {
ret.addAll(exportActionScript3(handler, outdir, exportMode, parallel));
} else {
ret.addAll(exportActionScript2(handler, outdir, exportMode, parallel, evl));
@@ -1286,7 +1325,7 @@ public final class SWF implements SWFContainerItem, Timelined {
public static void writeLibrary(SWF fswf, Set<Integer> library, OutputStream fos) throws IOException {
for (int c : library) {
CharacterTag ch = fswf.characters.get(c);
CharacterTag ch = fswf.getCharacter(c);
if (ch instanceof FontTag) {
fos.write(Utf8Helper.getBytes("function " + getTypePrefix(ch) + c + "(ctx,ch,textColor){\r\n"));
fos.write(Utf8Helper.getBytes(((FontTag) ch).toHtmlCanvas(1)));
@@ -1327,8 +1366,8 @@ public final class SWF implements SWFContainerItem, Timelined {
if (containerId == 0) {
tim = getTimeline();
} else {
tim = ((Timelined) characters.get(containerId)).getTimeline();
path = File.separator + Helper.makeFileName(characters.get(containerId).getExportFileName());
tim = ((Timelined) getCharacter(containerId)).getTimeline();
path = File.separator + Helper.makeFileName(getCharacter(containerId).getExportFileName());
}
if (frames == null) {
int frameCnt = tim.getFrames().size();
@@ -1411,7 +1450,7 @@ public final class SWF implements SWFContainerItem, Timelined {
writeLibrary(fswf, library, fos);
String currentName = ftim.id == 0 ? "main" : getTypePrefix(fswf.characters.get(ftim.id)) + ftim.id;
String currentName = ftim.id == 0 ? "main" : getTypePrefix(fswf.getCharacter(ftim.id)) + ftim.id;
fos.write(Utf8Helper.getBytes("function " + currentName + "(ctx,ctrans,frame,ratio,time){\r\n"));
fos.write(Utf8Helper.getBytes("\tctx.save();\r\n"));
@@ -1856,7 +1895,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
public int deobfuscateIdentifiers(RenameType renameType) throws InterruptedException {
findFileAttributes();
FileAttributesTag fileAttributes = getFileAttributes();
if (fileAttributes == null) {
int cnt = 0;
cnt += deobfuscateAS2Identifiers(renameType);
@@ -2217,7 +2256,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
boolean parallel = Configuration.parallelSpeedUp.get();
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true);
pack.toSource(writer, swf.abcList, script.traits.traits, ScriptExportMode.AS, parallel);
pack.toSource(writer, swf.getAbcList(), script.traits.traits, ScriptExportMode.AS, parallel);
HighlightedText hilightedCode = new HighlightedText(writer);
CachedDecompilation res = new CachedDecompilation(hilightedCode);
swf.as3Cache.put(pack, res);
@@ -2298,13 +2337,13 @@ public final class SWF implements SWFContainerItem, Timelined {
continue;
}
DepthState layer = frameObj.layers.get(i);
if (!timeline.swf.characters.containsKey(layer.characterId)) {
if (!timeline.swf.getCharacters().containsKey(layer.characterId)) {
continue;
}
if (!layer.isVisible) {
continue;
}
CharacterTag character = timeline.swf.characters.get(layer.characterId);
CharacterTag character = timeline.swf.getCharacter(layer.characterId);
if (colorTransform == null) {
colorTransform = new ColorTransform();
@@ -2512,13 +2551,13 @@ public final class SWF implements SWFContainerItem, Timelined {
continue;
}
DepthState layer = frameObj.layers.get(i);
if (!timeline.swf.characters.containsKey(layer.characterId)) {
if (!timeline.swf.getCharacters().containsKey(layer.characterId)) {
continue;
}
if (!layer.isVisible) {
continue;
}
CharacterTag character = timeline.swf.characters.get(layer.characterId);
CharacterTag character = timeline.swf.getCharacter(layer.characterId);
if (colorTransform == null) {
colorTransform = new ColorTransform();
@@ -2657,13 +2696,13 @@ public final class SWF implements SWFContainerItem, Timelined {
continue;
}
DepthState layer = frameObj.layers.get(i);
if (!timeline.swf.characters.containsKey(layer.characterId)) {
if (!timeline.swf.getCharacters().containsKey(layer.characterId)) {
continue;
}
if (!layer.isVisible) {
continue;
}
CharacterTag character = timeline.swf.characters.get(layer.characterId);
CharacterTag character = timeline.swf.getCharacter(layer.characterId);
Matrix mat = new Matrix(layer.matrix);
mat = mat.preConcatenate(transformation);
@@ -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.abc.avm2.parser.script;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -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.abc.avm2.parser.script;
import com.jpexs.decompiler.flash.SWC;
@@ -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.abc.types.traits;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -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.abc.types.traits;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2010-2015 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.swf;
import com.jpexs.helpers.Helper;
/**
*
* @author JPEXS
*/
public class IndenetedStringBuilder {
private final StringBuilder builder = new StringBuilder();
private final String indentString;
private int indent;
public IndenetedStringBuilder(String indentString) {
super();
this.indentString = indentString;
}
public void indent() {
indent++;
}
public void unindent() {
indent--;
}
public void appendLine(String str) {
for (int i = 0; i < indent; i++) {
builder.append(indentString);
}
builder.append(str);
builder.append(Helper.newLine);
}
@Override
public String toString() {
return builder.toString();
}
}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2010-2015 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.swf;
import com.jpexs.decompiler.flash.SWF;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class SwfFile {
public SWF getSwf() {
return null;
}
public void saveTo(String fileName) throws IOException {
/*SWF swf = getSwf();
try (FileOutputStream fos = new FileOutputStream(fileName)) {
swf.saveTo(fos, SWFCompression.ZLIB);
}*/
}
}
@@ -0,0 +1,257 @@
/*
* Copyright (C) 2010-2015 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.swf;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.LazyObject;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class SwfJavaExporter {
private static final String javaIndentString = " ";
private static final String[] allowedSubTypes = new String[] { "List", "String", "ByteArrayRange", "RECT", "MATRIX", "CXFORMWITHALPHA",
"CXFORM", "CLIPEVENTFLAGS", "CLIPACTIONRECORD", "CLIPACTIONS", "COLORMATRIXFILTER", "RGBA", "ARGB", "RGB",
"CONVOLUTIONFILTER", "BLURFILTER", "DROPSHADOWFILTER", "GLOWFILTER", "BEVELFILTER", "GRADIENTGLOWFILTER", "GRADIENTBEVELFILTER",
"FILTERLIST", "FILTER", "BUTTONRECORD", "BUTTONCONDACTION", "GRADRECORD", "GRADIENT", "FOCALGRADIENT", "FILLSTYLE",
"FILLSTYLEARRAY", "LINESTYLE", "LINESTYLE2", "LINESTYLEARRAY", "SHAPERECORD", "SHAPE", "SHAPEWITHSTYLE", "SHAPERECORDS",
"SOUNDINFO", "SOUNDENVELOPE", "GLYPHENTRY", "TEXTRECORD", "MORPHGRADRECORD", "MORPHGRADIENT", "MORPHFOCALGRADIENT",
"MORPHFILLSTYLE", "MORPHFILLSTYLEARRAY", "MORPHLINESTYLE", "MORPHLINESTYLE2", "MORPHLINESTYLEARRAY", "KERNINGRECORD",
"LANGCODE", "ZONERECORD", "ZONEDATA", "PIX15", "PIX24", "COLORMAPDATA", "BITMAPDATA", "ALPHABITMAPDATA", "ALPHACOLORMAPDATA" };
public List<File> exportJavaCode(SWF swf, String outdir) throws IOException {
final File file = new File(outdir + File.separator + Helper.makeFileName("SwfFile.java"));
CodeFormatting codeFormatting = Configuration.getCodeFormatting();
codeFormatting.indentString = javaIndentString;
try (FileTextWriter writer = new FileTextWriter(codeFormatting, new FileOutputStream(file))) {
exportJavaCode(swf, writer);
}
List<File> ret = new ArrayList<>();
ret.add(file);
return ret;
}
public void exportJavaCode(SWF swf, GraphTextWriter writer) throws IOException {
Map<String, Integer> objectNames = new HashMap<>();
writer.append("package com.jpexs.decompiler.flash.exporters.swf;").newLine();
writer.newLine();
writer.append("import com.jpexs.decompiler.flash.SWF;").newLine();
writer.append("import com.jpexs.decompiler.flash.SWFCompression;").newLine();
writer.append("import com.jpexs.decompiler.flash.tags.*;").newLine();
writer.append("import com.jpexs.decompiler.flash.types.*;").newLine();
writer.append("import com.jpexs.decompiler.flash.types.filters.*;").newLine();
writer.append("import com.jpexs.decompiler.flash.types.shaperecords.*;").newLine();
writer.append("import com.jpexs.helpers.ByteArrayRange;").newLine();
writer.append("import java.io.FileOutputStream;").newLine();
writer.append("import java.io.IOException;").newLine();
writer.append("import java.util.ArrayList;").newLine();
writer.append("import java.util.List;").newLine();
writer.newLine();
writer.append("@SuppressWarnings(\"unchecked\")").newLine();
writer.append("public class SwfFile {").newLine();
writer.newLine();
writer.indent();
IndenetedStringBuilder sb = new IndenetedStringBuilder(javaIndentString);
generateJavaCode(writer, sb, objectNames, swf, 0);
writer.unindent();
writer.append(" public SWF getSwf() {").newLine();
writer.append(" SWF swf = swf();").newLine();
writer.append(" swf.updateCharacters();").newLine();
writer.append(" return swf;").newLine();
writer.append(" }").newLine();
writer.newLine();
writer.append(" public void saveTo(String fileName) throws IOException {").newLine();
writer.append(" SWF swf = getSwf();").newLine();
writer.append(" swf.clearModified();").newLine();
writer.append(" try (FileOutputStream fos = new FileOutputStream(fileName)) {").newLine();
writer.append(" swf.saveTo(fos, SWFCompression.ZLIB);").newLine();
writer.append(" }").newLine();
writer.append(" }").newLine();
writer.append("}").newLine();
}
private static String getNextId(Map<String, Integer> objectNames, String type) {
Integer nextId = objectNames.get(type);
if (nextId == null) {
nextId = 0;
} else {
nextId++;
}
objectNames.put(type, nextId);
return type + nextId;
}
private static String getIndent(int indent, String indentStr) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indent; i++) {
sb.append(indentStr);
}
return sb.toString();
}
private static Object generateJavaCode(GraphTextWriter writer, IndenetedStringBuilder sb, Map<String, Integer> objectNames, Object obj, int level){
if (obj == null) {
return null;
}
Class cls = obj.getClass();
Object value = null;
if (cls == Byte.class || cls == byte.class ||
cls == Short.class || cls == short.class ||
cls == Integer.class || cls == int.class ||
cls == Long.class || cls == long.class ||
cls == Float.class || cls == float.class ||
cls == Double.class || cls == double.class ||
cls == Boolean.class || cls == boolean.class ||
cls == Character.class || cls == char.class ||
cls == String.class) {
value = obj;
if (value instanceof Float) {
value = value + "f";
} else if (value instanceof String) {
value = "\"" + Helper.escapeJavaString((String) value) + "\"";
}
} else if (cls.isEnum()) {
value = cls.getSimpleName() + "." + obj;
} else if (obj instanceof ByteArrayRange) {
ByteArrayRange range = (ByteArrayRange) obj;
String className = "ByteArrayRange";
String tagObjName = getNextId(objectNames, "objByteArrayRange");
byte[] data = range.getRangeData();
StringBuilder sb2 = new StringBuilder();
final int maxBytePerString = 32767;
boolean isLong = data.length > maxBytePerString;
if (isLong) {
// string should be splitted to avoid "constant string too long" compile error
sb2.append("String.join(\"\", ");
}
int stringCount = (int) Math.ceil(data.length / (double) maxBytePerString);
for (int i = 0; i < stringCount; i++) {
if (i != 0) {
sb2.append(", ");
}
sb2.append("\"");
int from = i * maxBytePerString;
int to = Math.min(from + maxBytePerString, data.length);
for (int j = from; j < to; j++) {
sb2.append(String.format("%02x", data[j]));
}
sb2.append("\"");
}
if (isLong) {
sb2.append(")");
}
sb.appendLine(className + " " + tagObjName + " = new ByteArrayRange(" + sb2.toString() + ");");
value = tagObjName;
} else if (List.class.isAssignableFrom(cls)) {
List list = (List) obj;
String tagObjName = getNextId(objectNames, "objList");
sb.appendLine("List " + tagObjName + " = new ArrayList();");
for (int i = 0; i < list.size(); i++) {
Object val = generateJavaCode(writer, sb, objectNames, list.get(i), level + 1);
sb.appendLine(tagObjName + ".add(" + val + ");");
}
value = tagObjName;
} else if (cls.isArray()) {
String tagObjName = getNextId(objectNames, "objArray");
String arrayType = cls.getComponentType().getSimpleName();
int length = Array.getLength(obj);
sb.appendLine(arrayType + "[] " + tagObjName + " = new " + arrayType + "[" + length + "];");
for (int i = 0; i < length; i++) {
Object val = generateJavaCode(writer, sb, objectNames, Array.get(obj, i), level + 1);
sb.appendLine(tagObjName + "[" + i + "] = " + val + ";");
}
value = tagObjName;
} else {
if (obj instanceof LazyObject) {
((LazyObject) obj).load();
}
String className = obj.getClass().getSimpleName();
boolean isSwf = level == 0;
String resultName = isSwf ? "swf" : "result";
String tagObjName = isSwf ? "swf" : getNextId(objectNames, "obj" + className);
IndenetedStringBuilder sb2 = new IndenetedStringBuilder(javaIndentString);
sb2.indent();
sb2.indent();
String indent = getIndent(writer.getIndent() + 1, javaIndentString);
Field fields[] = obj.getClass().getFields();
for (Field f : fields) {
if (Modifier.isStatic(f.getModifiers())) {
continue;
}
Internal inter = f.getAnnotation(Internal.class);
if (inter != null) {
continue;
}
try {
f.setAccessible(true);
Object value2 = generateJavaCode(writer, sb2, objectNames, f.get(obj), level + 1);
if (value2 != null) {
sb2.appendLine(resultName + "." + f.getName() + " = " + value2 + ";");
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(SwfJavaExporter.class.getName()).log(Level.SEVERE, null, ex);
}
}
writer.append("private " + className + " " + tagObjName + "(" + (isSwf ? "" : "SWF swf") + ") {").newLine();
writer.indent();
writer.append(className + " " + resultName + " = new " + className + "(" + (obj instanceof Tag ? "swf" : "") + ");" + Helper.newLine);
writer.append(sb2.toString());
writer.append(indent + "return " + resultName + ";").newLine();
writer.unindent();
writer.append("}").newLine().newLine();
value = tagObjName + "(swf)";
}
return value;
}
}
@@ -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.helpers;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightData;
@@ -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.helpers;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightData;
@@ -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.helpers;
import com.jpexs.decompiler.flash.configuration.Configuration;
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2010-2015 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.helpers;
/**
*
* @author JPEXS
*/
public interface LazyObject {
public void load();
}
@@ -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.abc.ABC;
@@ -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;
@@ -26,6 +27,7 @@ import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA;
import com.jpexs.decompiler.flash.types.ARGB;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
@@ -64,9 +66,9 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
public static final int FORMAT_8BIT_COLORMAPPED = 3;
public static final int FORMAT_32BIT_ARGB = 5;
@Internal
@HideInRawEdit
private ALPHACOLORMAPDATA colorMapData;
@Internal
@HideInRawEdit
private ALPHABITMAPDATA bitmapData;
@Internal
private boolean decompressed = false;
@@ -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;
@@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.types.COLORMAPDATA;
import com.jpexs.decompiler.flash.types.PIX24;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
@@ -65,9 +67,9 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
public static final int FORMAT_15BIT_RGB = 4;
public static final int FORMAT_24BIT_RGB = 5;
@Internal
@HideInRawEdit
private COLORMAPDATA colorMapData;
@Internal
@HideInRawEdit
private BITMAPDATA bitmapData;
@Internal
private boolean decompressed = false;
@@ -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;
@@ -202,7 +203,7 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
}
RECT rect = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
for (BUTTONRECORD r : characters) {
CharacterTag ch = swf.characters.get(r.characterId);
CharacterTag ch = swf.getCharacter(r.characterId);
if (ch instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) ch;
if (!added.contains(bt)) {
@@ -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;
@@ -38,7 +39,7 @@ import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
@@ -74,7 +75,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
* Actions to perform
*/
//public List<Action> actions;
@Internal
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 7;
@@ -253,7 +254,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
}
RECT rect = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
for (BUTTONRECORD r : characters) {
CharacterTag ch = swf.characters.get(r.characterId);
CharacterTag ch = swf.getCharacter(r.characterId);
if (ch instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) ch;
if (!added.contains(bt)) {
@@ -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;
@@ -26,7 +27,6 @@ import com.jpexs.decompiler.flash.types.LANGCODE;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.helpers.ByteArrayRange;
@@ -57,8 +57,6 @@ public class DefineFont2Tag extends FontTag {
public boolean fontFlagsBold;
public LANGCODE languageCode;
public String fontName;
@Internal
public int numGlyphs;
public List<SHAPE> glyphShapeTable;
@SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes")
@@ -136,6 +134,7 @@ public class DefineFont2Tag extends FontTag {
byte[] fontNameBytes = Utf8Helper.getBytes(fontName);
sos.writeUI8(fontNameBytes.length);
sos.write(fontNameBytes);
int numGlyphs = glyphShapeTable.size();
sos.writeUI16(numGlyphs);
List<Long> offsetTable = new ArrayList<>();
@@ -232,7 +231,7 @@ public class DefineFont2Tag extends FontTag {
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
}
numGlyphs = sis.readUI16("numGlyphs");
int numGlyphs = sis.readUI16("numGlyphs");
long[] offsetTable = new long[numGlyphs];
long pos = sis.getPos();
for (int i = 0; i < numGlyphs; i++) { //offsetTable
@@ -428,9 +427,6 @@ public class DefineFont2Tag extends FontTag {
fontAdvanceTable.set(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character)));
}
}
if (!exists) {
numGlyphs++;
}
setModified(true);
}
@@ -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;
@@ -28,7 +29,6 @@ import com.jpexs.decompiler.flash.types.LANGCODE;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.helpers.ByteArrayRange;
@@ -56,8 +56,6 @@ public class DefineFont3Tag extends FontTag {
public boolean fontFlagsBold;
public LANGCODE languageCode;
public String fontName;
@Internal
public int numGlyphs;
public List<SHAPE> glyphShapeTable;
@@ -142,7 +140,7 @@ public class DefineFont3Tag extends FontTag {
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
}
numGlyphs = sis.readUI16("numGlyphs");
int numGlyphs = sis.readUI16("numGlyphs");
long[] offsetTable = new long[numGlyphs];
long pos = sis.getPos();
for (int i = 0; i < numGlyphs; i++) { //offsetTable
@@ -209,6 +207,7 @@ public class DefineFont3Tag extends FontTag {
List<Long> offsetTable = new ArrayList<>();
ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream();
SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion());
int numGlyphs = glyphShapeTable.size();
for (int i = 0; i < numGlyphs; i++) {
offsetTable.add(sos3.getPos());
sos3.writeSHAPE(glyphShapeTable.get(i), 1);
@@ -428,9 +427,6 @@ public class DefineFont3Tag extends FontTag {
fontAdvanceTable.set(pos, (int) getDivider() * Math.round(FontHelper.getFontAdvance(fnt, character)));
}
}
if (!exists) {
numGlyphs++;
}
setModified(true);
}
@@ -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;
@@ -96,7 +97,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
boolean foundSomething = false;
for (int c : characters) {
Tag t = swf.characters.get(c);
Tag t = swf.getCharacter(c);
RECT r = null;
if (t instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) t;
@@ -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;
@@ -23,7 +24,7 @@ import com.jpexs.decompiler.flash.abc.ABCInputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayInputStream;
@@ -43,7 +44,7 @@ public class DoABCDefineTag extends Tag implements ABCContainerTag {
/**
* ActionScript 3 bytecodes
*/
@Internal
@HideInRawEdit
private final ABC abc;
/**
* A 32-bit flags value, which may contain the following bits set:
@@ -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;
@@ -22,7 +23,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ABCInputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -37,7 +38,7 @@ public class DoABCTag extends Tag implements ABCContainerTag {
/**
* ActionScript 3 bytecodes
*/
@Internal
@HideInRawEdit
private final ABC abc;
public static final int ID = 72;
@@ -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;
@@ -24,7 +25,7 @@ import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
import java.io.IOException;
@@ -43,7 +44,7 @@ public class DoActionTag extends Tag implements ASMSource {
* List of actions to perform
*/
//public List<Action> actions = new ArrayList<Action>();
@Internal
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 12;
@@ -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;
@@ -27,7 +28,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
@@ -49,7 +50,7 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource {
* List of actions to perform
*/
//public List<Action> actions = new ArrayList<Action>();
@Internal
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 59;
@@ -12,13 +12,14 @@
* 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.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -27,7 +28,7 @@ import java.io.OutputStream;
public class JPEGTablesTag extends Tag {
public static final int ID = 8;
@Internal
@HideInRawEdit
public byte[] jpegData;
/**
@@ -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;
@@ -31,7 +32,7 @@ import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.filters.FILTER;
import com.jpexs.helpers.ByteArrayRange;
@@ -123,7 +124,7 @@ public class PlaceObject2Tag extends CharacterIdTag implements ASMSourceContaine
* @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data
*/
@Conditional("placeFlagHasClipActions")
@Internal //TODO: make editable
@HideInRawEdit //TODO: make editable
public CLIPACTIONS clipActions;
public static final int ID = 26;
@@ -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.EndOfStreamException;
@@ -32,6 +33,7 @@ import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
@@ -180,7 +182,7 @@ public class PlaceObject3Tag extends CharacterIdTag implements ASMSourceContaine
* @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data
*/
@Conditional(value = "placeFlagHasClipActions", minSwfVersion = 5)
@Internal //TODO: make editable
@HideInRawEdit //TODO: make editable
public CLIPACTIONS clipActions;
/**
* If PlaceFlagHasVisible, 0 = Place invisible, 1 = Place visible
@@ -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.EndOfStreamException;
@@ -32,6 +33,7 @@ import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
@@ -180,7 +182,7 @@ public class PlaceObject4Tag extends CharacterIdTag implements ASMSourceContaine
* @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data
*/
@Conditional(value = "placeFlagHasClipActions", minSwfVersion = 5)
@Internal //TODO: make editable
@HideInRawEdit //TODO: make editable
public CLIPACTIONS clipActions;
/**
* If PlaceFlagHasVisible, 0 = Place invisible, 1 = Place visible
@@ -12,13 +12,14 @@
* 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.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -33,7 +34,7 @@ public class SoundStreamBlockTag extends Tag {
public static final int ID = 19;
@Internal
@HideInRawEdit
public ByteArrayRange streamSoundData;
/**
@@ -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;
@@ -415,10 +416,18 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
}
public long getPos() {
if (originalRange == null) {
return -1;
}
return originalRange.getPos();
}
public long getDataPos() {
if (originalRange == null) {
return -1;
}
return originalRange.getPos() + (isLongOriginal() ? 6 : 2);
}
@@ -474,8 +483,8 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
for (Integer characterId : needed2) {
if (!visited.contains(characterId)) {
visited.add(characterId);
if (swf.characters.containsKey(characterId)) {
swf.characters.get(characterId).getNeededCharacters(needed2);
if (swf.getCharacters().containsKey(characterId)) {
swf.getCharacter(characterId).getNeededCharacters(needed2);
break;
}
}
@@ -483,7 +492,7 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
}
for (Integer characterId : needed2) {
if (swf.characters.containsKey(characterId)) {
if (swf.getCharacters().containsKey(characterId)) {
needed.add(characterId);
}
}
@@ -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.SWF;
@@ -23,6 +24,7 @@ import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
import com.jpexs.decompiler.flash.exporters.shape.PathExporter;
import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter;
import com.jpexs.decompiler.flash.helpers.LazyObject;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
@@ -42,7 +44,7 @@ import java.util.Set;
*
* @author JPEXS
*/
public abstract class ShapeTag extends CharacterTag implements DrawableTag {
public abstract class ShapeTag extends CharacterTag implements DrawableTag, LazyObject {
private final int markerSize = 10;
@@ -51,6 +53,11 @@ public abstract class ShapeTag extends CharacterTag implements DrawableTag {
}
public abstract SHAPEWITHSTYLE getShapes();
@Override
public void load() {
getShapes();
}
public abstract int getShapeNum();
@@ -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.SWF;
@@ -291,7 +292,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
}
}
if (rec.styleFlagsHasFont) {
font = (FontTag) swf.characters.get(rec.fontId);
font = (FontTag) swf.getCharacter(rec.fontId);
glyphs = font == null ? null : font.getGlyphShapeTable();
textHeight = rec.textHeight;
}
@@ -337,7 +338,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
ExportRectangle result = null;
for (TEXTRECORD rec : textRecords) {
if (rec.styleFlagsHasFont) {
font = (FontTag) swf.characters.get(rec.fontId);
font = (FontTag) swf.getCharacter(rec.fontId);
glyphs = font == null ? null : font.getGlyphShapeTable();
textHeight = rec.textHeight;
}
@@ -428,7 +429,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
}
}
if (rec.styleFlagsHasFont) {
font = (FontTag) swf.characters.get(rec.fontId);
font = (FontTag) swf.getCharacter(rec.fontId);
fontId = rec.fontId;
glyphs = font.getGlyphShapeTable();
textHeight = rec.textHeight;
@@ -474,7 +475,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
}
}
if (rec.styleFlagsHasFont) {
font = (FontTag) swf.characters.get(rec.fontId);
font = (FontTag) swf.getCharacter(rec.fontId);
glyphs = font.getGlyphShapeTable();
textHeight = rec.textHeight;
}
@@ -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.gfx;
import com.jpexs.decompiler.flash.SWF;
@@ -387,7 +388,6 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
ret.codeTable = new ArrayList<>();
ret.glyphShapeTable = new ArrayList<>();
List<SHAPE> shp = getGlyphShapeTable();
ret.numGlyphs = shp.size();
for (int g = 0; g < shp.size(); g++) {
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
ret.codeTable.add((int) glyphToChar(g));
@@ -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.SWF;
@@ -353,11 +354,11 @@ public class Timeline {
for (int depth : frameObj.layers.keySet()) {
DepthState layer = frameObj.layers.get(depth);
if (layer.characterId != -1) {
if (!swf.characters.containsKey(layer.characterId)) {
if (!swf.getCharacters().containsKey(layer.characterId)) {
continue;
}
usedCharacters.add(layer.characterId);
swf.characters.get(layer.characterId).getNeededCharactersDeep(usedCharacters);
swf.getCharacter(layer.characterId).getNeededCharactersDeep(usedCharacters);
}
}
}
@@ -391,7 +392,7 @@ public class Timeline {
for (int d = maxDepth; d >= 0; d--) {
DepthState ds = fr.layers.get(d);
if (ds != null) {
CharacterTag c = swf.characters.get(ds.characterId);
CharacterTag c = swf.getCharacter(ds.characterId);
if (c instanceof Timelined) {
int frameCount = ((Timelined) c).getTimeline().frames.size();
if (frameCount == 0) {
@@ -437,7 +438,7 @@ public class Timeline {
if (!ds.isVisible) {
continue;
}
CharacterTag c = swf.characters.get(ds.characterId);
CharacterTag c = swf.getCharacter(ds.characterId);
if (c instanceof DrawableTag) {
Matrix m = new Matrix(ds.matrix);
m = m.preConcatenate(transformation);
@@ -507,7 +508,7 @@ public class Timeline {
if (!ds.isVisible) {
continue;
}
CharacterTag c = swf.characters.get(ds.characterId);
CharacterTag c = swf.getCharacter(ds.characterId);
if (c instanceof DrawableTag) {
Matrix m = new Matrix(ds.matrix);
m = m.preConcatenate(transformation);
@@ -567,13 +568,13 @@ public class Timeline {
continue;
}
DepthState layer = frameObj.layers.get(i);
if (!swf.characters.containsKey(layer.characterId)) {
if (!swf.getCharacters().containsKey(layer.characterId)) {
continue;
}
if (!layer.isVisible) {
continue;
}
CharacterTag character = swf.characters.get(layer.characterId);
CharacterTag character = swf.getCharacter(layer.characterId);
if (character instanceof DrawableTag) {
DrawableTag drawable = (DrawableTag) character;
if (!drawable.isSingleFrame()) {
@@ -12,10 +12,10 @@
* 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.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import java.io.Serializable;
@@ -35,8 +35,6 @@ public class MORPHGRADIENT implements Serializable {
*/
@SWFType(value = BasicType.UB, count = 2)
public int interPolationMode;
@Internal
public int numGradients;
public MORPHGRADRECORD[] gradientRecords;
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2010-2015 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.types.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Field is internal
*
* @author JPEXS
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface HideInRawEdit {
}
@@ -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.shaperecords;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -26,8 +27,8 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType;
*/
public class CurvedEdgeRecord extends SHAPERECORD {
public boolean typeFlag = true;
public boolean straightFlag = false;
public static final boolean typeFlag = true;
public static final boolean straightFlag = false;
@Calculated
@SWFType(value = BasicType.UB, count = 4)
@@ -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.shaperecords;
import com.jpexs.decompiler.flash.types.BasicType;
@@ -24,7 +25,8 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType;
*/
public class EndShapeRecord extends SHAPERECORD {
public boolean typeFlag = false;
public static final boolean typeFlag = false;
@SWFType(value = BasicType.UB, count = 5)
public int endOfShape = 0;
@@ -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.shaperecords;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -38,8 +39,8 @@ public class StraightEdgeRecord extends SHAPERECORD {
ser.deltaY = (int) readSB(ser.numBits + 2);
}
*/
public boolean typeFlag = true;
public boolean straightFlag = true;
public static final boolean typeFlag = true;
public static final boolean straightFlag = true;
@Calculated
@SWFType(value = BasicType.UB, count = 4)
@@ -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.shaperecords;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -30,7 +31,7 @@ import java.util.Set;
*/
public final class StyleChangeRecord extends SHAPERECORD implements Cloneable {
public boolean typeFlag = false;
public static final boolean typeFlag = false;
public boolean stateNewStyles;
public boolean stateLineStyle;
public boolean stateFillStyle1;
@@ -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.xfl;
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
@@ -2679,7 +2680,7 @@ public class XFLConverter {
public static void convertSWF(AbortRetryIgnoreHandler handler, SWF swf, String swfFileName, String outfile, boolean compressed, String generator, String generatorVerName, String generatorVersion, boolean parallel, FLAVersion flaVersion) throws IOException {
FileAttributesTag fa = swf.fileAttributes;
FileAttributesTag fa = swf.getFileAttributes();
boolean useAS3 = false;
boolean useNetwork = false;
@@ -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.helpers;
/**
@@ -39,6 +40,16 @@ public class ByteArrayRange {
this.length = length;
}
public ByteArrayRange(String hexString) {
byte[] array = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length() / 2; i++) {
array[i] = (byte) Integer.parseInt(hexString.substring(i * 2, i * 2 + 2), 16);
}
this.array = array;
this.pos = 0;
this.length = array.length;
}
public byte[] getArray() {
return array;
}
@@ -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.helpers;
import com.jpexs.decompiler.flash.AppResources;
@@ -179,6 +180,42 @@ public class Helper {
return ret.toString();
}
/**
* Escapes string by adding backslashes
*
* @param s String to escape
* @return Escaped string
*/
public static String escapeJavaString(String s) {
StringBuilder ret = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\n') {
ret.append("\\n");
} else if (c == '\r') {
ret.append("\\r");
} else if (c == '\t') {
ret.append("\\t");
} else if (c == '\b') {
ret.append("\\b");
} else if (c == '\t') {
ret.append("\\t");
} else if (c == '\f') {
ret.append("\\f");
} else if (c == '\\') {
ret.append("\\\\");
} else if (c == '"') {
ret.append("\\\"");
} else if (c < 32) {
ret.append("\\u").append(padZeros(Integer.toHexString((int) c), 4));
} else {
ret.append(c);
}
}
return ret.toString();
}
public static String getValidHtmlId(String text) {
// ID and NAME tokens must begin with a letter ([A-Za-z]) and
// may be followed by any number of letters, digits ([0-9]),