mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 13:38:26 +00:00
swf.tags and sprite.subtags are private to avoid modifying the list without setting the isModified flag + some small chages
This commit is contained in:
@@ -157,10 +157,10 @@ public class IdentifiersDeobfuscation {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void deobfuscateInstanceNames(boolean as3, HashMap<DottedChain, DottedChain> namesMap, RenameType renameType, List<Tag> tags, Map<DottedChain, DottedChain> selected) {
|
||||
public void deobfuscateInstanceNames(boolean as3, HashMap<DottedChain, DottedChain> namesMap, RenameType renameType, Iterable<Tag> tags, Map<DottedChain, DottedChain> selected) {
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
deobfuscateInstanceNames(as3, namesMap, renameType, ((DefineSpriteTag) t).subTags, selected);
|
||||
deobfuscateInstanceNames(as3, namesMap, renameType, ((DefineSpriteTag) t).getTags(), selected);
|
||||
}
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
PlaceObjectTypeTag po = (PlaceObjectTypeTag) t;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ReadOnlyTagList implements Iterable<Tag> {
|
||||
|
||||
public static final ReadOnlyTagList EMPTY = new ReadOnlyTagList(new ArrayList<>());
|
||||
|
||||
private final List<Tag> list;
|
||||
|
||||
public ReadOnlyTagList(List<Tag> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Tag> iterator() {
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
public Tag get(int index) {
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
public int indexOf(Tag tag) {
|
||||
return list.indexOf(tag);
|
||||
}
|
||||
|
||||
public ArrayList<Tag> toArrayList() {
|
||||
return new ArrayList<>(list);
|
||||
}
|
||||
}
|
||||
@@ -131,6 +131,7 @@ import com.jpexs.decompiler.flash.types.MATRIX;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFField;
|
||||
import com.jpexs.decompiler.flash.types.filters.BlendComposite;
|
||||
import com.jpexs.decompiler.flash.types.filters.FILTER;
|
||||
import com.jpexs.decompiler.flash.xfl.FLAVersion;
|
||||
@@ -207,9 +208,12 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
/**
|
||||
* Tags inside of file
|
||||
*/
|
||||
public List<Tag> tags = new ArrayList<>();
|
||||
@SWFField
|
||||
private List<Tag> tags = new ArrayList<>();
|
||||
|
||||
@Internal
|
||||
public ReadOnlyTagList readOnlyTags;
|
||||
|
||||
public boolean hasEndTag = true;
|
||||
|
||||
/**
|
||||
@@ -293,6 +297,9 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SWF.class.getName());
|
||||
|
||||
@Internal
|
||||
private boolean isModified;
|
||||
|
||||
@Internal
|
||||
private Timeline timeline;
|
||||
|
||||
@@ -346,14 +353,16 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
resetTimelines(this);
|
||||
updateCharacters();
|
||||
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag spriteTag = (DefineSpriteTag) tag;
|
||||
for (Tag tag1 : spriteTag.subTags) {
|
||||
for (Tag tag1 : spriteTag.getTags()) {
|
||||
tag1.setSwf(null);
|
||||
}
|
||||
|
||||
spriteTag.subTags.clear();
|
||||
for (int i = spriteTag.getTags().size() - 1; i >= 0; i--) {
|
||||
spriteTag.removeTag(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (tag instanceof DefineBinaryDataTag) {
|
||||
@@ -401,7 +410,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
synchronized (this) {
|
||||
if (characters == null) {
|
||||
Map<Integer, CharacterTag> chars = new HashMap<>();
|
||||
parseCharacters(tags, chars);
|
||||
parseCharacters(getTags(), chars);
|
||||
characters = Collections.unmodifiableMap(chars);
|
||||
}
|
||||
}
|
||||
@@ -415,7 +424,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
synchronized (this) {
|
||||
if (dependentCharacters == null) {
|
||||
Map<Integer, Set<Integer>> dep = new HashMap<>();
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof CharacterTag) {
|
||||
int characterId = ((CharacterTag) tag).getCharacterId();
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
@@ -529,7 +538,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
synchronized (this) {
|
||||
if (abcList == null) {
|
||||
ArrayList<ABCContainerTag> newAbcList = new ArrayList<>();
|
||||
getAbcTags(tags, newAbcList);
|
||||
getAbcTags(getTags(), newAbcList);
|
||||
abcList = newAbcList;
|
||||
}
|
||||
}
|
||||
@@ -544,7 +553,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public MetadataTag getMetadata() {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof MetadataTag) {
|
||||
return (MetadataTag) t;
|
||||
}
|
||||
@@ -554,7 +563,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public FileAttributesTag getFileAttributes() {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof FileAttributesTag) {
|
||||
return (FileAttributesTag) t;
|
||||
}
|
||||
@@ -564,7 +573,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public SetBackgroundColorTag getBackgroundColor() {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof SetBackgroundColorTag) {
|
||||
return (SetBackgroundColorTag) t;
|
||||
}
|
||||
@@ -574,7 +583,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public EnableTelemetryTag getEnableTelemetry() {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof EnableTelemetryTag) {
|
||||
return (EnableTelemetryTag) t;
|
||||
}
|
||||
@@ -597,7 +606,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
if (jtt == null) {
|
||||
synchronized (this) {
|
||||
if (jtt == null) {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof JPEGTablesTag) {
|
||||
jtt = (JPEGTablesTag) t;
|
||||
break;
|
||||
@@ -611,7 +620,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public String getDocumentClass() {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof SymbolClassTag) {
|
||||
SymbolClassTag sc = (SymbolClassTag) t;
|
||||
for (int i = 0; i < sc.tags.size(); i++) {
|
||||
@@ -672,7 +681,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
public void resetTimelines(Timelined timelined) {
|
||||
timelined.resetTimeline();
|
||||
if (timelined instanceof SWF) {
|
||||
for (Tag t : ((SWF) timelined).tags) {
|
||||
for (Tag t : ((SWF) timelined).getTags()) {
|
||||
if (t instanceof Timelined) {
|
||||
resetTimelines((Timelined) t);
|
||||
}
|
||||
@@ -680,7 +689,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
private void parseCharacters(List<Tag> list, Map<Integer, CharacterTag> characters) {
|
||||
private void parseCharacters(Iterable<Tag> list, Map<Integer, CharacterTag> characters) {
|
||||
for (Tag t : list) {
|
||||
if (t instanceof CharacterTag) {
|
||||
int characterId = ((CharacterTag) t).getCharacterId();
|
||||
@@ -693,7 +702,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
parseCharacters(((DefineSpriteTag) t).getSubTags(), characters);
|
||||
parseCharacters(((DefineSpriteTag) t).getTags(), characters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,7 +726,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return false;
|
||||
}
|
||||
path.add(sprite.spriteId);
|
||||
for (Tag t : sprite.subTags) {
|
||||
for (Tag t : sprite.getTags()) {
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
if (!isSpriteValid((DefineSpriteTag) t, path)) {
|
||||
return false;
|
||||
@@ -751,7 +760,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
*/
|
||||
public List<Tag> getTagData(int tagId) {
|
||||
List<Tag> ret = new ArrayList<>();
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag.getId() == tagId) {
|
||||
ret.add(tag);
|
||||
}
|
||||
@@ -817,7 +826,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
sos.writeFIXED8(frameRate);
|
||||
sos.writeUI16(frameCount);
|
||||
|
||||
sos.writeTags(tags);
|
||||
sos.writeTags(getTags());
|
||||
if (hasEndTag) {
|
||||
sos.writeUI16(0);
|
||||
}
|
||||
@@ -940,7 +949,11 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
for (Tag tag : tags) {
|
||||
if (isModified) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag.isModified()) {
|
||||
return true;
|
||||
}
|
||||
@@ -948,14 +961,21 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified(boolean value) {
|
||||
isModified = value;
|
||||
}
|
||||
|
||||
public void clearModified() {
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag.isModified()) {
|
||||
tag.createOriginalData();
|
||||
tag.setModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
isModified = false;
|
||||
|
||||
try {
|
||||
uncompressedData = saveToByteArray();
|
||||
} catch (IOException ex) {
|
||||
@@ -1093,6 +1113,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
hasEndTag = false;
|
||||
}
|
||||
this.tags = tags;
|
||||
readOnlyTags = null;
|
||||
if (!checkOnly) {
|
||||
checkInvalidSprites();
|
||||
updateCharacters();
|
||||
@@ -1174,10 +1195,10 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
private static void getAbcTags(List<Tag> list, List<ABCContainerTag> actionScripts) {
|
||||
private static void getAbcTags(Iterable<Tag> list, List<ABCContainerTag> actionScripts) {
|
||||
for (Tag t : list) {
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
getAbcTags(((DefineSpriteTag) t).getSubTags(), actionScripts);
|
||||
getAbcTags(((DefineSpriteTag) t).getTags(), actionScripts);
|
||||
}
|
||||
if (t instanceof ABCContainerTag) {
|
||||
actionScripts.add((ABCContainerTag) t);
|
||||
@@ -1187,7 +1208,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public void assignExportNamesToSymbols() {
|
||||
HashMap<Integer, String> exportNames = new HashMap<>();
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof ExportAssetsTag) {
|
||||
ExportAssetsTag eat = (ExportAssetsTag) t;
|
||||
for (int i = 0; i < eat.tags.size(); i++) {
|
||||
@@ -1199,7 +1220,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof CharacterTag) {
|
||||
CharacterTag ct = (CharacterTag) t;
|
||||
if (exportNames.containsKey(ct.getCharacterId())) {
|
||||
@@ -1211,7 +1232,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public void assignClassesToSymbols() {
|
||||
HashMap<Integer, String> classes = new HashMap<>();
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof SymbolClassTag) {
|
||||
SymbolClassTag sct = (SymbolClassTag) t;
|
||||
for (int i = 0; i < sct.tags.size(); i++) {
|
||||
@@ -1221,7 +1242,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof CharacterTag) {
|
||||
CharacterTag ct = (CharacterTag) t;
|
||||
if (classes.containsKey(ct.getCharacterId())) {
|
||||
@@ -1608,7 +1629,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public final void addEventListener(EventListener listener) {
|
||||
listeners.add(listener);
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
(((ABCContainerTag) t).getABC()).addEventListener(listener);
|
||||
}
|
||||
@@ -1617,7 +1638,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public final void removeEventListener(EventListener listener) {
|
||||
listeners.remove(listener);
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
(((ABCContainerTag) t).getABC()).removeEventListener(listener);
|
||||
}
|
||||
@@ -1630,13 +1651,13 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
public static void populateVideoFrames(int streamId, List<Tag> tags, HashMap<Integer, VideoFrameTag> output) {
|
||||
public static void populateVideoFrames(int streamId, Iterable<Tag> tags, HashMap<Integer, VideoFrameTag> output) {
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof VideoFrameTag) {
|
||||
output.put(((VideoFrameTag) t).frameNum, (VideoFrameTag) t);
|
||||
}
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
populateVideoFrames(streamId, ((DefineSpriteTag) t).getSubTags(), output);
|
||||
populateVideoFrames(streamId, ((DefineSpriteTag) t).getTags(), output);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1907,7 +1928,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void getVariables(List<Tag> tags, String path, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes) throws InterruptedException {
|
||||
private void getVariables(Iterable<Tag> tags, String path, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes) throws InterruptedException {
|
||||
List<String> processed = new ArrayList<>();
|
||||
for (Tag t : tags) {
|
||||
String subPath = path + "/" + t.toString();
|
||||
@@ -1921,7 +1942,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
getVariables(((DefineSpriteTag) t).getSubTags(), path + "/" + t.toString(), variables, actionsMap, functions, strings, usageTypes);
|
||||
getVariables(((DefineSpriteTag) t).getTags(), path + "/" + t.toString(), variables, actionsMap, functions, strings, usageTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1964,19 +1985,19 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public int deobfuscateAS3Identifiers(RenameType renameType) {
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof ABCContainerTag) {
|
||||
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, true);
|
||||
tag.setModified(true);
|
||||
}
|
||||
}
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof ABCContainerTag) {
|
||||
((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(deobfuscated, renameType, false);
|
||||
tag.setModified(true);
|
||||
}
|
||||
}
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof SymbolClassTag) {
|
||||
SymbolClassTag sc = (SymbolClassTag) tag;
|
||||
for (int i = 0; i < sc.names.size(); i++) {
|
||||
@@ -1988,7 +2009,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
sc.setModified(true);
|
||||
}
|
||||
}
|
||||
deobfuscation.deobfuscateInstanceNames(true, deobfuscated, renameType, tags, new HashMap<>());
|
||||
deobfuscation.deobfuscateInstanceNames(true, deobfuscated, renameType, getTags(), new HashMap<>());
|
||||
return deobfuscated.size();
|
||||
}
|
||||
|
||||
@@ -2026,7 +2047,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
HashMap<DirectValueActionItem, String> usageTypes = new HashMap<>();
|
||||
|
||||
int ret = 0;
|
||||
getVariables(tags, "", allVariableNames, actionsMap, allFunctions, allStrings, usageTypes);
|
||||
getVariables(getTags(), "", allVariableNames, actionsMap, allFunctions, allStrings, usageTypes);
|
||||
informListeners("rename", "");
|
||||
int fc = 0;
|
||||
for (MyEntry<DirectValueActionItem, ConstantPool> it : allVariableNames) {
|
||||
@@ -2036,13 +2057,13 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
informListeners("rename", "classes");
|
||||
int classCount = 0;
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof DoInitActionTag) {
|
||||
classCount++;
|
||||
}
|
||||
}
|
||||
int cnt = 0;
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof DoInitActionTag) {
|
||||
cnt++;
|
||||
informListeners("rename", "class " + cnt + "/" + classCount);
|
||||
@@ -2252,7 +2273,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
src.setModified();
|
||||
}
|
||||
|
||||
deobfuscation.deobfuscateInstanceNames(false, deobfuscated, renameType, tags, selected);
|
||||
deobfuscation.deobfuscateInstanceNames(false, deobfuscated, renameType, getTags(), selected);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2303,7 +2324,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
public void clearImageCache() {
|
||||
frameCache.clear();
|
||||
rectCache.clear();
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof ImageTag) {
|
||||
((ImageTag) tag).clearCache();
|
||||
}
|
||||
@@ -2317,10 +2338,20 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
IdentifiersDeobfuscation.clearCache();
|
||||
}
|
||||
|
||||
public void clearReadOnlyListCache() {
|
||||
readOnlyTags = null;
|
||||
for (Tag tag : tags) {
|
||||
if (tag instanceof DefineSpriteTag) {
|
||||
((DefineSpriteTag) tag).clearReadOnlyListCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAllCache() {
|
||||
characters = null;
|
||||
abcList = null;
|
||||
timeline = null;
|
||||
clearReadOnlyListCache();
|
||||
clearImageCache();
|
||||
clearScriptCache();
|
||||
Cache.clearAll();
|
||||
@@ -2876,13 +2907,15 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
private void removeTagWithDependenciesFromTimeline(Tag toRemove, Timeline timeline) {
|
||||
Map<Integer, Integer> stage = new HashMap<>();
|
||||
Set<Integer> dependingChars = new HashSet<>();
|
||||
Timelined timelined = timeline.timelined;
|
||||
ReadOnlyTagList tags = timelined.getTags();
|
||||
if (toRemove instanceof CharacterTag) {
|
||||
int characterId = ((CharacterTag) toRemove).getCharacterId();
|
||||
|
||||
if (characterId != 0) {
|
||||
dependingChars.add(characterId);
|
||||
for (int i = 0; i < timeline.tags.size(); i++) {
|
||||
Tag t = timeline.tags.get(i);
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
Tag t = tags.get(i);
|
||||
if (t instanceof CharacterIdTag) {
|
||||
CharacterIdTag c = (CharacterIdTag) t;
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
@@ -2895,8 +2928,8 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < timeline.tags.size(); i++) {
|
||||
Tag t = timeline.tags.get(i);
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
Tag t = tags.get(i);
|
||||
if (t instanceof RemoveTag) {
|
||||
RemoveTag rt = (RemoveTag) t;
|
||||
int depth = rt.getDepth();
|
||||
@@ -2904,7 +2937,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
int currentCharId = stage.get(depth);
|
||||
stage.remove(depth);
|
||||
if (dependingChars.contains(currentCharId)) {
|
||||
timeline.tags.remove(i);
|
||||
timelined.removeTag(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
@@ -2917,7 +2950,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
if (placeCharId != 0) {
|
||||
stage.put(depth, placeCharId);
|
||||
if (dependingChars.contains(placeCharId)) {
|
||||
timeline.tags.remove(i);
|
||||
timelined.removeTag(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
@@ -2926,7 +2959,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
if (t instanceof CharacterIdTag) {
|
||||
CharacterIdTag c = (CharacterIdTag) t;
|
||||
if (dependingChars.contains(c.getCharacterId())) {
|
||||
timeline.tags.remove(i);
|
||||
timelined.removeTag(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
@@ -2935,13 +2968,13 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
t.getNeededCharacters(needed);
|
||||
for (int dep : dependingChars) {
|
||||
if (needed.contains(dep)) {
|
||||
timeline.tags.remove(i);
|
||||
timelined.removeTag(i);
|
||||
i--;
|
||||
//continue;
|
||||
}
|
||||
}
|
||||
if (t == toRemove) {
|
||||
timeline.tags.remove(i);
|
||||
timelined.removeTag(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
@@ -2958,10 +2991,12 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
characterId = ((CharacterTag) toRemove).getCharacterId();
|
||||
modified = timeline.removeCharacter(characterId);
|
||||
}
|
||||
for (int i = 0; i < timeline.tags.size(); i++) {
|
||||
Tag t = timeline.tags.get(i);
|
||||
Timelined timelined = timeline.timelined;
|
||||
ReadOnlyTagList tags = timelined.getTags();
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
Tag t = tags.get(i);
|
||||
if (t == toRemove) {
|
||||
timeline.tags.remove(t);
|
||||
timelined.removeTag(t);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
@@ -3002,6 +3037,16 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
clearImageCache();
|
||||
}
|
||||
|
||||
public void removeTag(int index) {
|
||||
setModified(true);
|
||||
tags.remove(index);
|
||||
}
|
||||
|
||||
public void removeTag(Tag tag) {
|
||||
setModified(true);
|
||||
tags.remove(tag);
|
||||
}
|
||||
|
||||
public void removeTag(Tag tag, boolean removeDependencies) {
|
||||
Timelined timelined = tag.getTimelined();
|
||||
removeTagInternal(timelined, tag, removeDependencies);
|
||||
@@ -3012,39 +3057,75 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
private void removeTagInternal(Timelined timelined, Tag tag, boolean removeDependencies) {
|
||||
if (tag instanceof ShowFrameTag || ShowFrameTag.isNestedTagType(tag.getId())) {
|
||||
List<Tag> tags;
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
tags = sprite.getSubTags();
|
||||
} else {
|
||||
tags = this.tags;
|
||||
}
|
||||
tags.remove(tag);
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
sprite.setModified(true);
|
||||
}
|
||||
timelined.removeTag(tag);
|
||||
timelined.setModified(true);
|
||||
timelined.resetTimeline();
|
||||
} else {
|
||||
// timeline should be always the swf here
|
||||
if (removeDependencies) {
|
||||
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
sprite.setModified(true);
|
||||
}
|
||||
timelined.setModified(true);
|
||||
} else {
|
||||
removeTagFromTimeline(tag, timelined.getTimeline());
|
||||
boolean modified = removeTagFromTimeline(tag, timelined.getTimeline());
|
||||
if (modified) {
|
||||
timelined.setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyTagList getTags() {
|
||||
if (readOnlyTags == null) {
|
||||
readOnlyTags = new ReadOnlyTagList(tags);
|
||||
}
|
||||
|
||||
return readOnlyTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tag to the SWF
|
||||
*
|
||||
* @param tag
|
||||
*/
|
||||
@Override
|
||||
public void addTag(Tag tag) {
|
||||
setModified(true);
|
||||
tags.add(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tag to the SWF
|
||||
*
|
||||
* @param index
|
||||
* @param tag
|
||||
*/
|
||||
@Override
|
||||
public void addTag(int index, Tag tag) {
|
||||
setModified(true);
|
||||
tags.add(index, tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a tag in the SWF
|
||||
*
|
||||
* @param oldTag
|
||||
* @param newTag
|
||||
*/
|
||||
public void replaceTag(Tag oldTag, Tag newTag) {
|
||||
setModified(true);
|
||||
int index = tags.indexOf(oldTag);
|
||||
if (index != -1) {
|
||||
tags.set(index, newTag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tag to the SWF
|
||||
* If targetTreeItem is:
|
||||
* - Frame: adds the tag to the Frame. Frame can be a frame of the main
|
||||
* timeline or a DefineSprite frame
|
||||
* - DefineSprite: adds the tag to the and of the DefineSprite's tag list
|
||||
* - DefineSprite: adds the tag to the end of the DefineSprite's tag list
|
||||
* - Any other tag in the SWF: adds the new tag exactly before the specified
|
||||
* tag
|
||||
* - Other: adds the tag to the end of the SWF's tag list
|
||||
@@ -3064,13 +3145,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
tag.setTimelined(timelined);
|
||||
|
||||
List<Tag> tags;
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
tags = sprite.subTags;
|
||||
} else {
|
||||
tags = swf.tags;
|
||||
}
|
||||
ReadOnlyTagList tags = timelined.getTags();
|
||||
|
||||
int index;
|
||||
if (frame != null) {
|
||||
@@ -3082,11 +3157,11 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
} else if (timelined instanceof DefineSpriteTag) {
|
||||
index = -1;
|
||||
} else if (targetTreeItem instanceof Tag) {
|
||||
if (tag instanceof CharacterIdTag && targetTreeItem instanceof CharacterTag) {
|
||||
if (tag instanceof CharacterIdTag && !(tag instanceof CharacterTag) && targetTreeItem instanceof CharacterTag) {
|
||||
((CharacterIdTag) tag).setCharacterId(((CharacterTag) targetTreeItem).getCharacterId());
|
||||
}
|
||||
|
||||
index = tags.indexOf(targetTreeItem); // todo: honfika: why not index + 1?
|
||||
index = tags.indexOf((Tag) targetTreeItem); // todo: honfika: why not index + 1?
|
||||
} else {
|
||||
index = -1;
|
||||
if (tag instanceof CharacterTag) {
|
||||
@@ -3101,9 +3176,9 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
if (index > -1) {
|
||||
tags.add(index, tag);
|
||||
timelined.addTag(index, tag);
|
||||
} else {
|
||||
tags.add(tag);
|
||||
timelined.addTag(tag);
|
||||
}
|
||||
|
||||
timelined.resetTimeline();
|
||||
@@ -3147,7 +3222,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
int maxId = Math.max(tags.size(), getNextCharacterId());
|
||||
int id = maxId;
|
||||
// first set the chatacter ids to surely not used ids
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof CharacterTag) {
|
||||
CharacterTag characterTag = (CharacterTag) tag;
|
||||
replaceCharacter(characterTag.getCharacterId(), id++);
|
||||
@@ -3155,7 +3230,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
// then set them to 1,2,3...
|
||||
id = 1;
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof CharacterTag) {
|
||||
CharacterTag characterTag = (CharacterTag) tag;
|
||||
replaceCharacter(characterTag.getCharacterId(), id++);
|
||||
@@ -3165,7 +3240,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
|
||||
boolean modified = false;
|
||||
for (Tag tag : tags) {
|
||||
for (Tag tag : getTags()) {
|
||||
boolean modified2 = false;
|
||||
if (tag instanceof CharacterIdTag) {
|
||||
CharacterIdTag characterIdTag = (CharacterIdTag) tag;
|
||||
@@ -3343,7 +3418,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
* @return the tag or null if not found
|
||||
*/
|
||||
public DebugIDTag getDebugId() {
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof DebugIDTag) {
|
||||
return (DebugIDTag) t;
|
||||
}
|
||||
|
||||
@@ -1081,7 +1081,7 @@ public class SWFInputStream implements AutoCloseable {
|
||||
// out.println(Utils.formatHex((int)tag.getPos(), 8) + ": " + Utils.indent(level, "") + Utils.format(tag.toString(), 25 - 2*level) + " tagId="+tag.getId()+" len="+tag.getOrigDataLength()+": "+Utils.bytesToHexString(64, tag.getData(version), 0));
|
||||
if (tag instanceof DefineSpriteTag) {
|
||||
int i = 0;
|
||||
for (Tag subTag : ((DefineSpriteTag) tag).getSubTags()) {
|
||||
for (Tag subTag : ((DefineSpriteTag) tag).getTags()) {
|
||||
dumpTag(out, subTag, i++, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ public class SWFOutputStream extends OutputStream {
|
||||
* @param tags List of tag values
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeTags(List<Tag> tags) throws IOException {
|
||||
public void writeTags(Iterable<Tag> tags) throws IOException {
|
||||
for (Tag tag : tags) {
|
||||
tag.writeTag(this);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public class SWFSearch {
|
||||
SWF swf = noCheck ? new SWF(pmi) : new SWF(pmi, null, null, null, false, true, true);
|
||||
boolean valid = swf.fileSize > 0
|
||||
&& swf.version > 0
|
||||
&& (!swf.tags.isEmpty() || noCheck)
|
||||
&& (!swf.getTags().isEmpty() || noCheck)
|
||||
&& swf.version <= SWF.MAX_VERSION;
|
||||
if (valid) {
|
||||
long limit = pmi.getPos();
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
@@ -38,7 +39,7 @@ import java.util.List;
|
||||
*/
|
||||
public class BinaryDataExporter {
|
||||
|
||||
public List<File> exportBinaryData(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, BinaryDataExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportBinaryData(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, BinaryDataExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.google.typography.font.tools.conversion.woff.WoffWriter;
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.ApplicationInfo;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -57,7 +58,7 @@ import java.util.logging.Logger;
|
||||
*/
|
||||
public class FontExporter {
|
||||
|
||||
public List<File> exportFonts(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, final FontExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportFonts(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final FontExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.jpexs.decompiler.flash.helpers.BMPFile;
|
||||
import com.jpexs.decompiler.flash.helpers.ImageHelper;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||
@@ -144,7 +145,7 @@ public class FrameExporter {
|
||||
|
||||
public List<File> exportFrames(AbortRetryIgnoreHandler handler, String outdir, final SWF swf, int containerId, List<Integer> frames, final FrameExportSettings settings, final EventListener evl) throws IOException, InterruptedException {
|
||||
final List<File> ret = new ArrayList<>();
|
||||
if (swf.tags.isEmpty()) {
|
||||
if (swf.getTags().isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
Timeline tim0;
|
||||
@@ -180,7 +181,8 @@ public class FrameExporter {
|
||||
if (settings.mode == FrameExportMode.SVG) {
|
||||
for (int i = 0; i < frames.size(); i++) {
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("frame", i + 1, frames.size(), tim.parentTag == null ? "" : tim.parentTag.getName());
|
||||
Tag parentTag = tim.getParentTag();
|
||||
evl.handleExportingEvent("frame", i + 1, frames.size(), parentTag == null ? "" : parentTag.getName());
|
||||
}
|
||||
|
||||
final int fi = i;
|
||||
@@ -205,7 +207,8 @@ public class FrameExporter {
|
||||
}, handler).run();
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("frame", i + 1, frames.size(), tim.parentTag == null ? "" : tim.parentTag.getName());
|
||||
Tag parentTag = tim.getParentTag();
|
||||
evl.handleExportedEvent("frame", i + 1, frames.size(), parentTag == null ? "" : parentTag.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +217,8 @@ public class FrameExporter {
|
||||
|
||||
if (settings.mode == FrameExportMode.CANVAS) {
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("canvas", 1, 1, tim.parentTag == null ? "" : tim.parentTag.getName());
|
||||
Tag parentTag = tim.getParentTag();
|
||||
evl.handleExportingEvent("canvas", 1, 1, parentTag == null ? "" : parentTag.getName());
|
||||
}
|
||||
|
||||
final Timeline ftim = tim;
|
||||
@@ -319,7 +323,8 @@ public class FrameExporter {
|
||||
}, handler).run();
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("canvas", 1, 1, tim.parentTag == null ? "" : tim.parentTag.getName());
|
||||
Tag parentTag = tim.getParentTag();
|
||||
evl.handleExportedEvent("canvas", 1, 1, parentTag == null ? "" : parentTag.getName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -346,14 +351,17 @@ public class FrameExporter {
|
||||
return null;
|
||||
}
|
||||
|
||||
Tag parentTag = tim.getParentTag();
|
||||
String tagName = parentTag == null ? "" : parentTag.getName();
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("frame", pos + 1, fframes.size(), tim.parentTag == null ? "" : tim.parentTag.getName());
|
||||
evl.handleExportingEvent("frame", pos + 1, fframes.size(), tagName);
|
||||
}
|
||||
|
||||
BufferedImage result = SWF.frameToImageGet(ftim, fframes.get(pos++), 0, null, 0, ftim.displayRect, new Matrix(), new ColorTransform(), fbackgroundColor, false, settings.zoom).getBufferedImage();
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("frame", pos, fframes.size(), tim.parentTag == null ? "" : tim.parentTag.getName());
|
||||
evl.handleExportedEvent("frame", pos, fframes.size(), tagName);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings;
|
||||
@@ -42,7 +43,7 @@ import java.util.List;
|
||||
*/
|
||||
public class ImageExporter {
|
||||
|
||||
public List<File> exportImages(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, ImageExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportImages(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, ImageExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
@@ -51,7 +52,7 @@ import java.util.Set;
|
||||
public class MorphShapeExporter {
|
||||
|
||||
//TODO: implement morphshape export. How to handle 65536 frames?
|
||||
public List<File> exportMorphShapes(AbortRetryIgnoreHandler handler, final String outdir, List<Tag> tags, final MorphShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportMorphShapes(AbortRetryIgnoreHandler handler, final String outdir, ReadOnlyTagList tags, final MorphShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -49,7 +50,7 @@ import java.util.List;
|
||||
*/
|
||||
public class MovieExporter {
|
||||
|
||||
public List<File> exportMovies(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, final MovieExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportMovies(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final MovieExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
@@ -97,7 +98,7 @@ public class MovieExporter {
|
||||
public byte[] exportMovie(DefineVideoStreamTag videoStream, MovieExportMode mode) throws IOException {
|
||||
SWF swf = videoStream.getSwf();
|
||||
HashMap<Integer, VideoFrameTag> frames = new HashMap<>();
|
||||
SWF.populateVideoFrames(videoStream.characterID, swf.tags, frames);
|
||||
SWF.populateVideoFrames(videoStream.characterID, swf.getTags(), frames);
|
||||
if (frames.isEmpty()) {
|
||||
return SWFInputStream.BYTE_ARRAY_EMPTY;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
@@ -57,7 +58,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class ShapeExporter {
|
||||
|
||||
public List<File> exportShapes(AbortRetryIgnoreHandler handler, final String outdir, List<Tag> tags, final ShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportShapes(AbortRetryIgnoreHandler handler, final String outdir, ReadOnlyTagList tags, final ShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -52,7 +53,7 @@ import java.util.List;
|
||||
*/
|
||||
public class SoundExporter {
|
||||
|
||||
public List<File> exportSounds(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, final SoundExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportSounds(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final SoundExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
|
||||
import com.jpexs.decompiler.flash.tags.SymbolClassTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
@@ -39,7 +40,7 @@ public class SymbolClassExporter {
|
||||
|
||||
public static final String SYMBOL_CLASS_EXPORT_FILENAME = "symbols.csv";
|
||||
|
||||
public List<File> exportNames(final String outdir, List<Tag> tags, EventListener evl) throws IOException {
|
||||
public List<File> exportNames(final String outdir, ReadOnlyTagList tags, EventListener evl) throws IOException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
int count = 0;
|
||||
for (Tag t : tags) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
@@ -48,7 +49,7 @@ public class TextExporter {
|
||||
|
||||
public static final String TEXT_EXPORT_FILENAME_PLAIN = "textsplain.txt";
|
||||
|
||||
public List<File> exportTexts(AbortRetryIgnoreHandler handler, String outdir, List<Tag> tags, final TextExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
public List<File> exportTexts(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final TextExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (tags.isEmpty()) {
|
||||
return ret;
|
||||
|
||||
@@ -96,7 +96,7 @@ public class ImageImporter extends TagImporter {
|
||||
}
|
||||
|
||||
imageTag.setModified(true);
|
||||
swf.tags.set(swf.tags.indexOf(it), imageTag);
|
||||
swf.replaceTag(it, imageTag);
|
||||
swf.updateCharacters();
|
||||
return imageTag;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.importers;
|
||||
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.ShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
@@ -95,7 +96,9 @@ public class ShapeImporter {
|
||||
|
||||
private final Set<String> shownWarnings = new HashSet<>();
|
||||
|
||||
private final SvgColor TRANSPARENT = new SvgColor(new Color(0, true));
|
||||
private final Color TRANSPARENT = new Color(0, true);
|
||||
|
||||
private final SvgColor SVG_TRANSPARENT = new SvgColor(TRANSPARENT);
|
||||
|
||||
private ShapeTag shapeTag;
|
||||
|
||||
@@ -169,13 +172,7 @@ public class ShapeImporter {
|
||||
throw new Error("Unsupported image type tag.");
|
||||
}
|
||||
|
||||
int idx = swf.tags.indexOf(st);
|
||||
if (idx != -1) {
|
||||
swf.tags.add(idx, imageTag);
|
||||
} else {
|
||||
swf.tags.add(imageTag);
|
||||
}
|
||||
|
||||
swf.addTag(imageTag, st);
|
||||
swf.updateCharacters();
|
||||
return imageTag;
|
||||
}
|
||||
@@ -518,7 +515,6 @@ public class ShapeImporter {
|
||||
serz.command = 'Z';
|
||||
x = startPoint.x;
|
||||
y = startPoint.y;
|
||||
serz.params = new double[]{x, y};
|
||||
pathCommands.add(serz);
|
||||
break;
|
||||
case 'L':
|
||||
@@ -821,13 +817,10 @@ public class ShapeImporter {
|
||||
double sqrt2RYHalf = Math.sqrt(2) * ry / 2;
|
||||
double sqrt2Minus1RY = (Math.sqrt(2) - 1) * ry;
|
||||
|
||||
Point startPoint = new Point(0, 0);
|
||||
List<PathCommand> pathCommands = new ArrayList<>();
|
||||
PathCommand scr = new PathCommand();
|
||||
scr.command = 'M';
|
||||
scr.params = new double[]{cx + rx, cy};
|
||||
startPoint.x = cx + rx;
|
||||
startPoint.y = cy;
|
||||
pathCommands.add(scr);
|
||||
|
||||
double[] points = new double[]{
|
||||
@@ -871,16 +864,12 @@ public class ShapeImporter {
|
||||
|
||||
PathCommand serz = new PathCommand();
|
||||
serz.command = 'Z';
|
||||
serz.params = new double[]{startPoint.x, startPoint.y};
|
||||
pathCommands.add(serz);
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style);
|
||||
}
|
||||
|
||||
private void processRect(int shapeNum, SHAPEWITHSTYLE shapes, Element childElement, Matrix transform, SvgStyle style) {
|
||||
|
||||
Point startPoint = new Point(0, 0);
|
||||
|
||||
String attr = childElement.getAttribute("x");
|
||||
double x = attr.length() > 0 ? Double.parseDouble(attr) : 0;
|
||||
|
||||
@@ -920,8 +909,6 @@ public class ShapeImporter {
|
||||
scr.command = 'M';
|
||||
scr.params = new double[]{x + width, y + ry};
|
||||
pathCommands.add(scr);
|
||||
startPoint.x = x + width;
|
||||
startPoint.y = y + ry;
|
||||
|
||||
double sqrt2RXHalf = Math.sqrt(2) * rx / 2;
|
||||
double sqrt2Minus1RX = (Math.sqrt(2) - 1) * rx;
|
||||
@@ -969,8 +956,6 @@ public class ShapeImporter {
|
||||
PathCommand scr = new PathCommand();
|
||||
scr.command = 'M';
|
||||
scr.params = new double[]{x, y};
|
||||
startPoint.x = x;
|
||||
startPoint.y = y;
|
||||
pathCommands.add(scr);
|
||||
|
||||
double[] points = new double[]{
|
||||
@@ -990,7 +975,6 @@ public class ShapeImporter {
|
||||
|
||||
PathCommand serz = new PathCommand();
|
||||
serz.command = 'Z';
|
||||
serz.params = new double[]{startPoint.x, startPoint.y};
|
||||
pathCommands.add(serz);
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style);
|
||||
@@ -1036,7 +1020,6 @@ public class ShapeImporter {
|
||||
String data = childElement.getAttribute("points");
|
||||
|
||||
char command = 'M';
|
||||
Point startPoint = new Point(0, 0);
|
||||
double x0 = 0;
|
||||
double y0 = 0;
|
||||
|
||||
@@ -1057,7 +1040,6 @@ public class ShapeImporter {
|
||||
scr.params = new double[]{x, y};
|
||||
|
||||
pathCommands.add(scr);
|
||||
startPoint = new Point(x, y);
|
||||
break;
|
||||
case 'L':
|
||||
PathCommand serl = new PathCommand();
|
||||
@@ -1077,7 +1059,6 @@ public class ShapeImporter {
|
||||
if (close) {
|
||||
PathCommand serz = new PathCommand();
|
||||
serz.command = 'Z';
|
||||
serz.params = new double[]{startPoint.x, startPoint.y};
|
||||
pathCommands.add(serz);
|
||||
}
|
||||
|
||||
@@ -1101,13 +1082,13 @@ public class ShapeImporter {
|
||||
SWF swf = new SWF();
|
||||
DefineShape4Tag st = new DefineShape4Tag(swf);
|
||||
st = (DefineShape4Tag) (new ShapeImporter().importSvg(st, svgDataS));
|
||||
swf.tags.add(st);
|
||||
swf.addTag(st);
|
||||
SerializableImage si = new SerializableImage(800, 600, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
BitmapExporter.export(swf, st.shapes, Color.yellow, si, new Matrix(), new ColorTransform());
|
||||
List<Tag> li = new ArrayList<>();
|
||||
li.add(st);
|
||||
ImageIO.write(si.getBufferedImage(), "PNG", new File(name + ".imported.png"));
|
||||
new ShapeExporter().exportShapes(null, "./outex/", li, new ShapeExportSettings(ShapeExportMode.SVG, 1), null);
|
||||
new ShapeExporter().exportShapes(null, "./outex/", new ReadOnlyTagList(li), new ShapeExportSettings(ShapeExportMode.SVG, 1), null);
|
||||
}
|
||||
|
||||
//Test for SVG
|
||||
@@ -1641,11 +1622,11 @@ public class ShapeImporter {
|
||||
}
|
||||
|
||||
private Color parseColor(String rgbStr) {
|
||||
SvgFill fill = parseFill(new HashMap<>(), rgbStr);
|
||||
SvgFill fill = parseFill(new HashMap<>(), rgbStr, null);
|
||||
return fill.toColor();
|
||||
}
|
||||
|
||||
private SvgFill parseFill(Map<String, Element> idMap, String rgbStr) {
|
||||
private SvgFill parseFill(Map<String, Element> idMap, String rgbStr, SvgStyle style) {
|
||||
if (rgbStr == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1653,7 +1634,7 @@ public class ShapeImporter {
|
||||
// named colors from: http://www.w3.org/TR/SVG/types.html#ColorKeywords
|
||||
switch (rgbStr) {
|
||||
case "none":
|
||||
return TRANSPARENT;
|
||||
return SVG_TRANSPARENT;
|
||||
case "aliceblue":
|
||||
return new SvgColor(240, 248, 255);
|
||||
case "antiquewhite":
|
||||
@@ -1959,11 +1940,11 @@ public class ShapeImporter {
|
||||
if (e != null) {
|
||||
String tagName = e.getTagName();
|
||||
if ("linearGradient".equals(tagName)) {
|
||||
return parseGradient(idMap, e, new SvgStyle()); //? new style
|
||||
return parseGradient(idMap, e, new SvgStyle(style)); //? new style
|
||||
}
|
||||
|
||||
if ("radialGradient".equals(tagName)) {
|
||||
return parseGradient(idMap, e, new SvgStyle()); //? new style
|
||||
return parseGradient(idMap, e, new SvgStyle(style)); //? new style
|
||||
}
|
||||
|
||||
if ("pattern".equals(tagName)) {
|
||||
@@ -2168,6 +2149,8 @@ public class ShapeImporter {
|
||||
|
||||
class SvgStyle implements Cloneable {
|
||||
|
||||
public Color color;
|
||||
|
||||
public SvgFill fill;
|
||||
|
||||
public double opacity;
|
||||
@@ -2190,6 +2173,8 @@ public class ShapeImporter {
|
||||
|
||||
public double strokeMiterLimit;
|
||||
|
||||
public SvgStyle parentStyle;
|
||||
|
||||
public SvgStyle() {
|
||||
fill = new SvgColor(Color.black);
|
||||
fillOpacity = 1;
|
||||
@@ -2204,6 +2189,11 @@ public class ShapeImporter {
|
||||
strokeMiterLimit = 4;
|
||||
}
|
||||
|
||||
public SvgStyle(SvgStyle parentStyle) {
|
||||
this();
|
||||
this.parentStyle = parentStyle;
|
||||
}
|
||||
|
||||
public SvgFill getFillWithOpacity() {
|
||||
if (fill == null) {
|
||||
return null;
|
||||
@@ -2272,15 +2262,26 @@ public class ShapeImporter {
|
||||
}
|
||||
|
||||
switch (name) {
|
||||
case "color": {
|
||||
Color color = parseColor(value);
|
||||
if (color != null) {
|
||||
style.color = color == TRANSPARENT ? null : color;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "fill": {
|
||||
SvgFill fill = parseFill(idMap, value);
|
||||
SvgFill fill = parseFill(idMap, value, style);
|
||||
if (fill != null) {
|
||||
style.fill = fill == TRANSPARENT ? null : fill;
|
||||
style.fill = fill == SVG_TRANSPARENT ? null : fill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "stop-color": {
|
||||
if ("inherit".equals(value) || "currentColor".equals(value)) {
|
||||
if ("currentColor".equals(value)) {
|
||||
if (style.parentStyle != null) {
|
||||
style.stopColor = style.parentStyle.color;
|
||||
}
|
||||
} else if ("inherit".equals(value)) {
|
||||
showWarning(value + "StopColorNotSupported", "The stop color value '" + value + "' is not supported.");
|
||||
} else {
|
||||
style.stopColor = parseColor(value);
|
||||
@@ -2302,9 +2303,9 @@ public class ShapeImporter {
|
||||
}
|
||||
break;
|
||||
case "stroke": {
|
||||
SvgFill strokeFill = parseFill(idMap, value);
|
||||
SvgFill strokeFill = parseFill(idMap, value, style);
|
||||
if (strokeFill != null) {
|
||||
style.strokeFill = strokeFill == TRANSPARENT ? null : strokeFill;
|
||||
style.strokeFill = strokeFill == SVG_TRANSPARENT ? null : strokeFill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2362,7 +2363,7 @@ public class ShapeImporter {
|
||||
SvgStyle result = clone();
|
||||
|
||||
String[] styles = new String[]{
|
||||
"fill", "fill-opacity",
|
||||
"color", "fill", "fill-opacity",
|
||||
"stroke", "stroke-width", "stroke-opacity", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit",
|
||||
"opacity", "stop-color", "stop-opacity"
|
||||
};
|
||||
|
||||
@@ -142,6 +142,7 @@ public class SwfXmlImporter {
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new InputSource(new StringReader(xml)));
|
||||
processElement(doc.getDocumentElement(), swf, swf, null);
|
||||
swf.clearAllCache();
|
||||
} catch (ParserConfigurationException | SAXException ex) {
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class SymbolClassImporter {
|
||||
nameMap.put(characterId, name);
|
||||
}
|
||||
|
||||
for (Tag tag : swf.tags) {
|
||||
for (Tag tag : swf.getTags()) {
|
||||
if (tag instanceof ExportAssetsTag) {
|
||||
ExportAssetsTag eat = (ExportAssetsTag) tag;
|
||||
for (int i = 0; i < eat.tags.size(); i++) {
|
||||
|
||||
@@ -80,12 +80,6 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
|
||||
*/
|
||||
public List<BUTTONCONDACTION> actions = new ArrayList<>();
|
||||
|
||||
private Timeline timeline;
|
||||
|
||||
private boolean isSingleFrameInitialized;
|
||||
|
||||
private boolean isSingleFrame;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -258,40 +252,7 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFrame() {
|
||||
if (!isSingleFrameInitialized) {
|
||||
initialiteIsSingleFrame();
|
||||
}
|
||||
return isSingleFrame;
|
||||
}
|
||||
|
||||
private synchronized void initialiteIsSingleFrame() {
|
||||
if (!isSingleFrameInitialized) {
|
||||
isSingleFrame = getTimeline().isSingleFrame();
|
||||
isSingleFrameInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timeline getTimeline() {
|
||||
if (timeline != null) {
|
||||
return timeline;
|
||||
}
|
||||
|
||||
timeline = new Timeline(swf, this, new ArrayList<>(), buttonId, getRect());
|
||||
initTimeline(timeline);
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
if (timeline != null) {
|
||||
timeline.reset(swf, this, new ArrayList<>(), buttonId, getRect());
|
||||
initTimeline(timeline);
|
||||
}
|
||||
}
|
||||
|
||||
private void initTimeline(Timeline timeline) {
|
||||
protected void initTimeline(Timeline timeline) {
|
||||
int maxDepth = 0;
|
||||
Frame frameUp = new Frame(timeline, 0);
|
||||
Frame frameDown = new Frame(timeline, 0);
|
||||
|
||||
@@ -78,12 +78,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
private Timeline timeline;
|
||||
|
||||
private boolean isSingleFrameInitialized;
|
||||
|
||||
private boolean isSingleFrame;
|
||||
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
@@ -322,21 +316,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFrame() {
|
||||
if (!isSingleFrameInitialized) {
|
||||
initialiteIsSingleFrame();
|
||||
}
|
||||
return isSingleFrame;
|
||||
}
|
||||
|
||||
private synchronized void initialiteIsSingleFrame() {
|
||||
if (!isSingleFrameInitialized) {
|
||||
isSingleFrame = getTimeline().isSingleFrame();
|
||||
isSingleFrameInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
|
||||
return writer;
|
||||
@@ -358,27 +337,9 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timeline getTimeline() {
|
||||
if (timeline != null) {
|
||||
return timeline;
|
||||
}
|
||||
|
||||
timeline = new Timeline(swf, this, new ArrayList<>(), buttonId, getRect());
|
||||
initTimeline(timeline);
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
if (timeline != null) {
|
||||
timeline.reset(swf, this, new ArrayList<>(), buttonId, getRect());
|
||||
initTimeline(timeline);
|
||||
}
|
||||
}
|
||||
|
||||
private void initTimeline(Timeline timeline) {
|
||||
protected void initTimeline(Timeline timeline) {
|
||||
ColorTransform clrTrans = null;
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineButtonCxformTag) {
|
||||
DefineButtonCxformTag cx = (DefineButtonCxformTag) t;
|
||||
clrTrans = cx.buttonColorTransform;
|
||||
@@ -417,17 +378,23 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
}
|
||||
|
||||
timeline.addFrame(frameUp);
|
||||
|
||||
if (frameOver.layers.isEmpty()) {
|
||||
frameOver = frameUp;
|
||||
}
|
||||
|
||||
timeline.addFrame(frameOver);
|
||||
|
||||
if (frameDown.layers.isEmpty()) {
|
||||
frameDown = frameOver;
|
||||
}
|
||||
|
||||
timeline.addFrame(frameDown);
|
||||
|
||||
if (frameHit.layers.isEmpty()) {
|
||||
frameHit = frameUp;
|
||||
}
|
||||
|
||||
timeline.addFrame(frameHit);
|
||||
}
|
||||
|
||||
|
||||
@@ -466,7 +466,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacters(List<Tag> tags) {
|
||||
public String getCharacters() {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int i : codeTable) {
|
||||
ret.append((char) i);
|
||||
|
||||
@@ -396,12 +396,12 @@ public class DefineFont3Tag extends FontTag {
|
||||
public void addCharacter(char character, Font font) {
|
||||
|
||||
//Font Align Zones will be removed as adding new character zones is not supported:-(
|
||||
for (int i = 0; i < swf.tags.size(); i++) {
|
||||
Tag t = swf.tags.get(i);
|
||||
for (int i = 0; i < swf.getTags().size(); i++) {
|
||||
Tag t = swf.getTags().get(i);
|
||||
if (t instanceof DefineFontAlignZonesTag) {
|
||||
DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t;
|
||||
if (fa.fontID == fontId) {
|
||||
swf.tags.remove(i);
|
||||
swf.removeTag(t);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
@@ -467,7 +467,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacters(List<Tag> tags) {
|
||||
public String getCharacters() {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int i : codeTable) {
|
||||
ret.append((char) i);
|
||||
|
||||
@@ -139,7 +139,7 @@ public class DefineFontTag extends FontTag {
|
||||
|
||||
private void ensureFontInfo() {
|
||||
if (fontInfoTag == null) {
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineFontInfoTag) {
|
||||
if (((DefineFontInfoTag) t).fontId == fontId) {
|
||||
fontInfoTag = (DefineFontInfoTag) t;
|
||||
@@ -331,7 +331,7 @@ public class DefineFontTag extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacters(List<Tag> tags) {
|
||||
public String getCharacters() {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ensureFontInfo();
|
||||
if (fontInfoTag != null) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags;
|
||||
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
@@ -33,6 +34,8 @@ 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.SWFField;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
@@ -74,7 +77,11 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
/**
|
||||
* A series of tags
|
||||
*/
|
||||
public List<Tag> subTags;
|
||||
@SWFField
|
||||
private List<Tag> subTags;
|
||||
|
||||
@Internal
|
||||
public ReadOnlyTagList readOnlyTags;
|
||||
|
||||
public boolean hasEndTag;
|
||||
|
||||
@@ -121,6 +128,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
subTags.remove(subTags.size() - 1);
|
||||
}
|
||||
this.subTags = subTags;
|
||||
readOnlyTags = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +141,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(spriteId);
|
||||
sos.writeUI16(frameCount);
|
||||
sos.writeTags(subTags);
|
||||
sos.writeTags(getTags());
|
||||
if (hasEndTag) {
|
||||
sos.writeUI16(0);
|
||||
}
|
||||
@@ -142,7 +150,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
@Override
|
||||
public Timeline getTimeline() {
|
||||
if (timeline == null) {
|
||||
timeline = new Timeline(swf, this, subTags, spriteId, getRect());
|
||||
timeline = new Timeline(swf, this, spriteId, getRect());
|
||||
}
|
||||
return timeline;
|
||||
}
|
||||
@@ -150,7 +158,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
if (timeline != null) {
|
||||
timeline.reset(swf, this, subTags, spriteId, getRect());
|
||||
timeline.reset(swf, this, spriteId, getRect());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +216,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
|
||||
HashMap<Integer, Integer> depthMap = new HashMap<>();
|
||||
boolean foundSomething = false;
|
||||
for (Tag t : subTags) {
|
||||
for (Tag t : getTags()) {
|
||||
MATRIX m = null;
|
||||
int characterId = -1;
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
@@ -268,14 +276,10 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<Tag> getSubTags() {
|
||||
return subTags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified(boolean value) {
|
||||
if (!value) {
|
||||
for (Tag subTag : subTags) {
|
||||
for (Tag subTag : getTags()) {
|
||||
subTag.setModified(false);
|
||||
}
|
||||
}
|
||||
@@ -283,17 +287,50 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
super.setModified(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyTagList getTags() {
|
||||
if (readOnlyTags == null) {
|
||||
readOnlyTags = new ReadOnlyTagList(subTags);
|
||||
}
|
||||
|
||||
return readOnlyTags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTag(int index) {
|
||||
setModified(true);
|
||||
subTags.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTag(Tag tag) {
|
||||
setModified(true);
|
||||
subTags.remove(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTag(Tag tag) {
|
||||
setModified(true);
|
||||
subTags.add(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTag(int index, Tag tag) {
|
||||
setModified(true);
|
||||
subTags.add(index, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createOriginalData() {
|
||||
super.createOriginalData();
|
||||
for (Tag subTag : subTags) {
|
||||
for (Tag subTag : getTags()) {
|
||||
subTag.createOriginalData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNeededCharacters(Set<Integer> needed) {
|
||||
for (Tag t : subTags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof CharacterIdTag) {
|
||||
needed.add(((CharacterIdTag) t).getCharacterId());
|
||||
}
|
||||
@@ -374,11 +411,15 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
if (super.isModified()) {
|
||||
return true;
|
||||
}
|
||||
for (Tag t : subTags) {
|
||||
for (Tag t : getTags()) {
|
||||
if (t.isModified()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clearReadOnlyListCache() {
|
||||
readOnlyTags = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
if (deep) {
|
||||
if (this instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) this;
|
||||
for (Tag subTag : sprite.subTags) {
|
||||
for (Tag subTag : sprite.getTags()) {
|
||||
subTag.setSwf(swf);
|
||||
}
|
||||
}
|
||||
@@ -426,6 +426,10 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
return SWFInputStream.resolveTag(copy, 0, false, true, false);
|
||||
}
|
||||
|
||||
public boolean canUndo() {
|
||||
return originalRange != null && isModified();
|
||||
}
|
||||
|
||||
public void undo() throws InterruptedException, IOException {
|
||||
byte[] data = getOriginalData();
|
||||
if (data == null) { //If the tag is newly created in GUI it has no original data
|
||||
@@ -534,8 +538,9 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
}
|
||||
|
||||
public void setModified(boolean value) {
|
||||
boolean oldValue = modified;
|
||||
modified = value;
|
||||
if (value) {
|
||||
if (value && oldValue != value) {
|
||||
informListeners();
|
||||
}
|
||||
}
|
||||
@@ -607,7 +612,7 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
}
|
||||
|
||||
public void getDependentCharacters(Set<Integer> dependent) {
|
||||
for (Tag tag : swf.tags) {
|
||||
for (Tag tag : swf.getTags()) {
|
||||
if (tag instanceof CharacterTag) {
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
tag.getNeededCharactersDeep(needed);
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
@@ -47,6 +49,12 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim
|
||||
|
||||
public static int FRAME_HITTEST = 3;
|
||||
|
||||
private Timeline timeline;
|
||||
|
||||
private boolean isSingleFrameInitialized;
|
||||
|
||||
private boolean isSingleFrame;
|
||||
|
||||
public ButtonTag(SWF swf, int id, String name, ByteArrayRange data) {
|
||||
super(swf, id, name, data);
|
||||
}
|
||||
@@ -81,7 +89,7 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim
|
||||
}
|
||||
|
||||
public DefineButtonSoundTag getSounds() {
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineButtonSoundTag) {
|
||||
DefineButtonSoundTag st = (DefineButtonSoundTag) t;
|
||||
if (st.buttonId == getCharacterId()) {
|
||||
@@ -96,4 +104,61 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim
|
||||
public void toHtmlCanvas(StringBuilder result, double unitDivisor) {
|
||||
getTimeline().toHtmlCanvas(result, unitDivisor, Arrays.asList(0)); //TODO: handle states?
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFrame() {
|
||||
if (!isSingleFrameInitialized) {
|
||||
initialiteIsSingleFrame();
|
||||
}
|
||||
return isSingleFrame;
|
||||
}
|
||||
|
||||
private synchronized void initialiteIsSingleFrame() {
|
||||
if (!isSingleFrameInitialized) {
|
||||
isSingleFrame = getTimeline().isSingleFrame();
|
||||
isSingleFrameInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timeline getTimeline() {
|
||||
if (timeline != null) {
|
||||
return timeline;
|
||||
}
|
||||
|
||||
timeline = new Timeline(swf, this, getCharacterId(), getRect());
|
||||
initTimeline(timeline);
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
if (timeline != null) {
|
||||
timeline.reset(swf, this, getCharacterId(), getRect());
|
||||
initTimeline(timeline);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void initTimeline(Timeline timeline);
|
||||
|
||||
@Override
|
||||
public ReadOnlyTagList getTags() {
|
||||
return ReadOnlyTagList.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTag(int index) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTag(Tag tag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTag(Tag tag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTag(int index, Tag tag) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
return fontStyle;
|
||||
}
|
||||
|
||||
public abstract String getCharacters(List<Tag> tags);
|
||||
public abstract String getCharacters();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -209,7 +209,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
}
|
||||
|
||||
protected void shiftGlyphIndices(int fontId, int startIndex) {
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
List<TEXTRECORD> textRecords = null;
|
||||
if (t instanceof StaticTextTag) {
|
||||
textRecords = ((StaticTextTag) t).textRecords;
|
||||
@@ -379,7 +379,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
}
|
||||
|
||||
public DefineFontNameTag getFontNameTag() {
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineFontNameTag) {
|
||||
DefineFontNameTag dfn = (DefineFontNameTag) t;
|
||||
if (dfn.fontId == getFontId()) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.helpers.FontHelper;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.LANGCODE;
|
||||
@@ -316,7 +315,7 @@ public final class DefineCompactedFont extends FontTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacters(List<Tag> tags) {
|
||||
public String getCharacters() {
|
||||
FontType ft = fonts.get(0);
|
||||
StringBuilder ret = new StringBuilder(ft.glyphInfo.size());
|
||||
for (GlyphInfoType gi : ft.glyphInfo) {
|
||||
|
||||
@@ -70,14 +70,10 @@ public class Timeline {
|
||||
|
||||
public Timelined timelined;
|
||||
|
||||
public Tag parentTag;
|
||||
|
||||
public int maxDepth;
|
||||
|
||||
public int fontFrameNum = -1;
|
||||
|
||||
public List<Tag> tags;
|
||||
|
||||
private final List<Frame> frames = new ArrayList<>();
|
||||
|
||||
private final Map<Integer, Integer> depthMaxFrame = new HashMap<>();
|
||||
@@ -135,11 +131,15 @@ public class Timeline {
|
||||
return soundStramBlocks.get(head);
|
||||
}
|
||||
|
||||
public void reset(SWF swf) {
|
||||
reset(swf, null, swf.tags, 0, swf.displayRect);
|
||||
public Tag getParentTag() {
|
||||
return timelined instanceof Tag ? (Tag) timelined : null;
|
||||
}
|
||||
|
||||
public void reset(SWF swf, Tag parentTag, List<Tag> tags, int id, RECT displayRect) {
|
||||
public void reset(SWF swf) {
|
||||
reset(swf, swf, 0, swf.displayRect);
|
||||
}
|
||||
|
||||
public void reset(SWF swf, Timelined timelined, int id, RECT displayRect) {
|
||||
initialized = false;
|
||||
frames.clear();
|
||||
depthMaxFrame.clear();
|
||||
@@ -152,9 +152,7 @@ public class Timeline {
|
||||
this.swf = swf;
|
||||
this.displayRect = displayRect;
|
||||
this.frameRate = swf.frameRate;
|
||||
this.timelined = parentTag == null ? swf : (Timelined) parentTag;
|
||||
this.parentTag = parentTag;
|
||||
this.tags = tags;
|
||||
this.timelined = timelined;
|
||||
as2RootPackage = new AS2Package(null, null, swf);
|
||||
}
|
||||
|
||||
@@ -207,17 +205,15 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public Timeline(SWF swf) {
|
||||
this(swf, null, swf.tags, 0, swf.displayRect);
|
||||
this(swf, swf, 0, swf.displayRect);
|
||||
}
|
||||
|
||||
public Timeline(SWF swf, Tag parentTag, List<Tag> tags, int id, RECT displayRect) {
|
||||
public Timeline(SWF swf, Timelined timelined, 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;
|
||||
this.timelined = timelined;
|
||||
as2RootPackage = new AS2Package(null, null, swf);
|
||||
}
|
||||
|
||||
@@ -226,7 +222,7 @@ public class Timeline {
|
||||
Frame frame = new Frame(this, frameIdx++);
|
||||
frame.layersChanged = true;
|
||||
boolean newFrameNeeded = false;
|
||||
for (Tag t : tags) {
|
||||
for (Tag t : timelined.getTags()) {
|
||||
boolean isNested = ShowFrameTag.isNestedTagType(t.getId());
|
||||
if (isNested) {
|
||||
newFrameNeeded = true;
|
||||
@@ -348,9 +344,9 @@ public class Timeline {
|
||||
calculateMaxDepthFrames();
|
||||
|
||||
createASPackages();
|
||||
if (parentTag == null) {
|
||||
if (timelined instanceof SWF) {
|
||||
// popuplate only for main timeline
|
||||
populateSoundStreamBlocks(0, tags);
|
||||
populateSoundStreamBlocks(0, timelined.getTags());
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
@@ -433,7 +429,7 @@ public class Timeline {
|
||||
}
|
||||
}
|
||||
|
||||
private void populateSoundStreamBlocks(int containerId, List<Tag> tags) {
|
||||
private void populateSoundStreamBlocks(int containerId, Iterable<Tag> tags) {
|
||||
List<SoundStreamBlockTag> blocks = null;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof SoundStreamHeadTypeTag) {
|
||||
@@ -446,7 +442,7 @@ public class Timeline {
|
||||
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) t;
|
||||
populateSoundStreamBlocks(sprite.getCharacterId(), sprite.getSubTags());
|
||||
populateSoundStreamBlocks(sprite.getCharacterId(), sprite.getTags());
|
||||
}
|
||||
|
||||
if (blocks == null) {
|
||||
@@ -487,8 +483,8 @@ public class Timeline {
|
||||
|
||||
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
|
||||
boolean modified = false;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
Tag t = tags.get(i);
|
||||
for (int i = 0; i < timelined.getTags().size(); i++) {
|
||||
Tag t = timelined.getTags().get(i);
|
||||
if (t instanceof CharacterIdTag && ((CharacterIdTag) t).getCharacterId() == oldCharacterId) {
|
||||
((CharacterIdTag) t).setCharacterId(newCharacterId);
|
||||
((Tag) t).setModified(true);
|
||||
@@ -500,10 +496,10 @@ public class Timeline {
|
||||
|
||||
public boolean removeCharacter(int characterId) {
|
||||
boolean modified = false;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
Tag t = tags.get(i);
|
||||
for (int i = 0; i < timelined.getTags().size(); i++) {
|
||||
Tag t = timelined.getTags().get(i);
|
||||
if (t instanceof CharacterIdTag && ((CharacterIdTag) t).getCharacterId() == characterId) {
|
||||
tags.remove(i);
|
||||
timelined.removeTag(i);
|
||||
i--;
|
||||
modified = true;
|
||||
}
|
||||
@@ -726,7 +722,7 @@ public class Timeline {
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Timeline) {
|
||||
Timeline timelineObj = (Timeline) obj;
|
||||
return timelined.equals(timelineObj.timelined) && parentTag == timelineObj.parentTag;
|
||||
return timelined.equals(timelineObj.timelined);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
|
||||
/**
|
||||
@@ -27,4 +29,16 @@ public interface Timelined extends BoundedTag {
|
||||
public Timeline getTimeline();
|
||||
|
||||
public void resetTimeline();
|
||||
|
||||
public void setModified(boolean value);
|
||||
|
||||
public ReadOnlyTagList getTags();
|
||||
|
||||
public void removeTag(int index);
|
||||
|
||||
public void removeTag(Tag tag);
|
||||
|
||||
public void addTag(Tag tag);
|
||||
|
||||
public void addTag(int index, Tag tag);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.xfl;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFCompression;
|
||||
@@ -216,8 +217,8 @@ public class XFLConverter {
|
||||
+ "<SolidColor color=\"")
|
||||
.append(ls.color.toHexRGB()).append("\"")
|
||||
.append(shapeNum == 3 ? " alpha=\"" + ((RGBA) ls.color).getAlphaFloat() + "\"" : "").append(" />"
|
||||
+ "</fill>"
|
||||
+ "</SolidStroke>");
|
||||
+ "</fill>"
|
||||
+ "</SolidStroke>");
|
||||
}
|
||||
|
||||
private static void convertLineStyle(HashMap<Integer, CharacterTag> characters, LINESTYLE2 ls, int shapeNum, StringBuilder ret) {
|
||||
@@ -759,7 +760,7 @@ public class XFLConverter {
|
||||
return layers;
|
||||
}
|
||||
|
||||
private static int getLayerCount(List<Tag> tags) {
|
||||
private static int getLayerCount(ReadOnlyTagList tags) {
|
||||
int maxDepth = 0;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
@@ -776,11 +777,11 @@ public class XFLConverter {
|
||||
return maxDepth;
|
||||
}
|
||||
|
||||
private static void walkShapeUsages(List<Tag> timeLineTags, HashMap<Integer, CharacterTag> characters, HashMap<Integer, Integer> usages) {
|
||||
private static void walkShapeUsages(ReadOnlyTagList timeLineTags, HashMap<Integer, CharacterTag> characters, HashMap<Integer, Integer> usages) {
|
||||
for (Tag t : timeLineTags) {
|
||||
if (t instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) t;
|
||||
walkShapeUsages(sprite.subTags, characters, usages);
|
||||
walkShapeUsages(sprite.getTags(), characters, usages);
|
||||
}
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
PlaceObjectTypeTag po = (PlaceObjectTypeTag) t;
|
||||
@@ -811,7 +812,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Integer> getNonLibraryShapes(List<Tag> tags, HashMap<Integer, CharacterTag> characters) {
|
||||
private static List<Integer> getNonLibraryShapes(ReadOnlyTagList tags, HashMap<Integer, CharacterTag> characters) {
|
||||
HashMap<Integer, Integer> usages = new HashMap<>();
|
||||
walkShapeUsages(tags, characters, usages);
|
||||
List<Integer> ret = new ArrayList<>();
|
||||
@@ -829,7 +830,7 @@ public class XFLConverter {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static HashMap<Integer, CharacterTag> getCharacters(List<Tag> tags) {
|
||||
private static HashMap<Integer, CharacterTag> getCharacters(ReadOnlyTagList tags) {
|
||||
HashMap<Integer, CharacterTag> ret = new HashMap<>();
|
||||
int maxId = 0;
|
||||
for (Tag t : tags) {
|
||||
@@ -1029,7 +1030,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static String convertSymbolInstance(String name, MATRIX matrix, ColorTransform colorTransform, boolean cacheAsBitmap, int blendMode, List<FILTER> filters, boolean isVisible, RGBA backgroundColor, CLIPACTIONS clipActions, CharacterTag tag, HashMap<Integer, CharacterTag> characters, List<Tag> tags, FLAVersion flaVersion) {
|
||||
private static String convertSymbolInstance(String name, MATRIX matrix, ColorTransform colorTransform, boolean cacheAsBitmap, int blendMode, List<FILTER> filters, boolean isVisible, RGBA backgroundColor, CLIPACTIONS clipActions, CharacterTag tag, HashMap<Integer, CharacterTag> characters, ReadOnlyTagList tags, FLAVersion flaVersion) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
if (matrix == null) {
|
||||
matrix = new MATRIX();
|
||||
@@ -1167,7 +1168,7 @@ public class XFLConverter {
|
||||
return date.getTime() / 1000;
|
||||
}
|
||||
|
||||
private static void convertLibrary(SWF swf, Map<Integer, String> characterVariables, Map<Integer, String> characterClasses, List<Integer> nonLibraryShapes, String backgroundColor, List<Tag> tags, HashMap<Integer, CharacterTag> characters, HashMap<String, byte[]> files, HashMap<String, byte[]> datfiles, FLAVersion flaVersion, StringBuilder ret) {
|
||||
private static void convertLibrary(SWF swf, Map<Integer, String> characterVariables, Map<Integer, String> characterClasses, List<Integer> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<Integer, CharacterTag> characters, HashMap<String, byte[]> files, HashMap<String, byte[]> datfiles, FLAVersion flaVersion, StringBuilder ret) {
|
||||
|
||||
//TODO: Imported assets
|
||||
//linkageImportForRS="true" linkageIdentifier="xxx" linkageURL="yyy.swf"
|
||||
@@ -1303,10 +1304,10 @@ public class XFLConverter {
|
||||
symbolStr.append("</DOMTimeline>");
|
||||
} else if (symbol instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) symbol;
|
||||
if (sprite.subTags.isEmpty()) { //probably AS2 class
|
||||
if (sprite.getTags().isEmpty()) { //probably AS2 class
|
||||
continue;
|
||||
}
|
||||
symbolStr.append(convertTimeline(sprite.spriteId, nonLibraryShapes, backgroundColor, tags, sprite.getSubTags(), characters, "Symbol " + symbol.getCharacterId(), flaVersion, files));
|
||||
symbolStr.append(convertTimeline(sprite.spriteId, nonLibraryShapes, backgroundColor, tags, sprite.getTags(), characters, "Symbol " + symbol.getCharacterId(), flaVersion, files));
|
||||
} else if (symbol instanceof ShapeTag) {
|
||||
itemIcon = "1";
|
||||
ShapeTag shape = (ShapeTag) symbol;
|
||||
@@ -1632,7 +1633,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void convertFrame(boolean shapeTween, HashMap<Integer, CharacterTag> characters, List<Tag> tags, SoundStreamHeadTypeTag soundStreamHead, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, StringBuilder ret) {
|
||||
private static void convertFrame(boolean shapeTween, HashMap<Integer, CharacterTag> characters, ReadOnlyTagList tags, SoundStreamHeadTypeTag soundStreamHead, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, StringBuilder ret) {
|
||||
DefineSoundTag sound = null;
|
||||
if (startSound != null) {
|
||||
for (Tag t : tags) {
|
||||
@@ -1759,7 +1760,7 @@ public class XFLConverter {
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
private static void convertFrames(String prevStr, String afterStr, List<Integer> nonLibraryShapes, List<Tag> tags, List<Tag> timelineTags, HashMap<Integer, CharacterTag> characters, int depth, FLAVersion flaVersion, HashMap<String, byte[]> files, StringBuilder ret) {
|
||||
private static void convertFrames(String prevStr, String afterStr, List<Integer> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap<Integer, CharacterTag> characters, int depth, FLAVersion flaVersion, HashMap<String, byte[]> files, StringBuilder ret) {
|
||||
StringBuilder ret2 = new StringBuilder();
|
||||
prevStr += "<frames>";
|
||||
int frame = -1;
|
||||
@@ -1785,7 +1786,7 @@ public class XFLConverter {
|
||||
MorphShapeTag shapeTweener = null;
|
||||
|
||||
//Add ShowFrameTag to the end when there is one last missing
|
||||
List<Tag> timTags = new ArrayList<>(timelineTags);
|
||||
List<Tag> timTags = timelineTags.toArrayList();
|
||||
boolean needsFrameAdd = false;
|
||||
SWF swf = null;
|
||||
for (int i = timTags.size() - 1; i >= 0; i--) {
|
||||
@@ -1933,7 +1934,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void convertFonts(List<Tag> tags, StringBuilder ret) {
|
||||
private static void convertFonts(ReadOnlyTagList tags, StringBuilder ret) {
|
||||
StringBuilder ret2 = new StringBuilder();
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof FontTag) {
|
||||
@@ -1960,7 +1961,7 @@ public class XFLConverter {
|
||||
}
|
||||
String embedRanges = "";
|
||||
|
||||
String fontChars = font.getCharacters(tags);
|
||||
String fontChars = font.getCharacters();
|
||||
if ("".equals(fontChars)) {
|
||||
continue;
|
||||
}
|
||||
@@ -2003,7 +2004,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static String convertActionScriptLayer(int spriteId, List<Tag> tags, List<Tag> timeLineTags, String backgroundColor) {
|
||||
private static String convertActionScriptLayer(int spriteId, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, String backgroundColor) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
|
||||
String script = "";
|
||||
@@ -2065,7 +2066,7 @@ public class XFLConverter {
|
||||
return retStr;
|
||||
}
|
||||
|
||||
private static String convertLabelsLayer(int spriteId, List<Tag> tags, List<Tag> timeLineTags, String backgroundColor) {
|
||||
private static String convertLabelsLayer(int spriteId, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, String backgroundColor) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
int duration = 0;
|
||||
int frame = 0;
|
||||
@@ -2121,7 +2122,7 @@ public class XFLConverter {
|
||||
return retStr;
|
||||
}
|
||||
|
||||
private static void convertSoundLayer(int layerIndex, String backgroundColor, HashMap<Integer, CharacterTag> characters, List<Tag> tags, List<Tag> timeLineTags, HashMap<String, byte[]> files, StringBuilder ret) {
|
||||
private static void convertSoundLayer(int layerIndex, String backgroundColor, HashMap<Integer, CharacterTag> characters, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, HashMap<String, byte[]> files, StringBuilder ret) {
|
||||
StringBuilder ret2 = new StringBuilder();
|
||||
StartSoundTag lastStartSound = null;
|
||||
SoundStreamHeadTypeTag lastSoundStreamHead = null;
|
||||
@@ -2179,7 +2180,7 @@ public class XFLConverter {
|
||||
if (ret2.length() > 0) {
|
||||
ret.append("<DOMLayer name=\"Layer ").append(layerIndex).append("\" color=\"").append(randomOutlineColor()).append("\">"
|
||||
+ "<frames>").append(ret2).append("</frames>"
|
||||
+ "</DOMLayer>");
|
||||
+ "</DOMLayer>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2193,7 +2194,7 @@ public class XFLConverter {
|
||||
return outlineColor.toHexRGB();
|
||||
}
|
||||
|
||||
private static String convertTimeline(int spriteId, List<Integer> nonLibraryShapes, String backgroundColor, List<Tag> tags, List<Tag> timelineTags, HashMap<Integer, CharacterTag> characters, String name, FLAVersion flaVersion, HashMap<String, byte[]> files) {
|
||||
private static String convertTimeline(int spriteId, List<Integer> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap<Integer, CharacterTag> characters, String name, FLAVersion flaVersion, HashMap<String, byte[]> files) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ret.append("<DOMTimeline name=\"").append(name).append("\">");
|
||||
ret.append("<layers>");
|
||||
@@ -2292,7 +2293,7 @@ public class XFLConverter {
|
||||
}, handler).run();
|
||||
}
|
||||
|
||||
private static Map<Integer, String> getCharacterClasses(List<Tag> tags) {
|
||||
private static Map<Integer, String> getCharacterClasses(ReadOnlyTagList tags) {
|
||||
Map<Integer, String> ret = new HashMap<>();
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof SymbolClassTag) {
|
||||
@@ -2307,7 +2308,7 @@ public class XFLConverter {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Map<Integer, String> getCharacterVariables(List<Tag> tags) {
|
||||
private static Map<Integer, String> getCharacterVariables(ReadOnlyTagList tags) {
|
||||
Map<Integer, String> ret = new HashMap<>();
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ExportAssetsTag) {
|
||||
@@ -2337,7 +2338,7 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
SWF swf = tag.getSwf();
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof CSMTextSettingsTag) {
|
||||
CSMTextSettingsTag c = (CSMTextSettingsTag) t;
|
||||
if (c.textID == tag.getCharacterId()) {
|
||||
@@ -2427,7 +2428,7 @@ public class XFLConverter {
|
||||
fontName = null;
|
||||
textHeight = rec.textHeight;
|
||||
font = swf.getFont(fontId);
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineFontNameTag) {
|
||||
if (((DefineFontNameTag) t).fontId == fontId) {
|
||||
fontName = ((DefineFontNameTag) t).fontName;
|
||||
@@ -2552,7 +2553,7 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
if (det.html) {
|
||||
ret.append(convertHTMLText(swf.tags, det, txt));
|
||||
ret.append(convertHTMLText(swf.getTags(), det, txt));
|
||||
} else {
|
||||
ret.append("<DOMTextRun>");
|
||||
ret.append("<characters>").append(xmlString(txt)).append("</characters>");
|
||||
@@ -2571,7 +2572,7 @@ public class XFLConverter {
|
||||
}
|
||||
if (det.hasFont) {
|
||||
String fontName = null;
|
||||
for (Tag u : swf.tags) {
|
||||
for (Tag u : swf.getTags()) {
|
||||
if (u instanceof DefineFontNameTag) {
|
||||
if (((DefineFontNameTag) u).fontId == det.fontId) {
|
||||
fontName = ((DefineFontNameTag) u).fontName;
|
||||
@@ -2677,10 +2678,10 @@ public class XFLConverter {
|
||||
}
|
||||
final HashMap<String, byte[]> files = new HashMap<>();
|
||||
final HashMap<String, byte[]> datfiles = new HashMap<>();
|
||||
HashMap<Integer, CharacterTag> characters = getCharacters(swf.tags);
|
||||
List<Integer> nonLibraryShapes = getNonLibraryShapes(swf.tags, characters);
|
||||
Map<Integer, String> characterClasses = getCharacterClasses(swf.tags);
|
||||
Map<Integer, String> characterVariables = getCharacterVariables(swf.tags);
|
||||
HashMap<Integer, CharacterTag> characters = getCharacters(swf.getTags());
|
||||
List<Integer> nonLibraryShapes = getNonLibraryShapes(swf.getTags(), characters);
|
||||
Map<Integer, String> characterClasses = getCharacterClasses(swf.getTags());
|
||||
Map<Integer, String> characterVariables = getCharacterVariables(swf.getTags());
|
||||
|
||||
String backgroundColor = "#ffffff";
|
||||
SetBackgroundColorTag setBgColorTag = swf.getBackgroundColor();
|
||||
@@ -2701,22 +2702,22 @@ public class XFLConverter {
|
||||
domDocument.append(" height=\"").append(doubleToString(height)).append("\"");
|
||||
}
|
||||
domDocument.append(">");
|
||||
convertFonts(swf.tags, domDocument);
|
||||
convertLibrary(swf, characterVariables, characterClasses, nonLibraryShapes, backgroundColor, swf.tags, characters, files, datfiles, flaVersion, domDocument);
|
||||
convertFonts(swf.getTags(), domDocument);
|
||||
convertLibrary(swf, characterVariables, characterClasses, nonLibraryShapes, backgroundColor, swf.getTags(), characters, files, datfiles, flaVersion, domDocument);
|
||||
domDocument.append("<timelines>");
|
||||
domDocument.append(convertTimeline(0, nonLibraryShapes, backgroundColor, swf.tags, swf.tags, characters, "Scene 1", flaVersion, files));
|
||||
domDocument.append(convertTimeline(0, nonLibraryShapes, backgroundColor, swf.getTags(), swf.getTags(), characters, "Scene 1", flaVersion, files));
|
||||
domDocument.append("</timelines>");
|
||||
domDocument.append("</DOMDocument>");
|
||||
String domDocumentStr = prettyFormatXML(domDocument.toString());
|
||||
|
||||
for (Tag t : swf.tags) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DoInitActionTag) {
|
||||
DoInitActionTag dia = (DoInitActionTag) t;
|
||||
int chid = dia.getCharacterId();
|
||||
if (characters.containsKey(chid)) {
|
||||
if (characters.get(chid) instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) characters.get(chid);
|
||||
if (sprite.subTags.isEmpty()) {
|
||||
if (sprite.getTags().isEmpty()) {
|
||||
String data = convertActionScript(dia);
|
||||
String expName = dia.getSwf().getExportName(dia.spriteId);
|
||||
expName = expName != null ? expName : "_unk_";
|
||||
@@ -3136,7 +3137,7 @@ public class XFLConverter {
|
||||
ret.append("<AdjustColorFilter brightness=\"").append(normBrightness(b)).append("\" contrast=\"").append(normContrast(c)).append("\" saturation=\"").append(normSaturation(s)).append("\" hue=\"").append(normHue(h)).append("\"/>");
|
||||
}
|
||||
|
||||
private static String convertHTMLText(List<Tag> tags, DefineEditTextTag det, String html) {
|
||||
private static String convertHTMLText(ReadOnlyTagList tags, DefineEditTextTag det, String html) {
|
||||
HTMLTextParser tparser = new HTMLTextParser(tags, det);
|
||||
XMLReader parser;
|
||||
try {
|
||||
@@ -3190,7 +3191,7 @@ public class XFLConverter {
|
||||
|
||||
private String alignment = null;
|
||||
|
||||
private final List<Tag> tags;
|
||||
private final ReadOnlyTagList tags;
|
||||
|
||||
private boolean bold = false;
|
||||
|
||||
@@ -3216,7 +3217,7 @@ public class XFLConverter {
|
||||
public void warning(SAXParseException e) throws SAXException {
|
||||
}
|
||||
|
||||
public HTMLTextParser(List<Tag> tags, DefineEditTextTag det) {
|
||||
public HTMLTextParser(ReadOnlyTagList tags, DefineEditTextTag det) {
|
||||
if (det.hasFont) {
|
||||
String fontName = null;
|
||||
FontTag ft = null;
|
||||
|
||||
Reference in New Issue
Block a user