diff --git a/CHANGELOG.md b/CHANGELOG.md index 74354dec6..3c4f8b20d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ All notable changes to this project will be documented in this file. - [#2575] dumpSWF CLI command displayed import assets GUI dialog - [#2573] AS3 - Incorrect uint/int/Number coercion - AS3 local registers type propagation -- [#2566] Export bounds of sprites and buttons not containg filter offsets +- [#2566], [#2594] Export bounds of sprites and buttons not containg filter offsets - [#2582] Font normalizer setting small texts when no assigned glyph found - PDF export - not rendering video stream frames - [#2585] AS1/2 direct editation - continue and break in for..in loop @@ -4082,6 +4082,7 @@ Major version of SWF to XML export changed to 2. [#2575]: https://www.free-decompiler.com/flash/issues/2575 [#2573]: https://www.free-decompiler.com/flash/issues/2573 [#2566]: https://www.free-decompiler.com/flash/issues/2566 +[#2594]: https://www.free-decompiler.com/flash/issues/2594 [#2582]: https://www.free-decompiler.com/flash/issues/2582 [#2585]: https://www.free-decompiler.com/flash/issues/2585 [#2589]: https://www.free-decompiler.com/flash/issues/2589 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 32dd06e8b..19f83db3a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -161,6 +161,7 @@ import com.jpexs.decompiler.flash.types.SOUNDINFO; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFField; import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.filters.FILTER; import com.jpexs.decompiler.flash.types.sound.SoundInfoSoundCacheEntry; import com.jpexs.decompiler.flash.xfl.FLAVersion; import com.jpexs.decompiler.flash.xfl.XFLConverter; @@ -186,6 +187,7 @@ import com.jpexs.helpers.SerializableImage; import com.jpexs.helpers.utf8.Utf8Helper; import java.awt.AlphaComposite; import java.awt.Color; +import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; @@ -5001,8 +5003,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { RECT rect = displayRect; SerializableImage image = new SerializableImage( - rect.getWidth() == 0 ? 1 /*FIXME: is this necessary?*/ : (int) (rect.getWidth() * zoom * aaScale / SWF.unitDivisor), - rect.getHeight() == 0 ? 1 : (int) (rect.getHeight() * zoom * aaScale / SWF.unitDivisor), SerializableImage.TYPE_INT_ARGB_PRE); + rect.getWidth() == 0 ? 1 /*FIXME: is this necessary?*/ : (int) Math.ceil(rect.getWidth() * zoom * aaScale / SWF.unitDivisor), + rect.getHeight() == 0 ? 1 : (int) Math.ceil(rect.getHeight() * zoom * aaScale / SWF.unitDivisor), SerializableImage.TYPE_INT_ARGB_PRE); if (backGroundColor == null) { image.fillTransparent(); } else { @@ -6425,4 +6427,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { //ignore } } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } + + @Override + public RECT getRectWithFilters() { + return getRect(); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index 0a7405a8e..a461e4b12 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -41,7 +41,6 @@ import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.base.RenderContext; -import com.jpexs.decompiler.flash.tags.base.StaticTextTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.enums.ImageFormat; import com.jpexs.decompiler.flash.timeline.DepthState; @@ -248,8 +247,9 @@ public class FrameExporter { int max = subFrameMode ? subframeLength : fframes.size(); int fframe = subFrameMode ? fframes.get(0) : fframes.get(pos++); - int realAaScale = Configuration.calculateRealAaScale(tim.displayRect.getWidth(), tim.displayRect.getHeight(), settings.zoom, settings.aaScale); - BufferedImage result = SWF.frameToImageGet(tim, fframe, subFrameMode ? pos++ : 0, null, 0, tim.displayRect, new Matrix(), null, backgroundColor == null && !usesTransparency ? Color.white : backgroundColor, settings.zoom, true, realAaScale).getBufferedImage(); + RECT diplayRect = tim.getDisplayRectWithFilters(); + int realAaScale = Configuration.calculateRealAaScale(diplayRect.getWidth(), diplayRect.getHeight(), settings.zoom, settings.aaScale); + BufferedImage result = SWF.frameToImageGet(tim, fframe, subFrameMode ? pos++ : 0, null, 0, diplayRect, new Matrix(), null, backgroundColor == null && !usesTransparency ? Color.white : backgroundColor, settings.zoom, true, realAaScale).getBufferedImage(); if (CancellableWorker.isInterrupted()) { return null; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index e3e541640..a3701cd63 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -248,15 +248,15 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer { } double x = filter.getDeltaX(); double y = filter.getDeltaY(); - deltaXMax += x * SWF.unitDivisor; - deltaYMax += y * SWF.unitDivisor; + deltaXMax += x; + deltaYMax += y; } } - r2.Xmin -= deltaXMax; - r2.Ymin -= deltaYMax; - r2.Xmax += deltaXMax; - r2.Ymax += deltaYMax; + r2.Xmin -= Math.ceil(deltaXMax) * SWF.unitDivisor; + r2.Ymin -= Math.ceil(deltaYMax) * SWF.unitDivisor; + r2.Xmax += Math.ceil(deltaXMax) * SWF.unitDivisor; + r2.Ymax += Math.ceil(deltaYMax) * SWF.unitDivisor; rect.Xmin = Math.min(r2.Xmin, rect.Xmin); rect.Ymin = Math.min(r2.Ymin, rect.Ymin); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java index e4c725b48..661b0814b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java @@ -68,6 +68,7 @@ import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.io.IOException; import java.io.StringReader; @@ -1642,4 +1643,13 @@ public class DefineEditTextTag extends TextTag { return ret; } + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } + + @Override + public RECT getRectWithFilters() { + return getRect(); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 077b9e6ed..4e6abdcdc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -44,13 +44,12 @@ import com.jpexs.decompiler.flash.types.filters.FILTER; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Cache; import com.jpexs.helpers.SerializableImage; +import java.awt.Dimension; import java.awt.Shape; -import java.awt.geom.AffineTransform; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -174,7 +173,7 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { @Override public Timeline getTimeline() { if (timeline == null) { - timeline = new Timeline(swf, this, spriteId, getRect()); + timeline = new Timeline(swf, this, spriteId, getRect(), getFilterDimensions()); } return timeline; } @@ -230,6 +229,67 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { return ret; } + @Override + public Dimension getFilterDimensions() { + HashMap depthMap = new HashMap<>(); + + int totalDeltaX = 0; + int totalDeltaY = 0; + + for (Tag t : getTags()) { + if (t instanceof RemoveTag) { + RemoveTag rt = (RemoveTag) t; + depthMap.remove(rt.getDepth()); + } else if (t instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag pot = (PlaceObjectTypeTag) t; + + if (pot.flagMove() != depthMap.containsKey(pot.getDepth())) { + continue; + } + + List filters = pot.getFilters(); + + int chId = pot.getCharacterId(); + String chClass = pot.getClassName(); + + CharacterTag ch = null; + if (chId != -1) { + ch = swf.getCharacter(chId); + } + if (chClass != null) { + ch = swf.getCharacterByClass(chClass); + } + if (ch instanceof DrawableTag) { + Dimension filterDimension = ((DrawableTag) ch).getFilterDimensions(); + + totalDeltaX = Math.max(totalDeltaX, filterDimension.width); + totalDeltaY = Math.max(totalDeltaY, filterDimension.height); + } + + double deltaXMax = 0; + double deltaYMax = 0; + + if (filters != null && !filters.isEmpty()) { + // calculate size after applying the filters + for (FILTER filter : filters) { + if (!filter.enabled) { + continue; + } + double x = filter.getDeltaX(); + double y = filter.getDeltaY(); + deltaXMax += x; + deltaYMax += y; + } + + totalDeltaX = Math.max(totalDeltaX, (int) (Math.ceil(deltaXMax) * SWF.unitDivisor)); + totalDeltaY = Math.max(totalDeltaY, (int) (Math.ceil(deltaYMax) * SWF.unitDivisor)); + } + } + } + + return new Dimension(totalDeltaX, totalDeltaY); + } + @Override public RECT getRect() { return getRect(new HashSet<>()); @@ -250,8 +310,6 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { for (Tag t : getTags()) { MATRIX m = null; int characterId = -1; - double deltaXMax = 0; - double deltaYMax = 0; if (t instanceof RemoveTag) { RemoveTag rt = (RemoveTag) t; depthMap.remove(rt.getDepth()); @@ -286,24 +344,7 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { characterId = chi; } } - - List filters = pot.getFilters(); - - deltaXMax = 0; - deltaYMax = 0; - - if (filters != null && !filters.isEmpty()) { - // calculate size after applying the filters - for (FILTER filter : filters) { - if (!filter.enabled) { - continue; - } - double x = filter.getDeltaX(); - double y = filter.getDeltaY(); - deltaXMax += x * SWF.unitDivisor; - deltaYMax += y * SWF.unitDivisor; - } - } + } else { continue; } @@ -321,7 +362,7 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { RECT r = getCharacterBounds(need, added); if (m != null) { - AffineTransform trans = SWF.matrixToTransform(m); + /*AffineTransform trans = SWF.matrixToTransform(m); java.awt.Point topleft = new java.awt.Point(); trans.transform(new java.awt.Point(r.Xmin, r.Ymin), topleft); @@ -335,13 +376,17 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { r.Xmin = (int) Math.min(Math.min(Math.min(topleft.x, topright.x), bottomleft.x), bottomright.x); r.Ymin = (int) Math.min(Math.min(Math.min(topleft.y, topright.y), bottomleft.y), bottomright.y); r.Xmax = (int) Math.max(Math.max(Math.max(topleft.x, topright.x), bottomleft.x), bottomright.x); - r.Ymax = (int) Math.max(Math.max(Math.max(topleft.y, topright.y), bottomleft.y), bottomright.y); + r.Ymax = (int) Math.max(Math.max(Math.max(topleft.y, topright.y), bottomleft.y), bottomright.y);*/ + Matrix mat = new Matrix(m); + ExportRectangle r2 = mat.transform(new ExportRectangle(r)); + r.Xmin = (int) r2.xMin; + r.Xmax = (int) r2.xMax; + r.Ymin = (int) r2.yMin; + r.Ymax = (int) r2.yMax; + + //System.err.println("xmin = " + (r.Xmin / 20)); } - - r.Xmin -= deltaXMax; - r.Ymin -= deltaYMax; - r.Xmax += deltaXMax; - r.Ymax += deltaYMax; + ret.Xmin = Math.min(r.Xmin, ret.Xmin); ret.Ymin = Math.min(r.Ymin, ret.Ymin); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java index d82e3dd2b..c6d60c9ff 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java @@ -50,6 +50,7 @@ import com.jpexs.video.SimpleMediaPlayer; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; @@ -541,7 +542,7 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim } this.tags = new ReadOnlyTagList(tags); - timeline = new Timeline(swf, this, characterID, getRect()) { + timeline = new Timeline(swf, this, characterID, getRect(), getFilterDimensions()) { @Override public void getSounds(int frame, int time, ButtonTag mouseOverButton, int mouseButton, List sounds, List soundClasses, List soundInfos) { } @@ -600,4 +601,8 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim return numFrames; } + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java index b73c8ff71..fc6826db3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.types.RECT; +import java.awt.Dimension; import java.util.Set; /** @@ -47,4 +48,18 @@ public interface BoundedTag { * @return Rectangle including strokes */ public RECT getRectWithStrokes(); + + /** + * Gets filter dimensions. + * + * @return Filter dimensions + */ + public Dimension getFilterDimensions(); + + /** + * Gets rectangle including filters. + * + * @return RECT with filters applied + */ + public RECT getRectWithFilters(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java index a7c0042ec..7cb30ebf6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java @@ -28,8 +28,10 @@ import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BUTTONRECORD; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.filters.FILTER; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.SerializableImage; +import java.awt.Dimension; import java.awt.Shape; import java.io.IOException; import java.util.ArrayList; @@ -173,7 +175,7 @@ public abstract class ButtonTag extends DrawableTag implements Timelined { return timeline; } - timeline = new Timeline(swf, this, getCharacterId(), getRect()); + timeline = new Timeline(swf, this, getCharacterId(), getRect(), getFilterDimensions()); initTimeline(timeline); return timeline; } @@ -400,4 +402,45 @@ public abstract class ButtonTag extends DrawableTag implements Timelined { } selectedRecord.fromPlaceObject(placeTag); } + + @Override + public Dimension getFilterDimensions() { + int totalDeltaX = 0; + int totalDeltaY = 0; + for (BUTTONRECORD rec : getRecords()) { + + int chId = rec.characterId; + CharacterTag ch = null; + if (chId != -1) { + ch = swf.getCharacter(chId); + } + if (ch instanceof DrawableTag) { + Dimension filterDimension = ((DrawableTag) ch).getFilterDimensions(); + + totalDeltaX = Math.max(totalDeltaX, filterDimension.width); + totalDeltaY = Math.max(totalDeltaY, filterDimension.height); + } + + double deltaXMax = 0; + double deltaYMax = 0; + if (rec.filterList != null && !rec.filterList.isEmpty()) { + // calculate size after applying the filters + for (FILTER filter : rec.filterList) { + if (!filter.enabled) { + continue; + } + double x = filter.getDeltaX(); + double y = filter.getDeltaY(); + deltaXMax += x; + deltaYMax += y; + } + + totalDeltaX = Math.max(totalDeltaX, (int) (Math.ceil(deltaXMax) * SWF.unitDivisor)); + totalDeltaY = Math.max(totalDeltaY, (int) (Math.ceil(deltaYMax) * SWF.unitDivisor)); + } + } + return new Dimension(totalDeltaX, totalDeltaY); + } + + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java index 325c955a2..8a149fd03 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java @@ -21,8 +21,10 @@ import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.SerializableImage; +import java.awt.Dimension; import java.awt.Shape; import java.io.IOException; @@ -140,4 +142,15 @@ public abstract class DrawableTag extends CharacterTag implements BoundedTag { * @return True if single frame, false if not */ public abstract boolean isSingleFrame(); + + @Override + public RECT getRectWithFilters() { + RECT r = new RECT(getRect()); + Dimension filterDimension = getFilterDimensions(); + r.Xmin -= filterDimension.width; + r.Xmax += filterDimension.width; + r.Ymin -= filterDimension.height; + r.Ymax += filterDimension.height; + return r; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index f2200329a..711e281c6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -36,6 +36,7 @@ import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.Rectangle; import java.awt.Shape; @@ -857,4 +858,9 @@ public abstract class FontTag extends DrawableTag implements AloneTag { * Update tables of bounds */ public abstract void updateBounds(); + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java index 64e154ca6..e4b0a6b4a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java @@ -420,4 +420,9 @@ public abstract class ImageTag extends DrawableTag { return true; } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java index 431b95309..29b2f1df8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MorphShapeTag.java @@ -43,6 +43,7 @@ import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.SerializableImage; +import java.awt.Dimension; import java.awt.Shape; import java.util.ArrayList; import java.util.HashSet; @@ -478,4 +479,9 @@ public abstract class MorphShapeTag extends DrawableTag { updateStartBounds(); updateEndBounds(); } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java index ea5ba43d6..8ff6f037e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java @@ -38,6 +38,7 @@ import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.SerializableImage; import java.awt.Color; +import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; @@ -316,4 +317,9 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject { shapes.clearCachedOutline(); shapeBounds = SHAPERECORD.getBounds(shapes.shapeRecords, shapes.lineStyles, getShapeNum(), false); } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java index ff1781b27..cd2852040 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java @@ -44,6 +44,7 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; +import java.awt.Dimension; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; @@ -1065,4 +1066,9 @@ public abstract class StaticTextTag extends TextTag { public void toHtmlCanvas(StringBuilder result, double unitDivisor) { staticTextToHtmlCanvas(unitDivisor, swf, textRecords, getTextNum(), result, textBounds, textMatrix, null); } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } } 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 c3a417518..dba5f6979 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 @@ -79,6 +79,7 @@ import com.jpexs.helpers.SerializableImage; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; @@ -127,6 +128,11 @@ public class Timeline { * Display rect. */ public RECT displayRect; + + /** + * Filters dimension. + */ + public Dimension filterDimension; /** * Frame rate. @@ -465,7 +471,7 @@ public class Timeline { * @param swf SWF */ public Timeline(SWF swf) { - this(swf, swf, 0, swf.displayRect); + this(swf, swf, 0, swf.displayRect, swf.getFilterDimensions()); } /** @@ -475,13 +481,15 @@ public class Timeline { * @param timelined Timelined * @param id Timeline id - usually characterId or 0 for SWF main timeline * @param displayRect Display rect + * @param filterDimension Filters dimension */ - public Timeline(SWF swf, Timelined timelined, int id, RECT displayRect) { + public Timeline(SWF swf, Timelined timelined, int id, RECT displayRect, Dimension filterDimension) { this.id = id; this.swf = swf; this.displayRect = displayRect; this.frameRate = swf.frameRate; this.timelined = timelined; + this.filterDimension = filterDimension; as2RootPackage = new AS2Package(null, null, swf, false, false); } @@ -1159,14 +1167,14 @@ public class Timeline { deltaXMax += x; deltaYMax += y; } - rect.xMin -= deltaXMax * unzoom * SWF.unitDivisor; - rect.xMax += deltaXMax * unzoom * SWF.unitDivisor; - rect.yMin -= deltaYMax * unzoom * SWF.unitDivisor; - rect.yMax += deltaYMax * unzoom * SWF.unitDivisor; - viewRect2.xMin -= deltaXMax * SWF.unitDivisor; - viewRect2.xMax += deltaXMax * SWF.unitDivisor; - viewRect2.yMin -= deltaYMax * SWF.unitDivisor; - viewRect2.yMax += deltaYMax * SWF.unitDivisor; + rect.xMin -= Math.ceil(deltaXMax * unzoom) * SWF.unitDivisor; + rect.xMax += Math.ceil(deltaXMax * unzoom) * SWF.unitDivisor; + rect.yMin -= Math.ceil(deltaYMax * unzoom) * SWF.unitDivisor; + rect.yMax += Math.ceil(deltaYMax * unzoom) * SWF.unitDivisor; + viewRect2.xMin -= Math.ceil(deltaXMax) * SWF.unitDivisor; + viewRect2.xMax += Math.ceil(deltaXMax) * SWF.unitDivisor; + viewRect2.yMin -= Math.ceil(deltaYMax) * SWF.unitDivisor; + viewRect2.yMax += Math.ceil(deltaYMax) * SWF.unitDivisor; } drawMatrix.translate(rect.xMin, rect.yMin); @@ -2263,4 +2271,18 @@ public class Timeline { ensureInitialized(); return new ArrayList<>(scenes); } + + /** + * Gets display rect including filters. + * + * @return RECT with filters applied + */ + public RECT getDisplayRectWithFilters() { + RECT r = new RECT(displayRect); + r.Xmin -= filterDimension.width; + r.Xmax += filterDimension.width; + r.Ymin -= filterDimension.height; + r.Ymax += filterDimension.height; + return r; + } } diff --git a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java index d76baf298..470a39074 100644 --- a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java @@ -349,7 +349,7 @@ public class FolderPreviewPanel extends JPanel { oh = height * SWF.unitDivisor; } else if (treeItem instanceof BoundedTag) { BoundedTag boundedTag = (BoundedTag) treeItem; - RECT rect = boundedTag.getRect(); + RECT rect = boundedTag.getRectWithFilters(); ow = rect.getWidth(); oh = rect.getHeight(); width = (int) (rect.getWidth() / SWF.unitDivisor) + 1; diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 5fb3e618a..2ddfe9cf6 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -6245,7 +6245,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se @Override public Timeline getTimeline() { - return new Timeline(origSwf, this, Integer.MAX_VALUE, buttonRecord.getTag().getRect()); + return new Timeline(origSwf, this, Integer.MAX_VALUE, buttonRecord.getTag().getRect(), buttonRecord.getTag().getFilterDimensions()); } @Override @@ -6332,6 +6332,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se public RECT getRectWithStrokes() { return getRect(); } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } + + @Override + public RECT getRectWithFilters() { + return getRect(); + } }; previewPanel.showImagePanel(tim, origSwf, 0, true, true, !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false, true, true, true); } else if (treeItem instanceof DefineFont4Tag) { diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 47d0324c5..4ca463fee 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -2878,7 +2878,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel @Override public Timeline getTimeline() { - return new Timeline(origSwf, this, Integer.MAX_VALUE, frect); + return new Timeline(origSwf, this, Integer.MAX_VALUE, frect, getFilterDimensions()); } @Override @@ -2968,6 +2968,16 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel public RECT getRectWithStrokes() { return getRect(); } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } + + @Override + public RECT getRectWithFilters() { + return getRect(); + } }; imagePanel.setTimelined(tim, origSwf, 0, true, true, true, true, true, false, true, true, true); diff --git a/src/com/jpexs/decompiler/flash/gui/TimelinedMaker.java b/src/com/jpexs/decompiler/flash/gui/TimelinedMaker.java index d9724a88c..56c2fc777 100644 --- a/src/com/jpexs/decompiler/flash/gui/TimelinedMaker.java +++ b/src/com/jpexs/decompiler/flash/gui/TimelinedMaker.java @@ -51,6 +51,7 @@ 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.Dimension; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -213,7 +214,7 @@ public class TimelinedMaker { @Override public Timeline getTimeline() { if (tim == null) { - Timeline timeline = new Timeline(tag.getSwf(), this, fChId, getRect()); + Timeline timeline = new Timeline(tag.getSwf(), this, fChId, getRect(), getFilterDimensions()); initTimeline(timeline); tim = timeline; } @@ -368,6 +369,16 @@ public class TimelinedMaker { public SWF getSwf() { return tag.getSwf(); } + + @Override + public Dimension getFilterDimensions() { + return new Dimension(0, 0); + } + + @Override + public RECT getRectWithFilters() { + return getRect(); + } }; } }