diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index eb4742ecb..68a640f33 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -2381,7 +2381,14 @@ public final class SWF implements SWFContainerItem, Timelined { if (drawableFrameCount == 0) { drawableFrameCount = 1; } - int dframe = (time + layer.time) % drawableFrameCount; + + int dframe; + if (timeline.fontFrameNum != -1) { + dframe = timeline.fontFrameNum; + } else { + dframe = (time + layer.time) % drawableFrameCount; + } + if (character instanceof ButtonTag) { dframe = ButtonTag.FRAME_UP; if (renderContext.stateUnderCursor == layer) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java index 9a4c9d6ea..8e9af038f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java @@ -52,7 +52,7 @@ import java.util.List; * * @author JPEXS */ -public final class DefineCompactedFont extends FontTag implements DrawableTag { +public final class DefineCompactedFont extends FontTag { public static final int ID = 1005; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 369b8581b..6ba93029e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -71,6 +71,8 @@ public class Timeline { public int maxDepth; + public int fontFrameNum = -1; + public List tags; private final List frames = new ArrayList<>(); diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 63989674b..ddd6fa26a 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -89,8 +89,6 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis private int counter = 0; - private AtomicBoolean shouldDraw = new AtomicBoolean(); - private SWF swf; private boolean loaded; @@ -376,7 +374,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis public void mouseEntered(MouseEvent e) { synchronized (ImagePanel.class) { lastMouseEvent = e; - shouldDraw.set(true); + redraw(); } } @@ -386,7 +384,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis stateUnderCursor = null; lastMouseEvent = null; hideMouseSelection(); - shouldDraw.set(true); + redraw(); } } @@ -395,7 +393,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis synchronized (ImagePanel.class) { mouseButton = e.getButton(); lastMouseEvent = e; - shouldDraw.set(true); + redraw(); if (stateUnderCursor != null) { ButtonTag b = (ButtonTag) swf.getCharacter(stateUnderCursor.characterId); DefineButtonSoundTag sounds = b.getSounds(); @@ -411,7 +409,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis synchronized (ImagePanel.class) { mouseButton = 0; lastMouseEvent = e; - shouldDraw.set(true); + redraw(); if (stateUnderCursor != null) { ButtonTag b = (ButtonTag) swf.getCharacter(stateUnderCursor.characterId); DefineButtonSoundTag sounds = b.getSounds(); @@ -428,7 +426,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis public void mouseMoved(MouseEvent e) { synchronized (ImagePanel.class) { lastMouseEvent = e; - shouldDraw.set(true); + redraw(); DepthState lastUnderCur = stateUnderCursor; if (stateUnderCursor != null) { if (lastUnderCur == null || lastUnderCur.instanceId != stateUnderCursor.instanceId) { @@ -457,19 +455,25 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis public void mouseDragged(MouseEvent e) { synchronized (ImagePanel.class) { lastMouseEvent = e; - shouldDraw.set(true); + redraw(); } } }); } + private void redraw() { + if (timer == null) { + startTimer(counter, timelined.getTimeline()); + } + } + @Override public synchronized void zoom(Zoom zoom) { boolean modified = this.zoom.value != zoom.value || this.zoom.fit != zoom.fit; if (modified) { this.zoom = zoom; - shouldDraw.set(true); + redraw(); if (textTag != null) { setText(textTag, newTextTag); } @@ -558,7 +562,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis time = 0; drawReady = false; - shouldDraw.set(true); + redraw(); play(); } @@ -715,10 +719,10 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis } private static SerializableImage getFrame(SWF swf, int frame, int time, Timelined drawable, DepthState stateUnderCursor, int mouseButton, int selectedDepth, double zoom) { - String key = "drawable_" + frame + "_" + drawable.hashCode() + "_" + mouseButton + "_depth" + selectedDepth + "_" + (stateUnderCursor == null ? "out" : stateUnderCursor.hashCode()) + "_" + zoom; + Timeline timeline = drawable.getTimeline(); + String key = "drawable_" + frame + "_" + drawable.hashCode() + "_" + mouseButton + "_depth" + selectedDepth + "_" + (stateUnderCursor == null ? "out" : stateUnderCursor.hashCode()) + "_" + zoom + "_" + timeline.fontFrameNum; SerializableImage img = swf.getFromCache(key); if (img == null) { - Timeline timeline = drawable.getTimeline(); boolean shouldCache = timeline.isSingleFrame(frame); if (drawable instanceof BoundedTag) { BoundedTag bounded = (BoundedTag) drawable; @@ -940,25 +944,21 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis stopInternal(); if (timelined != null) { Timeline timeline = timelined.getTimeline(); - int frameRate = timeline.frameRate; - int msPerFrame = frameRate == 0 ? 1000 : 1000 / frameRate; - - final int cnt = counter; - final boolean singleFrame = timeline.getRealFrameCount() <= 1 && timeline.isSingleFrame(); - shouldDraw.set(true); - startTimer(cnt, singleFrame, msPerFrame); + startTimer(counter, timeline); } } - private void startTimer(int cnt, boolean singleFrame, int msPerFrame) { + private void startTimer(int cnt, Timeline timeline) { + + int frameRate = timeline.frameRate; + int msPerFrame = frameRate == 0 ? 1000 : 1000 / frameRate; + final boolean singleFrame = (timeline.getRealFrameCount() <= 1 && timeline.isSingleFrame()); TimerTask task = new TimerTask() { public final int taskCounter = cnt; public final boolean isSingleFrame = singleFrame; - private final AtomicBoolean first = shouldDraw; - @Override public void run() { try { @@ -1030,8 +1030,7 @@ public final class ImagePanel extends JPanel implements ActionListener, MediaDis this.frame = frame; stopInternal(); - shouldDraw.set(true); - startTimer(counter, true, 0); + redraw(); fireMediaDisplayStateChanged(); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index e14f3ec75..95e451ccc 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2900,6 +2900,10 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } public static Timelined makeTimelined(final Tag tag) { + return makeTimelined(tag, -1); + } + + public static Timelined makeTimelined(final Tag tag, final int fontFrameNum) { return new Timelined() { @@ -2926,16 +2930,19 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } } else if (tag instanceof FontTag) { int pageCount = PreviewPanel.getFontPageCount((FontTag) tag); - for (int i = 0; i < pageCount; i++) { - Frame f = new Frame(tim, i); - DepthState ds = new DepthState(tag.getSwf(), f); - ds.characterId = ((CharacterTag) tag).getCharacterId(); - ds.matrix = new MATRIX(); - ds.time = i; - f.layers.put(1, ds); - f.layersChanged = true; - tim.addFrame(f); + int frame = fontFrameNum; + if (frame < 0 || frame >= pageCount) { + frame = 0; } + + Frame f = new Frame(tim, 0); + DepthState ds = new DepthState(tag.getSwf(), f); + ds.characterId = ((CharacterTag) tag).getCharacterId(); + ds.matrix = new MATRIX(); + f.layers.put(1, ds); + f.layersChanged = true; + tim.addFrame(f); + tim.fontFrameNum = frame; } else { Frame f = new Frame(tim, 0); DepthState ds = new DepthState(tag.getSwf(), f); diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index ee7245ad5..a17ac5ae6 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -1211,7 +1211,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { int pageCount = getFontPageCount(fontTag); fontPageNum = (fontPageNum + pageCount - 1) % pageCount; if (mainPanel.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) { - imagePanel.setTimelined(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum); + imagePanel.setTimelined(MainPanel.makeTimelined(fontTag, fontPageNum), fontTag.getSwf(), 0); } } break; @@ -1220,7 +1220,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { int pageCount = getFontPageCount(fontTag); fontPageNum = (fontPageNum + 1) % pageCount; if (mainPanel.isInternalFlashViewerSelected() /*|| ft instanceof GFxDefineCompactedFont*/) { - imagePanel.setTimelined(MainPanel.makeTimelined(fontTag), fontTag.getSwf(), fontPageNum); + imagePanel.setTimelined(MainPanel.makeTimelined(fontTag, fontPageNum), fontTag.getSwf(), 0); } } break;