diff --git a/CHANGELOG.md b/CHANGELOG.md index b50e0f567..211053baa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ All notable changes to this project will be documented in this file. - Generic tag editor - Default values for filters - AS1/2 P-code actions inline documentation - AS1/2 P-code hilight currently selected action argument in action documentation -- [#2098] Shape points editation - Protection against saving too large edges +- [#2098] Shape points editation, transform - Protection against saving too large edges/rects ### Fixed - Close action on SWF inside DefineBinaryData diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/RECT.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/RECT.java index 85e698525..972fdd414 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/RECT.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/RECT.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.types; +import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.types.annotations.Calculated; import com.jpexs.decompiler.flash.types.annotations.SWFType; import java.awt.Point; @@ -93,4 +94,13 @@ public class RECT implements Serializable { public Point getBottomRight() { return new Point(Xmax, Ymax); } + + public void calculateBits() { + nbits = SWFOutputStream.getNeededBitsS(Xmin, Xmax, Ymin, Ymax); + } + + public boolean isTooLarge() { + calculateBits(); + return !SWFOutputStream.fitsInUB(5, nbits); + } } diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 09a4d7817..14d8486a8 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -2097,6 +2097,23 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel ); } + private boolean checkShapeLarge(List shapeRecords) { + for (SHAPERECORD rec : shapeRecords) { + if (rec.isTooLarge()) { + ViewMessages.showMessageDialog(this, AppStrings.translate("error.shapeTooLarge"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + return true; + } + } + return false; + } + private boolean checkRectLarge(RECT rect) { + if (rect.isTooLarge()) { + ViewMessages.showMessageDialog(this, AppStrings.translate("error.shapeTooLarge"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + return true; + } + return false; + } + private void saveDisplayEditTag(boolean refreshTree) { if (displayEditMode == EDIT_TRANSFORM) { Matrix matrix = displayEditImagePanel.getNewMatrix(); @@ -2108,13 +2125,33 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel if (displayEditTag instanceof ShapeTag) { ShapeTag shape = (ShapeTag) displayEditTag; - transformSHAPE(matrix, shape.shapes, shape.getShapeNum()); - transformStyles(matrix, shape.shapes.fillStyles, shape.shapes.lineStyles, shape.getShapeNum()); - - shape.shapeBounds = transformRECT(matrix, shape.shapeBounds); + + RECT newShapeBounds = transformRECT(matrix, shape.shapeBounds); + if (checkRectLarge(newShapeBounds)) { + return; + } + RECT newEdgeBounds = null; if (shape instanceof DefineShape4Tag) { DefineShape4Tag shape4 = (DefineShape4Tag) shape; - shape4.edgeBounds = transformRECT(matrix, shape4.edgeBounds); + newEdgeBounds = transformRECT(matrix, shape4.edgeBounds); + if (checkRectLarge(newEdgeBounds)) { + return; + } + } + + oldShapeRecords = Helper.deepCopy(shape.shapes.shapeRecords); + transformSHAPE(matrix, shape.shapes, shape.getShapeNum()); + if (checkShapeLarge(shape.shapes.shapeRecords)) { + shape.shapes.shapeRecords = oldShapeRecords; + return; + } + oldShapeRecords = null; + transformStyles(matrix, shape.shapes.fillStyles, shape.shapes.lineStyles, shape.getShapeNum()); + + shape.shapeBounds = newShapeBounds; + if (shape instanceof DefineShape4Tag) { + DefineShape4Tag shape4 = (DefineShape4Tag) shape; + shape4.edgeBounds = newEdgeBounds; } shape.shapes.clearCachedOutline(); shape.getSwf().clearShapeCache(); @@ -2124,21 +2161,53 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel MorphShapeTag morphShape = (MorphShapeTag) displayEditTag; if (morphDisplayMode == MORPH_START) { - transformSHAPE(matrix, morphShape.startEdges, morphShape.getShapeNum() == 1 ? 3 : 4); - morphShape.startBounds = transformRECT(matrix, morphShape.startBounds); + RECT newShapeBounds = transformRECT(matrix, morphShape.startBounds); + if (checkRectLarge(newShapeBounds)) { + return; + } + RECT newEdgeBounds = null; if (morphShape instanceof DefineMorphShape2Tag) { DefineMorphShape2Tag morphShape2 = (DefineMorphShape2Tag) morphShape; - morphShape2.startEdgeBounds = transformRECT(matrix, morphShape2.startEdgeBounds); + newEdgeBounds = transformRECT(matrix, morphShape2.startEdgeBounds); + } + + oldShapeRecords = Helper.deepCopy(morphShape.startEdges.shapeRecords); + transformSHAPE(matrix, morphShape.startEdges, morphShape.getShapeNum() == 1 ? 3 : 4); + if (checkShapeLarge(morphShape.startEdges.shapeRecords)) { + morphShape.startEdges.shapeRecords = oldShapeRecords; + return; + } + oldShapeRecords = null; + morphShape.startBounds = newShapeBounds; + if (morphShape instanceof DefineMorphShape2Tag) { + DefineMorphShape2Tag morphShape2 = (DefineMorphShape2Tag) morphShape; + morphShape2.startEdgeBounds = newEdgeBounds; } transformMorphStyles(matrix, morphShape.morphFillStyles, morphShape.morphLineStyles, morphShape.getShapeNum(), true, false); } if (morphDisplayMode == MORPH_END) { - transformSHAPE(matrix, morphShape.endEdges, morphShape.getShapeNum() == 1 ? 3 : 4); - morphShape.endBounds = transformRECT(matrix, morphShape.endBounds); + RECT newShapeBounds = transformRECT(matrix, morphShape.endBounds); + if (checkRectLarge(newShapeBounds)) { + return; + } + RECT newEdgeBounds = null; if (morphShape instanceof DefineMorphShape2Tag) { DefineMorphShape2Tag morphShape2 = (DefineMorphShape2Tag) morphShape; - morphShape2.endEdgeBounds = transformRECT(matrix, morphShape2.endEdgeBounds); + newEdgeBounds = transformRECT(matrix, morphShape2.endEdgeBounds); + } + + oldShapeRecords = Helper.deepCopy(morphShape.endEdges.shapeRecords); + transformSHAPE(matrix, morphShape.endEdges, morphShape.getShapeNum() == 1 ? 3 : 4); + if (checkShapeLarge(morphShape.endEdges.shapeRecords)) { + morphShape.endEdges.shapeRecords = oldShapeRecords; + return; + } + oldShapeRecords = null; + morphShape.endBounds = newShapeBounds; + if (morphShape instanceof DefineMorphShape2Tag) { + DefineMorphShape2Tag morphShape2 = (DefineMorphShape2Tag) morphShape; + morphShape2.endEdgeBounds = newEdgeBounds; } transformMorphStyles(matrix, morphShape.morphFillStyles, morphShape.morphLineStyles, morphShape.getShapeNum(), false, true); } @@ -2158,38 +2227,63 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel List shapeRecords = null; if (displayEditTag instanceof ShapeTag) { ShapeTag shape = (ShapeTag) displayEditTag; - shapeRecords = shape.shapes.shapeRecords; + if (checkShapeLarge(shape.shapes.shapeRecords)) { + return; + } } if (displayEditTag instanceof MorphShapeTag) { MorphShapeTag morphShape = (MorphShapeTag) displayEditTag; if (morphDisplayMode == MORPH_START) { - shapeRecords = morphShape.getStartEdges().shapeRecords; - } - if (morphDisplayMode == MORPH_END) { - shapeRecords = morphShape.getEndEdges().shapeRecords; - } - } - if (shapeRecords != null) { - for (SHAPERECORD rec : shapeRecords) { - if (rec.isTooLarge()) { - ViewMessages.showMessageDialog(this, AppStrings.translate("error.shapeTooLarge"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + if (checkShapeLarge(morphShape.getStartEdges().shapeRecords)) { return; } } - } + if (morphDisplayMode == MORPH_END) { + if (checkShapeLarge(morphShape.getEndEdges().shapeRecords)) { + return; + } + } + } displayEditImagePanel.setHilightedPoints(null); displayEditTag.setModified(true); if (displayEditTag instanceof ShapeTag) { ShapeTag shape = (ShapeTag) displayEditTag; shape.updateBounds(); + if (checkRectLarge(shape.shapeBounds)) { + return; + } + if (shape instanceof DefineShape4Tag) { + DefineShape4Tag shape4 = (DefineShape4Tag) shape; + if (checkRectLarge(shape4.edgeBounds)) { + return; + } + } } if (displayEditTag instanceof MorphShapeTag) { MorphShapeTag morphShape = (MorphShapeTag) displayEditTag; if (morphDisplayMode == MORPH_START) { morphShape.updateStartBounds(); + if (checkRectLarge(morphShape.endBounds)) { + return; + } + if (morphShape instanceof DefineMorphShape2Tag) { + DefineMorphShape2Tag morphShape2 = (DefineMorphShape2Tag) morphShape; + if (checkRectLarge(morphShape2.endEdgeBounds)) { + return; + } + } } if (morphDisplayMode == MORPH_END) { morphShape.updateEndBounds(); + if (checkRectLarge(morphShape.startBounds)) { + return; + } + if (morphShape instanceof DefineMorphShape2Tag) { + DefineMorphShape2Tag morphShape2 = (DefineMorphShape2Tag) morphShape; + if (checkRectLarge(morphShape2.startEdgeBounds)) { + return; + } + } } } oldShapeRecords = null; diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 16ce7f87d..646be3e7b 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1172,4 +1172,4 @@ import.sprite.result = %count% sprites imported. menu.file.import.sprite = Import sprites from GIF -error.shapeTooLarge = One or more edge lengths of the shape is too large to save.\r\nPlease move points closer, resize shape or insert a point in the middle of long edges before proceeding. +error.shapeTooLarge = Some lengths in the shape are too large to save.\r\nPlease move points closer, resize shape and/or insert a point in the middle of long edges before proceeding. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 8cc0e021e..1ce69c3f7 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -1149,4 +1149,4 @@ binarydata.swfInside.packer = Vypad\u00e1 to, \u017ee uvnit\u0159 v tomto Binary button.replaceWithGif = Nahradit GIFem... -error.shapeTooLarge = Jedna \u010di v\u00edce hran v tvaru je moc dlouh\u00e1 pro ulo\u017een\u00ed.\r\nPros\u00edm p\u0159ed pokra\u010dov\u00e1n\u00edm p\u0159esu\u0148te body bl\u00ed\u017ee, zmen\u0161ete tvar nebo vlo\u017ete bod doprost\u0159ed dlouh\u00e9 hrany. +error.shapeTooLarge = N\u011bkter\u00e9 d\u00e9lky ve tvaru jsou p\u0159\u00edli\u0161 velk\u00e9 pro ulo\u017een\u00ed.\r\nPros\u00edm p\u0159ed pokra\u010dov\u00e1n\u00edm p\u0159esu\u0148te body bl\u00ed\u017ee, zmen\u0161ete tvar a/nebo vlo\u017ete bod doprost\u0159ed dlouh\u00e9 hrany.