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 9e6b62089..ece225cb4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -328,6 +328,9 @@ public final class SWF implements SWFContainerItem, Timelined { @Internal private final Cache frameCache = Cache.getInstance(false, false, "frame"); + @Internal + private final Cache displayObjectCache = Cache.getInstance(false, false, "displayObject"); + @Internal private final Cache rectCache = Cache.getInstance(true, true, "rect"); @@ -399,6 +402,7 @@ public final class SWF implements SWFContainerItem, Timelined { as2Cache.clear(); as3Cache.clear(); frameCache.clear(); + displayObjectCache.clear(); soundCache.clear(); timeline = null; @@ -2483,6 +2487,13 @@ public final class SWF implements SWFContainerItem, Timelined { return null; } + public SerializableImage getFromCache(PlaceObjectTypeTag key) { + if (displayObjectCache.contains(key)) { + return displayObjectCache.get(key); + } + return null; + } + public byte[] getFromCache(SoundTag soundTag) { if (soundCache.contains(soundTag)) { return soundCache.get(soundTag); @@ -2496,12 +2507,17 @@ public final class SWF implements SWFContainerItem, Timelined { } } + public void putToCache(PlaceObjectTypeTag key, SerializableImage img) { + displayObjectCache.put(key, img); + } + public void putToCache(SoundTag soundTag, byte[] data) { soundCache.put(soundTag, data); } public void clearImageCache() { frameCache.clear(); + displayObjectCache.clear(); rectCache.clear(); for (Tag tag : getTags()) { if (tag instanceof ImageTag) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/RenderContext.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/RenderContext.java index cd2d48b80..616d4ca72 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/RenderContext.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/RenderContext.java @@ -19,9 +19,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.timeline.DepthState; import com.jpexs.helpers.SerializableImage; import java.awt.Point; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * @@ -37,7 +35,5 @@ public class RenderContext { public ButtonTag mouseOverButton; - public Map shapeCache = new HashMap<>(); - public SerializableImage borderImage; } 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 9c5e08fc5..3dbaece6b 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 @@ -606,7 +606,7 @@ public class Timeline { Matrix mat = transformation.concatenate(layerMatrix); rect = mat.transform(rect); - boolean cacheAsBitmap = layer.cacheAsBitmap() && drawable.isSingleFrame(); + boolean cacheAsBitmap = layer.cacheAsBitmap() && layer.placeObjectTag != null && drawable.isSingleFrame(); /* // draw bounds AffineTransform trans = mat.preConcatenate(Matrix.getScaleInstance(1 / SWF.unitDivisor)).toTransform(); g.setTransform(trans); @@ -622,50 +622,12 @@ public class Timeline { g.drawLine(r.Xmax, r.Ymin, r.Xmin, r.Ymax); g.setComposite(AlphaComposite.Dst);*/ - if (filters != null && filters.size() > 0) { - // calculate size after applying the filters - double deltaXMax = 0; - double deltaYMax = 0; - for (FILTER filter : filters) { - double x = filter.getDeltaX(); - double y = filter.getDeltaY(); - deltaXMax = Math.max(x, deltaXMax); - deltaYMax = Math.max(y, deltaYMax); - } - rect.xMin -= deltaXMax * unzoom; - rect.xMax += deltaXMax * unzoom; - rect.yMin -= deltaYMax * unzoom; - rect.yMax += deltaYMax * unzoom; - } - - rect.xMin -= 1 * unzoom; - rect.yMin -= 1 * unzoom; - rect.xMin = Math.max(0, rect.xMin); - rect.yMin = Math.max(0, rect.yMin); - - int newWidth = (int) (rect.getWidth() / unzoom); - int newHeight = (int) (rect.getHeight() / unzoom); - int deltaX = (int) (rect.xMin / unzoom); - int deltaY = (int) (rect.yMin / unzoom); - newWidth = Math.min(image.getWidth() - deltaX, newWidth) + 1; - newHeight = Math.min(image.getHeight() - deltaY, newHeight) + 1; - - if (newWidth <= 0 || newHeight <= 0) { - return; - } - - Matrix m = mat.preConcatenate(Matrix.getTranslateInstance(-rect.xMin, -rect.yMin)); - //strokeTransform = strokeTransform.clone(); - //strokeTransform.translate(-rect.xMin, -rect.yMin); - drawMatrix.translate(rect.xMin, rect.yMin); - SerializableImage img = null; - String cacheKey = null; - if (drawable instanceof ShapeTag) { - cacheKey = ((ShapeTag) drawable).getCharacterId() + m.toString() + (clrTrans == null ? "" : clrTrans.toString()); - //img = renderContext.shapeCache.get(cacheKey); + if (cacheAsBitmap) { + swf.getFromCache(layer.placeObjectTag); } + int stateCount = renderContext.stateUnderCursor == null ? 0 : renderContext.stateUnderCursor.size(); int dframe; if (fontFrameNum != -1) { dframe = fontFrameNum; @@ -673,40 +635,77 @@ public class Timeline { dframe = time % drawableFrameCount; } - if (drawable instanceof ButtonTag) { - dframe = ButtonTag.FRAME_UP; - if (renderContext.cursorPosition != null) { - Shape buttonShape = drawable.getOutline(ButtonTag.FRAME_HITTEST, time, ratio, renderContext, absMat, true); - if (buttonShape.contains(renderContext.cursorPosition)) { - renderContext.mouseOverButton = (ButtonTag) drawable; - if (renderContext.mouseButton > 0) { - dframe = ButtonTag.FRAME_DOWN; - } else { - dframe = ButtonTag.FRAME_OVER; + if (img == null) { + if (filters != null && filters.size() > 0) { + // calculate size after applying the filters + double deltaXMax = 0; + double deltaYMax = 0; + for (FILTER filter : filters) { + double x = filter.getDeltaX(); + double y = filter.getDeltaY(); + deltaXMax = Math.max(x, deltaXMax); + deltaYMax = Math.max(y, deltaYMax); + } + rect.xMin -= deltaXMax * unzoom; + rect.xMax += deltaXMax * unzoom; + rect.yMin -= deltaYMax * unzoom; + rect.yMax += deltaYMax * unzoom; + } + + rect.xMin -= 1 * unzoom; + rect.yMin -= 1 * unzoom; + rect.xMin = Math.max(0, rect.xMin); + rect.yMin = Math.max(0, rect.yMin); + + int newWidth = (int) (rect.getWidth() / unzoom); + int newHeight = (int) (rect.getHeight() / unzoom); + int deltaX = (int) (rect.xMin / unzoom); + int deltaY = (int) (rect.yMin / unzoom); + newWidth = Math.min(image.getWidth() - deltaX, newWidth) + 1; + newHeight = Math.min(image.getHeight() - deltaY, newHeight) + 1; + + if (newWidth <= 0 || newHeight <= 0) { + return; + } + + Matrix m = mat.preConcatenate(Matrix.getTranslateInstance(-rect.xMin, -rect.yMin)); + //strokeTransform = strokeTransform.clone(); + //strokeTransform.translate(-rect.xMin, -rect.yMin); + drawMatrix.translate(rect.xMin, rect.yMin); + + if (drawable instanceof ButtonTag) { + dframe = ButtonTag.FRAME_UP; + if (renderContext.cursorPosition != null) { + Shape buttonShape = drawable.getOutline(ButtonTag.FRAME_HITTEST, time, ratio, renderContext, absMat, true); + if (buttonShape.contains(renderContext.cursorPosition)) { + renderContext.mouseOverButton = (ButtonTag) drawable; + if (renderContext.mouseButton > 0) { + dframe = ButtonTag.FRAME_DOWN; + } else { + dframe = ButtonTag.FRAME_OVER; + } } } } - } - int stateCount = renderContext.stateUnderCursor == null ? 0 : renderContext.stateUnderCursor.size(); - if (img == null) { img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB); img.fillTransparent(); drawable.toImage(dframe, time, ratio, renderContext, img, isClip || clipDepth > -1, m, strokeTransform, absMat, clrTrans); - if (cacheKey != null) { - renderContext.shapeCache.put(cacheKey, img); + if (filters != null) { + for (FILTER filter : filters) { + img = filter.apply(img); + } } - } - if (filters != null) { - for (FILTER filter : filters) { - img = filter.apply(img); + if (blendMode > 1) { + if (colorTransForm != null) { + img = colorTransForm.apply(img); + } } - } - if (blendMode > 1) { - if (colorTransForm != null) { - img = colorTransForm.apply(img); + + if (cacheAsBitmap) { + swf.putToCache(layer.placeObjectTag, img); } }