diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java index 581b8da88..f6845e380 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java @@ -297,9 +297,9 @@ public class IdentifiersDeobfuscation { return "\u00A7" + escapeOIdentifier(s) + "\u00A7"; } - private static final Cache as3NameCache = Cache.getInstance(false, "as3_ident"); + private static final Cache as3NameCache = Cache.getInstance(false, true, "as3_ident"); - private static final Cache as2NameCache = Cache.getInstance(false, "as2_ident"); + private static final Cache as2NameCache = Cache.getInstance(false, true, "as2_ident"); /** * Ensures identifier is valid and if not, uses paragraph syntax 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 2beb769cf..67873b9ef 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -308,13 +308,13 @@ public final class SWF implements SWFContainerItem, Timelined { private final IdentifiersDeobfuscation deobfuscation = new IdentifiersDeobfuscation(); @Internal - private static Cache frameCache = Cache.getInstance(false, "frame"); + private static Cache frameCache = Cache.getInstance(false, false, "frame"); @Internal - private final Cache as2Cache = Cache.getInstance(true, "as2"); + private final Cache as2Cache = Cache.getInstance(true, false, "as2"); @Internal - private final Cache as3Cache = Cache.getInstance(true, "as3"); + private final Cache as3Cache = Cache.getInstance(true, false, "as3"); public void updateCharacters() { characters = null; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/ShapeExporterBase.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/ShapeExporterBase.java index 8fb5f25b6..bf2e32476 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/ShapeExporterBase.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/ShapeExporterBase.java @@ -31,6 +31,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 com.jpexs.helpers.Cache; import java.awt.Color; import java.util.ArrayList; import java.util.Arrays; @@ -47,17 +48,19 @@ public abstract class ShapeExporterBase implements IShapeExporter { protected final SHAPE shape; - protected List _fillStyles; + private final List _fillStyles; - protected List _lineStyles; + private final List _lineStyles; - protected List>> _fillEdgeMaps; + private final List>> _fillEdgeMaps; - protected List>> _lineEdgeMaps; + private final List>> _lineEdgeMaps; - private boolean edgeMapsCreated; + private final ColorTransform colorTransform; - protected ColorTransform colorTransform; + private static final Cache>>> fillEdgeMapCache = Cache.getInstance(true, true, "fillEdgeMap"); + + private static final Cache>>> lineEdgeMapCache = Cache.getInstance(true, true, "lineEdgeMap"); public ShapeExporterBase(SHAPE shape, ColorTransform colorTransform) { this.shape = shape; @@ -69,14 +72,23 @@ public abstract class ShapeExporterBase implements IShapeExporter { _fillStyles.addAll(Arrays.asList(shapeWithStyle.fillStyles.fillStyles)); _lineStyles.addAll(Arrays.asList(shapeWithStyle.lineStyles.lineStyles)); } + + List>> fillEdgeMaps = fillEdgeMapCache.get(shape); + List>> lineEdgeMaps = lineEdgeMapCache.get(shape); + if (fillEdgeMaps == null || lineEdgeMaps == null) { + // Create edge maps + fillEdgeMaps = new ArrayList<>(); + lineEdgeMaps = new ArrayList<>(); + createEdgeMaps(shape, _fillStyles, _lineStyles, fillEdgeMaps, lineEdgeMaps); + fillEdgeMapCache.put(shape, fillEdgeMaps); + lineEdgeMapCache.put(shape, lineEdgeMaps); + } + + _fillEdgeMaps = fillEdgeMaps; + _lineEdgeMaps = lineEdgeMaps; } public void export() { - // Create edge maps - _fillEdgeMaps = new ArrayList<>(); - _lineEdgeMaps = new ArrayList<>(); - createEdgeMaps(_fillStyles, _lineStyles, _fillEdgeMaps, _lineEdgeMaps); - // Let the doc handler know that a shape export starts beginShape(); // Export fills and strokes for each group separately @@ -90,107 +102,104 @@ public abstract class ShapeExporterBase implements IShapeExporter { endShape(); } - protected void createEdgeMaps(List fillStyles, List lineStyles, + private void createEdgeMaps(SHAPE shape, List fillStyles, List lineStyles, List>> fillEdgeMaps, List>> lineEdgeMaps) { - if (!edgeMapsCreated) { - int xPos = 0; - int yPos = 0; - int fillStyleIdxOffset = 0; - int lineStyleIdxOffset = 0; - int currentFillStyleIdx0 = 0; - int currentFillStyleIdx1 = 0; - int currentLineStyleIdx = 0; - List subPath = new ArrayList<>(); - Map> currentFillEdgeMap = new HashMap<>(); - Map> currentLineEdgeMap = new HashMap<>(); - List records = shape.shapeRecords; - for (int i = 0; i < records.size(); i++) { - SHAPERECORD shapeRecord = records.get(i); - if (shapeRecord instanceof StyleChangeRecord) { - StyleChangeRecord styleChangeRecord = (StyleChangeRecord) shapeRecord; - if (styleChangeRecord.stateLineStyle || styleChangeRecord.stateFillStyle0 || styleChangeRecord.stateFillStyle1) { - processSubPath(subPath, currentLineStyleIdx, currentFillStyleIdx0, currentFillStyleIdx1, currentFillEdgeMap, currentLineEdgeMap); - subPath = new ArrayList<>(); - } - if (styleChangeRecord.stateNewStyles) { - fillStyleIdxOffset = fillStyles.size(); - lineStyleIdxOffset = lineStyles.size(); - appendFillStyles(fillStyles, styleChangeRecord.fillStyles.fillStyles); - appendLineStyles(lineStyles, styleChangeRecord.lineStyles.lineStyles); - } - // Check if all styles are reset to 0. - // This (probably) means that a new group starts with the next record - if (styleChangeRecord.stateLineStyle && styleChangeRecord.lineStyle == 0 - && styleChangeRecord.stateFillStyle0 && styleChangeRecord.fillStyle0 == 0 - && styleChangeRecord.stateFillStyle1 && styleChangeRecord.fillStyle1 == 0) { - cleanEdgeMap(currentFillEdgeMap); - cleanEdgeMap(currentLineEdgeMap); - fillEdgeMaps.add(currentFillEdgeMap); - lineEdgeMaps.add(currentLineEdgeMap); - currentFillEdgeMap = new HashMap<>(); - currentLineEdgeMap = new HashMap<>(); - currentLineStyleIdx = 0; - currentFillStyleIdx0 = 0; - currentFillStyleIdx1 = 0; - } else { - if (styleChangeRecord.stateLineStyle) { - currentLineStyleIdx = styleChangeRecord.lineStyle; - if (currentLineStyleIdx > 0) { - currentLineStyleIdx += lineStyleIdxOffset; - } - } - if (styleChangeRecord.stateFillStyle0) { - currentFillStyleIdx0 = styleChangeRecord.fillStyle0; - if (currentFillStyleIdx0 > 0) { - currentFillStyleIdx0 += fillStyleIdxOffset; - } - } - if (styleChangeRecord.stateFillStyle1) { - currentFillStyleIdx1 = styleChangeRecord.fillStyle1; - if (currentFillStyleIdx1 > 0) { - currentFillStyleIdx1 += fillStyleIdxOffset; - } - } - } - if (styleChangeRecord.stateMoveTo) { - xPos = styleChangeRecord.moveDeltaX; - yPos = styleChangeRecord.moveDeltaY; - } - } else if (shapeRecord instanceof StraightEdgeRecord) { - StraightEdgeRecord straightEdgeRecord = (StraightEdgeRecord) shapeRecord; - PointInt from = new PointInt(xPos, yPos); - if (straightEdgeRecord.generalLineFlag) { - xPos += straightEdgeRecord.deltaX; - yPos += straightEdgeRecord.deltaY; - } else { - if (straightEdgeRecord.vertLineFlag) { - yPos += straightEdgeRecord.deltaY; - } else { - xPos += straightEdgeRecord.deltaX; - } - } - PointInt to = new PointInt(xPos, yPos); - subPath.add(new StraightEdge(from, to, currentLineStyleIdx, currentFillStyleIdx1)); - } else if (shapeRecord instanceof CurvedEdgeRecord) { - CurvedEdgeRecord curvedEdgeRecord = (CurvedEdgeRecord) shapeRecord; - PointInt from = new PointInt(xPos, yPos); - int xPosControl = xPos + curvedEdgeRecord.controlDeltaX; - int yPosControl = yPos + curvedEdgeRecord.controlDeltaY; - xPos = xPosControl + curvedEdgeRecord.anchorDeltaX; - yPos = yPosControl + curvedEdgeRecord.anchorDeltaY; - PointInt control = new PointInt(xPosControl, yPosControl); - PointInt to = new PointInt(xPos, yPos); - subPath.add(new CurvedEdge(from, control, to, currentLineStyleIdx, currentFillStyleIdx1)); - } else if (shapeRecord instanceof EndShapeRecord) { - // We're done. Process the last subpath, if any + int xPos = 0; + int yPos = 0; + int fillStyleIdxOffset = 0; + int lineStyleIdxOffset = 0; + int currentFillStyleIdx0 = 0; + int currentFillStyleIdx1 = 0; + int currentLineStyleIdx = 0; + List subPath = new ArrayList<>(); + Map> currentFillEdgeMap = new HashMap<>(); + Map> currentLineEdgeMap = new HashMap<>(); + List records = shape.shapeRecords; + for (int i = 0; i < records.size(); i++) { + SHAPERECORD shapeRecord = records.get(i); + if (shapeRecord instanceof StyleChangeRecord) { + StyleChangeRecord styleChangeRecord = (StyleChangeRecord) shapeRecord; + if (styleChangeRecord.stateLineStyle || styleChangeRecord.stateFillStyle0 || styleChangeRecord.stateFillStyle1) { processSubPath(subPath, currentLineStyleIdx, currentFillStyleIdx0, currentFillStyleIdx1, currentFillEdgeMap, currentLineEdgeMap); + subPath = new ArrayList<>(); + } + if (styleChangeRecord.stateNewStyles) { + fillStyleIdxOffset = fillStyles.size(); + lineStyleIdxOffset = lineStyles.size(); + appendFillStyles(fillStyles, styleChangeRecord.fillStyles.fillStyles); + appendLineStyles(lineStyles, styleChangeRecord.lineStyles.lineStyles); + } + // Check if all styles are reset to 0. + // This (probably) means that a new group starts with the next record + if (styleChangeRecord.stateLineStyle && styleChangeRecord.lineStyle == 0 + && styleChangeRecord.stateFillStyle0 && styleChangeRecord.fillStyle0 == 0 + && styleChangeRecord.stateFillStyle1 && styleChangeRecord.fillStyle1 == 0) { cleanEdgeMap(currentFillEdgeMap); cleanEdgeMap(currentLineEdgeMap); fillEdgeMaps.add(currentFillEdgeMap); lineEdgeMaps.add(currentLineEdgeMap); + currentFillEdgeMap = new HashMap<>(); + currentLineEdgeMap = new HashMap<>(); + currentLineStyleIdx = 0; + currentFillStyleIdx0 = 0; + currentFillStyleIdx1 = 0; + } else { + if (styleChangeRecord.stateLineStyle) { + currentLineStyleIdx = styleChangeRecord.lineStyle; + if (currentLineStyleIdx > 0) { + currentLineStyleIdx += lineStyleIdxOffset; + } + } + if (styleChangeRecord.stateFillStyle0) { + currentFillStyleIdx0 = styleChangeRecord.fillStyle0; + if (currentFillStyleIdx0 > 0) { + currentFillStyleIdx0 += fillStyleIdxOffset; + } + } + if (styleChangeRecord.stateFillStyle1) { + currentFillStyleIdx1 = styleChangeRecord.fillStyle1; + if (currentFillStyleIdx1 > 0) { + currentFillStyleIdx1 += fillStyleIdxOffset; + } + } } + if (styleChangeRecord.stateMoveTo) { + xPos = styleChangeRecord.moveDeltaX; + yPos = styleChangeRecord.moveDeltaY; + } + } else if (shapeRecord instanceof StraightEdgeRecord) { + StraightEdgeRecord straightEdgeRecord = (StraightEdgeRecord) shapeRecord; + PointInt from = new PointInt(xPos, yPos); + if (straightEdgeRecord.generalLineFlag) { + xPos += straightEdgeRecord.deltaX; + yPos += straightEdgeRecord.deltaY; + } else { + if (straightEdgeRecord.vertLineFlag) { + yPos += straightEdgeRecord.deltaY; + } else { + xPos += straightEdgeRecord.deltaX; + } + } + PointInt to = new PointInt(xPos, yPos); + subPath.add(new StraightEdge(from, to, currentLineStyleIdx, currentFillStyleIdx1)); + } else if (shapeRecord instanceof CurvedEdgeRecord) { + CurvedEdgeRecord curvedEdgeRecord = (CurvedEdgeRecord) shapeRecord; + PointInt from = new PointInt(xPos, yPos); + int xPosControl = xPos + curvedEdgeRecord.controlDeltaX; + int yPosControl = yPos + curvedEdgeRecord.controlDeltaY; + xPos = xPosControl + curvedEdgeRecord.anchorDeltaX; + yPos = yPosControl + curvedEdgeRecord.anchorDeltaY; + PointInt control = new PointInt(xPosControl, yPosControl); + PointInt to = new PointInt(xPos, yPos); + subPath.add(new CurvedEdge(from, control, to, currentLineStyleIdx, currentFillStyleIdx1)); + } else if (shapeRecord instanceof EndShapeRecord) { + // We're done. Process the last subpath, if any + processSubPath(subPath, currentLineStyleIdx, currentFillStyleIdx0, currentFillStyleIdx1, currentFillEdgeMap, currentLineEdgeMap); + cleanEdgeMap(currentFillEdgeMap); + cleanEdgeMap(currentLineEdgeMap); + fillEdgeMaps.add(currentFillEdgeMap); + lineEdgeMaps.add(currentLineEdgeMap); } - edgeMapsCreated = true; } } 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 031ab4230..22cf194fa 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 @@ -86,7 +86,7 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer { private boolean isSingleFrame; - private static final Cache rectCache = Cache.getInstance(true, "rect_button2"); + private static final Cache rectCache = Cache.getInstance(true, true, "rect_button2"); @Override public int getCharacterId() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 63b90bf86..b106eb54a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -92,7 +92,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { private boolean isSingleFrame; - private static final Cache rectCache = Cache.getInstance(true, "rect_button"); + private static final Cache rectCache = Cache.getInstance(true, true, "rect_button"); @Override public List getRecords() { 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 50abbb3eb..99122af31 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 @@ -84,7 +84,7 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli private boolean isSingleFrame; - private static final Cache rectCache = Cache.getInstance(true, "rect_sprite"); + private static final Cache rectCache = Cache.getInstance(true, true, "rect_sprite"); @Override public Timeline getTimeline() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/Cache.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/Cache.java index c15a4f537..d5c2255d8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/helpers/Cache.java +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/Cache.java @@ -43,6 +43,8 @@ public class Cache implements Freed { private final boolean weak; + private final boolean memoryOnly; + private final String name; static { @@ -59,8 +61,8 @@ public class Cache implements Freed { }); } - public static Cache getInstance(boolean weak, String name) { - Cache instance = new Cache<>(weak, name); + public static Cache getInstance(boolean weak, boolean memoryOnly, String name) { + Cache instance = new Cache<>(weak, memoryOnly, name); instances.add(instance); return instance; } @@ -97,6 +99,9 @@ public class Cache implements Freed { private void initCache() { int thisStorageType = storageType; + if (memoryOnly) { + thisStorageType = STORAGE_MEMORY; + } Map newCache = null; if (thisStorageType == STORAGE_FILES) { try { @@ -118,9 +123,10 @@ public class Cache implements Freed { this.cache = newCache; } - private Cache(boolean weak, String name) { + private Cache(boolean weak, boolean memoryOnly, String name) { this.weak = weak; this.name = name; + this.memoryOnly = memoryOnly; initCache(); } diff --git a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java index edc3d0ce0..73e606404 100644 --- a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java @@ -91,7 +91,7 @@ public class FolderPreviewPanel extends JPanel { public FolderPreviewPanel(final MainPanel mainPanel, List items) { this.items = items; - cachedPreviews = Cache.getInstance(false, "preview"); + cachedPreviews = Cache.getInstance(false, false, "preview"); addMouseListener(new MouseAdapter() {