allow adding new tags (todo: add constructor for all supported tagtypes)

This commit is contained in:
honfika@gmail.com
2014-11-05 00:12:57 +01:00
parent 49765d71b7
commit e7b2fbdfa2
9 changed files with 196 additions and 102 deletions

View File

@@ -191,7 +191,7 @@ public class DefineFont2Tag extends FontTag {
return baos.toByteArray();
}
public DefineFont2Tag(SWF swf) throws IOException {
public DefineFont2Tag(SWF swf) {
super(swf, ID, "DefineFont2", null);
}

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.tags.base.FontTag;
@@ -135,6 +136,14 @@ public class DefineFontTag extends FontTag {
return baos.toByteArray();
}
/**
* Constructor
* @param swf
*/
public DefineFontTag(SWF swf) {
super(swf, ID, "DefineFont", null);
}
/**
* Constructor
*

View File

@@ -355,49 +355,44 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
@Override
public FontTag toClassicFont() {
try {
DefineFont2Tag ret = new DefineFont2Tag(swf);
ret.fontId = getFontId();
ret.fontFlagsBold = isBold();
ret.fontFlagsItalic = isItalic();
ret.fontFlagsWideOffsets = true;
ret.fontFlagsWideCodes = true;
ret.fontFlagsHasLayout = true;
ret.fontAscent = (getAscent());
ret.fontDescent = (getDescent());
ret.fontLeading = (getLeading());
ret.fontAdvanceTable = new ArrayList<>();
ret.fontBoundsTable = new ArrayList<>();
ret.codeTable = new ArrayList<>();
ret.glyphShapeTable = new ArrayList<>();
List<SHAPE> shp = getGlyphShapeTable();
ret.numGlyphs = shp.size();
for (int g = 0; g < shp.size(); g++) {
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
ret.codeTable.add((int) glyphToChar(g));
DefineFont2Tag ret = new DefineFont2Tag(swf);
ret.fontId = getFontId();
ret.fontFlagsBold = isBold();
ret.fontFlagsItalic = isItalic();
ret.fontFlagsWideOffsets = true;
ret.fontFlagsWideCodes = true;
ret.fontFlagsHasLayout = true;
ret.fontAscent = (getAscent());
ret.fontDescent = (getDescent());
ret.fontLeading = (getLeading());
ret.fontAdvanceTable = new ArrayList<>();
ret.fontBoundsTable = new ArrayList<>();
ret.codeTable = new ArrayList<>();
ret.glyphShapeTable = new ArrayList<>();
List<SHAPE> shp = getGlyphShapeTable();
ret.numGlyphs = shp.size();
for (int g = 0; g < shp.size(); g++) {
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
ret.codeTable.add((int) glyphToChar(g));
SHAPE shpX = resizeShape(shp.get(g));
ret.glyphShapeTable.add(shpX);
ret.fontBoundsTable.add(getGlyphBounds(g));
}
ret.fontName = getFontNameIntag();
ret.languageCode = new LANGCODE(1);
ret.fontKerningTable = new ArrayList<>();
FontType ft = fonts.get(0);
for (int i = 0; i < ft.kerning.size(); i++) {
KERNINGRECORD kr = new KERNINGRECORD();
kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance);
kr.fontKerningCode1 = ft.kerning.get(i).char1;
kr.fontKerningCode2 = ft.kerning.get(i).char2;
ret.fontKerningTable.add(kr);
}
return ret;
} catch (IOException ex) {
Logger.getLogger(DefineCompactedFont.class.getName()).log(Level.SEVERE, null, ex);
SHAPE shpX = resizeShape(shp.get(g));
ret.glyphShapeTable.add(shpX);
ret.fontBoundsTable.add(getGlyphBounds(g));
}
return null;
ret.fontName = getFontNameIntag();
ret.languageCode = new LANGCODE(1);
ret.fontKerningTable = new ArrayList<>();
FontType ft = fonts.get(0);
for (int i = 0; i < ft.kerning.size(); i++) {
KERNINGRECORD kr = new KERNINGRECORD();
kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance);
kr.fontKerningCode1 = ft.kerning.get(i).char1;
kr.fontKerningCode2 = ft.kerning.get(i).char2;
ret.fontKerningTable.add(kr);
}
return ret;
}
@Override

View File

@@ -33,6 +33,7 @@ public class SWFList implements List<SWF>, SWFContainerItem {
public String name;
public boolean isBundle;
public Class bundleClass;
public SWFSourceInfo sourceInfo;
public List<SWF> swfs = new ArrayList<>();

View File

@@ -28,6 +28,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode;
import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode;
import com.jpexs.decompiler.flash.exporters.modes.TextExportMode;
import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
@@ -65,16 +66,16 @@ public class ExportDialog extends AppDialog {
boolean cancelled = false;
String[] optionNames = {
"shapes",
"texts",
"images",
"movies",
"sounds",
"scripts",
"binaryData",
"frames",
"fonts",
"morphshapes"
TagTreeModel.FOLDER_SHAPES,
TagTreeModel.FOLDER_TEXTS,
TagTreeModel.FOLDER_IMAGES,
TagTreeModel.FOLDER_MOVIES,
TagTreeModel.FOLDER_SOUNDS,
TagTreeModel.FOLDER_SPRITES,
TagTreeModel.FOLDER_BINARY_DATA,
TagTreeModel.FOLDER_FRAMES,
TagTreeModel.FOLDER_FONTS,
TagTreeModel.FOLDER_MORPHSHAPES
};
//Display options only when these classes found

View File

@@ -292,6 +292,7 @@ public class Main {
Stopwatch sw = Stopwatch.startNew();
if (bundle != null) {
result.isBundle = true;
result.bundleClass = bundle.getClass();
result.name = new File(sourceInfo.getFileTitleOrName()).getName();
for (Entry<String, SeekableInputStream> streamEntry : bundle.getAll().entrySet()) {
InputStream stream = streamEntry.getValue();

View File

@@ -522,3 +522,5 @@ menu.debugger.replacetrace = Replace trace calls
menu.debugger.showlog = Show Log
message.debugger = This SWF Debugger can only be used to print messages to log window, browser console or alerts.\r\nIt is NOT designed for features like step code, breakpoints etc.
contextmenu.addTag = Add tag

View File

@@ -16,7 +16,9 @@
*/
package com.jpexs.decompiler.flash.gui.tagtree;
import com.jpexs.decompiler.flash.SWC;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.ZippedSWFBundle;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.MainFrameRibbonMenu;
@@ -53,10 +55,14 @@ import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.timeline.AS2Package;
import com.jpexs.decompiler.flash.timeline.AS3Package;
@@ -78,9 +84,12 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
@@ -106,6 +115,7 @@ public class TagTree extends JTree implements ActionListener {
private static final String ACTION_REMOVE_ITEM = "REMOVEITEM";
private static final String ACTION_REMOVE_ITEM_WITH_DEPENDENCIES = "REMOVEITEMWITHDEPENDENCIES";
private static final String ACTION_CLOSE_SWF = "CLOSESWF";
private static final String ACTION_ADD_TAG = "ADDTAG";
private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE";
private static final String ACTION_OPEN_SWFINSIDE = "OPENSWFINSIDE";
@@ -204,57 +214,36 @@ public class TagTree extends JTree implements ActionListener {
|| (t instanceof DefineCompactedFont)) {
return TreeNodeType.FONT;
}
if ((t instanceof DefineTextTag)
|| (t instanceof DefineText2Tag)
|| (t instanceof DefineEditTextTag)) {
// DefineText, DefineText2, DefineEditTextTag
if (t instanceof TextTag) {
return TreeNodeType.TEXT;
}
if ((t instanceof DefineBitsTag)
|| (t instanceof DefineBitsJPEG2Tag)
|| (t instanceof DefineBitsJPEG3Tag)
|| (t instanceof DefineBitsJPEG4Tag)
|| (t instanceof DefineBitsLosslessTag)
|| (t instanceof DefineBitsLossless2Tag)) {
// DefineBits, DefineBitsJPEG2, DefineBitsJPEG3, DefineBitsJPEG4, DefineBitsLossless, DefineBitsLossless2
if (t instanceof ImageTag) {
return TreeNodeType.IMAGE;
}
if ((t instanceof DefineShapeTag)
|| (t instanceof DefineShape2Tag)
|| (t instanceof DefineShape3Tag)
|| (t instanceof DefineShape4Tag)) {
// DefineShape, DefineShape2, DefineShape3, DefineShape4
if (t instanceof ShapeTag) {
return TreeNodeType.SHAPE;
}
if ((t instanceof DefineMorphShapeTag) || (t instanceof DefineMorphShape2Tag)) {
// DefineMorphShape, DefineMorphShape2
if (t instanceof MorphShapeTag) {
return TreeNodeType.MORPH_SHAPE;
}
if (t instanceof DefineSpriteTag) {
return TreeNodeType.SPRITE;
}
if ((t instanceof DefineButtonTag) || (t instanceof DefineButton2Tag)) {
// DefineButton, DefineButton2
if (t instanceof ButtonTag) {
return TreeNodeType.BUTTON;
}
if (t instanceof ASMSource) {
return TreeNodeType.AS;
}
if (t instanceof ScriptPack) {
return TreeNodeType.AS;
}
if (t instanceof AS2Package) {
return TreeNodeType.PACKAGE;
}
if (t instanceof AS3Package) {
return TreeNodeType.PACKAGE;
}
if ((t instanceof Frame)
|| (t instanceof FrameScript)) {
return TreeNodeType.FRAME;
}
if (t instanceof ShowFrameTag) {
return TreeNodeType.SHOW_FRAME;
}
if (t instanceof DefineVideoStreamTag) {
return TreeNodeType.MOVIE;
}
@@ -267,17 +256,41 @@ public class TagTree extends JTree implements ActionListener {
return TreeNodeType.BINARY_DATA;
}
if (t instanceof ASMSource) {
return TreeNodeType.AS;
}
if (t instanceof ScriptPack) {
return TreeNodeType.AS;
}
if (t instanceof AS2Package) {
return TreeNodeType.PACKAGE;
}
if (t instanceof AS3Package) {
return TreeNodeType.PACKAGE;
}
if ((t instanceof Frame)
|| (t instanceof FrameScript)) {
return TreeNodeType.FRAME;
}
if (t instanceof ShowFrameTag) {
return TreeNodeType.SHOW_FRAME;
}
if (t instanceof SWF) {
return TreeNodeType.FLASH;
}
if (t instanceof SWFList) {
SWFList slist = (SWFList) t;
if (slist.name != null) {
if (slist.name.toLowerCase().endsWith(".zip")) {
if (slist.bundleClass != null) {
if (slist.bundleClass == ZippedSWFBundle.class) {
return TreeNodeType.BUNDLE_ZIP;
}
if (slist.name.toLowerCase().endsWith(".swc")) {
} else if (slist.bundleClass == SWC.class) {
return TreeNodeType.BUNDLE_SWC;
} else {
return TreeNodeType.BUNDLE_BINARY;
@@ -296,6 +309,50 @@ public class TagTree extends JTree implements ActionListener {
return TreeNodeType.FOLDER;
}
public List<Class> getTreeItemClasses(String folderName) {
List<Class> ret = null;
switch (folderName) {
case TagTreeModel.FOLDER_SHAPES:
ret = Arrays.asList((Class) DefineShapeTag.class, DefineShape2Tag.class, DefineShape3Tag.class, DefineShape4Tag.class);
break;
case TagTreeModel.FOLDER_MORPHSHAPES:
ret = Arrays.asList((Class) DefineMorphShapeTag.class, DefineMorphShape2Tag.class);
break;
case TagTreeModel.FOLDER_SPRITES:
ret = Arrays.asList((Class) DefineSpriteTag.class);
break;
case TagTreeModel.FOLDER_TEXTS:
ret = Arrays.asList((Class) DefineTextTag.class, DefineText2Tag.class, DefineEditTextTag.class);
break;
case TagTreeModel.FOLDER_IMAGES:
ret = Arrays.asList((Class) DefineBitsTag.class, DefineBitsJPEG2Tag.class, DefineBitsJPEG3Tag.class, DefineBitsJPEG4Tag.class, DefineBitsLosslessTag.class, DefineBitsLossless2Tag.class);
break;
case TagTreeModel.FOLDER_MOVIES:
ret = Arrays.asList((Class) DefineVideoStreamTag.class);
break;
case TagTreeModel.FOLDER_SOUNDS:
ret = Arrays.asList((Class) DefineSoundTag.class, SoundStreamHeadTag.class, SoundStreamHead2Tag.class);
break;
case TagTreeModel.FOLDER_BUTTONS:
ret = Arrays.asList((Class) DefineButtonTag.class, DefineButton2Tag.class);
break;
case TagTreeModel.FOLDER_FONTS:
ret = Arrays.asList((Class) DefineFontTag.class, DefineFont2Tag.class, DefineFont3Tag.class, DefineFont4Tag.class, DefineCompactedFont.class);
break;
case TagTreeModel.FOLDER_BINARY_DATA:
ret = Arrays.asList((Class) DefineBinaryDataTag.class);
break;
case TagTreeModel.FOLDER_FRAMES:
ret = new ArrayList<>();
break;
case TagTreeModel.FOLDER_OTHERS:
ret = new ArrayList<>();
break;
}
return ret;
}
public void createContextMenu(final List<SWFList> swfs) {
final JPopupMenu contextPopupMenu = new JPopupMenu();
@@ -341,6 +398,9 @@ public class TagTree extends JTree implements ActionListener {
closeSelectionMenuItem.addActionListener(this);
contextPopupMenu.add(closeSelectionMenuItem);
final JMenu addTagMenu = new JMenu(mainPanel.translate("contextmenu.addTag"));
contextPopupMenu.add(addTagMenu);
final JMenu moveTagMenu = new JMenu(mainPanel.translate("contextmenu.moveTag"));
contextPopupMenu.add(moveTagMenu);
@@ -376,6 +436,7 @@ public class TagTree extends JTree implements ActionListener {
replaceSelectionMenuItem.setVisible(false);
closeSelectionMenuItem.setVisible(false);
moveTagMenu.setVisible(false);
addTagMenu.setVisible(false);
expandRecursiveMenuItem.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
@@ -411,6 +472,31 @@ public class TagTree extends JTree implements ActionListener {
closeSelectionMenuItem.setVisible(true);
}
if (item instanceof FolderItem) {
final FolderItem folderItem = (FolderItem) item;
List<Class> allowedTagTypes = getTreeItemClasses(folderItem.getName());
addTagMenu.removeAll();
for (final Class cl : allowedTagTypes) {
JMenuItem tagItem = new JMenuItem(cl.getSimpleName());
tagItem.addActionListener(new ActionListener() {
@Override
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent ae) {
try {
SWF swf = folderItem.getSwf();
swf.tags.add((Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[] {swf}));
mainPanel.refreshTree();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(TagTree.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
addTagMenu.add(tagItem);
}
addTagMenu.setVisible(true);
}
if (item instanceof Tag && swfs.size() > 1) {
final Tag tag = (Tag) item;
moveTagMenu.removeAll();
@@ -620,7 +706,7 @@ public class TagTree extends JTree implements ActionListener {
ret.add(d);
}
if (d instanceof ScriptPack) {
ret.add((ScriptPack) d);
ret.add(d);
}
}
return ret;

View File

@@ -17,7 +17,6 @@
package com.jpexs.decompiler.flash.gui.tagtree;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFBundle;
import com.jpexs.decompiler.flash.SWFContainerItem;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.TreeNodeType;
@@ -53,16 +52,16 @@ import javax.swing.tree.TreePath;
public class TagTreeModel implements TreeModel {
public static final String FOLDER_SHAPES = "shapes";
public static final String FOLDER_MORPHSHAPES = "morphshapes";
public static final String FOLDER_SPRITES = "sprites";
public static final String FOLDER_TEXTS = "texts";
public static final String FOLDER_IMAGES = "images";
public static final String FOLDER_MOVIES = "movies";
public static final String FOLDER_SOUNDS = "sounds";
public static final String FOLDER_BINARY_DATA = "binaryData";
public static final String FOLDER_FONTS = "fonts";
public static final String FOLDER_SPRITES = "sprites";
public static final String FOLDER_SHAPES = "shapes";
public static final String FOLDER_MORPHSHAPES = "morphshapes";
public static final String FOLDER_BUTTONS = "buttons";
public static final String FOLDER_FONTS = "fonts";
public static final String FOLDER_BINARY_DATA = "binaryData";
public static final String FOLDER_FRAMES = "frames";
public static final String FOLDER_OTHERS = "others";
public static final String FOLDER_SCRIPTS = "scripts";
@@ -176,7 +175,7 @@ public class TagTreeModel implements TreeModel {
}
}
nodeList.add(new HeaderItem(swf, AppStrings.translate("node.header")));
nodeList.add(new HeaderItem(swf, translate("node.header")));
if (!shapes.isEmpty()) {
FolderItem shapesNode = new FolderItem(translate("node.shapes"), FOLDER_SHAPES, swf, shapes);
@@ -373,7 +372,7 @@ public class TagTreeModel implements TreeModel {
TreeItem parentNode = (TreeItem) parent;
if (parentNode == root) {
return swfs.get(index);
} else if (parentNode instanceof SWFBundle) {
} else if (parentNode instanceof SWFList) {
return ((SWFList) parentNode).swfs.get(index);
} else if (parentNode instanceof SWF) {
return getSwfFolders((SWF) parentNode).get(index);
@@ -406,7 +405,7 @@ public class TagTreeModel implements TreeModel {
TreeItem parentNode = (TreeItem) parent;
if (parentNode == root) {
return swfs.size();
} else if (parentNode instanceof SWFBundle) {
} else if (parentNode instanceof SWFList) {
return ((SWFList) parentNode).swfs.size();
} else if (parentNode instanceof SWF) {
return getSwfFolders((SWF) parentNode).size();
@@ -451,7 +450,7 @@ public class TagTreeModel implements TreeModel {
TreeItem childNode = (TreeItem) child;
if (parentNode == root) {
return swfs.indexOf(childNode);
} else if (parentNode instanceof SWFBundle) {
} else if (parentNode instanceof SWFList) {
return ((SWFList) parentNode).swfs.indexOf(childNode);
} else if (parentNode instanceof SWF) {
return getSwfFolders((SWF) parentNode).indexOf(childNode);