From 6c709bc5e505cf52a12f75cc6ce6b88d3bd9ce02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 29 Mar 2021 10:05:56 +0200 Subject: [PATCH] Fixed: Flash viewer - slow on larger zooms (now only diplayed rect is rendered) --- CHANGELOG.md | 1 + .../src/com/jpexs/decompiler/flash/SWF.java | 4 +- .../flash/exporters/FrameExporter.java | 2 +- .../flash/exporters/ShapeExporter.java | 2 +- .../commonshape/ExportRectangle.java | 27 ++++- .../flash/tags/DefineEditTextTag.java | 2 +- .../flash/tags/DefineSpriteTag.java | 5 +- .../decompiler/flash/tags/base/ButtonTag.java | 5 +- .../flash/tags/base/DrawableTag.java | 3 +- .../decompiler/flash/tags/base/FontTag.java | 3 +- .../decompiler/flash/tags/base/ImageTag.java | 3 +- .../flash/tags/base/MorphShapeTag.java | 3 +- .../decompiler/flash/tags/base/ShapeTag.java | 3 +- .../flash/tags/base/StaticTextTag.java | 2 +- .../decompiler/flash/timeline/Timeline.java | 48 +++++--- .../graph/GraphPartMarkedArrayList.java | 3 + .../flash/gui/FolderPreviewPanel.java | 12 +- .../decompiler/flash/gui/ImagePanel.java | 104 +++++++++++++++--- 18 files changed, 186 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4579a8087..d47de5a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. - Generic tag editor - remove more items at once - [#1669] Flash viewer - Smoothed vs non-smoothed bitmaps - PDF export - Smoothed bitmaps +- Flash viewer - slow on larger zooms (now only diplayed rect is rendered) ## [14.3.1] - 2021-03-25 ### Fixed 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 1a8f3924e..a6191fc88 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -76,6 +76,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.dumpview.DumpInfo; import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode; import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter; @@ -2908,7 +2909,8 @@ public final class SWF implements SWFContainerItem, Timelined { RenderContext renderContext = new RenderContext(); renderContext.cursorPosition = cursorPosition; renderContext.mouseButton = mouseButton; - timeline.toImage(frame, time, renderContext, image, false, m, new Matrix(), m, colorTransform, zoom, false); + ExportRectangle viewRect = new ExportRectangle(rect); + timeline.toImage(frame, time, renderContext, image, false, m, new Matrix(), m, colorTransform, zoom, false, viewRect, m); return image; } 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 dbff29981..7ad221792 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 @@ -558,7 +558,7 @@ public class FrameExporter { renderContext.stateUnderCursor = new ArrayList<>(); try { - tim.toImage(fframe, fframe, renderContext, image, false, m, new Matrix(), m, null, zoom, true); + tim.toImage(fframe, fframe, renderContext, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java index 0694a2ad7..7bc0ed580 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java @@ -122,7 +122,7 @@ public class ShapeExporter { } Matrix m = Matrix.getScaleInstance(settings.zoom); m.translate(-rect.Xmin, -rect.Ymin); - st.toImage(0, 0, 0, new RenderContext(), img, false, m, m, m, new CXFORMWITHALPHA(), unzoom, false); + st.toImage(0, 0, 0, new RenderContext(), img, false, m, m, m, m, new CXFORMWITHALPHA(), unzoom, false, new ExportRectangle(rect)); if (settings.mode == ShapeExportMode.PNG) { ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, file); } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/ExportRectangle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/ExportRectangle.java index c2397fc8d..da1c9b39b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/ExportRectangle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/ExportRectangle.java @@ -12,11 +12,14 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.exporters.commonshape; import com.jpexs.decompiler.flash.types.RECT; import java.awt.geom.Rectangle2D; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -46,6 +49,13 @@ public class ExportRectangle { this.yMax = rect.Ymax; } + public ExportRectangle(ExportRectangle rect) { + this.xMin = rect.xMin; + this.yMin = rect.yMin; + this.xMax = rect.xMax; + this.yMax = rect.yMax; + } + public ExportRectangle(Rectangle2D rect) { this.xMin = rect.getMinX(); this.yMin = rect.getMinY(); @@ -96,4 +106,19 @@ public class ExportRectangle { return "[ExportRectangle x=" + xMin + ",y=" + yMin + ", w=" + getWidth() + ", h=" + getHeight() + "]"; } + public boolean intersects(ExportRectangle rect) { + if (xMax < rect.xMin) { + return false; + } + if (yMax < rect.yMin) { + return false; + } + if (xMin > rect.xMax) { + return false; + } + if (yMin > rect.yMax) { + return false; + } + return true; //? + } } 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 b0cee910e..ae944a764 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 @@ -961,7 +961,7 @@ public class DefineEditTextTag extends TextTag { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { render(TextRenderMode.BITMAP, image, null, null, transformation, colorTransform, 1); } 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 84eba8963..e8b061a91 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 @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; +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.tags.base.BoundedTag; @@ -368,8 +369,8 @@ public class DefineSpriteTag extends DrawableTag implements Timelined { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { - getTimeline().toImage(frame, time, renderContext, image, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage); + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { + getTimeline().toImage(frame, time, renderContext, image, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage, viewRect, fullTransformation); } @Override 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 133715409..68d94ae02 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 @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.SWF; +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.tags.DefineButtonSoundTag; @@ -97,8 +98,8 @@ public abstract class ButtonTag extends DrawableTag implements Timelined { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { - getTimeline().toImage(frame, time, renderContext, image, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage); + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { + getTimeline().toImage(frame, time, renderContext, image, isClip, transformation, strokeTransformation, absoluteTransformation, colorTransform, unzoom, sameImage, viewRect, fullTransformation); } @Override 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 278b94c78..51a336f85 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 @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.SWF; +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; @@ -45,7 +46,7 @@ public abstract class DrawableTag extends CharacterTag implements BoundedTag { public abstract Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, boolean stroked); - public abstract void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix prevTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage); + public abstract void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix prevTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect); public abstract void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException; 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 b33186319..ba142fff5 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 @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; +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.exporters.shape.CanvasShapeExporter; @@ -432,7 +433,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { SHAPERECORD.shapeListToImage(swf, getGlyphShapeTable(), image, frame, Color.black, colorTransform); } 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 b92d2aaf1..4c3012122 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 @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; +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.exporters.shape.BitmapExporter; @@ -230,7 +231,7 @@ public abstract class ImageTag extends DrawableTag { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { BitmapExporter.export(swf, getShape(), null, image, transformation, strokeTransformation, colorTransform); } 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 631cf9fc0..b3b88a0dd 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 @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.SWF; +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.exporters.morphshape.CanvasMorphShapeExporter; @@ -313,7 +314,7 @@ public abstract class MorphShapeTag extends DrawableTag { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { SHAPEWITHSTYLE shape = getShapeAtRatio(ratio); // morphShape using shapeNum=3, morphShape2 using shapeNum=4 // todo: Currently the generated image is not cached, because the cache 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 11009eeb0..537bce978 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 @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.configuration.Configuration; +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.exporters.shape.BitmapExporter; @@ -171,7 +172,7 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { BitmapExporter.export(swf, getShapes(), null, image, transformation, strokeTransformation, colorTransform); if (Configuration._debugMode.get()) { // show control points List paths = PathExporter.export(swf, getShapes()); 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 7b1d47b6c..304c63781 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 @@ -652,7 +652,7 @@ public abstract class StaticTextTag extends TextTag { } @Override - public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect) { staticTextToImage(swf, textRecords, getTextNum(), image, textMatrix, transformation, colorTransform); /*try { TextTag originalTag = (TextTag) getOriginalTag(); 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 264a8b9b2..984419503 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 @@ -616,7 +616,7 @@ public class Timeline { toImage(frame, time, renderContext, image, isClip, transforms[i], absoluteTransformation, colorTransform, targetRect[i]); } }*/ - private void drawDrawable(Matrix strokeTransform, DepthState layer, Matrix layerMatrix, Graphics2D g, ColorTransform colorTransForm, int blendMode, List clips, Matrix transformation, boolean isClip, int clipDepth, Matrix absMat, int time, int ratio, RenderContext renderContext, SerializableImage image, DrawableTag drawable, List filters, double unzoom, ColorTransform clrTrans, boolean sameImage) { + private void drawDrawable(Matrix strokeTransform, DepthState layer, Matrix layerMatrix, Graphics2D g, ColorTransform colorTransForm, int blendMode, List clips, Matrix transformation, boolean isClip, int clipDepth, Matrix absMat, int time, int ratio, RenderContext renderContext, SerializableImage image, DrawableTag drawable, List filters, double unzoom, ColorTransform clrTrans, boolean sameImage, ExportRectangle viewRect, Matrix fullTransformation) { Matrix drawMatrix = new Matrix(); int drawableFrameCount = drawable.getNumFrames(); if (drawableFrameCount == 0) { @@ -629,6 +629,32 @@ public class Timeline { Matrix mat = transformation.concatenate(layerMatrix); rect = mat.transform(rect); + + ExportRectangle viewRectZoom = new ExportRectangle(viewRect); + viewRectZoom.xMin *= unzoom; + viewRectZoom.xMax *= unzoom; + viewRectZoom.yMin *= unzoom; + viewRectZoom.yMax *= unzoom; + + viewRectZoom.xMax -= viewRectZoom.xMin; + viewRectZoom.xMin = 0; + viewRectZoom.yMax -= viewRectZoom.yMin; + viewRectZoom.yMin = 0; + + /*viewRectZoom.yMin += 5; + viewRectZoom.xMin += 5; + viewRectZoom.xMax -= 5; + viewRectZoom.yMax -= 5;*/ + + g.setColor(Color.green); + g.setTransform(drawMatrix.toTransform()); + + ExportRectangle fullRect = fullTransformation.concatenate(layerMatrix).transform(new ExportRectangle(boundRect)); + if (!viewRectZoom.intersects(fullRect)) { + //System.err.println("hidden " + layer.characterId); + return; + } + strokeTransform = strokeTransform.concatenate(layerMatrix); boolean cacheAsBitmap = layer.cacheAsBitmap() && layer.placeObjectTag != null && drawable.isSingleFrame(); @@ -729,6 +755,7 @@ public class Timeline { img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB_PRE); img.fillTransparent(); + Matrix mfull = mat.clone(); if (canUseSameImage && sameImage) { img = image; m = mat.clone(); @@ -760,7 +787,7 @@ public class Timeline { } if (!(drawable instanceof ImageTag) || (swf.isAS3() && layer.hasImage)) { - drawable.toImage(dframe, time, ratio, renderContext, img, isClip || clipDepth > -1, m, strokeTransform, absMat, clrTrans2, unzoom, sameImage); + drawable.toImage(dframe, time, ratio, renderContext, img, isClip || clipDepth > -1, m, strokeTransform, absMat, mfull, clrTrans2, unzoom, sameImage, viewRect); } else { // todo: show one time warning } @@ -885,7 +912,7 @@ public class Timeline { } } - public void toImage(int frame, int time, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage) { + public void toImage(int frame, int time, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, Matrix fullTransformation) { //double unzoom = SWF.unitDivisor; //unzoom = SWF.unitDivisor; if (getFrameCount() <= frame) { @@ -1015,26 +1042,15 @@ public class Timeline { Rectangle2D r = new Rectangle2D.Double(p1.xMin, p1.yMin, p1.getWidth(), p1.getHeight()); g.setClip(r); - drawDrawable(strokeTransformation.preConcatenate(layerMatrix), layer, transforms[s], g, colorTransform, layer.blendMode, clips, transformation, isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans, sameImage); + drawDrawable(strokeTransformation.preConcatenate(layerMatrix), layer, transforms[s], g, colorTransform, layer.blendMode, clips, transformation, isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans, sameImage, viewRect, fullTransformation); s++; } } g.setClip(c); - /* - for (int s = 0; s < 9; s++) { - g.setTransform(new AffineTransform()); - ExportRectangle p1 = transformation.transform(targetRect[s]); - g.setClip(c); - - Rectangle2D r = new Rectangle2D.Double(p1.xMin, p1.yMin, p1.getWidth(), p1.getHeight()); - g.setColor(Color.blue); - g.draw(r); - - }*/ g.setTransform(origTransform); } else { - drawDrawable(strokeTransformation, layer, layerMatrix, g, colorTransform, layer.blendMode, clips, transformation, isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans, sameImage); + drawDrawable(strokeTransformation, layer, layerMatrix, g, colorTransform, layer.blendMode, clips, transformation, isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans, sameImage, viewRect, fullTransformation); } } else if (character instanceof BoundedTag) { showPlaceholder = true; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java index f1bcc119c..a944cc0ac 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java @@ -13,6 +13,7 @@ public class GraphPartMarkedArrayList extends ArrayList { private List> listParts = new ArrayList<>(); private List currentParts = new ArrayList<>(); + @SuppressWarnings("unchecked") public GraphPartMarkedArrayList(Collection collection) { super(collection); if (collection instanceof GraphPartMarkedArrayList) { @@ -64,6 +65,7 @@ public class GraphPartMarkedArrayList extends ArrayList { return -1; } + @SuppressWarnings("unchecked") @Override public boolean addAll(Collection c) { if (c instanceof GraphPartMarkedArrayList) { @@ -78,6 +80,7 @@ public class GraphPartMarkedArrayList extends ArrayList { return super.addAll(c); } + @SuppressWarnings("unchecked") @Override public boolean addAll(int index, Collection c) { if (c instanceof GraphPartMarkedArrayList) { diff --git a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java index 9a1b5ca14..10182477d 100644 --- a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.BoundedTag; @@ -290,9 +291,13 @@ public class FolderPreviewPanel extends JPanel { int height = 0; SerializableImage imgSrc = null; Matrix m = new Matrix(); + double ow = 1; + double oh = 1; if (treeItem instanceof Frame) { Frame fn = (Frame) treeItem; RECT rect = swf.displayRect; + ow = rect.getWidth(); + oh = rect.getHeight(); double zoom = 1.0; if (rect.getWidth() > 0) { double ratio = (PREVIEW_SIZE - 1) * SWF.unitDivisor / (rect.getWidth()); @@ -321,9 +326,13 @@ public class FolderPreviewPanel extends JPanel { imgSrc = ((ImageTag) treeItem).getImageCached(); width = imgSrc.getWidth(); height = imgSrc.getHeight(); + ow = width * SWF.unitDivisor; + oh = height * SWF.unitDivisor; } else if (treeItem instanceof BoundedTag) { BoundedTag boundedTag = (BoundedTag) treeItem; RECT rect = boundedTag.getRect(); + ow = rect.getWidth(); + oh = rect.getHeight(); width = (int) (rect.getWidth() / SWF.unitDivisor) + 1; height = (int) (rect.getHeight() / SWF.unitDivisor) + 1; m.translate(-rect.Xmin, -rect.Ymin); @@ -362,7 +371,8 @@ public class FolderPreviewPanel extends JPanel { image.fillTransparent(); if (imgSrc == null) { DrawableTag drawable = (DrawableTag) treeItem; - drawable.toImage(0, 0, 0, new RenderContext(), image, false, m, m, m, null, scale, false); + ExportRectangle viewRectangle = new ExportRectangle(0, 0, ow, oh); + drawable.toImage(0, 0, 0, new RenderContext(), image, false, m, m, m, m, null, scale, false, viewRectangle); } else { Graphics2D g = (Graphics2D) image.getGraphics(); g.setTransform(m.toTransform()); diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 6895086b6..bab1ffa92 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -45,6 +45,7 @@ import com.jpexs.decompiler.flash.types.ConstantColorColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Reference; @@ -204,6 +205,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private static Cursor shearXCursor; private static Cursor shearYCursor; + private Point offsetPoint = new Point(0, 0); + private Rectangle _rect = null; + private static Cursor loadCursor(String name, int x, int y) throws IOException { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image = ImageIO.read(MainPanel.class.getResource("/com/jpexs/decompiler/flash/gui/graphics/cursors/" + name + ".png")); @@ -336,7 +340,6 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private SerializableImage _img; - private Rectangle _rect = null; private ButtonTag mouseOverButton = null; @@ -346,7 +349,6 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private Point dragStart = null; - private Point offsetPoint = new Point(0, 0); private synchronized SerializableImage getImg() { return _img; @@ -393,7 +395,16 @@ public final class ImagePanel extends JPanel implements MediaDisplay { g2.setComposite(AlphaComposite.SrcOver); if (rect != null && img != null) { - g2.drawImage(img.getBufferedImage(), rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, 0, 0, img.getWidth(), img.getHeight(), null); + int x = rect.x < 0 ? 0 : rect.x; + int y = rect.y < 0 ? 0 : rect.y; + //x = rect.x; + //y = rect.y; + //System.err.println("rect:" + rect); + g2.drawImage(img.getBufferedImage(), x, y, x + img.getWidth(), y + img.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null); + +//rect.x + rect.width, rect.y + rect.height, 0, 0, img.getWidth(), img.getHeight(), null); + //g2.setColor(Color.black); + //g2.drawRect(rect.x, rect.y, rect.width, rect.height); } } finally { if (g2 != null) { @@ -1087,8 +1098,11 @@ public final class ImagePanel extends JPanel implements MediaDisplay { private synchronized void calcRect() { if (_img != null) { - int w1 = (int) (_img.getWidth() * (lowQuality ? LQ_FACTOR : 1)); - int h1 = (int) (_img.getHeight() * (lowQuality ? LQ_FACTOR : 1)); + //int w1 = (int) (_img.getWidth() * (lowQuality ? LQ_FACTOR : 1)); + //int h1 = (int) (_img.getHeight() * (lowQuality ? LQ_FACTOR : 1)); + double zoomDouble = zoom.fit ? getZoomToFit() : zoom.value; + int w1 = (int) (timelined.getRect().getWidth() * zoomDouble / SWF.unitDivisor); + int h1 = (int) (timelined.getRect().getHeight() * zoomDouble / SWF.unitDivisor); int w2 = getWidth(); int h2 = getHeight(); @@ -1115,7 +1129,8 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } setAllowMove(h > h2 || w > w2); - _rect = new Rectangle(getWidth() / 2 - w / 2 + offsetPoint.x, getHeight() / 2 - h / 2 + offsetPoint.y, w, h); + Rectangle r2 = new Rectangle(getWidth() / 2 - w / 2 + offsetPoint.x, getHeight() / 2 - h / 2 + offsetPoint.y, w, h); + _rect = r2; } else { _rect = null; } @@ -1321,6 +1336,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } fireMediaDisplayStateChanged(); + iconPanel.calcRect(); + iconPanel.render(); + iconPanel.repaint(); } } @@ -1509,10 +1527,10 @@ public final class ImagePanel extends JPanel implements MediaDisplay { image.fillTransparent(); Matrix m = Matrix.getTranslateInstance(-rect.Xmin * zoomDouble, -rect.Ymin * zoomDouble); m.scale(zoomDouble); - textTag.toImage(0, 0, 0, new RenderContext(), image, false, m, m, m, new ConstantColorColorTransform(0xFFC0C0C0), zoomDouble, false); + textTag.toImage(0, 0, 0, new RenderContext(), image, false, m, m, m, m, new ConstantColorColorTransform(0xFFC0C0C0), zoomDouble, false, new ExportRectangle(rect)); if (newTextTag != null) { - newTextTag.toImage(0, 0, 0, new RenderContext(), image, false, m, m, m, new ConstantColorColorTransform(0xFF000000), zoomDouble, false); + newTextTag.toImage(0, 0, 0, new RenderContext(), image, false, m, m, m, m, new ConstantColorColorTransform(0xFF000000), zoomDouble, false, new ExportRectangle(rect)); } iconPanel.setImg(image); @@ -1616,7 +1634,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { fireMediaDisplayStateChanged(); } - private static SerializableImage getFrame(SWF swf, int frame, int time, Timelined drawable, RenderContext renderContext, int selectedDepth, int freeTransformDepth, double zoom, Reference registrationPointRef, Reference boundsRef, Matrix transform, Matrix temporaryMatrix) { + private static SerializableImage getFrame(ExportRectangle viewRect, SWF swf, int frame, int time, Timelined drawable, RenderContext renderContext, int selectedDepth, int freeTransformDepth, double zoom, Reference registrationPointRef, Reference boundsRef, Matrix transform, Matrix temporaryMatrix) { Timeline timeline = drawable.getTimeline(); //int mouseButton = renderContext.mouseButton; //Point cursorPosition = renderContext.cursorPosition; @@ -1627,16 +1645,20 @@ public final class ImagePanel extends JPanel implements MediaDisplay { //boolean shouldCache = timeline.isSingleFrame(frame); RECT rect = drawable.getRect(); - int width = (int) (rect.getWidth() * zoom); - int height = (int) (rect.getHeight() * zoom); + int width = (int) (viewRect.getWidth() * zoom); //int) (rect.getWidth() * zoom); + int height = (int) (viewRect.getHeight() * zoom);//(int) (rect.getHeight() * zoom);(int) (rect.getHeight() * zoom); SerializableImage image = new SerializableImage((int) Math.ceil(width / SWF.unitDivisor), (int) Math.ceil(height / SWF.unitDivisor), SerializableImage.TYPE_INT_ARGB); //renderContext.borderImage = new SerializableImage(image.getWidth(), image.getHeight(), SerializableImage.TYPE_INT_ARGB); image.fillTransparent(); Matrix m = new Matrix(); - m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); + //m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); + m.translate(-viewRect.xMin * zoom, -viewRect.yMin * zoom); m.scale(zoom); + + Matrix fullM = m.clone(); + //fullM.translate(viewRect.xMin * zoom, viewRect.yMin * zoom); MATRIX oldMatrix = null; if (freeTransformDepth > -1) { @@ -1648,7 +1670,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { timeline.getFrame(frame).layers.get(freeTransformDepth).matrix = newMatrix; } - timeline.toImage(frame, time, renderContext, image, false, m, new Matrix(), m, null, zoom, false); + timeline.toImage(frame, time, renderContext, image, false, m, new Matrix(), m, null, zoom, false, viewRect, fullM); Graphics2D gg = (Graphics2D) image.getGraphics(); gg.setStroke(new BasicStroke(3)); @@ -1908,7 +1930,61 @@ public final class ImagePanel extends JPanel implements MediaDisplay { synchronized (lock) { Reference registrationPointRef = new Reference<>(registrationPoint); Reference boundsRef = new Reference<>(bounds); - img = getFrame(swf, frame, time, timelined, renderContext, selectedDepth, freeTransformDepth, zoomDouble, registrationPointRef, boundsRef, transform, transformUpdated == null ? null : new Matrix(transformUpdated)); + + ExportRectangle aRect; + if (_rect == null) { + aRect = new ExportRectangle(timelined.getRectWithStrokes()); + aRect.xMin /= SWF.unitDivisor; + aRect.xMax /= SWF.unitDivisor; + aRect.yMin /= SWF.unitDivisor; + aRect.yMax /= SWF.unitDivisor; + aRect.xMin *= zoomDouble; + aRect.xMax *= zoomDouble; + aRect.yMin *= zoomDouble; + aRect.yMax *= zoomDouble; + } else { + aRect = new ExportRectangle(_rect); + } + + ExportRectangle viewRect = new ExportRectangle(new RECT()); + + + if (aRect.xMin >= 0) { + viewRect.xMin = 0; + } else { + viewRect.xMin = -aRect.xMin; + } + double w = timelined.getRect().getWidth() * zoomDouble / SWF.unitDivisor; + if (w - viewRect.xMin > iconPanel.getWidth()) { + viewRect.xMax = viewRect.xMin + iconPanel.getWidth(); + } else { + viewRect.xMax = w; + } + + if (aRect.yMin >= 0) { + viewRect.yMin = 0; + } else { + viewRect.yMin = -aRect.yMin; + } + double h = timelined.getRect().getHeight() * zoomDouble / SWF.unitDivisor; + + if (h - viewRect.yMin > iconPanel.getHeight()) { + viewRect.yMax = viewRect.yMin + iconPanel.getHeight(); + } else { + viewRect.yMax = h; + } + + viewRect.xMin *= SWF.unitDivisor; + viewRect.xMax *= SWF.unitDivisor; + viewRect.yMin *= SWF.unitDivisor; + viewRect.yMax *= SWF.unitDivisor; + + viewRect.xMin /= zoomDouble; + viewRect.xMax /= zoomDouble; + viewRect.yMin /= zoomDouble; + viewRect.yMax /= zoomDouble; + + img = getFrame(viewRect, swf, frame, time, timelined, renderContext, selectedDepth, freeTransformDepth, zoomDouble, registrationPointRef, boundsRef, transform, transformUpdated == null ? null : new Matrix(transformUpdated)); bounds = boundsRef.getVal(); registrationPoint = registrationPointRef.getVal(); }