From 1483379b859f151b0400ced3b291e4a811286676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 9 Jun 2013 19:23:31 +0200 Subject: [PATCH] Internal flash viewer - displaying morphshapes --- trunk/src/com/jpexs/decompiler/flash/SWF.java | 6 +- .../decompiler/flash/gui/ImagePanel.java | 51 ++++++++++ .../jpexs/decompiler/flash/gui/MainFrame.java | 4 +- .../flash/tags/DefineButton2Tag.java | 7 +- .../flash/tags/DefineButtonTag.java | 7 +- .../flash/tags/DefineMorphShape2Tag.java | 98 ++++++++++++++++++- .../flash/tags/DefineMorphShapeTag.java | 98 ++++++++++++++++++- .../flash/tags/DefineShape2Tag.java | 7 +- .../flash/tags/DefineShape3Tag.java | 7 +- .../flash/tags/DefineShape4Tag.java | 7 +- .../decompiler/flash/tags/DefineShapeTag.java | 7 +- .../flash/tags/DefineSpriteTag.java | 7 +- .../decompiler/flash/tags/DefineText2Tag.java | 7 +- .../decompiler/flash/tags/DefineTextTag.java | 7 +- .../flash/tags/base/DrawableTag.java | 4 +- .../jpexs/decompiler/flash/types/MATRIX.java | 16 +++ .../flash/types/MORPHFILLSTYLE.java | 32 ++++++ .../flash/types/MORPHFILLSTYLEARRAY.java | 9 ++ .../decompiler/flash/types/MORPHGRADIENT.java | 36 +++++++ .../flash/types/MORPHLINESTYLE.java | 7 ++ .../flash/types/MORPHLINESTYLE2.java | 19 ++++ .../flash/types/MORPHLINESTYLEARRAY.java | 17 ++++ .../flash/types/shaperecords/SHAPERECORD.java | 18 ++-- .../types/shaperecords/StyleChangeRecord.java | 15 ++- 24 files changed, 469 insertions(+), 24 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 38fd1a68b..ee6ebe28f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -1425,7 +1425,7 @@ public class SWF { g.setTransform(trans); if (character instanceof DrawableTag) { DrawableTag drawable = (DrawableTag) character; - BufferedImage img = drawable.toImage(1/*layer.duration*/, allTags, displayRect, characters); + BufferedImage img = drawable.toImage(layer.ratio < 0 ? 0 : layer.ratio/*layer.duration*/, allTags, displayRect, characters); if (layer.filters != null) { @@ -1440,7 +1440,7 @@ public class SWF { if (layer.colorTransFormAlpha != null) { img = layer.colorTransFormAlpha.apply(img); } - Point imgPos = drawable.getImagePos(characters); + Point imgPos = drawable.getImagePos(layer.ratio < 0 ? 0 : layer.ratio, characters); if (imgPos.x < 0) { imgPos.x = 0; } @@ -1562,7 +1562,7 @@ public class SWF { HashMap layers = new HashMap<>(); int maxDepth = 0; - int f = 1; + int f = 0; Color backgroundColor = new Color(0, 0, 0, 0); for (Tag t : controlTags) { if (t instanceof SetBackgroundColorTag) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index b65f896b6..d1528605d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -16,8 +16,14 @@ */ package com.jpexs.decompiler.flash.gui; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; import java.awt.BorderLayout; import java.awt.Image; +import java.util.HashMap; +import java.util.Timer; +import java.util.TimerTask; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; @@ -25,6 +31,10 @@ import javax.swing.JPanel; public class ImagePanel extends JPanel { public JLabel label = new JLabel(); + public DrawableTag drawable; + private Timer timer; + private int percent; + private int frame; public ImagePanel() { super(new BorderLayout()); @@ -33,11 +43,52 @@ public class ImagePanel extends JPanel { } public void setImage(byte data[]) { + if (timer != null) { + timer.cancel(); + } ImageIcon icon = new ImageIcon(data); label.setIcon(icon); } + public void setDrawable(final DrawableTag drawable, final SWF swf, final HashMap characters) { + this.drawable = drawable; + if (timer != null) { + timer.cancel(); + } + + if (drawable.getNumFrames() == 0) { + label.setIcon(null); + return; + } + if (drawable.getNumFrames() == 1) { + setImage(drawable.toImage(0, swf.tags, swf.displayRect, characters)); + return; + } + timer = new Timer(); + + percent = 0; + timer.schedule(new TimerTask() { + @Override + public void run() { + int nframe = percent * drawable.getNumFrames() / 100; + if (nframe != frame) { + ImageIcon icon = new ImageIcon(drawable.toImage(nframe, swf.tags, swf.displayRect, characters)); + label.setIcon(icon); + } + if (percent == 100) { + percent = 0; + } else { + percent++; + } + + } + }, 0, 20); + } + public void setImage(Image image) { + if (timer != null) { + timer.cancel(); + } ImageIcon icon = new ImageIcon(image); label.setIcon(icon); } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 990327a70..a0e367f3c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -1863,7 +1863,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi imagePanel.setImage(((ImageTag) tagObj).getImage(swf.tags)); } else if ((tagObj instanceof DrawableTag) && (!(tagObj instanceof TextTag)) && (miInternalViewer.isSelected())) { showCard(CARDDRAWPREVIEWPANEL); - previewImagePanel.setImage(((DrawableTag) tagObj).toImage(1, swf.tags, swf.displayRect, characters)); + previewImagePanel.setDrawable((DrawableTag) tagObj, swf, characters);//.setImage(((DrawableTag) tagObj).toImage(1, swf.tags, swf.displayRect, characters)); } else if (tagObj instanceof FrameNode && ((FrameNode) tagObj).isDisplayed() && (miInternalViewer.isSelected())) { showCard(CARDDRAWPREVIEWPANEL); FrameNode fn = (FrameNode) tagObj; @@ -1875,7 +1875,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi containerId = ((DefineSpriteTag) fn.getParent()).spriteId; rect = ((DefineSpriteTag) fn.getParent()).getRect(characters); } - previewImagePanel.setImage(SWF.frameToImage(containerId, ((FrameNode) tagObj).getFrame(), swf.tags, controlTags, rect, swf.frameCount)); + previewImagePanel.setImage(SWF.frameToImage(containerId, ((FrameNode) tagObj).getFrame() - 1, swf.tags, controlTags, rect, swf.frameCount)); } else if (((tagObj instanceof FrameNode) && ((FrameNode) tagObj).isDisplayed()) || ((tagObj instanceof CharacterTag) || (tagObj instanceof FontTag)) && (tagObj instanceof Tag)) { try { diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index f957d595d..cfae24b03 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -240,7 +240,12 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded } @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(0, 0); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index f892eaaaa..20773f256 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -254,7 +254,12 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT } @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(0, 0); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java index feffc00a2..2f91be29e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java @@ -20,16 +20,27 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; 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.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; +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 java.awt.Point; import java.awt.geom.GeneralPath; +import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -40,7 +51,7 @@ import java.util.Set; * * @author JPEXS */ -public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, MorphShapeTag { +public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, MorphShapeTag, DrawableTag { public int characterId; public RECT startBounds; @@ -176,4 +187,89 @@ public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, Mo public List getPaths(List tags) { return null; //FIXME } + + @Override + public BufferedImage toImage(int frame, List tags, RECT displayRect, HashMap characters) { + List finalRecords = new ArrayList<>(); + FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(frame); + LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), frame); + int endIndex = 0; + + for (int startIndex = 0; startIndex < startEdges.shapeRecords.size(); startIndex++, endIndex++) { + + if (startIndex == 0) { + StyleChangeRecord scr1 = (StyleChangeRecord) startEdges.shapeRecords.get(startIndex); + StyleChangeRecord scr2 = (StyleChangeRecord) startEdges.shapeRecords.get(endIndex); + StyleChangeRecord scr = (StyleChangeRecord) scr1.clone(); + if (scr1.stateMoveTo && scr2.stateMoveTo) { + scr.moveDeltaX = scr1.moveDeltaX + (scr2.moveDeltaX - scr1.moveDeltaX) * frame / 65535; + scr.moveDeltaY = scr1.moveDeltaY + (scr2.moveDeltaY - scr1.moveDeltaY) * frame / 65535; + finalRecords.add(scr); + continue; + } + } + SHAPERECORD edge1 = null; + do { + edge1 = startEdges.shapeRecords.get(startIndex); + if (edge1 instanceof StyleChangeRecord) { + finalRecords.add(edge1); + edge1 = null; + startIndex++; + } + } while (edge1 == null); + SHAPERECORD edge2 = endEdges.shapeRecords.get(endIndex); + if (edge1 instanceof EndShapeRecord) { + finalRecords.add(edge1); + break; + } + if (edge2 instanceof EndShapeRecord) { + break; + } + if ((edge1 instanceof StyleChangeRecord) && (edge2 instanceof StyleChangeRecord)) { + StyleChangeRecord scr1 = (StyleChangeRecord) edge1; + StyleChangeRecord scr2 = (StyleChangeRecord) edge2; + StyleChangeRecord scr = (StyleChangeRecord) scr1.clone(); + if (scr1.stateMoveTo && scr2.stateMoveTo) { + scr.moveDeltaX = scr1.moveDeltaX + (scr2.moveDeltaX - scr1.moveDeltaX) * frame / 65535; + scr.moveDeltaY = scr1.moveDeltaY + (scr2.moveDeltaY - scr1.moveDeltaY) * frame / 65535; + finalRecords.add(scr); + continue; + } + } + CurvedEdgeRecord cer1 = null; + if (edge1 instanceof CurvedEdgeRecord) { + cer1 = (CurvedEdgeRecord) edge1; + } else if (edge1 instanceof StraightEdgeRecord) { + cer1 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge1); + } + CurvedEdgeRecord cer2 = null; + if (edge2 instanceof CurvedEdgeRecord) { + cer2 = (CurvedEdgeRecord) edge2; + } else if (edge2 instanceof StraightEdgeRecord) { + cer2 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge2); + } + if ((cer2 == null) || (cer1 == null)) { + continue; + } + CurvedEdgeRecord cer = new CurvedEdgeRecord(); + cer.controlDeltaX = cer1.controlDeltaX + (cer2.controlDeltaX - cer1.controlDeltaX) * frame / 65535; + cer.controlDeltaY = cer1.controlDeltaY + (cer2.controlDeltaY - cer1.controlDeltaY) * frame / 65535; + cer.anchorDeltaX = cer1.anchorDeltaX + (cer2.anchorDeltaX - cer1.anchorDeltaX) * frame / 65535; + cer.anchorDeltaY = cer1.anchorDeltaY + (cer2.anchorDeltaY - cer1.anchorDeltaY) * frame / 65535; + finalRecords.add(cer); + } + return SHAPERECORD.shapeToImage(tags, 4, fillStyles, lineStyles, finalRecords); + } + + @Override + public Point getImagePos(int frame, HashMap characters) { + return new Point( + (startBounds.Xmin + (endBounds.Xmin - startBounds.Xmin) * frame / 65535) / 20, + (startBounds.Ymin + (endBounds.Ymin - startBounds.Ymin) * frame / 65535) / 20); + } + + @Override + public int getNumFrames() { + return 65536; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java index 94c287b8a..1e73c007a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java @@ -20,16 +20,27 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; 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.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; +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 java.awt.Point; import java.awt.geom.GeneralPath; +import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -40,7 +51,7 @@ import java.util.Set; * * @author JPEXS */ -public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, MorphShapeTag { +public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, MorphShapeTag, DrawableTag { public int characterId; public RECT startBounds; @@ -163,4 +174,89 @@ public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, Mor public List getPaths(List tags) { return null; //FIXME } + + @Override + public BufferedImage toImage(int frame, List tags, RECT displayRect, HashMap characters) { + List finalRecords = new ArrayList<>(); + FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(frame); + LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), frame); + int endIndex = 0; + + for (int startIndex = 0; startIndex < startEdges.shapeRecords.size(); startIndex++, endIndex++) { + + if (startIndex == 0) { + StyleChangeRecord scr1 = (StyleChangeRecord) startEdges.shapeRecords.get(startIndex); + StyleChangeRecord scr2 = (StyleChangeRecord) startEdges.shapeRecords.get(endIndex); + StyleChangeRecord scr = (StyleChangeRecord) scr1.clone(); + if (scr1.stateMoveTo && scr2.stateMoveTo) { + scr.moveDeltaX = scr1.moveDeltaX + (scr2.moveDeltaX - scr1.moveDeltaX) * frame / 65535; + scr.moveDeltaY = scr1.moveDeltaY + (scr2.moveDeltaY - scr1.moveDeltaY) * frame / 65535; + finalRecords.add(scr); + continue; + } + } + SHAPERECORD edge1 = null; + do { + edge1 = startEdges.shapeRecords.get(startIndex); + if (edge1 instanceof StyleChangeRecord) { + finalRecords.add(edge1); + edge1 = null; + startIndex++; + } + } while (edge1 == null); + SHAPERECORD edge2 = endEdges.shapeRecords.get(endIndex); + if (edge1 instanceof EndShapeRecord) { + finalRecords.add(edge1); + break; + } + if (edge2 instanceof EndShapeRecord) { + break; + } + if ((edge1 instanceof StyleChangeRecord) && (edge2 instanceof StyleChangeRecord)) { + StyleChangeRecord scr1 = (StyleChangeRecord) edge1; + StyleChangeRecord scr2 = (StyleChangeRecord) edge2; + StyleChangeRecord scr = (StyleChangeRecord) scr1.clone(); + if (scr1.stateMoveTo && scr2.stateMoveTo) { + scr.moveDeltaX = scr1.moveDeltaX + (scr2.moveDeltaX - scr1.moveDeltaX) * frame / 65535; + scr.moveDeltaY = scr1.moveDeltaY + (scr2.moveDeltaY - scr1.moveDeltaY) * frame / 65535; + finalRecords.add(scr); + continue; + } + } + CurvedEdgeRecord cer1 = null; + if (edge1 instanceof CurvedEdgeRecord) { + cer1 = (CurvedEdgeRecord) edge1; + } else if (edge1 instanceof StraightEdgeRecord) { + cer1 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge1); + } + CurvedEdgeRecord cer2 = null; + if (edge2 instanceof CurvedEdgeRecord) { + cer2 = (CurvedEdgeRecord) edge2; + } else if (edge2 instanceof StraightEdgeRecord) { + cer2 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge2); + } + if ((cer2 == null) || (cer1 == null)) { + continue; + } + CurvedEdgeRecord cer = new CurvedEdgeRecord(); + cer.controlDeltaX = cer1.controlDeltaX + (cer2.controlDeltaX - cer1.controlDeltaX) * frame / 65535; + cer.controlDeltaY = cer1.controlDeltaY + (cer2.controlDeltaY - cer1.controlDeltaY) * frame / 65535; + cer.anchorDeltaX = cer1.anchorDeltaX + (cer2.anchorDeltaX - cer1.anchorDeltaX) * frame / 65535; + cer.anchorDeltaY = cer1.anchorDeltaY + (cer2.anchorDeltaY - cer1.anchorDeltaY) * frame / 65535; + finalRecords.add(cer); + } + return SHAPERECORD.shapeToImage(tags, 1, fillStyles, lineStyles, finalRecords); + } + + @Override + public Point getImagePos(int frame, HashMap characters) { + return new Point( + (startBounds.Xmin + (endBounds.Xmin - startBounds.Xmin) * frame / 65535) / 20, + (startBounds.Ymin + (endBounds.Ymin - startBounds.Ymin) * frame / 65535) / 20); + } + + @Override + public int getNumFrames() { + return 65536; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java index 90f351732..43e2c2ce4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java @@ -39,7 +39,7 @@ public class DefineShape2Tag extends CharacterTag implements BoundedTag, ShapeTa public SHAPEWITHSTYLE shapes; @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(shapeBounds.Xmin / 20, shapeBounds.Ymin / 20); } @@ -90,4 +90,9 @@ public class DefineShape2Tag extends CharacterTag implements BoundedTag, ShapeTa public List getPaths(List tags) { return SHAPERECORD.shapeToPaths(tags, 2, shapes.shapeRecords); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java index 5bedd0b7a..8e6bacb8e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java @@ -39,7 +39,7 @@ public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTa public SHAPEWITHSTYLE shapes; @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(shapeBounds.Xmin / 20, shapeBounds.Ymin / 20); } @@ -90,4 +90,9 @@ public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTa public List getPaths(List tags) { return SHAPERECORD.shapeToPaths(tags, 3, shapes.shapeRecords); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java index 72c058479..70de483b0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java @@ -43,7 +43,7 @@ public class DefineShape4Tag extends CharacterTag implements BoundedTag, ShapeTa public SHAPEWITHSTYLE shapes; @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(shapeBounds.Xmin / 20, shapeBounds.Ymin / 20); } @@ -99,4 +99,9 @@ public class DefineShape4Tag extends CharacterTag implements BoundedTag, ShapeTa public List getPaths(List tags) { return SHAPERECORD.shapeToPaths(tags, 4, shapes.shapeRecords); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java index db730160c..44bec09bd 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java @@ -82,7 +82,7 @@ public class DefineShapeTag extends CharacterTag implements BoundedTag, ShapeTag } @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(shapeBounds.Xmin / 20, shapeBounds.Ymin / 20); } @@ -90,4 +90,9 @@ public class DefineShapeTag extends CharacterTag implements BoundedTag, ShapeTag public List getPaths(List tags) { return SHAPERECORD.shapeToPaths(tags, 1, shapes.shapeRecords); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index e74cfecbe..3714d3f2b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -242,8 +242,13 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT } @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { RECT displayRect = getRect(characters); return new Point(0, 0); //displayRect.Xmin,displayRect.Ymin); } + + @Override + public int getNumFrames() { + return frameCount; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java index 5b263ad95..390fe9917 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java @@ -483,7 +483,12 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag, } @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(0, 0); } + + @Override + public int getNumFrames() { + return 1; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java index 3117d2295..c0fbcc22a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java @@ -495,7 +495,12 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag, } @Override - public Point getImagePos(HashMap characters) { + public Point getImagePos(int frame, HashMap characters) { return new Point(0, 0); } + + @Override + public int getNumFrames() { + return 1; + } } 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 f54cc01db..5234b09ef 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java @@ -31,5 +31,7 @@ public interface DrawableTag { public BufferedImage toImage(int frame, List tags, RECT displayRect, HashMap characters); - public Point getImagePos(HashMap characters); + public Point getImagePos(int frame, HashMap characters); + + public int getNumFrames(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MATRIX.java b/trunk/src/com/jpexs/decompiler/flash/types/MATRIX.java index 47ca4c2bd..23c0a1d28 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MATRIX.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MATRIX.java @@ -96,6 +96,14 @@ public class MATRIX implements Serializable { return ret; } + public int getRotateSkew0() { + return hasRotate ? rotateSkew0 : 0; + } + + public int getRotateSkew1() { + return hasRotate ? rotateSkew1 : 0; + } + public float getRotateSkew0Float() { return (hasRotate ? toFloat(rotateSkew0) : 0); } @@ -112,6 +120,14 @@ public class MATRIX implements Serializable { return (hasScale ? toFloat(scaleY) : 1); } + public int getScaleX() { + return (hasScale ? (scaleX) : (1 << 16)); + } + + public int getScaleY() { + return (hasScale ? (scaleY) : (1 << 16)); + } + public MATRIX merge(MATRIX m) { MATRIX ret = new MATRIX(); ret.translateX = m.translateX + this.translateX; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLE.java b/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLE.java index 6d02ca92d..6c5c82e72 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLE.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLE.java @@ -55,6 +55,38 @@ public class MORPHFILLSTYLE implements NeedsCharacters { return ret; } + private MATRIX morphMatrix(MATRIX a, MATRIX b, int ratio) { + if (a == null) { + return null; + } + if (b == null) { + return null; + } + MATRIX ret = new MATRIX(); + ret.scaleX = a.getScaleX() + (b.getScaleX() - a.getScaleX()) * ratio / 65535; + ret.scaleY = a.getScaleY() + (b.getScaleY() - a.getScaleY()) * ratio / 65535; + ret.rotateSkew0 = a.getRotateSkew0() + (b.getRotateSkew0() - a.getRotateSkew0()) * ratio / 65535; + ret.rotateSkew1 = a.getRotateSkew1() + (b.getRotateSkew1() - a.getRotateSkew1()) * ratio / 65535; + ret.translateX = a.translateX + (b.translateX - a.translateX) * ratio / 65535; + ret.translateY = a.translateY + (b.translateY - a.translateY) * ratio / 65535; + ret.hasRotate = true; + ret.hasScale = true; + return ret; + } + + public FILLSTYLE getFillStyleAt(int ratio) { + FILLSTYLE ret = new FILLSTYLE(); + ret.bitmapId = bitmapId; + ret.bitmapMatrix = morphMatrix(startBitmapMatrix, endBitmapMatrix, ratio); + ret.colorA = MORPHGRADIENT.morphColor(startColor, endColor, ratio); + ret.fillStyleType = fillStyleType; + if (gradient != null) { + ret.gradient = gradient.getGradientAt(ratio); + } + ret.gradientMatrix = morphMatrix(startGradientMatrix, endGradientMatrix, ratio); + return ret; + } + public FILLSTYLE getStartFillStyle() { FILLSTYLE ret = new FILLSTYLE(); ret.bitmapId = bitmapId; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLEARRAY.java b/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLEARRAY.java index e12760d28..1a83cb9c8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLEARRAY.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MORPHFILLSTYLEARRAY.java @@ -37,6 +37,15 @@ public class MORPHFILLSTYLEARRAY implements NeedsCharacters { return ret; } + public FILLSTYLEARRAY getFillStylesAt(int ratio) { + FILLSTYLEARRAY ret = new FILLSTYLEARRAY(); + ret.fillStyles = new FILLSTYLE[fillStyles.length]; + for (int m = 0; m < fillStyles.length; m++) { + ret.fillStyles[m] = fillStyles[m].getFillStyleAt(ratio); + } + return ret; + } + public FILLSTYLEARRAY getStartFillStyles() { FILLSTYLEARRAY ret = new FILLSTYLEARRAY(); ret.fillStyles = new FILLSTYLE[fillStyles.length]; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MORPHGRADIENT.java b/trunk/src/com/jpexs/decompiler/flash/types/MORPHGRADIENT.java index d5a759e59..b01af9eb0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MORPHGRADIENT.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MORPHGRADIENT.java @@ -26,6 +26,42 @@ public class MORPHGRADIENT { public MORPHGRADRECORD gradientRecords[]; public int numGradientsExtra; + public static RGBA morphColor(RGBA c1, RGBA c2, int ratio) { + int r = (c1.red + (c2.red - c1.red) * ratio / 65535); + int g = (c1.green + (c2.green - c1.green) * ratio / 65535); + int b = (c1.blue + (c2.blue - c1.blue) * ratio / 65535); + int a = (c1.alpha + (c2.alpha - c1.alpha) * ratio / 65535); + if (r > 255) { + r = 255; + } + if (g > 255) { + g = 255; + } + if (b > 255) { + b = 255; + } + if (a > 255) { + a = 255; + } + return new RGBA(r, g, b, a); + } + + public GRADIENT getGradientAt(int ratio) { + GRADIENT ret = new GRADIENT(); + ret.gradientRecords = new GRADRECORD[gradientRecords.length]; + for (int m = 0; m < gradientRecords.length; m++) { + + + + + int gratio = (gradientRecords[m].startRatio + (gradientRecords[m].endRatio - gradientRecords[m].startRatio) * ratio / 65535); + ret.gradientRecords[m] = new GRADRECORD(); + ret.gradientRecords[m].colorA = morphColor(gradientRecords[m].startColor, gradientRecords[m].endColor, ratio); + ret.gradientRecords[m].ratio = gratio; + } + return ret; + } + public GRADIENT getStartGradient() { GRADIENT ret = new GRADIENT(); ret.gradientRecords = new GRADRECORD[gradientRecords.length]; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE.java b/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE.java index b9e1ebc13..f1fe61bf3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE.java @@ -34,6 +34,13 @@ public class MORPHLINESTYLE { return ret; } + public LINESTYLE getLineStyleAt(int ratio) { + LINESTYLE ret = new LINESTYLE(); + ret.colorA = MORPHGRADIENT.morphColor(startColor, endColor, ratio); + ret.width = startWidth + (endWidth - startWidth) * ratio / 65535; + return ret; + } + public LINESTYLE getEndLineStyle() { LINESTYLE ret = new LINESTYLE(); ret.colorA = endColor; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE2.java b/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE2.java index 1e102d635..e95a7ee78 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE2.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLE2.java @@ -43,6 +43,25 @@ public class MORPHLINESTYLE2 { public RGBA endColor; public MORPHFILLSTYLE fillType; + public LINESTYLE2 getLineStyle2At(int ratio) { + LINESTYLE2 ret = new LINESTYLE2(); + ret.width = startWidth + (endWidth - startWidth) * ratio / 65535; + ret.startCapStyle = startCapStyle; + ret.joinStyle = joinStyle; + ret.hasFillFlag = hasFillFlag; + ret.noHScaleFlag = noHScaleFlag; + ret.noVScaleFlag = noVScaleFlag; + ret.pixelHintingFlag = pixelHintingFlag; + ret.noClose = noClose; + ret.endCapStyle = endCapStyle; + ret.miterLimitFactor = miterLimitFactor; + ret.color = MORPHGRADIENT.morphColor(startColor, endColor, ratio); + if (hasFillFlag) { + ret.fillType = fillType.getFillStyleAt(ratio); + } + return ret; + } + public LINESTYLE2 getStartLineStyle2() { LINESTYLE2 ret = new LINESTYLE2(); ret.width = startWidth; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLEARRAY.java b/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLEARRAY.java index 5a5fa4624..6a6ee08fb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLEARRAY.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/MORPHLINESTYLEARRAY.java @@ -25,6 +25,23 @@ public class MORPHLINESTYLEARRAY { public MORPHLINESTYLE lineStyles[]; public MORPHLINESTYLE2 lineStyles2[]; + public LINESTYLEARRAY getLineStylesAt(int shapeNum, int ratio) { + LINESTYLEARRAY ret = new LINESTYLEARRAY(); + if (shapeNum == 1) { + ret.lineStyles = new LINESTYLE[lineStyles.length]; + for (int m = 0; m < lineStyles.length; m++) { + ret.lineStyles[m] = lineStyles[m].getLineStyleAt(ratio); + } + } + if (shapeNum == 2) { + ret.lineStyles2 = new LINESTYLE2[lineStyles2.length]; + for (int m = 0; m < lineStyles2.length; m++) { + ret.lineStyles2[m] = lineStyles2[m].getLineStyle2At(ratio); + } + } + return ret; + } + public LINESTYLEARRAY getStartLineStyles(int shapeNum) { LINESTYLEARRAY ret = new LINESTYLEARRAY(); if (shapeNum == 1) { 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 e67225634..c8db8dc41 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java @@ -621,12 +621,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters { if (r instanceof StyleChangeRecord) { StyleChangeRecord mv = (StyleChangeRecord) r; if (mv.stateMoveTo) { - StyleChangeRecord mv2 = null; - try { - mv2 = (StyleChangeRecord) mv.clone(); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(SHAPERECORD.class.getName()).log(Level.SEVERE, null, ex); - } + StyleChangeRecord mv2 = (StyleChangeRecord) mv.clone(); mv2.moveDeltaX = oldX; mv2.moveDeltaY = oldY; r = mv2; @@ -756,6 +751,8 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters { if (onepath == null) { onepath = new Path(); onepath.fillStyle0 = p.fillStyle0; + onepath.lineStyle = p.lineStyle; + onepath.lineStyle2 = p.lineStyle2; } if (onepath.start == null) { onepath.start = p.start; @@ -776,6 +773,15 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters { return ret; } + public static CurvedEdgeRecord straightToCurve(StraightEdgeRecord ser) { + CurvedEdgeRecord ret = new CurvedEdgeRecord(); + ret.controlDeltaX = ser.deltaX / 2; + ret.controlDeltaY = ser.deltaY / 2; + ret.anchorDeltaX = ser.deltaX / 2; + ret.anchorDeltaY = ser.deltaY / 2; + return ret; + } + /** * Convert shape to SVG * diff --git a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/StyleChangeRecord.java b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/StyleChangeRecord.java index b5f27260b..1bae85c11 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/StyleChangeRecord.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/StyleChangeRecord.java @@ -20,12 +20,14 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; /** * * @author JPEXS */ -public class StyleChangeRecord extends SHAPERECORD { +public class StyleChangeRecord extends SHAPERECORD implements Cloneable { public int typeFlag = 0; public boolean stateNewStyles; @@ -91,5 +93,16 @@ public class StyleChangeRecord extends SHAPERECORD { @Override public boolean isMove() { return stateMoveTo; + + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + Logger.getLogger(StyleChangeRecord.class.getName()).log(Level.SEVERE, null, ex); + } + return null; } }