diff --git a/CHANGELOG.md b/CHANGELOG.md index 84ce2f3ff..eeb9f0d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,11 +10,14 @@ All notable changes to this project will be documented in this file. - [#2005] Export files to directories by bundle names on multiple bundle (zips, etc.) selection - ActionScript Debugger - Call stack frames switching - view variables around call stack - ActionScript Debugger - Highlight lines of callstack +- [#2105] GFX - Basic tag info ### Fixed - [#1306], [#1768] Maximizing window on other than main monitor - AS3 Cast exception when used tree filter and then direct editing - [#2013] AS3 Multiname renaming - closing the script when renaming the class, nullpointer exception +- GFX - FontTextureInfo tag reading +- GFX - Fonts with stripped shapes ### Changed - Basic tag info panel always visible even when nothing to display (to avoid flickering) @@ -3202,6 +3205,7 @@ Major version of SWF to XML export changed to 2. [#1220]: https://www.free-decompiler.com/flash/issues/1220 [#1717]: https://www.free-decompiler.com/flash/issues/1717 [#2005]: https://www.free-decompiler.com/flash/issues/2005 +[#2105]: https://www.free-decompiler.com/flash/issues/2105 [#1306]: https://www.free-decompiler.com/flash/issues/1306 [#1768]: https://www.free-decompiler.com/flash/issues/1768 [#2013]: https://www.free-decompiler.com/flash/issues/2013 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 0f85541ca..0a2a537ca 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -139,6 +139,7 @@ import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.enums.ImageFormat; import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage2; +import com.jpexs.decompiler.flash.tags.gfx.ExporterInfo; import com.jpexs.decompiler.flash.timeline.AS2Package; import com.jpexs.decompiler.flash.timeline.Frame; import com.jpexs.decompiler.flash.timeline.FrameScript; @@ -412,9 +413,13 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { @Internal private AbcIndexing abcIndex; + @Internal private int numAbcIndexDependencies = 0; private volatile Map> uninitializedAs2ClassTraits = null; + + @Internal + private ExporterInfo exporterInfo = null; private static AbcIndexing playerGlobalAbcIndex; @@ -442,6 +447,24 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { public static final int LIBRARY_AIR = 0; public static final int LIBRARY_FLASH = 1; + public void setExporterInfo(ExporterInfo exporterInfo) { + this.exporterInfo = exporterInfo; + } + + public ExporterInfo getExporterInfo() { + return exporterInfo; + } + + public boolean hasStrippedShapesFromFonts() { + if (exporterInfo == null) { + return false; + } + if (exporterInfo.hasFlagShapesStrippedFromDefineFont()) { + return true; + } + return false; + } + public static AbcIndexing getPlayerGlobalAbcIndex() { return playerGlobalAbcIndex; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java index da2ee6209..1ab543905 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -1215,9 +1215,15 @@ public class SWFInputStream implements AutoCloseable { boolean doParse = true; - if (parseTags && !parallel1 && doParse && (tag instanceof TagStub)) { + if (((parseTags && !parallel1 && doParse) || (tag.getId() == ExporterInfo.ID)) && (tag instanceof TagStub)) { tag = resolveTag((TagStub) tag, level, parallel, skipUnusualTags, lazy, true); } + if (tag instanceof ExporterInfo) { + ExporterInfo ei = (ExporterInfo) tag; + if (swf != null) { + swf.setExporterInfo(ei); + } + } DumpInfo di = dumpInfo; if (di != null && tag != null) { di.name = tag.getName(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java index a80427596..e4959da54 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.types.LANGCODE; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPE; import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; @@ -72,6 +73,7 @@ public class DefineFont2Tag extends FontTag { public String fontName; + @Conditional("!strippedShapes") public List glyphShapeTable; @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") @@ -100,6 +102,12 @@ public class DefineFont2Tag extends FontTag { @Conditional("fontFlagsHasLayout") public List fontKerningTable; + @Internal + public long unknownGfx; + + @Internal + public boolean strippedShapes = false; + /** * Constructor * @@ -140,28 +148,41 @@ public class DefineFont2Tag extends FontTag { languageCode = sis.readLANGCODE("languageCode"); fontName = sis.readNetString("fontName"); int numGlyphs = sis.readUI16("numGlyphs"); - long[] offsetTable = new long[numGlyphs]; - long pos = sis.getPos(); - for (int i = 0; i < numGlyphs; i++) { //offsetTable - if (fontFlagsWideOffsets) { - offsetTable[i] = sis.readUI32("offset"); - } else { - offsetTable[i] = sis.readUI16("offset"); + + strippedShapes = swf.hasStrippedShapesFromFonts(); + + if (!strippedShapes) { + long[] offsetTable = new long[numGlyphs]; + long pos = sis.getPos(); + for (int i = 0; i < numGlyphs; i++) { //offsetTable + if (fontFlagsWideOffsets) { + offsetTable[i] = sis.readUI32("offset"); + } else { + offsetTable[i] = sis.readUI16("offset"); + } } - } - if (numGlyphs > 0 || fontFlagsHasLayout) { - if (fontFlagsWideOffsets) { - sis.readUI32("codeTableOffset"); - } else { - sis.readUI16("codeTableOffset"); + if (numGlyphs > 0 || fontFlagsHasLayout) { + if (fontFlagsWideOffsets) { + sis.readUI32("codeTableOffset"); + } else { + sis.readUI16("codeTableOffset"); + } } - } - glyphShapeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - sis.seek(pos + offsetTable[i]); - glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + sis.seek(pos + offsetTable[i]); + glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); + } + } else { + if (numGlyphs > 0 || fontFlagsHasLayout) { + unknownGfx = sis.readUI32("unknownGfx"); + } + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + glyphShapeTable.add(new SHAPE()); + } } codeTable = new ArrayList<>(); //[numGlyphs]; @@ -260,33 +281,37 @@ public class DefineFont2Tag extends FontTag { int numGlyphs = glyphShapeTable.size(); sos.writeUI16(numGlyphs); - List offsetTable = new ArrayList<>(); - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + if (!swf.hasStrippedShapesFromFonts()) { + List offsetTable = new ArrayList<>(); + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion(), getCharset()); - for (int i = 0; i < numGlyphs; i++) { - offsetTable.add((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos()); - sos3.writeSHAPE(glyphShapeTable.get(i), 1); - } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); - for (Long offset : offsetTable) { - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) (long) offset); + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion(), getCharset()); + for (int i = 0; i < numGlyphs; i++) { + offsetTable.add((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos()); + sos3.writeSHAPE(glyphShapeTable.get(i), 1); } - } + byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); + for (Long offset : offsetTable) { + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) (long) offset); + } + } - if (numGlyphs > 0 || fontFlagsHasLayout) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) offset); + if (numGlyphs > 0 || fontFlagsHasLayout) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) offset); + } } - } - if (numGlyphs > 0) { - sos.write(baGlyphShapes); + if (!swf.hasStrippedShapesFromFonts() && numGlyphs > 0) { + sos.write(baGlyphShapes); + } + } else { + sos.writeUI32(unknownGfx); } for (int i = 0; i < numGlyphs; i++) { if (fontFlagsWideCodes) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java index e41ff7d67..63b51ebf8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java @@ -21,12 +21,14 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.helpers.FontHelper; import com.jpexs.decompiler.flash.tags.base.FontTag; +import com.jpexs.decompiler.flash.tags.gfx.ExporterInfo; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.KERNINGRECORD; import com.jpexs.decompiler.flash.types.LANGCODE; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPE; import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; @@ -72,6 +74,7 @@ public class DefineFont3Tag extends FontTag { public String fontName; + @Conditional("!strippedShapes") public List glyphShapeTable; @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") @@ -99,6 +102,12 @@ public class DefineFont3Tag extends FontTag { @Conditional("fontFlagsHasLayout") public List fontKerningTable; + + @Internal + public long unknownGfx; + + @Internal + public boolean strippedShapes = false; /** * Constructor @@ -133,26 +142,38 @@ public class DefineFont3Tag extends FontTag { languageCode = sis.readLANGCODE("languageCode"); fontName = sis.readNetString("fontName"); int numGlyphs = sis.readUI16("numGlyphs"); - long[] offsetTable = new long[numGlyphs]; - long pos = sis.getPos(); - for (int i = 0; i < numGlyphs; i++) { //offsetTable - if (fontFlagsWideOffsets) { - offsetTable[i] = sis.readUI32("offset"); - } else { - offsetTable[i] = sis.readUI16("offset"); + strippedShapes = swf.hasStrippedShapesFromFonts(); + + if (!strippedShapes) { + long[] offsetTable = new long[numGlyphs]; + long pos = sis.getPos(); + for (int i = 0; i < numGlyphs; i++) { //offsetTable + if (fontFlagsWideOffsets) { + offsetTable[i] = sis.readUI32("offset"); + } else { + offsetTable[i] = sis.readUI16("offset"); + } } - } - if (numGlyphs > 0 || fontFlagsHasLayout) { - if (fontFlagsWideOffsets) { - sis.readUI32("codeTableOffset"); - } else { - sis.readUI16("codeTableOffset"); + if (numGlyphs > 0 || fontFlagsHasLayout) { + if (fontFlagsWideOffsets) { + sis.readUI32("codeTableOffset"); + } else { + sis.readUI16("codeTableOffset"); + } + } + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + sis.seek(pos + offsetTable[i]); + glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); + } + } else { + if (numGlyphs > 0 || fontFlagsHasLayout) { + unknownGfx = sis.readUI32("unknownGfx"); + } + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + glyphShapeTable.add(new SHAPE()); } - } - glyphShapeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - sis.seek(pos + offsetTable[i]); - glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); } codeTable = new ArrayList<>(); for (int i = 0; i < numGlyphs; i++) { @@ -237,11 +258,14 @@ public class DefineFont3Tag extends FontTag { ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion(), getCharset()); int numGlyphs = glyphShapeTable.size(); - for (int i = 0; i < numGlyphs; i++) { - offsetTable.add(sos3.getPos()); - sos3.writeSHAPE(glyphShapeTable.get(i), 1); + byte[] baGlyphShapes = null; + if (!swf.hasStrippedShapesFromFonts()) { + for (int i = 0; i < numGlyphs; i++) { + offsetTable.add(sos3.getPos()); + sos3.writeSHAPE(glyphShapeTable.get(i), 1); + } + baGlyphShapes = baosGlyphShapes.toByteArray(); } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); sos.writeUI16(fontID); sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); @@ -256,24 +280,28 @@ public class DefineFont3Tag extends FontTag { sos.writeNetString(fontName); sos.writeUI16(numGlyphs); - for (long offset : offsetTable) { - long offset2 = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + offset; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset2); - } else { - sos.writeUI16((int) offset2); + if (!swf.hasStrippedShapesFromFonts()) { + for (long offset : offsetTable) { + long offset2 = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + offset; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset2); + } else { + sos.writeUI16((int) offset2); + } } - } - if (numGlyphs > 0 || fontFlagsHasLayout) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) offset); + if (numGlyphs > 0 || fontFlagsHasLayout) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) offset); + } } - } - if (numGlyphs > 0) { - sos.write(baGlyphShapes); + if (numGlyphs > 0) { + sos.write(baGlyphShapes); + } + } else { + sos.writeUI32(unknownGfx); } for (int i = 0; i < numGlyphs; i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java index 0f925a56f..9d670e30c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.tags.base.FontInfoTag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.annotations.Conditional; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; @@ -50,10 +51,17 @@ public class DefineFontTag extends FontTag { @SWFType(BasicType.UI16) public int fontId; + @Conditional("!strippedShapes") public List glyphShapeTable; @Internal private FontInfoTag fontInfoTag = null; + + @Internal + public long unknownGfx; + + @Internal + public boolean strippedShapes = false; /** * Constructor @@ -83,7 +91,9 @@ public class DefineFontTag extends FontTag { fontId = sis.readUI16("fontId"); glyphShapeTable = new ArrayList<>(); - if (sis.available() > 0) { + strippedShapes = swf.hasStrippedShapesFromFonts(); + + if (!strippedShapes && sis.available() > 0) { long pos = sis.getPos(); int firstOffset = sis.readUI16("firstOffset"); int nGlyphs = firstOffset / 2; @@ -98,6 +108,9 @@ public class DefineFontTag extends FontTag { glyphShapeTable.add(sis.readSHAPE(1, false, "shape")); } } + if (strippedShapes) { + unknownGfx = sis.readUI32("unknownGfx"); + } } /** @@ -109,17 +122,21 @@ public class DefineFontTag extends FontTag { @Override public synchronized void getData(SWFOutputStream sos) throws IOException { sos.writeUI16(fontId); - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - List offsetTable = new ArrayList<>(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion(), getCharset()); - for (SHAPE shape : glyphShapeTable) { - offsetTable.add(glyphShapeTable.size() * 2 + (int) sos2.getPos()); - sos2.writeSHAPE(shape, 1); - } - for (int offset : offsetTable) { - sos.writeUI16(offset); - } - sos.write(baos2.toByteArray()); + if (!swf.hasStrippedShapesFromFonts()) { + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + List offsetTable = new ArrayList<>(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion(), getCharset()); + for (SHAPE shape : glyphShapeTable) { + offsetTable.add(glyphShapeTable.size() * 2 + (int) sos2.getPos()); + sos2.writeSHAPE(shape, 1); + } + for (int offset : offsetTable) { + sos.writeUI16(offset); + } + sos.write(baos2.toByteArray()); + } else { + sos.writeUI32(unknownGfx); + } } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalGradient.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalGradient.java index de72da147..3947931d8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalGradient.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalGradient.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; @@ -90,4 +91,25 @@ public class DefineExternalGradient extends Tag { public String toString() { return tagName + " (g" + gradientId + ")"; } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + tagInfo.addInfo("general", "fileName", fileName); + String bitmapFormatStr = "0x" + Integer.toHexString(bitmapsFormat); + switch (bitmapsFormat) { + case BITMAP_FORMAT_DEFAULT: + bitmapFormatStr = "default (0)"; + break; + case BITMAP_FORMAT_TGA: + bitmapFormatStr = "TGA (1)"; + break; + case BITMAP_FORMAT_DDS: + bitmapFormatStr = "DDS (2)"; + break; + } + tagInfo.addInfo("general", "bitmapsFormat", bitmapFormatStr); + tagInfo.addInfo("general", "gradientSize", gradientSize); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java index 4f0774d32..460756b4f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.gfx.TgaSupport; import com.jpexs.decompiler.flash.helpers.ImageHelper; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.tags.enums.ImageFormat; import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; @@ -219,4 +220,25 @@ public class DefineExternalImage extends ImageTag { public boolean importSupported() { return false; } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + tagInfo.addInfo("general", "exportName", exportName); + tagInfo.addInfo("general", "fileName", fileName); + String bitmapFormatStr = "0x" + Integer.toHexString(bitmapFormat); + switch (bitmapFormat) { + case BITMAP_FORMAT_DEFAULT: + bitmapFormatStr = "default (0)"; + break; + case BITMAP_FORMAT_TGA: + bitmapFormatStr = "TGA (1)"; + break; + case BITMAP_FORMAT_DDS: + bitmapFormatStr = "DDS (2)"; + break; + } + tagInfo.addInfo("general", "bitmapFormat", bitmapFormatStr); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java index 4e8d958f9..a75c60d57 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.gfx.TgaSupport; import com.jpexs.decompiler.flash.helpers.ImageHelper; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.tags.enums.ImageFormat; import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; @@ -268,4 +269,38 @@ public class DefineExternalImage2 extends ImageTag { public void setCharacterId(int characterId) { } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + tagInfo.addInfo("general", "exportName", exportName); + tagInfo.addInfo("general", "fileName", fileName); + String bitmapFormatStr = "0x" + Integer.toHexString(bitmapFormat); + switch (bitmapFormat) { + case BITMAP_FORMAT_DEFAULT: + bitmapFormatStr = "default (0)"; + break; + case BITMAP_FORMAT_TGA: + bitmapFormatStr = "TGA (1)"; + break; + case BITMAP_FORMAT_DDS: + bitmapFormatStr = "DDS (2)"; + break; + case BITMAP_FORMAT2_JPEG: + bitmapFormatStr = "JPEG (10)"; + break; + case BITMAP_FORMAT2_TGA: + bitmapFormatStr = "TGA (13)"; + break; + case BITMAP_FORMAT2_DDS: + bitmapFormatStr = "DDS (14)"; + break; + } + tagInfo.addInfo("general", "bitmapFormat", bitmapFormatStr); + + if (unknownID != 0) { + tagInfo.addInfo("general", "imageId", imageID); + } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java index 8df2f6562..c77cfe49b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java @@ -235,6 +235,8 @@ public class DefineExternalSound extends CharacterTag implements SoundTag { public void getTagInfo(TagInfo tagInfo) { super.getTagInfo(tagInfo); SoundFormat soundFormat = getSoundFormat(); + tagInfo.addInfo("general", "exportName", exportName); + tagInfo.addInfo("general", "fileName", fileName); tagInfo.addInfo("general", "codecName", soundFormat.getFormatName()); tagInfo.addInfo("general", "exportFormat", soundFormat.getNativeExportFormat()); tagInfo.addInfo("general", "samplingRate", soundFormat.samplingRate); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java index 9a11513b1..ac075ff48 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java @@ -248,6 +248,7 @@ public class DefineExternalStreamSound extends Tag implements CharacterIdTag, So public void getTagInfo(TagInfo tagInfo) { super.getTagInfo(tagInfo); SoundFormat soundFormat = getSoundFormat(); + tagInfo.addInfo("general", "fileName", fileName); tagInfo.addInfo("general", "codecName", soundFormat.getFormatName()); tagInfo.addInfo("general", "exportFormat", soundFormat.getNativeExportFormat()); tagInfo.addInfo("general", "samplingRate", soundFormat.samplingRate); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java index 5c04b494c..7ad8178f6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java @@ -20,8 +20,11 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * @@ -74,4 +77,16 @@ public class DefineGradientMap extends Tag { indices[i] = sis.readUI16("index"); } } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + List indicesStr = new ArrayList<>(); + for (int index : indices) { + indicesStr.add("" + index); + } + + tagInfo.addInfo("general", "indices", String.join(", ", indicesStr)); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java index 6bd9ddab5..e798604b2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.tags.gfx; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.tags.enums.ImageFormat; import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; @@ -219,4 +220,15 @@ public class DefineSubImage extends ImageTag { } } } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + tagInfo.addInfo("general", "imageId", imageId); + tagInfo.addInfo("general", "x1", x1); + tagInfo.addInfo("general", "y1", y1); + tagInfo.addInfo("general", "x2", x2); + tagInfo.addInfo("general", "y2", y2); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfo.java index 0f511b1f2..101ee277b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfo.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; import java.util.ArrayList; @@ -49,15 +50,28 @@ public class ExporterInfo extends Tag { public List codeOffsets; + public static final int BITMAP_FORMAT_DEFAULT = 0; + public static final int BITMAP_FORMAT_TGA = 1; public static final int BITMAP_FORMAT_DDS = 2; + //It looks like gfxexport produces BITMAP_FORMAT2_* values for format, + //but BITMAP_FORMAT_* works the same way + public static final int BITMAP_FORMAT2_JPEG = 10; + + public static final int BITMAP_FORMAT2_TGA = 13; + + public static final int BITMAP_FORMAT2_DDS = 14; + public static final int FLAG_CONTAINS_GLYPH_TEXTURES = 1; public static final int FLAG_GLYPHS_STRIPPED_FROM_DEFINEFONT = 2; public static final int FLAG_GRADIENT_IMAGES_EXPORTED = 4; + + public static final int FLAG_SHAPES_STRIPPED_FROM_DEFINEFONT = 16; + /** * Gets data bytes @@ -117,4 +131,49 @@ public class ExporterInfo extends Tag { } } } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + tagInfo.addInfo("general", "version", version); + tagInfo.addInfo("general", "flags", "0x" + Long.toHexString(flags)); + String bitmapFormatStr = "0x" + Integer.toHexString(bitmapFormat); + switch (bitmapFormat) { + case BITMAP_FORMAT_DEFAULT: + bitmapFormatStr = "default (0)"; + break; + case BITMAP_FORMAT_TGA: + bitmapFormatStr = "TGA (1)"; + break; + case BITMAP_FORMAT_DDS: + bitmapFormatStr = "DDS (2)"; + break; + case BITMAP_FORMAT2_JPEG: + bitmapFormatStr = "JPEG (10)"; + break; + case BITMAP_FORMAT2_TGA: + bitmapFormatStr = "TGA (13)"; + break; + case BITMAP_FORMAT2_DDS: + bitmapFormatStr = "DDS (14)"; + break; + } + tagInfo.addInfo("general", "bitmapFormat", bitmapFormatStr); + tagInfo.addInfo("general", "prefix", prefix); + tagInfo.addInfo("general", "swfName", swfName); + + if (codeOffsets != null) { + List codeOffsetsStr = new ArrayList<>(); + for (long codeOffset : codeOffsets) { + codeOffsetsStr.add("" + codeOffset); + } + + tagInfo.addInfo("general", "codeOffsets", String.join(", ", codeOffsetsStr)); + } + } + + public boolean hasFlagShapesStrippedFromDefineFont() { + return (flags & FLAG_SHAPES_STRIPPED_FROM_DEFINEFONT) == FLAG_SHAPES_STRIPPED_FROM_DEFINEFONT; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java index 4a842fe0b..3a8f9f1f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagInfo; import com.jpexs.decompiler.flash.types.gfx.FONTINFO; import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; @@ -38,7 +39,9 @@ public class FontTextureInfo extends Tag { public static final String NAME = "FontTextureInfo"; - public long textureID; + public int textureID; + + public int unknownID; public int textureFormat; @@ -61,7 +64,18 @@ public class FontTextureInfo extends Tag { public static final int TEXTURE_FORMAT_TGA = 1; public static final int TEXTURE_FORMAT_DDS = 2; + + //It looks like gfxexport produces TEXTURE_FORMAT2_* values for format, + //but BITMAP_FORMAT_* works the same way + public static final int TEXTURE_FORMAT2_JPEG = 10; + public static final int TEXTURE_FORMAT2_TGA = 13; + + public static final int TEXTURE_FORMAT2_DDS = 14; + + public static final int UNKNOWN_IS_SINGLE = 0; + public static final int UNKNOWN_IS_MULTIPLE = 6; + /** * Gets data bytes * @@ -70,7 +84,8 @@ public class FontTextureInfo extends Tag { */ @Override public void getData(SWFOutputStream sos) throws IOException { - sos.writeUI32(textureID); + sos.writeUI16(textureID); + sos.writeUI16(unknownID); sos.writeUI16(textureFormat); sos.writeNetString(fileName); sos.writeUI16(textureWidth); @@ -106,7 +121,8 @@ public class FontTextureInfo extends Tag { @Override public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { - textureID = sis.readUI32("textureID"); + textureID = sis.readUI16("textureID"); + unknownID = sis.readUI16("unknownID"); textureFormat = sis.readUI16("textureFormat"); fileName = sis.readNetString("fileName"); textureWidth = sis.readUI16("textureWidth"); @@ -116,20 +132,64 @@ public class FontTextureInfo extends Tag { int numTexGlyphs = sis.readUI16("numTexGlyphs"); texGlyphs = new TEXGLYPH[numTexGlyphs]; MemoryInputStream mis = sis.getBaseStream(); + long misStartPos; + misStartPos = mis.getPos(); for (int i = 0; i < numTexGlyphs; i++) { GFxInputStream gis = new GFxInputStream(mis); gis.dumpInfo = sis.dumpInfo; texGlyphs[i] = new TEXGLYPH(gis); } - sis.skipBytes(mis.getPos()); + sis.skipBytes(mis.getPos() - misStartPos); int numFonts = sis.readUI16("numFonts"); fonts = new FONTINFO[numFonts]; mis = sis.getBaseStream(); + misStartPos = mis.getPos(); for (int i = 0; i < numFonts; i++) { GFxInputStream gis = new GFxInputStream(mis); gis.dumpInfo = sis.dumpInfo; fonts[i] = new FONTINFO(gis); } - sis.skipBytes(mis.getPos()); + sis.skipBytes(mis.getPos() - misStartPos); + } + + @Override + public String toString() { + return tagName + " (ft" + textureID + ")"; + } + + @Override + public void getTagInfo(TagInfo tagInfo) { + super.getTagInfo(tagInfo); + + tagInfo.addInfo("general", "textureId", textureID); + String textureFormatStr = "0x" + Integer.toHexString(textureFormat); + switch (textureFormat) { + case TEXTURE_FORMAT_DEFAULT: + textureFormatStr = "default (0)"; + break; + case TEXTURE_FORMAT_TGA: + textureFormatStr = "TGA (1)"; + break; + case TEXTURE_FORMAT_DDS: + textureFormatStr = "DDS (2)"; + break; + case TEXTURE_FORMAT2_JPEG: + textureFormatStr = "JPEG (10)"; + break; + case TEXTURE_FORMAT2_TGA: + textureFormatStr = "TGA (13)"; + break; + case TEXTURE_FORMAT2_DDS: + textureFormatStr = "DDS (14)"; + break; + } + tagInfo.addInfo("general", "textureFormat", textureFormatStr); + tagInfo.addInfo("general", "fileName", fileName); + tagInfo.addInfo("general", "width", textureWidth); + tagInfo.addInfo("general", "height", textureHeight); + tagInfo.addInfo("general", "padPixels", padPixels); + tagInfo.addInfo("general", "nominalGlyphSz", nominalGlyphSz); + tagInfo.addInfo("general", "glyphCount", texGlyphs.length); + tagInfo.addInfo("general", "fontCount", fonts.length); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/SHAPE.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/SHAPE.java index 7f7f302c7..3428bb4f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/SHAPE.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/SHAPE.java @@ -50,6 +50,11 @@ public class SHAPE implements NeedsCharacters, Serializable { private Shape cachedOutline; private Shape fastCachedOutline; + public SHAPE() { + shapeRecords = new ArrayList<>(); + shapeRecords.add(new EndShapeRecord()); + } + @Override public void getNeededCharacters(Set needed, SWF swf) { for (SHAPERECORD r : shapeRecords) { diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 646be3e7b..39bace7cb 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1173,3 +1173,26 @@ import.sprite.result = %count% sprites imported. menu.file.import.sprite = Import sprites from GIF 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. + +#after 19.1.2 +tagInfo.fileName = File name +tagInfo.exportName = Export name +tagInfo.bitmapFormat = Bitmap format +tagInfo.imageId = Image Id +tagInfo.x1 = x1 +tagInfo.y1 = y1 +tagInfo.x2 = x2 +tagInfo.y2 = y2 +tagInfo.bitmapsFormat = Bitmaps format +tagInfo.version = Version +tagInfo.flags = Flags +tagInfo.prefix = Prefix +tagInfo.swfName = SWF name +tagInfo.codeOffsets = Code offsets +tagInfo.gradientSize = Gradient size +tagInfo.textureId = Texture Id +tagInfo.textureFormat = Texture format +tagInfo.padPixels = Pad pixels +tagInfo.nominalGlyphSz = Nominal glyph size +tagInfo.glyphCount = Glyph count +tagInfo.fontCount = Font count \ No newline at end of file