diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 1635b82ff..4cbf6104e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -78,6 +78,7 @@ import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.VideoFrameTag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.BoundedTag; +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.Container; @@ -126,7 +127,6 @@ import com.jpexs.helpers.utf8.Utf8Helper; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics2D; -import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; @@ -825,6 +825,11 @@ public final class SWF implements TreeItem, Timelined { return uniqueAS3Packs(packs); } + @Override + public RECT getRect() { + return displayRect; + } + private class ExportPackTask implements Callable { ScriptPack pack; @@ -2262,7 +2267,7 @@ public final class SWF implements TreeItem, Timelined { return ret; } - public static SerializableImage frameToImageGet(Timeline timeline, int frame,Point mousePos,int mouseButton, RECT displayRect, Matrix transformation, ColorTransform colorTransform) { + public static SerializableImage frameToImageGet(Timeline timeline, int frame, DepthState stateUnderCursor, int mouseButton, RECT displayRect, Matrix transformation, ColorTransform colorTransform) { String key = "frame_" + frame + "_" + timeline.id + "_" + timeline.swf.hashCode(); SerializableImage image = getFromCache(key); if (image != null) { @@ -2279,12 +2284,12 @@ public final class SWF implements TreeItem, Timelined { image.fillTransparent(); Matrix m = new Matrix(); m.translate(-rect.Xmin, -rect.Ymin); - frameToImage(timeline, frame, mousePos,mouseButton,image, m, colorTransform); + frameToImage(timeline, frame, stateUnderCursor, mouseButton, image, m, colorTransform); putToCache(key, image); return image; } - public static void framesToImage(Timeline timeline, List ret, int startFrame, int stopFrame, Point mousePos,int mouseButton,RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation, ColorTransform colorTransform) { + public static void framesToImage(Timeline timeline, List ret, int startFrame, int stopFrame, DepthState stateUnderCursor, int mouseButton, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation, ColorTransform colorTransform) { RECT rect = displayRect; for (int f = 0; f < timeline.frames.size(); f++) { SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, @@ -2292,7 +2297,7 @@ public final class SWF implements TreeItem, Timelined { image.fillTransparent(); Matrix m = new Matrix(); m.translate(-rect.Xmin, -rect.Ymin); - frameToImage(timeline, f, mousePos,mouseButton,image, m, colorTransform); + frameToImage(timeline, f, stateUnderCursor, mouseButton, image, m, colorTransform); ret.add(image); } } @@ -2309,7 +2314,7 @@ public final class SWF implements TreeItem, Timelined { } - public static void frameToImage(Timeline timeline, int frame,Point mousePos,int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public static void frameToImage(Timeline timeline, int frame, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { float unzoom = (float) SWF.unitDivisor; if (timeline.frames.size() <= frame) { return; @@ -2359,6 +2364,19 @@ public final class SWF implements TreeItem, Timelined { SerializableImage img; Matrix drawMatrix = new Matrix(); int dframe = 0 + layer.time % drawable.getNumFrames(); + + if (character instanceof ButtonTag) { + ButtonTag bt = (ButtonTag) character; + dframe = ButtonTag.FRAME_UP; + if (stateUnderCursor == layer) { + if (mouseButton > 0) { + dframe = ButtonTag.FRAME_DOWN; + } else { + dframe = ButtonTag.FRAME_OVER; + } + } + } + if (drawable instanceof BoundedTag) { BoundedTag bounded = (BoundedTag) drawable; RECT boundRect = bounded.getRect(); @@ -2401,7 +2419,7 @@ public final class SWF implements TreeItem, Timelined { m.translate(-rect.xMin, -rect.yMin); drawMatrix.translate(rect.xMin, rect.yMin); - drawable.toImage(dframe, layer.ratio,mousePos,mouseButton, img, m, clrTrans); + drawable.toImage(dframe, layer.ratio, stateUnderCursor, mouseButton, img, m, clrTrans); } else if (drawable instanceof FontTag) { // only DefineFont tags FontTag fontTag = (FontTag) drawable; diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java b/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java index 0f59c203a..de880522b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java @@ -204,4 +204,9 @@ public class Matrix { translateX, translateY); return transform; } + + @Override + public String toString() { + return "[Matrix scale:" + scaleX + "," + scaleY + ", rotate:" + rotateSkew0 + "," + rotateSkew1 + ", translate:" + translateX + "," + translateY + "]"; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index e5953c557..7ff3d7464 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -21,21 +21,24 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.gui.player.FlashDisplay; import com.jpexs.decompiler.flash.tags.base.BoundedTag; -import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.tags.base.ButtonTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.helpers.SerializableImage; import java.awt.AlphaComposite; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Cursor; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -44,6 +47,7 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; +import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.swing.ImageIcon; @@ -55,22 +59,18 @@ import javax.swing.JPanel; public final class ImagePanel extends JPanel implements ActionListener, FlashDisplay { static final String ACTION_SELECT_BKCOLOR = "SELECTCOLOR"; - static final int frameRate = 25; - // play morph shape in 2 second(s) - // this settings should be synchronized with frameCount and frameRate - // settings in Mainpanel.createAndShowTempSwf - static final int morphShapeAnimationLength = 2; - public JLabel label = new JLabel(); - public DrawableTag drawable; + private JLabel label = new JLabel(); + private Timelined timelined; + private boolean stillFrame = false; private Timer timer; private int frame = -1; private SWF swf; private boolean loaded; - private Point mousePos = null; private int mouseButton; - - + private JLabel debugLabel = new JLabel("-"); + private DepthState stateUnderCursor = null; + private MouseEvent lastMouseEvent = null; @Override public void setBackground(Color bg) { @@ -100,29 +100,83 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis label.removeMouseMotionListener(l); } + private void updatePos(MouseEvent e) { + if (e == null) { + return; + } + lastMouseEvent = e; + boolean handCursor = false; + DepthState newStateUnderCursor = null; + if (timelined != null) { + Timeline tim = ((Timelined) timelined).getTimeline(); + BoundedTag bounded = (BoundedTag) timelined; + RECT rect = bounded.getRect(); + int width = rect.getWidth(); + double scale = 1.0; + if (width > swf.displayRect.getWidth()) { + scale = (double) swf.displayRect.getWidth() / (double) width; + } + Matrix m = new Matrix(); + m.translate(-rect.Xmin, -rect.Ymin); + m.scale(scale); + List objs = tim.frames.get(frame).getObjectsUnderCursor(e.getPoint(), mouseButton, m); + String ret = ""; + ret += " [" + e.getX() + "," + e.getY() + "] : "; + + boolean first = true; + for (DepthState ds : objs) { + if (!first) { + ret += ", "; + } + first = false; + CharacterTag c = tim.swf.characters.get(ds.characterId); + if (c instanceof ButtonTag) { + newStateUnderCursor = ds; + handCursor = true; + } + ret += c.toString(); + if (timelined instanceof ButtonTag) { + handCursor = true; + } + } + if (objs.isEmpty()) { + ret += " - "; + } + debugLabel.setText(ret); + + if (handCursor) { + label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } else { + label.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + if (newStateUnderCursor != stateUnderCursor) { + stateUnderCursor = newStateUnderCursor; + drawFrame(); + } + } + } + public ImagePanel() { super(new BorderLayout()); label.setHorizontalAlignment(JLabel.CENTER); setOpaque(true); setBackground(View.DEFAULT_BACKGROUND_COLOR); - - - - JPanel labelPan = new JPanel(new GridBagLayout()){ + + JPanel labelPan = new JPanel(new GridBagLayout()) { @Override protected void paintComponent(Graphics g) { - Graphics2D g2d=(Graphics2D)g; + Graphics2D g2d = (Graphics2D) g; g2d.setPaint(View.transparentPaint); - g2d.fill(new Rectangle(0,0,getWidth(),getHeight())); + g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); g2d.setComposite(AlphaComposite.SrcOver); g2d.setPaint(View.swfBackgroundColor); - g2d.fill(new Rectangle(0,0,getWidth(),getHeight())); + g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); } - - }; - labelPan.add(label,new GridBagConstraints()); - add(labelPan,BorderLayout.CENTER); + + }; + labelPan.add(label, new GridBagConstraints()); + add(labelPan, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(new BorderLayout()); JPanel buttonsPanel = new JPanel(new FlowLayout()); @@ -133,42 +187,49 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis buttonsPanel.add(selectColorButton); bottomPanel.add(buttonsPanel, BorderLayout.EAST); add(bottomPanel, BorderLayout.SOUTH); + add(debugLabel, BorderLayout.NORTH); label.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { - mousePos = e.getPoint(); drawFrame(); } @Override public void mouseExited(MouseEvent e) { - mousePos = null; + stateUnderCursor = null; drawFrame(); + debugLabel.setText(" - "); } - - - @Override public void mousePressed(MouseEvent e) { mouseButton = e.getButton(); + updatePos(e); drawFrame(); } @Override public void mouseReleased(MouseEvent e) { mouseButton = 0; + updatePos(e); drawFrame(); } - -}); + + }); label.addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { - - } -}); + + updatePos(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + updatePos(e); + } + + }); } @Override @@ -194,59 +255,33 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis if (timer != null) { timer.cancel(); } - drawable = null; + timelined = null; loaded = true; ImageIcon icon = new ImageIcon(data); label.setIcon(icon); } - public void setDrawable(final DrawableTag drawable, final SWF swf, int frameRate) { + public void setTimelined(final Timelined drawable, final SWF swf, int frame) { pause(); - this.drawable = drawable; + if (drawable instanceof ButtonTag) { + frame = ButtonTag.FRAME_UP; + } + this.timelined = drawable; this.swf = swf; + if (frame > -1) { + this.frame = frame; + this.stillFrame = true; + } else { + this.frame = 0; + this.stillFrame = false; + } loaded = true; - if (drawable.getNumFrames() == 0) { + if (drawable.getTimeline().frames.isEmpty()) { label.setIcon(null); return; } frame = 0; - /*if (drawable.getNumFrames() == 1) { - Matrix mat = new Matrix(); - mat.translateX = swf.displayRect.Xmin; - mat.translateY = swf.displayRect.Ymin; - String key = "drawable_0_" + drawable.hashCode(); - SerializableImage img = SWF.getFromCache(key); - if (img == null) { - if (drawable instanceof BoundedTag) { - BoundedTag bounded = (BoundedTag) drawable; - RECT rect = bounded.getRect(); - int width = (int) (rect.getWidth() / SWF.unitDivisor); - int height = (int) (rect.getHeight() / SWF.unitDivisor); - if (rect.getWidth() > width * SWF.unitDivisor) { - width++; - } - if (rect.getHeight()> height * SWF.unitDivisor) { - height++; - } - SerializableImage image = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB); - image.fillTransparent(); - Matrix m = new Matrix(); - m.translate(-rect.Xmin, -rect.Ymin); - drawable.toImage(0, 0, mousePos,mouseButton,image, m, new ColorTransform()); - img = image; - } else if (drawable instanceof FontTag) { - // only DefineFont tags - FontTag fontTag = (FontTag) drawable; - img = fontTag.toImage(0, 0, Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform()); - } - SWF.putToCache(key, img); - } - if (img != null) { - setImage(img); - } - return; - }*/ play(); } @@ -255,8 +290,9 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis if (timer != null) { timer.cancel(); } - drawable = null; + timelined = null; loaded = true; + stillFrame = true; ImageIcon icon = new ImageIcon(image.getBufferedImage()); label.setIcon(icon); } @@ -268,10 +304,13 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis @Override public int getTotalFrames() { - if (drawable == null) { + if (timelined == null) { return 0; } - return drawable.getNumFrames(); + if (stillFrame) { + return 1; + } + return timelined.getTimeline().frames.size(); } @Override @@ -283,21 +322,16 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis } private void nextFrame() { - int newframe = frame == drawable.getNumFrames() - 1 ? 0 : frame + 1; - if (drawable instanceof MorphShapeTag) { - newframe = frame + drawable.getNumFrames() / frameRate / morphShapeAnimationLength; - if (newframe > drawable.getNumFrames()) { - newframe = 0; - } - } + int newframe = frame == timelined.getTimeline().frames.size() - 1 ? 0 : frame + 1; if (newframe != frame) { frame = newframe; + updatePos(lastMouseEvent); drawFrame(); } } - private static SerializableImage getFrame(SWF swf, int frame, DrawableTag drawable,Point mousePos, int mouseButton) { - String key = "drawable_" + frame + "_" + drawable.hashCode()+"_"+mouseButton+"_"+(mousePos==null?"out":"over"); + private static SerializableImage getFrame(SWF swf, int frame, Timelined drawable, DepthState stateUnderCursor, int mouseButton) { + String key = "drawable_" + frame + "_" + drawable.hashCode() + "_" + mouseButton + "_" + (stateUnderCursor == null ? "out" : stateUnderCursor.hashCode()); SerializableImage img = SWF.getFromCache(key); if (img == null) { if (drawable instanceof BoundedTag) { @@ -319,7 +353,7 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis Matrix m = new Matrix(); m.translate(-rect.Xmin, -rect.Ymin); m.scale(scale); - drawable.toImage(frame, frame,mousePos,mouseButton, image, m, new ColorTransform()); + drawable.getTimeline().toImage(frame, frame, stateUnderCursor, mouseButton, image, m, new ColorTransform()); img = image; } else if (drawable instanceof FontTag) { // only DefineFont tags @@ -332,13 +366,13 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis } private void drawFrame() { - if (drawable == null) { + if (timelined == null) { return; } Matrix mat = new Matrix(); mat.translateX = swf.displayRect.Xmin; mat.translateY = swf.displayRect.Ymin; - ImageIcon icon = new ImageIcon(getFrame(swf, frame, drawable,mousePos,mouseButton).getBufferedImage()); + ImageIcon icon = new ImageIcon(getFrame(swf, frame, timelined, stateUnderCursor, mouseButton).getBufferedImage()); label.setIcon(icon); } @@ -352,15 +386,15 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis @Override public void play() { pause(); - if (drawable.getNumFrames() > 1) { + if (!stillFrame && timelined.getTimeline().frames.size() > 1) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { nextFrame(); } - }, 0, 1000 / frameRate); - }else{ + }, 0, 1000 / timelined.getTimeline().frameRate); + } else { drawFrame(); } } @@ -373,10 +407,13 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis @Override public boolean isPlaying() { - if (drawable == null) { + if (timelined == null) { return false; } - return (drawable.getNumFrames() <= 1) || (timer != null); + if (stillFrame) { + return false; + } + return (timelined.getTimeline().frames.size() <= 1) || (timer != null); } @Override @@ -387,13 +424,13 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis @Override public int getFrameRate() { - if (drawable == null) { + if (timelined == null) { return 1; } - if (drawable instanceof MorphShapeTag) { - return drawable.getNumFrames() / morphShapeAnimationLength; + if (stillFrame) { + return 1; } - return frameRate; + return timelined.getTimeline().frameRate; } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java index fdc6cad46..d9d1ad2fb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -29,7 +29,6 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.gui.abc.ABCPanel; import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel; import com.jpexs.decompiler.flash.gui.abc.DeobfuscationDialog; @@ -98,7 +97,10 @@ import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; import com.jpexs.decompiler.flash.tags.text.ParseException; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Frame; import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.treeitems.FrameNodeItem; import com.jpexs.decompiler.flash.treeitems.StringItem; import com.jpexs.decompiler.flash.treeitems.TreeItem; @@ -106,7 +108,6 @@ import com.jpexs.decompiler.flash.treenodes.ContainerNode; import com.jpexs.decompiler.flash.treenodes.FrameNode; import com.jpexs.decompiler.flash.treenodes.TagNode; import com.jpexs.decompiler.flash.treenodes.TreeNode; -import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.GLYPHENTRY; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; @@ -221,7 +222,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private GenericTagPanel genericTagPanel; private JPanel folderPreviewPanel; private final ImagePanel previewImagePanel; - private final SWFPreviewPanel swfPreviewPanel; + private final ImagePanel swfPreviewPanel; private boolean isWelcomeScreen = true; private static final String CARDFLASHPANEL = "Flash card"; private static final String CARDSWFPREVIEWPANEL = "SWF card"; @@ -285,6 +286,13 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private static final String ACTION_CLOSE_SWF = "CLOSESWF"; private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE"; + // play morph shape in 2 second(s) + // this settings should be synchronized with frameCount and frameRate + // settings in Mainpanel.createAndShowTempSwf + static final int morphShapeAnimationLength = 2; + + static final int morphShapeAnimationFrameRate = 30; + private static final Logger logger = Logger.getLogger(MainPanel.class.getName()); public void setPercent(int percent) { @@ -437,7 +445,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } moveTagMenu.setVisible(true); } - + TreeModel model = tagTree.getModel(); expandRecursiveMenuItem.setVisible(model.getChildCount(treeNode) > 0); } @@ -817,7 +825,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec shapesCard.add(previewPanel, BorderLayout.CENTER); displayPanel.add(shapesCard, CARDDRAWPREVIEWPANEL); - swfPreviewPanel = new SWFPreviewPanel(); + swfPreviewPanel = new ImagePanel(); displayPanel.add(swfPreviewPanel, CARDSWFPREVIEWPANEL); displayPanel.add(new JPanel(), CARDEMPTYPANEL); @@ -2076,7 +2084,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } return false; } - + public void removeTag(Tag tag) { tag.getSwf().removeTag(tag); refreshTree(); @@ -2212,7 +2220,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec return; } View.expandTreeNodesRecursive(tagTree, path, true); - } + } break; case ACTION_REMOVE_ITEM: List sel = getSelected(tagTree); @@ -2425,9 +2433,9 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec SWFNode swfNode = (SWFNode) treeNode; SWF swf = swfNode.getItem(); if (mainMenu.isInternalFlashViewerSelected()) { - showCard(CARDSWFPREVIEWPANEL); - swfPreviewPanel.load(swf); - swfPreviewPanel.play(); + showCard(CARDDRAWPREVIEWPANEL); + + previewImagePanel.setTimelined(swf, swf, -1); } else { showCard(CARDFLASHPANEL); parametersPanel.setVisible(false); @@ -2471,9 +2479,17 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec showCard(CARDIMAGEPANEL); imagePanel.setImage(imageTag.getImage()); } else if ((tagObj instanceof DrawableTag) && (!(tagObj instanceof TextTag)) && (!(tagObj instanceof FontTag)) && (mainMenu.isInternalFlashViewerSelected())) { - Tag tag = (Tag) tagObj; + final Tag tag = (Tag) tagObj; showCard(CARDDRAWPREVIEWPANEL); - previewImagePanel.setDrawable((DrawableTag) tag, tag.getSwf(), 50/*FIXME*/); + DrawableTag d = (DrawableTag) tag; + Timelined timelined = null; + if (tagObj instanceof Timelined && !(tagObj instanceof ButtonTag)) { + timelined = (Timelined) tag; + } else { + timelined = makeTimelined(tag); + } + + previewImagePanel.setTimelined(timelined, tag.getSwf(), -1); } else if ((tagObj instanceof FontTag) && (mainMenu.isInternalFlashViewerSelected())) { FontTag fontTag = (FontTag) tagObj; showCard(CARDFLASHPANEL); @@ -2490,15 +2506,16 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec int containerId = 0; RECT rect = swf.displayRect; int totalFrameCount = swf.frameCount; - Timeline timeline = swf.getTimeline(); + Timelined timelined = swf; if (fn.getParent() instanceof DefineSpriteTag) { controlTags = ((DefineSpriteTag) fn.getParent()).subTags; containerId = ((DefineSpriteTag) fn.getParent()).spriteId; rect = ((DefineSpriteTag) fn.getParent()).getRect(); totalFrameCount = ((DefineSpriteTag) fn.getParent()).frameCount; - timeline = ((DefineSpriteTag) fn.getParent()).getTimeline(); + timelined = ((DefineSpriteTag) fn.getParent()); } - previewImagePanel.setImage(SWF.frameToImageGet(timeline, fn.getFrame() - 1, null,0,rect, Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform())); + previewImagePanel.setTimelined(timelined, swf, fn.getFrame() - 1); + //previewImagePanel.setImage(SWF.frameToImageGet(timeline, fn.getFrame() - 1, null,0,rect, Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform())); } else if (((tagObj instanceof FrameNodeItem) && ((FrameNodeItem) tagObj).isDisplayed()) || ((tagObj instanceof CharacterTag) || (tagObj instanceof FontTag)) && (tagObj instanceof Tag)) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); createAndShowTempSwf(tagObj); @@ -2903,7 +2920,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private void showFontTag(FontTag ft) { if (mainMenu.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, INTERNAL_VIEWER_CARD); - internelViewerPanel.setDrawable(ft, ft.getSwf(), 1); + internelViewerPanel.setTimelined(makeTimelined(ft), ft.getSwf(), 0); } else { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); } @@ -2917,7 +2934,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private void showTextTag(TextTag textTag) { if (mainMenu.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, INTERNAL_VIEWER_CARD); - internelViewerPanel.setDrawable(textTag, textTag.getSwf(), 1); + internelViewerPanel.setTimelined(makeTimelined(textTag), textTag.getSwf(), 0); } else { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); } @@ -3074,4 +3091,47 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec tf.setVisible(true); } } + + private static Timelined makeTimelined(final Tag tag) { + + return new Timelined() { + + private Timeline tim; + + @Override + public Timeline getTimeline() { + if (tim != null) { + return tim; + } + tim = new Timeline(tag.getSwf(), new ArrayList(), ((CharacterTag) tag).getCharacterId(), getRect()); + if (tag instanceof MorphShapeTag) { + tim.frameRate = morphShapeAnimationFrameRate; + int framesCnt = tim.frameRate * morphShapeAnimationLength; + for (int i = 0; i < framesCnt; i++) { + Frame f = new Frame(tim); + DepthState ds = new DepthState(tag.getSwf(), f); + ds.characterId = ((CharacterTag) tag).getCharacterId(); + ds.matrix = new MATRIX(); + ds.ratio = i * 65535 / framesCnt; + f.layers.put(1, ds); + tim.frames.add(f); + } + } else { + Frame f = new Frame(tim); + DepthState ds = new DepthState(tag.getSwf(), f); + ds.characterId = ((CharacterTag) tag).getCharacterId(); + ds.matrix = new MATRIX(); + f.layers.put(1, ds); + tim.frames.add(f); + } + tim.displayRect = getRect(); + return tim; + } + + @Override + public RECT getRect() { + return ((BoundedTag) tag).getRect(); + } + }; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/PreviewImage.java b/trunk/src/com/jpexs/decompiler/flash/gui/PreviewImage.java index 7b7ed62a4..f032738d4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/PreviewImage.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/PreviewImage.java @@ -81,7 +81,7 @@ public class PreviewImage extends JPanel { setSize(dim); setLayout(null); setBorder(BorderFactory.createLineBorder(Color.black)); - + if (treeItem instanceof Tag) { JPopupMenu contextMenu = new JPopupMenu(); final JMenuItem removeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.remove")); @@ -99,7 +99,7 @@ public class PreviewImage extends JPanel { contextMenu.add(removeMenuItem); this.setComponentPopupMenu(contextMenu); } - + this.addMouseListener(new MouseListener() { @Override @@ -168,7 +168,7 @@ public class PreviewImage extends JPanel { } else if (treeItem instanceof FrameNodeItem) { FrameNodeItem fn = (FrameNodeItem) treeItem; RECT rect = swf.displayRect; - imgSrc = SWF.frameToImageGet(swf.getTimeline(), fn.getFrame() - 1, null,0,rect, Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform()); + imgSrc = SWF.frameToImageGet(swf.getTimeline(), fn.getFrame() - 1, null, 0, rect, Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform()); width = (imgSrc.getWidth()); height = (imgSrc.getHeight()); } else if (treeItem instanceof ImageTag) { @@ -219,7 +219,7 @@ public class PreviewImage extends JPanel { image.fillTransparent(); if (imgSrc == null) { DrawableTag drawable = (DrawableTag) treeItem; - drawable.toImage(0, 0,null,0, image, m, new ColorTransform()); + drawable.toImage(0, 0, null, 0, image, m, new ColorTransform()); } else { Graphics2D g = (Graphics2D) image.getGraphics(); g.setTransform(m.toTransform()); @@ -249,12 +249,12 @@ public class PreviewImage extends JPanel { @Override protected void paintComponent(Graphics g) { - Graphics2D g2d=(Graphics2D)g; + Graphics2D g2d = (Graphics2D) g; g2d.setPaint(View.transparentPaint); - g2d.fill(new Rectangle(0,0,getWidth(),getHeight())); + g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); g2d.setComposite(AlphaComposite.SrcOver); g2d.setPaint(View.swfBackgroundColor); - g2d.fill(new Rectangle(0,0,getWidth(),getHeight())); + g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); if (image != null) { int x = (getWidth() / 2) - (image.getWidth(this) / 2); int y = (getHeight() / 2) - (image.getHeight(this) / 2); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java deleted file mode 100644 index f0c41cc3f..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.AppStrings; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.exporters.Matrix; -import com.jpexs.decompiler.flash.gui.player.FlashDisplay; -import com.jpexs.decompiler.flash.gui.player.PlayerControls; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.helpers.SerializableImage; -import java.awt.BorderLayout; -import java.util.ArrayList; -import java.util.List; -import java.util.Stack; -import java.util.Timer; -import java.util.TimerTask; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.SwingConstants; - -/** - * - * @author JPEXS - */ -public class SWFPreviewPanel extends JPanel implements FlashDisplay { - - ImagePanel pan; - Timer timer; - int frame = 1; - List frameImages; - JLabel buffering = new JLabel(AppStrings.translate("work.buffering") + "..."); - - public SWFPreviewPanel() { - pan = new ImagePanel(); - pan.setBackground(View.swfBackgroundColor); - setLayout(new BorderLayout()); - add(new JScrollPane(pan), BorderLayout.CENTER); - buffering.setHorizontalAlignment(JLabel.CENTER); - buffering.setVisible(false); - JLabel prevLabel = new HeaderLabel(AppStrings.translate("swfpreview.internal")); - prevLabel.setHorizontalAlignment(SwingConstants.CENTER); - //prevLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); - add(prevLabel, BorderLayout.NORTH); - //add(buffering, BorderLayout.SOUTH); - add(new PlayerControls(this), BorderLayout.SOUTH); - } - private SWF swf; - - public void load(final SWF swf) { - this.swf = swf; - List frames = new ArrayList<>(); - frame = 0; - frameImages = frames; - new Thread() { - @Override - public void run() { - buffering.setVisible(true); - //TODO: handle mouse move and clicks - SWF.framesToImage(swf.getTimeline(), frameImages, 0, swf.frameCount - 1,null,0, swf.displayRect, swf.frameCount, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform()); - buffering.setVisible(false); - } - }.start(); - - } - - public void stop() { - if (timer != null) { - timer.cancel(); - timer = null; - } - } - - @Override - public void play() { - if (swf == null) { - return; - } - if (swf.frameRate == 0) { - return; - } - stop(); - timer = new Timer(); - timer.schedule(new TimerTask() { - @Override - public void run() { - nextFrame(); - } - }, 0, 1000 / swf.frameRate); - } - - private void nextFrame() { - int newframe = frame == swf.frameCount - 1 ? 0 : frame + 1; - if (newframe != frame) { - if (frameImages != null && frameImages.size() > newframe) { - frame = newframe; - drawFrame(); - pan.setBackground(View.swfBackgroundColor); - } - } - } - - private void drawFrame() { - pan.setImage(frameImages.get(frame)); - } - - @Override - public int getCurrentFrame() { - return frame; - } - - @Override - public int getTotalFrames() { - if (swf == null) { - return 0; - } - return swf.frameCount; - } - - @Override - public void pause() { - if (timer != null) { - timer.cancel(); - timer = null; - } - } - - @Override - public void rewind() { - frame = 0; - drawFrame(); - } - - @Override - public boolean isPlaying() { - return timer != null; - } - - @Override - public void gotoFrame(int frame) { - this.frame = frame; - drawFrame(); - } - - @Override - public int getFrameRate() { - if (swf == null) { - return 1; - } - return swf.frameRate; - } - - @Override - public boolean isLoaded() { - return true; - } -} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/View.java b/trunk/src/com/jpexs/decompiler/flash/gui/View.java index f8a9d6191..1f8208132 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/View.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/View.java @@ -80,24 +80,23 @@ public class View { public static final Color DEFAULT_BACKGROUND_COLOR = new Color(217, 231, 250); public static Color swfBackgroundColor = DEFAULT_BACKGROUND_COLOR; - private static final BufferedImage transparentTexture; public static final TexturePaint transparentPaint; - - private static final Color transparentColor1 = new Color(0x99,0x99,0x99); - private static final Color transparentColor2 = new Color(0x66,0x66,0x66); - - static{ + + private static final Color transparentColor1 = new Color(0x99, 0x99, 0x99); + private static final Color transparentColor2 = new Color(0x66, 0x66, 0x66); + + static { transparentTexture = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); - Graphics g=transparentTexture.getGraphics(); + Graphics g = transparentTexture.getGraphics(); g.setColor(transparentColor1); g.fillRect(0, 0, 16, 16); g.setColor(transparentColor2); g.fillRect(0, 0, 8, 8); g.fillRect(8, 8, 8, 8); - transparentPaint = new TexturePaint(View.transparentTexture, new Rectangle(0,0,transparentTexture.getWidth(),transparentTexture.getHeight())); + transparentPaint = new TexturePaint(View.transparentTexture, new Rectangle(0, 0, transparentTexture.getWidth(), transparentTexture.getHeight())); } - + /** * Sets windows Look and Feel */ @@ -448,7 +447,7 @@ public class View { TreePath tp = new TreePath(path.toArray(new Object[path.size()])); tree.expandPath(tp); } - + public static void expandTreeNodesRecursive(JTree tree, TreePath parent, boolean expand) { TreeModel model = tree.getModel(); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/WrapLayout.java b/trunk/src/com/jpexs/decompiler/flash/gui/WrapLayout.java index 39d8b2d39..2a3c7f42a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/WrapLayout.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/WrapLayout.java @@ -20,7 +20,11 @@ package com.jpexs.decompiler.flash.gui; * * @author JPEXS */ -import java.awt.*; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index dd47e59cd..1c3194ad4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -21,7 +21,6 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.ButtonTag; @@ -34,13 +33,11 @@ import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; import com.jpexs.decompiler.flash.types.BUTTONRECORD; 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.Reserved; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.Cache; -import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -58,7 +55,7 @@ import java.util.logging.Logger; * * @author JPEXS */ -public class DefineButton2Tag extends CharacterTag implements Container, BoundedTag, ButtonTag { +public class DefineButton2Tag extends ButtonTag implements Container { /** * ID for this character @@ -244,19 +241,6 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded return trackAsMenu; } - @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - Timeline tim = getTimeline(); - //TODO: handle exact position - frame = 0; - if (mouseButton > 0 && tim.frames.size() > 1) { - frame = 1; - } else if (mousePos != null && tim.frames.size() > 2) { - frame = 2; - } - SWF.frameToImage(tim, frame, mousePos, mouseButton, image, transformation, colorTransform); - } - @Override public Point getImagePos(int frame) { RECT r = getRect(); @@ -276,30 +260,13 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded timeline = new Timeline(swf, new ArrayList(), buttonId, getRect()); int maxDepth = 0; - Frame frameUp = null; - Frame frameDown = null; - Frame frameOver = null; + Frame frameUp = new Frame(timeline); + Frame frameDown = new Frame(timeline); + Frame frameOver = new Frame(timeline); + Frame frameHit = new Frame(timeline); for (BUTTONRECORD r : this.characters) { - Frame frame = new Frame(timeline); - if (r.buttonStateUp) { - if (frameUp == null) { - frameUp = frame; - } - frame = frameUp; - - } else if (r.buttonStateDown) { - if (frameDown == null) { - frameDown = frame; - } - frame = frameDown; - } else if (r.buttonStateOver) { - if (frameOver == null) { - frameOver = frame; - } - frame = frameOver; - } - DepthState layer = new DepthState(swf,frame); + DepthState layer = new DepthState(swf, null); layer.colorTransForm = r.colorTransform; layer.blendMode = r.blendMode; layer.filters = r.filterList; @@ -308,18 +275,34 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded if (r.placeDepth > maxDepth) { maxDepth = r.placeDepth; } - frame.layers.put(r.placeDepth, layer); + + if (r.buttonStateUp) { + frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false)); + } + if (r.buttonStateDown) { + frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false)); + } + if (r.buttonStateOver) { + frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false)); + } + if (r.buttonStateHitTest) { + frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false)); + } } - if (frameUp != null) { - timeline.frames.add(frameUp); + timeline.frames.add(frameUp); + if (frameOver.layers.isEmpty()) { + frameOver = frameUp; } - if (frameDown != null) { - timeline.frames.add(frameDown); + timeline.frames.add(frameOver); + if (frameDown.layers.isEmpty()) { + frameDown = frameOver; } - if (frameOver != null) { - timeline.frames.add(frameOver); + timeline.frames.add(frameDown); + if (frameHit.layers.isEmpty()) { + frameHit = frameUp; } + timeline.frames.add(frameHit); return timeline; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index f880792fd..fa7302bc5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -24,7 +24,6 @@ import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; @@ -45,7 +44,6 @@ import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Helper; import com.jpexs.helpers.MemoryInputStream; -import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -62,7 +60,7 @@ import java.util.logging.Logger; * * @author JPEXS */ -public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedTag, ButtonTag { +public class DefineButtonTag extends ButtonTag implements ASMSource { /** * ID for this character @@ -266,19 +264,6 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT return false; } - @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - Timeline tim = getTimeline(); - //TODO: handle exact position - frame = 0; - if (mouseButton > 0 && tim.frames.size() > 1) { - frame = 1; - } else if (mousePos != null && tim.frames.size() > 2) { - frame = 2; - } - SWF.frameToImage(tim, frame, mousePos,mouseButton, image, transformation, colorTransform); - } - @Override public Point getImagePos(int frame) { RECT r = getRect(); @@ -325,32 +310,13 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT } } int maxDepth = 0; - Frame frameUp = null; - Frame frameDown = null; - Frame frameOver = null; + Frame frameUp = new Frame(timeline); + Frame frameDown = new Frame(timeline); + Frame frameOver = new Frame(timeline); + Frame frameHit = new Frame(timeline); for (BUTTONRECORD r : this.characters) { - - Frame frame = new Frame(timeline); - if (r.buttonStateUp) { - if(frameUp==null){ - frameUp = frame; - } - frame = frameUp; - - }else if (r.buttonStateDown) { - if(frameDown==null){ - frameDown = frame; - } - frame = frameDown; - }else if (r.buttonStateOver) { - if(frameOver==null){ - frameOver = frame; - } - frame = frameOver; - } - - - DepthState layer = new DepthState(swf,frame); + + DepthState layer = new DepthState(swf, null); layer.colorTransForm = clrTrans; layer.blendMode = r.blendMode; layer.filters = r.filterList; @@ -359,15 +325,35 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT if (r.placeDepth > maxDepth) { maxDepth = r.placeDepth; } - - frame.layers.put(r.placeDepth, layer); + + if (r.buttonStateUp) { + frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false)); + } + if (r.buttonStateDown) { + frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false)); + } + if (r.buttonStateOver) { + frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false)); + } + if (r.buttonStateHitTest) { + frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false)); + } + } - if(frameUp!=null){ - timeline.frames.add(frameUp); + timeline.frames.add(frameUp); + if (frameOver.layers.isEmpty()) { + frameOver = frameUp; } - if(frameDown!=null){ - timeline.frames.add(frameDown); + timeline.frames.add(frameOver); + if (frameDown.layers.isEmpty()) { + frameDown = frameOver; } + timeline.frames.add(frameDown); + if (frameHit.layers.isEmpty()) { + frameHit = frameUp; + } + timeline.frames.add(frameHit); + return timeline; } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java index 20365e565..0ffc0abca 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java @@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.tags.dynamictext.Word; import com.jpexs.decompiler.flash.tags.text.ParseException; import com.jpexs.decompiler.flash.tags.text.ParsedSymbol; import com.jpexs.decompiler.flash.tags.text.TextLexer; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.GLYPHENTRY; @@ -758,7 +759,7 @@ public class DefineEditTextTag extends TextTag { } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { if (border) { // border is always black, fill color is always white? RGB borderColor = new RGBA(Color.black); diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java index 008decfa2..f818a4f51 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; @@ -43,6 +44,7 @@ import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -314,7 +316,7 @@ public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, Mo } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { SHAPEWITHSTYLE shape = getShapeAtRatio(ratio); // shapeNum: 4 // todo: Currently the generated image is not cached, because the cache @@ -334,4 +336,9 @@ public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, Mo public int getNumFrames() { return 65536; } + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + return transformation.toTransform().createTransformedShape(getShapeAtRatio(ratio).getOutline()); + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java index 6af48e576..4a5893cb1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; @@ -42,6 +43,7 @@ import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -297,7 +299,7 @@ public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, Mor } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { SHAPEWITHSTYLE shape = getShapeAtRatio(ratio); // shapeNum: 3 // todo: Currently the generated image is not cached, because the cache @@ -317,4 +319,10 @@ public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, Mor public int getNumFrames() { return 65536; } + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + return transformation.toTransform().createTransformedShape(getShapeAtRatio(ratio).getOutline()); + } + } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java index 7ee9ac1a9..291e15006 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java @@ -18,23 +18,19 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.exporters.BitmapExporter; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; -public class DefineShape2Tag extends CharacterTag implements ShapeTag { +public class DefineShape2Tag extends ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -69,11 +65,6 @@ public class DefineShape2Tag extends CharacterTag implements ShapeTag { return exporter.getSVG(); } - @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); - } - @Override public int getCharacterId() { return shapeId; diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java index f18c0544f..f680e25cf 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java @@ -18,23 +18,19 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.exporters.BitmapExporter; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; -public class DefineShape3Tag extends CharacterTag implements ShapeTag { +public class DefineShape3Tag extends ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -74,11 +70,10 @@ public class DefineShape3Tag extends CharacterTag implements ShapeTag { return exporter.getSVG(); } - @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); - } - + /* @Override + public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); + }*/ @Override public int getCharacterId() { return shapeId; diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java index 75380bf2a..859053a18 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java @@ -18,11 +18,8 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.exporters.BitmapExporter; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; @@ -30,12 +27,11 @@ import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.Reserved; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; -public class DefineShape4Tag extends CharacterTag implements ShapeTag { +public class DefineShape4Tag extends ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -77,11 +73,6 @@ public class DefineShape4Tag extends CharacterTag implements ShapeTag { return exporter.getSVG(); } - @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); - } - @Override public int getCharacterId() { return shapeId; diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java index da67c8836..c502e0326 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java @@ -19,24 +19,20 @@ 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.exporters.BitmapExporter; -import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Set; -public class DefineShapeTag extends CharacterTag implements ShapeTag { +public class DefineShapeTag extends ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -102,11 +98,10 @@ public class DefineShapeTag extends CharacterTag implements ShapeTag { return exporter.getSVG(); } - @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); - } - + /* @Override + public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); + }*/ @Override public Point getImagePos(int frame) { return new Point(shapeBounds.Xmin / SWF.unitDivisor, shapeBounds.Ymin / SWF.unitDivisor); diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 0376ee343..1a97cbaaa 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -29,6 +29,7 @@ import com.jpexs.decompiler.flash.tags.base.Container; import com.jpexs.decompiler.flash.tags.base.ContainerItem; import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BasicType; @@ -38,6 +39,7 @@ import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.Cache; import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; import java.awt.geom.AffineTransform; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -266,8 +268,8 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - SWF.frameToImage(getTimeline(), frame, mousePos, mouseButton, image, transformation, colorTransform); + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + SWF.frameToImage(getTimeline(), frame, stateUnderCursor, mouseButton, image, transformation, colorTransform); } @Override @@ -279,4 +281,9 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT public int getNumFrames() { return frameCount; } + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + return getTimeline().getOutline(frame, ratio, stateUnderCursor, mouseButton, transformation); + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java index 565d69c68..86e4a2808 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.text.ParseException; import com.jpexs.decompiler.flash.tags.text.ParsedSymbol; import com.jpexs.decompiler.flash.tags.text.TextLexer; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.GLYPHENTRY; @@ -487,7 +488,7 @@ public class DefineText2Tag extends TextTag { } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { staticTextToImage(swf, textRecords, 2, image, getTextMatrix(), transformation, colorTransform); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java index abb1f4f4b..45c70751b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java @@ -28,6 +28,7 @@ import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.text.ParseException; import com.jpexs.decompiler.flash.tags.text.ParsedSymbol; import com.jpexs.decompiler.flash.tags.text.TextLexer; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.GLYPHENTRY; @@ -503,7 +504,7 @@ public class DefineTextTag extends TextTag { } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { staticTextToImage(swf, textRecords, 1, image, getTextMatrix(), transformation, colorTransform); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java index ed3b57e52..2d1a1659c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java @@ -16,17 +16,43 @@ */ package com.jpexs.decompiler.flash.tags.base; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.exporters.Matrix; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BUTTONRECORD; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; import java.util.List; /** * * @author JPEXS */ -public interface ButtonTag extends DrawableTag, Timelined { +public abstract class ButtonTag extends CharacterTag implements BoundedTag, DrawableTag, Timelined { - public List getRecords(); + public static int FRAME_UP = 0; + public static int FRAME_OVER = 1; + public static int FRAME_DOWN = 2; + public static int FRAME_HITTEST = 3; + + public ButtonTag(SWF swf, int id, String name, byte[] data, long pos) { + super(swf, id, name, data, pos); + } + + public abstract List getRecords(); + + public abstract boolean trackAsMenu(); + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + return getTimeline().getOutline(frame, ratio, stateUnderCursor, mouseButton, transformation); + } + + @Override + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + SWF.frameToImage(getTimeline(), frame, stateUnderCursor, mouseButton, image, transformation, colorTransform); + } - public boolean trackAsMenu(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java index 173496ca1..1e1156f70 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java @@ -18,8 +18,10 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; /** * @@ -27,9 +29,11 @@ import com.jpexs.helpers.SerializableImage; */ public interface DrawableTag { - public void toImage(int frame, int ratio, java.awt.Point mousePos, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform); + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform); public Point getImagePos(int frame); public int getNumFrames(); + + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index 77143e6d9..b26b4be80 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -24,17 +24,24 @@ import com.jpexs.decompiler.flash.helpers.FontHelper; import com.jpexs.decompiler.flash.tags.DefineText2Tag; import com.jpexs.decompiler.flash.tags.DefineTextTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.GLYPHENTRY; +import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPE; import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.helpers.SerializableImage; +import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.GlyphMetrics; import java.awt.font.GlyphVector; +import java.awt.geom.Area; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -44,7 +51,7 @@ import java.util.Map; * * @author JPEXS */ -public abstract class FontTag extends CharacterTag implements AloneTag, DrawableTag { +public abstract class FontTag extends CharacterTag implements AloneTag, BoundedTag, DrawableTag { public FontTag(SWF swf, int id, String name, byte[] data, long pos) { super(swf, id, name, data, pos); @@ -250,8 +257,10 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable } @Override - public void toImage(int frame, int ratio, java.awt.Point mousePos,int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - throw new Error("this overload of toImage call is not supported on FontTag"); + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + Graphics2D g = (Graphics2D) image.getGraphics(); + g.setComposite(AlphaComposite.SrcOver); + g.drawImage(toImage(0, 0, new Matrix(), colorTransform).getBufferedImage(), transformation.toTransform(), null); } @Override @@ -263,4 +272,16 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable public int getNumFrames() { return 1; } + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + RECT r = getRect(); + return new Area(new Rectangle(r.Xmin, r.Ymin, r.getWidth(), r.getHeight())); + } + + @Override + public RECT getRect() { + return new RECT(0, (int) (500 * SWF.unitDivisor), 0, (int) (500 * SWF.unitDivisor)); + } + } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java index c3a939b7d..8670f5b6d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java @@ -16,17 +16,37 @@ */ package com.jpexs.decompiler.flash.tags.base; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.exporters.BitmapExporter; +import com.jpexs.decompiler.flash.exporters.Matrix; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; +import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; /** * * @author JPEXS */ -public interface ShapeTag extends BoundedTag, DrawableTag { +public abstract class ShapeTag extends CharacterTag implements BoundedTag, DrawableTag { - public SHAPEWITHSTYLE getShapes(); + public ShapeTag(SWF swf, int id, String name, byte[] data, long pos) { + super(swf, id, name, data, pos); + } - public String toSVG(); + public abstract SHAPEWITHSTYLE getShapes(); - public int getShapeNum(); + public abstract String toSVG(); + + public abstract int getShapeNum(); + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + return transformation.toTransform().createTransformedShape(getShapes().getOutline()); + } + + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation, colorTransform); + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java index 9e434302e..ae9cf91c7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.exporters.BitmapExporter; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.text.ParseException; +import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.FILLSTYLE; import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; @@ -42,6 +43,8 @@ import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; import java.awt.font.LineMetrics; import java.util.ArrayList; import java.util.HashMap; @@ -297,4 +300,10 @@ public abstract class TextTag extends CharacterTag implements BoundedTag, Drawab } } } + + @Override + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + RECT r = getBounds(); + return new Rectangle(r.Xmin, r.Ymin, r.getWidth(), r.getHeight()); //TODO: match character shapes + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java b/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java index 9dc78f661..d11aed95a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java @@ -51,13 +51,15 @@ public class DepthState { public int clipDepth = -1; public int time = 0; private final SWF swf; - private final Frame frame; - public DepthState(SWF swf,Frame frame) { + public Frame frame; + + public DepthState(SWF swf, Frame frame) { this.swf = swf; this.frame = frame; } - public DepthState(DepthState obj) { + public DepthState(DepthState obj, Frame frame, boolean addTime) { + this.frame = frame; swf = obj.swf; frame = obj.frame; characterId = obj.characterId; @@ -72,14 +74,17 @@ public class DepthState { clipActions = obj.clipActions; ratio = obj.ratio; clipDepth = obj.clipDepth; - time = obj.time + 1; + time = obj.time; + if (addTime) { + time++; + } } - - public void drawTo(SerializableImage img, Point mousePos, int mouseButton){ - CharacterTag c=swf.characters.get(characterId); - if(c instanceof DrawableTag){ - DrawableTag d = (DrawableTag)c; - d.toImage(time, ratio,mousePos, mouseButton,img, new Matrix(matrix), colorTransForm); + + public void drawTo(SerializableImage img, Point mousePos, int mouseButton) { + CharacterTag c = swf.characters.get(characterId); + if (c instanceof DrawableTag) { + DrawableTag d = (DrawableTag) c; + d.toImage(time, ratio, null, mouseButton, img, new Matrix(matrix), colorTransForm); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java index 5994ba5a5..495c54472 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java @@ -16,11 +16,21 @@ */ package com.jpexs.decompiler.flash.timeline; +import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.base.ButtonTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.RGBA; -import java.util.HashMap; -import java.util.Map; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import java.awt.Point; +import java.awt.Shape; +import java.awt.geom.Area; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; +import java.util.TreeMap; /** * @@ -28,21 +38,95 @@ import java.util.Map; */ public class Frame { - public Map layers = new HashMap<>(); + public TreeMap layers = new TreeMap<>(); public DoActionTag action; public RGB backgroundColor = new RGBA(0, 0, 0, 0); public Timeline timeline; - + public Frame(Timeline timeline) { this.timeline = timeline; } public Frame(Frame obj) { - layers = new HashMap<>(); + layers = new TreeMap<>(); + backgroundColor = obj.backgroundColor; timeline = obj.timeline; for (int depth : obj.layers.keySet()) { - layers.put(depth, new DepthState(obj.layers.get(depth))); + layers.put(depth, new DepthState(obj.layers.get(depth), this, true)); } } + private class Clip { + + public Shape shape; + public int depth; + + public Clip(Shape shape, int depth) { + this.shape = shape; + this.depth = depth; + } + + } + + public List getObjectsUnderCursor(Point mousePos, int mouseButton, Matrix transformation) { + List ret = new ArrayList<>(); + List keys = new ArrayList<>(layers.keySet()); + DepthState maxds = null; + Stack clips = new Stack<>(); + for (int d : keys) { //int i=keys.size()-1;i>=0;i--){ + //int d = keys.get(i); + DepthState ds = layers.get(d); + Clip currentClip = null; + for (int j = clips.size() - 1; j >= 0; j--) { + Clip cl = clips.get(j); + if (cl.depth >= d) { + clips.remove(j); + } + } + if (!clips.isEmpty()) { + currentClip = clips.peek(); + } + CharacterTag c = timeline.swf.characters.get(ds.characterId); + if (c instanceof DrawableTag) { + Matrix m = new Matrix(ds.matrix).concatenate(transformation); + int frame = ds.time % ((DrawableTag) c).getNumFrames(); + if (c instanceof ButtonTag) { + frame = ButtonTag.FRAME_HITTEST; + } + Shape outline = SHAPERECORD.twipToPixelShape(((DrawableTag) c).getOutline(frame, ds.ratio, null, mouseButton, m)); + + Area checkArea = new Area(outline); + if (currentClip != null) { + Area a = new Area(checkArea.getBounds()); + a.subtract(new Area(currentClip.shape)); + checkArea.subtract(a); + } + if (ds.clipDepth > -1) { + Clip clip = new Clip(checkArea, ds.clipDepth); + clips.push(clip); + } else if (checkArea.contains(mousePos)) { + maxds = ds; + } + } + } + if (maxds == null) { + return ret; + } + ret.add(maxds); + + CharacterTag c = timeline.swf.characters.get(maxds.characterId); + if (c instanceof Timelined) { + Timelined tc = ((Timelined) c); + + int frame = maxds.time % ((DrawableTag) c).getNumFrames();; + if (tc instanceof ButtonTag) { + frame = ButtonTag.FRAME_HITTEST; + } + + ret.addAll(tc.getTimeline().frames.get(frame).getObjectsUnderCursor(mousePos, mouseButton, new Matrix(maxds.matrix).preConcatenate(transformation))); + } + + return ret; + } + } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 86b6ad466..fe925d3bb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -22,6 +22,9 @@ import com.jpexs.decompiler.flash.tags.DoActionTag; import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.RemoveTag; import com.jpexs.decompiler.flash.types.CLIPACTIONS; @@ -30,9 +33,12 @@ import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.filters.FILTER; import com.jpexs.helpers.SerializableImage; -import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Area; import java.util.ArrayList; import java.util.List; +import java.util.Stack; /** * @@ -44,7 +50,7 @@ public class Timeline { public int id; public SWF swf; public RECT displayRect; - + public int frameRate; public int getMaxDepth() { int max_depth = 0; @@ -70,7 +76,8 @@ public class Timeline { this.id = id; this.swf = swf; this.displayRect = displayRect; - Frame frame = new Frame(this); + this.frameRate = swf.frameRate; + Frame frame = new Frame(this); for (Tag t : tags) { if (t instanceof SetBackgroundColorTag) { frame.backgroundColor = ((SetBackgroundColorTag) t).backgroundColor; @@ -79,7 +86,7 @@ public class Timeline { PlaceObjectTypeTag po = (PlaceObjectTypeTag) t; int depth = po.getDepth(); if (!frame.layers.containsKey(depth)) { - frame.layers.put(depth, new DepthState(swf,frame)); + frame.layers.put(depth, new DepthState(swf, frame)); } DepthState fl = frame.layers.get(depth); int characterId = po.getCharacterId(); @@ -151,7 +158,72 @@ public class Timeline { } } - public void toImage(int frame, int ratio, Point mousePos,int mouseButton,SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - SWF.frameToImage(this, frame, mousePos,mouseButton,image, transformation, colorTransform); + public void toImage(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + SWF.frameToImage(this, frame, stateUnderCursor, mouseButton, image, transformation, colorTransform); + } + + private class Clip { + + public Shape shape; + public int depth; + + public Clip(Shape shape, int depth) { + this.shape = shape; + this.depth = depth; + } + + } + + public Shape getOutline(int frame, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + Frame fr = this.frames.get(frame); + Area area = new Area(); + Stack clips = new Stack<>(); + for (int d = this.getMaxDepth(); d >= 0; d--) { + Clip currentClip = null; + for (int i = clips.size() - 1; i >= 0; i--) { + Clip cl = clips.get(i); + if (cl.depth <= d) { + clips.remove(i); + } + } + if (!clips.isEmpty()) { + currentClip = clips.peek(); + } + DepthState ds = fr.layers.get(d); + if (ds == null) { + continue; + } + if (!ds.isVisible) { + continue; + } + CharacterTag c = swf.characters.get(ds.characterId); + if ((c instanceof DrawableTag) && (c instanceof BoundedTag)) { + Matrix m = new Matrix(ds.matrix); + m = m.preConcatenate(transformation); + + Matrix drawMatrix = new Matrix(); + //drawMatrix.translate(rect.xMin, rect.yMin); + //System.out.println("m="+m); + //System.out.println("-------"); + Shape cshape = ((DrawableTag) c).getOutline(ds.time, ds.ratio, stateUnderCursor, mouseButton, m); + //cshape = SHAPERECORD.twipToPixelShape(cshape); + + //AffineTransform trans = drawMatrix.toTransform(); + //cshape = trans.createTransformedShape(cshape); + Area addArea = new Area(cshape); + if (currentClip != null) { + Area a = new Area(new Rectangle(displayRect.Xmin, displayRect.Ymin, displayRect.getWidth(), displayRect.getHeight())); + a.subtract(new Area(currentClip.shape)); + addArea.subtract(a); + } + if (ds.clipDepth > -1) { + Clip clip = new Clip(addArea, ds.clipDepth); + clips.push(clip); + } else { + area.add(addArea); + } + } + } + return area; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java index be3e4e3d4..761095e99 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java @@ -16,11 +16,13 @@ */ package com.jpexs.decompiler.flash.timeline; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; + /** * * @author JPEXS */ -public interface Timelined { +public interface Timelined extends BoundedTag { public Timeline getTimeline(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/types/SHAPE.java b/trunk/src/com/jpexs/decompiler/flash/types/SHAPE.java index d6aabe50a..5a5686d7a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/SHAPE.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/SHAPE.java @@ -16,10 +16,16 @@ */ package com.jpexs.decompiler.flash.types; +import com.jpexs.decompiler.flash.exporters.Matrix; +import com.jpexs.decompiler.flash.exporters.ShapeExporterBase; import com.jpexs.decompiler.flash.tags.base.NeedsCharacters; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.GeneralPath; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -48,4 +54,108 @@ public class SHAPE implements NeedsCharacters, Serializable { public RECT getBounds() { return SHAPERECORD.getBounds(shapeRecords); } + + public Shape getOutline() { + final List paths = new ArrayList<>(); + ShapeExporterBase se = new ShapeExporterBase(this, new ColorTransform()) { + private GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD); + + private double unitDivisor; + + @Override + public void export() { + unitDivisor = 1; + super.export(); + } + + @Override + public void beginShape() { + + } + + @Override + public void endShape(double xMin, double yMin, double xMax, double yMax) { + + } + + @Override + public void beginFills() { + + } + + @Override + public void endFills() { + + } + + @Override + public void beginLines() { + + } + + @Override + public void endLines() { + finalizePath(); + } + + @Override + public void beginFill(RGB color) { + finalizePath(); + } + + @Override + public void beginGradientFill(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) { + finalizePath(); + } + + @Override + public void beginBitmapFill(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) { + finalizePath(); + } + + @Override + public void endFill() { + finalizePath(); + } + + @Override + public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) { + finalizePath(); + } + + @Override + public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) { + + } + + @Override + public void moveTo(double x, double y) { + path.moveTo(x / unitDivisor, y / unitDivisor); + } + + @Override + public void lineTo(double x, double y) { + path.lineTo(x / unitDivisor, y / unitDivisor); + } + + @Override + public void curveTo(double controlX, double controlY, double anchorX, double anchorY) { + path.quadTo(controlX / unitDivisor, controlY / unitDivisor, + anchorX / unitDivisor, anchorY / unitDivisor); + } + + protected void finalizePath() { + paths.add(path); + path = new GeneralPath(GeneralPath.WIND_EVEN_ODD); //For correct intersections display + + } + }; + se.export(); + Area area = new Area(); + for (GeneralPath path : paths) { + area.add(new Area(path)); + } + + return area; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java index dcdf90406..fe444e07a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java @@ -29,8 +29,10 @@ import com.jpexs.helpers.SerializableImage; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; +import java.awt.Rectangle; import java.awt.Shape; import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; @@ -411,4 +413,20 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali ret.shapeRecords = recs; return ret; } + + public static Shape moveShapeToStart(Shape s) { + Rectangle bds = s.getBounds(); + s = AffineTransform.getTranslateInstance(-bds.x, -bds.y).createTransformedShape(s); + return s; + } + + public static Shape twipToPixelShape(Shape s) { + Rectangle bds = s.getBounds(); + int dx = -bds.x - bds.width / 2; + int dy = -bds.y - bds.height / 2; + s = AffineTransform.getTranslateInstance(dx, dy).createTransformedShape(s); + s = AffineTransform.getScaleInstance(1 / SWF.unitDivisor, 1 / SWF.unitDivisor).createTransformedShape(s); + s = AffineTransform.getTranslateInstance(-dx / SWF.unitDivisor, -dy / SWF.unitDivisor).createTransformedShape(s); + return s; + } } diff --git a/trunk/src/com/jpexs/helpers/Helper.java b/trunk/src/com/jpexs/helpers/Helper.java index 689a3b614..ac1571bdf 100644 --- a/trunk/src/com/jpexs/helpers/Helper.java +++ b/trunk/src/com/jpexs/helpers/Helper.java @@ -658,12 +658,11 @@ public class Helper { result.append(";").append(line).append(nl); } }*/ - int length = data.length; if (length > limit) { length = limit; } - + int rowCount = length / bytesPerRow; if (length % bytesPerRow > 0) { rowCount++; @@ -720,7 +719,7 @@ public class Helper { if (data.length > limit) { writer.appendNoHilight(AppStrings.translate("binaryData.truncateWarning").replace("%count%", Integer.toString(data.length - limit))); } - + return writer; }