From fb21f408cd9826797fd3b56781dd4f6077ce2aed Mon Sep 17 00:00:00 2001 From: honfika Date: Wed, 18 Jun 2014 20:48:08 +0200 Subject: [PATCH] prepare for dumpview --- src/com/jpexs/decompiler/flash/SWF.java | 337 +- .../decompiler/flash/SWFCompression.java | 26 + src/com/jpexs/decompiler/flash/SWFHeader.java | 45 + .../decompiler/flash/SWFInputStream.java | 5875 +++++++++-------- .../flash/SWFLimitedInputStream.java | 193 + .../decompiler/flash/SWFOutputStream.java | 3507 +++++----- .../decompiler/flash/ZippedSWFBundle.java | 219 +- .../flash/action/swf4/ActionPush.java | 744 +-- .../decompiler/flash/dumpview/DumpInfo.java | 50 + .../decompiler/flash/dumpview/Dumpable.java | 28 + .../flash/dumpview/DumpableItem.java | 39 + .../flash/dumpview/DumpableNode.java | 36 + .../flash/exporters/MovieExporter.java | 342 +- .../flash/exporters/SoundExporter.java | 294 +- .../flash/gui/MainFrameClassicMenu.java | 2 + .../flash/gui/MainFrameRibbonMenu.java | 13 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 2 +- .../decompiler/flash/gui/PreviewPanel.java | 4 +- .../decompiler/flash/gui/SoundTagPlayer.java | 421 +- .../flash/tags/CSMTextSettingsTag.java | 227 +- .../decompiler/flash/tags/DebugIDTag.java | 141 +- .../flash/tags/DefineBinaryDataTag.java | 147 +- .../flash/tags/DefineBitsJPEG2Tag.java | 203 +- .../flash/tags/DefineBitsJPEG3Tag.java | 275 +- .../flash/tags/DefineBitsJPEG4Tag.java | 300 +- .../flash/tags/DefineBitsLossless2Tag.java | 441 +- .../flash/tags/DefineBitsLosslessTag.java | 451 +- .../decompiler/flash/tags/DefineBitsTag.java | 253 +- .../flash/tags/DefineButton2Tag.java | 36 +- .../flash/tags/DefineButtonCxformTag.java | 147 +- .../flash/tags/DefineButtonSoundTag.java | 257 +- .../flash/tags/DefineButtonTag.java | 21 +- .../flash/tags/DefineEditTextTag.java | 7 +- .../decompiler/flash/tags/DefineFont2Tag.java | 888 ++- .../decompiler/flash/tags/DefineFont3Tag.java | 897 ++- .../decompiler/flash/tags/DefineFont4Tag.java | 167 +- .../flash/tags/DefineFontAlignZonesTag.java | 159 +- .../flash/tags/DefineFontInfo2Tag.java | 241 +- .../flash/tags/DefineFontInfoTag.java | 247 +- .../flash/tags/DefineFontNameTag.java | 79 +- .../decompiler/flash/tags/DefineFontTag.java | 651 +- .../flash/tags/DefineMorphShape2Tag.java | 9 +- .../flash/tags/DefineMorphShapeTag.java | 9 +- .../flash/tags/DefineScalingGridTag.java | 125 +- .../tags/DefineSceneAndFrameLabelDataTag.java | 211 +- .../flash/tags/DefineShape2Tag.java | 9 +- .../flash/tags/DefineShape3Tag.java | 9 +- .../flash/tags/DefineShape4Tag.java | 9 +- .../decompiler/flash/tags/DefineShapeTag.java | 9 +- .../decompiler/flash/tags/DefineSoundTag.java | 672 +- .../flash/tags/DefineSpriteTag.java | 8 +- .../decompiler/flash/tags/DefineText2Tag.java | 8 +- .../decompiler/flash/tags/DefineTextTag.java | 10 +- .../flash/tags/DefineVideoStreamTag.java | 248 +- .../decompiler/flash/tags/DoABCDefineTag.java | 234 +- .../jpexs/decompiler/flash/tags/DoABCTag.java | 186 +- .../decompiler/flash/tags/DoActionTag.java | 35 +- .../flash/tags/DoInitActionTag.java | 26 +- .../flash/tags/EnableDebugger2Tag.java | 157 +- .../flash/tags/EnableDebuggerTag.java | 143 +- .../flash/tags/EnableTelemetryTag.java | 167 +- .../jpexs/decompiler/flash/tags/EndTag.java | 114 +- .../flash/tags/ExportAssetsTag.java | 198 +- .../flash/tags/FileAttributesTag.java | 184 +- .../decompiler/flash/tags/FrameLabelTag.java | 139 +- .../flash/tags/ImportAssets2Tag.java | 243 +- .../flash/tags/ImportAssetsTag.java | 221 +- .../decompiler/flash/tags/JPEGTablesTag.java | 62 +- .../decompiler/flash/tags/MetadataTag.java | 115 +- .../flash/tags/PlaceObject2Tag.java | 11 +- .../flash/tags/PlaceObject3Tag.java | 10 +- .../flash/tags/PlaceObject4Tag.java | 10 +- .../decompiler/flash/tags/PlaceObjectTag.java | 10 +- .../decompiler/flash/tags/ProductInfoTag.java | 191 +- .../decompiler/flash/tags/ProtectTag.java | 151 +- .../flash/tags/RemoveObject2Tag.java | 83 +- .../flash/tags/RemoveObjectTag.java | 183 +- .../flash/tags/ScriptLimitsTag.java | 123 +- .../flash/tags/SetBackgroundColorTag.java | 104 +- .../decompiler/flash/tags/SetTabIndexTag.java | 159 +- .../decompiler/flash/tags/ShowFrameTag.java | 6 +- .../flash/tags/SoundStreamBlockTag.java | 93 +- .../flash/tags/SoundStreamHead2Tag.java | 457 +- .../flash/tags/SoundStreamHeadTag.java | 487 +- .../decompiler/flash/tags/StartSound2Tag.java | 139 +- .../decompiler/flash/tags/StartSoundTag.java | 147 +- .../decompiler/flash/tags/SymbolClassTag.java | 145 +- src/com/jpexs/decompiler/flash/tags/Tag.java | 109 +- .../jpexs/decompiler/flash/tags/TagStub.java | 127 +- .../decompiler/flash/tags/UnknownTag.java | 4 +- .../decompiler/flash/tags/VideoFrameTag.java | 156 +- .../decompiler/flash/tags/base/ButtonTag.java | 170 +- .../flash/tags/base/CharacterIdTag.java | 174 +- .../flash/tags/base/CharacterTag.java | 61 +- .../decompiler/flash/tags/base/FontTag.java | 4 +- .../decompiler/flash/tags/base/ImageTag.java | 168 +- .../decompiler/flash/tags/base/ShapeTag.java | 4 +- .../decompiler/flash/tags/base/TextTag.java | 4 +- .../flash/tags/gfx/DefineCompactedFont.java | 786 +-- .../tags/gfx/DefineExternalGradient.java | 165 +- .../flash/tags/gfx/DefineExternalImage.java | 173 +- .../flash/tags/gfx/DefineExternalImage2.java | 197 +- .../flash/tags/gfx/DefineExternalSound.java | 199 +- .../tags/gfx/DefineExternalStreamSound.java | 193 +- .../flash/tags/gfx/DefineGradientMap.java | 149 +- .../flash/tags/gfx/DefineSubImage.java | 165 +- .../flash/tags/gfx/ExporterInfoTag.java | 225 +- .../flash/tags/gfx/FontTextureInfo.java | 231 +- .../flash/types/BUTTONCONDACTION.java | 3 +- .../flash/types/CLIPACTIONRECORD.java | 4 +- .../decompiler/flash/types/gfx/FontType.java | 229 +- .../flash/types/gfx/GFxInputStream.java | 328 +- .../flash/types/sound/AdpcmDecoder.java | 562 +- .../flash/types/sound/MP3Decoder.java | 221 +- .../flash/types/sound/MP3SOUNDDATA.java | 117 +- .../flash/types/sound/NellyMoserDecoder.java | 130 +- .../flash/types/sound/NoDecoder.java | 82 +- .../flash/types/sound/SoundDecoder.java | 88 +- .../flash/types/sound/SoundFormat.java | 424 +- .../decompiler/flash/xfl/XFLConverter.java | 11 +- src/com/jpexs/helpers/Helper.java | 20 +- src/com/jpexs/helpers/NulStream.java | 31 + .../jpexs/decompiler/flash/SWFStreamTest.java | 361 +- 123 files changed, 15359 insertions(+), 15197 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/SWFCompression.java create mode 100644 src/com/jpexs/decompiler/flash/SWFHeader.java create mode 100644 src/com/jpexs/decompiler/flash/SWFLimitedInputStream.java create mode 100644 src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java create mode 100644 src/com/jpexs/decompiler/flash/dumpview/Dumpable.java create mode 100644 src/com/jpexs/decompiler/flash/dumpview/DumpableItem.java create mode 100644 src/com/jpexs/decompiler/flash/dumpview/DumpableNode.java create mode 100644 src/com/jpexs/helpers/NulStream.java diff --git a/src/com/jpexs/decompiler/flash/SWF.java b/src/com/jpexs/decompiler/flash/SWF.java index 086d40331..8c506fe0e 100644 --- a/src/com/jpexs/decompiler/flash/SWF.java +++ b/src/com/jpexs/decompiler/flash/SWF.java @@ -90,6 +90,7 @@ import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.SymbolClassTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.TagStub; import com.jpexs.decompiler.flash.tags.VideoFrameTag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.BoundedTag; @@ -146,6 +147,7 @@ import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Cache; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; +import com.jpexs.helpers.NulStream; import com.jpexs.helpers.ProgressListener; import com.jpexs.helpers.SerializableImage; import com.jpexs.helpers.utf8.Utf8Helper; @@ -163,7 +165,6 @@ import java.awt.print.PageFormat; import java.awt.print.Paper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -234,17 +235,13 @@ public final class SWF implements TreeItem, Timelined { */ public int version; /** - * Size of the file - */ + * Uncompressed size of the file + */ public long fileSize; /** - * Use compression + * Used compression mode */ - public boolean compressed = false; - /** - * Use LZMA compression - */ - public boolean lzma = false; + public SWFCompression compression = SWFCompression.NONE; /** * Compressed size of the file (LZMA) */ @@ -253,6 +250,7 @@ public final class SWF implements TreeItem, Timelined { * LZMA Properties */ public byte[] lzmaProperties; + public byte[] uncompressedData; public FileAttributesTag fileAttributes; /** * ScaleForm GFx @@ -307,7 +305,7 @@ public final class SWF implements TreeItem, Timelined { Tag t = tags.get(i); if (t instanceof DefineSpriteTag) { if (!isSpriteValid((DefineSpriteTag) t, new ArrayList())) { - tags.set(i, new Tag(this, t.getId(), "InvalidSprite", t.getOriginalHeaderData(), t.getOriginalData(), t.getPos())); + tags.set(i, new Tag(this, t.getId(), "InvalidSprite", t.getPos(), t.getOriginalLength())); } } } @@ -365,6 +363,17 @@ public final class SWF implements TreeItem, Timelined { * @throws IOException */ public void saveTo(OutputStream os) throws IOException { + saveTo(os, compression); + } + + /** + * Saves this SWF into new file + * + * @param os OutputStream to save SWF in + * @param compression + * @throws IOException + */ + public void saveTo(OutputStream os, SWFCompression compression) throws IOException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); SWFOutputStream sos = new SWFOutputStream(baos, version); @@ -378,9 +387,9 @@ public final class SWF implements TreeItem, Timelined { sos.writeUI16(0); } sos.close(); - if (compressed && lzma) { + if (compression == SWFCompression.LZMA) { os.write('Z'); - } else if (compressed) { + } else if (compression == SWFCompression.ZLIB) { os.write('C'); } else { if (gfx) { @@ -401,34 +410,32 @@ public final class SWF implements TreeItem, Timelined { sos = new SWFOutputStream(os, version); sos.writeUI32(data.length + 8); - if (compressed) { - if (lzma) { - Encoder enc = new Encoder(); - int val = lzmaProperties[0] & 0xFF; - int lc = val % 9; - int remainder = val / 9; - int lp = remainder % 5; - int pb = remainder / 5; - int dictionarySize = 0; - for (int i = 0; i < 4; i++) { - dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8); - } - enc.SetDictionarySize(dictionarySize); - enc.SetLcLpPb(lc, lp, pb); - baos = new ByteArrayOutputStream(); - enc.SetEndMarkerMode(true); - enc.Code(new ByteArrayInputStream(data), baos, -1, -1, null); - data = baos.toByteArray(); - byte[] udata = new byte[4]; - udata[0] = (byte) (data.length & 0xFF); - udata[1] = (byte) ((data.length >> 8) & 0xFF); - udata[2] = (byte) ((data.length >> 16) & 0xFF); - udata[3] = (byte) ((data.length >> 24) & 0xFF); - os.write(udata); - os.write(lzmaProperties); - } else { - os = new DeflaterOutputStream(os); + if (compression == SWFCompression.LZMA) { + Encoder enc = new Encoder(); + int val = lzmaProperties[0] & 0xFF; + int lc = val % 9; + int remainder = val / 9; + int lp = remainder % 5; + int pb = remainder / 5; + int dictionarySize = 0; + for (int i = 0; i < 4; i++) { + dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8); } + enc.SetDictionarySize(dictionarySize); + enc.SetLcLpPb(lc, lp, pb); + baos = new ByteArrayOutputStream(); + enc.SetEndMarkerMode(true); + enc.Code(new ByteArrayInputStream(data), baos, -1, -1, null); + data = baos.toByteArray(); + byte[] udata = new byte[4]; + udata[0] = (byte) (data.length & 0xFF); + udata[1] = (byte) ((data.length >> 8) & 0xFF); + udata[2] = (byte) ((data.length >> 16) & 0xFF); + udata[3] = (byte) ((data.length >> 24) & 0xFF); + os.write(udata); + os.write(lzmaProperties); + } else if (compression == SWFCompression.ZLIB) { + os = new DeflaterOutputStream(os); } os.write(data); } finally { @@ -438,6 +445,23 @@ public final class SWF implements TreeItem, Timelined { } } + public void clearModified() { + for (Tag tag : tags) { + if (tag.isModified()) { + tag.setModified(false); + } + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + saveTo(baos, SWFCompression.NONE); + byte[] swfData = baos.toByteArray(); + uncompressedData = swfData; + } catch (IOException ex) { + Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); + } + } + public SWF(InputStream is, boolean parallelRead) throws IOException, InterruptedException { this(is, null, parallelRead); } @@ -462,73 +486,7 @@ public final class SWF implements TreeItem, Timelined { * @throws java.io.IOException */ public SWF(InputStream is) throws IOException { - byte[] hdr = new byte[3]; - is.read(hdr); - String shdr = new String(hdr, Utf8Helper.charset); - if (!Arrays.asList( - "FWS", //Uncompressed Flash - "CWS", //ZLib compressed Flash - "ZWS", //LZMA compressed Flash - "GFX", //Uncompressed ScaleForm GFx - "CFX" //Compressed ScaleForm GFx - ).contains(shdr)) { - throw new IOException("Invalid SWF file"); - } - version = is.read(); - fileSize = (is.read() + (is.read() << 8) + (is.read() << 16) + (is.read() << 24)) & 0xffffffff; - - if (hdr[0] == 'C') { - is = new InflaterInputStream(is); - } - - if (hdr[0] == 'Z') { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - //outSize - is.read(); - is.read(); - is.read(); - is.read(); - int propertiesSize = 5; - lzmaProperties = new byte[propertiesSize]; - if (is.read(lzmaProperties, 0, propertiesSize) != propertiesSize) { - throw new IOException("LZMA:input .lzma file is too short"); - } - long dictionarySize = 0; - for (int i = 0; i < 4; i++) { - dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8); - if (dictionarySize > Runtime.getRuntime().freeMemory()) { - throw new IOException("LZMA: Too large dictionary size"); - } - } - - SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); - if (!decoder.SetDecoderProperties(lzmaProperties)) { - throw new IOException("LZMA:Incorrect stream properties"); - } - - if (!decoder.Code(is, baos, fileSize - 8)) { - throw new IOException("LZMA:Error in data stream"); - } - } else { - long toRead = fileSize - 8; - if (toRead > 0) { - byte[] bytes = new byte[4096]; - while (toRead > 4096) { - int read = is.read(bytes); - if (read == -1) { - throw new IOException("Invalid SWF file"); - } - toRead -= read; - } - while (toRead > 0) { - int read = is.read(bytes, 0, (int) toRead); - if (read == -1) { - throw new IOException("Invalid SWF file"); - } - toRead -= read; - } - } - } + decompress(is, new NulStream(), true); } /** @@ -542,60 +500,16 @@ public final class SWF implements TreeItem, Timelined { * @throws java.lang.InterruptedException */ public SWF(InputStream is, ProgressListener listener, boolean parallelRead, boolean checkOnly) throws IOException, InterruptedException { - byte[] hdr = new byte[3]; - is.read(hdr); - String shdr = new String(hdr, Utf8Helper.charset); - if (!Arrays.asList( - "FWS", //Uncompressed Flash - "CWS", //ZLib compressed Flash - "ZWS", //LZMA compressed Flash - "GFX", //Uncompressed ScaleForm GFx - "CFX" //Compressed ScaleForm GFx - ).contains(shdr)) { - throw new IOException("Invalid SWF file"); - } - version = is.read(); - SWFInputStream sis = new SWFInputStream(is, version, 4); - fileSize = sis.readUI32(); - - if (hdr[1] == 'F' && hdr[2] == 'X') { - gfx = true; - } - if (hdr[0] == 'C') { - byte[] uncompressedData = Helper.readStream(new InflaterInputStream(is)); - sis = new SWFInputStream(new ByteArrayInputStream(uncompressedData), version, 8); - compressed = true; - } - - if (hdr[0] == 'Z') { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - sis.readUI32(); //outSize - int propertiesSize = 5; - lzmaProperties = new byte[propertiesSize]; - if (sis.read(lzmaProperties, 0, propertiesSize) != propertiesSize) { - throw new IOException("LZMA:input .lzma file is too short"); - } - long dictionarySize = 0; - for (int i = 0; i < 4; i++) { - dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8); - if (dictionarySize > Runtime.getRuntime().freeMemory()) { - throw new IOException("LZMA: Too large dictionary size"); - } - } - - SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); - if (!decoder.SetDecoderProperties(lzmaProperties)) { - throw new IOException("LZMA:Incorrect stream properties"); - } - - if (!decoder.Code(sis, baos, fileSize - 8)) { - throw new IOException("LZMA:Error in data stream"); - } - sis = new SWFInputStream(new ByteArrayInputStream(baos.toByteArray()), version, 8); - compressed = true; - lzma = true; - } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFHeader header = decompress(is, baos, true); + version = header.version; + fileSize = header.fileSize; + gfx = header.gfx; + compression = header.compression; + uncompressedData = baos.toByteArray(); + SWFInputStream sis = new SWFInputStream(uncompressedData, version); + sis.read(new byte[8], 0, 8); // skip the header if (listener != null) { sis.addPercentListener(listener); } @@ -621,7 +535,7 @@ public final class SWF implements TreeItem, Timelined { } else { boolean hasNonUnknownTag = false; for (Tag tag : tags) { - if (tag.getOriginalData().length > 0 && Tag.getRequiredTags().contains(tag.getId())) { + if (tag.getOriginalLength() > 2 && Tag.getRequiredTags().contains(tag.getId())) { hasNonUnknownTag = true; } } @@ -763,36 +677,57 @@ public final class SWF implements TreeItem, Timelined { public static boolean decompress(InputStream fis, OutputStream fos) { try { - byte[] hdr = new byte[3]; - fis.read(hdr); - String shdr = new String(hdr, Utf8Helper.charset); - switch (shdr) { - case "CWS": { - int version = fis.read(); - SWFInputStream sis = new SWFInputStream(fis, version, 4); - long fileSize = sis.readUI32(); - SWFOutputStream sos = new SWFOutputStream(fos, version); - sos.write(Utf8Helper.getBytes("FWS")); - sos.writeUI8(version); - sos.writeUI32(fileSize); - InflaterInputStream iis = new InflaterInputStream(fis); - int i; - try { - while ((i = iis.read()) != -1) { - fos.write(i); - } - } catch (EOFException ex) { - } - fis.close(); - fos.close(); + decompress(fis, fos, false); + return true; + } catch (IOException ex) { + return false; + } + } + + private static SWFHeader decompress(InputStream is, OutputStream os, boolean allowUncompressed) throws IOException { + byte[] hdr = new byte[8]; + + // SWFheader: signature, version and fileSize + if (is.read(hdr) != 8) { + throw new IOException("SWF header is too short"); + } + + String signature = new String(hdr, 0, 3, Utf8Helper.charset); + if (!Arrays.asList( + "FWS", //Uncompressed Flash + "CWS", //ZLib compressed Flash + "ZWS", //LZMA compressed Flash + "GFX", //Uncompressed ScaleForm GFx + "CFX" //Compressed ScaleForm GFx + ).contains(signature)) { + throw new IOException("Invalid SWF file"); + } + + int version = hdr[3]; + SWFInputStream sis = new SWFInputStream(Arrays.copyOfRange(hdr, 4, 8), version, 4); + long fileSize = sis.readUI32(); + SWFHeader header = new SWFHeader(); + header.version = version; + header.fileSize = fileSize; + + if (hdr[1] == 'F' && hdr[2] == 'X') { + header.gfx = true; + } + + try (SWFOutputStream sos = new SWFOutputStream(os, version)) { + sos.write(Utf8Helper.getBytes("FWS")); + sos.writeUI8(version); + sos.writeUI32(fileSize); + + switch (hdr[0]) { + case 'C': { // CWS, CFX + Helper.copyStream(new InflaterInputStream(is), os, fileSize - 8); + header.compression = SWFCompression.ZLIB; break; } - case "ZWS": { - int version = fis.read(); - SWFInputStream sis = new SWFInputStream(fis, version, 4); - long fileSize = sis.readUI32(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - sis.readUI32(); + case 'Z': { // ZWS + sis.readUI32(); // compressed LZMA data size = compressed SWF - 17 byte, + // where 17 = 8 byte header + this 4 byte + 5 bytes decoder properties int propertiesSize = 5; byte[] lzmaProperties = new byte[propertiesSize]; if (sis.read(lzmaProperties, 0, propertiesSize) != propertiesSize) { @@ -802,26 +737,24 @@ public final class SWF implements TreeItem, Timelined { if (!decoder.SetDecoderProperties(lzmaProperties)) { throw new IOException("LZMA:Incorrect stream properties"); } - if (!decoder.Code(sis, baos, fileSize - 8)) { + if (!decoder.Code(is, os, fileSize - 8)) { throw new IOException("LZMA:Error in data stream"); } - try (SWFOutputStream sos = new SWFOutputStream(fos, version)) { - sos.write(Utf8Helper.getBytes("FWS")); - sos.write(version); - sos.writeUI32(fileSize); - sos.write(baos.toByteArray()); - } - fis.close(); - fos.close(); + + header.compression = SWFCompression.LZMA; break; } - default: - return false; + default: { // FWS, GFX + if (allowUncompressed) { + Helper.copyStream(is, os, fileSize - 8); + } else { + throw new IOException("SWF is not compressed"); + } + } } - } catch (IOException ex) { - return false; + + return header; } - return true; } public static boolean renameInvalidIdentifiers(RenameType renameType, InputStream fis, OutputStream fos) { diff --git a/src/com/jpexs/decompiler/flash/SWFCompression.java b/src/com/jpexs/decompiler/flash/SWFCompression.java new file mode 100644 index 000000000..8b1530d15 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/SWFCompression.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +/** + * + * @author JPEXS + */ +public enum SWFCompression { + + NONE, ZLIB, LZMA +} diff --git a/src/com/jpexs/decompiler/flash/SWFHeader.java b/src/com/jpexs/decompiler/flash/SWFHeader.java new file mode 100644 index 000000000..889778223 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/SWFHeader.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +/** + * + * @author JPEXS + */ +public class SWFHeader { + + /** + * Version of SWF + */ + public int version; + + /** + * Uncompressed size of the file + */ + public long fileSize; + + /** + * Used compression mode + */ + public SWFCompression compression = SWFCompression.NONE; + + /** + * ScaleForm GFx + */ + public boolean gfx = false; + +} diff --git a/src/com/jpexs/decompiler/flash/SWFInputStream.java b/src/com/jpexs/decompiler/flash/SWFInputStream.java index a148fe246..c64e28281 100644 --- a/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -1,2930 +1,2945 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionNop; -import com.jpexs.decompiler.flash.action.swf3.ActionGetURL; -import com.jpexs.decompiler.flash.action.swf3.ActionGoToLabel; -import com.jpexs.decompiler.flash.action.swf3.ActionGotoFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionNextFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionPlay; -import com.jpexs.decompiler.flash.action.swf3.ActionPrevFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionSetTarget; -import com.jpexs.decompiler.flash.action.swf3.ActionStop; -import com.jpexs.decompiler.flash.action.swf3.ActionStopSounds; -import com.jpexs.decompiler.flash.action.swf3.ActionToggleQuality; -import com.jpexs.decompiler.flash.action.swf3.ActionWaitForFrame; -import com.jpexs.decompiler.flash.action.swf4.ActionAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionAnd; -import com.jpexs.decompiler.flash.action.swf4.ActionAsciiToChar; -import com.jpexs.decompiler.flash.action.swf4.ActionCall; -import com.jpexs.decompiler.flash.action.swf4.ActionCharToAscii; -import com.jpexs.decompiler.flash.action.swf4.ActionCloneSprite; -import com.jpexs.decompiler.flash.action.swf4.ActionDivide; -import com.jpexs.decompiler.flash.action.swf4.ActionEndDrag; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionGetTime; -import com.jpexs.decompiler.flash.action.swf4.ActionGetURL2; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionGotoFrame2; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionLess; -import com.jpexs.decompiler.flash.action.swf4.ActionMBAsciiToChar; -import com.jpexs.decompiler.flash.action.swf4.ActionMBCharToAscii; -import com.jpexs.decompiler.flash.action.swf4.ActionMBStringExtract; -import com.jpexs.decompiler.flash.action.swf4.ActionMBStringLength; -import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionOr; -import com.jpexs.decompiler.flash.action.swf4.ActionPop; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionRandomNumber; -import com.jpexs.decompiler.flash.action.swf4.ActionRemoveSprite; -import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionSetTarget2; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionStartDrag; -import com.jpexs.decompiler.flash.action.swf4.ActionStringAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionStringEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionStringExtract; -import com.jpexs.decompiler.flash.action.swf4.ActionStringLength; -import com.jpexs.decompiler.flash.action.swf4.ActionStringLess; -import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; -import com.jpexs.decompiler.flash.action.swf4.ActionToInteger; -import com.jpexs.decompiler.flash.action.swf4.ActionTrace; -import com.jpexs.decompiler.flash.action.swf4.ActionWaitForFrame2; -import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; -import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; -import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; -import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitURShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; -import com.jpexs.decompiler.flash.action.swf5.ActionDelete; -import com.jpexs.decompiler.flash.action.swf5.ActionDelete2; -import com.jpexs.decompiler.flash.action.swf5.ActionEnumerate; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; -import com.jpexs.decompiler.flash.action.swf5.ActionInitArray; -import com.jpexs.decompiler.flash.action.swf5.ActionInitObject; -import com.jpexs.decompiler.flash.action.swf5.ActionLess2; -import com.jpexs.decompiler.flash.action.swf5.ActionModulo; -import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionReturn; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf5.ActionTargetPath; -import com.jpexs.decompiler.flash.action.swf5.ActionToNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionToString; -import com.jpexs.decompiler.flash.action.swf5.ActionTypeOf; -import com.jpexs.decompiler.flash.action.swf5.ActionWith; -import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; -import com.jpexs.decompiler.flash.action.swf6.ActionGreater; -import com.jpexs.decompiler.flash.action.swf6.ActionInstanceOf; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater; -import com.jpexs.decompiler.flash.action.swf7.ActionCastOp; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.action.swf7.ActionExtends; -import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; -import com.jpexs.decompiler.flash.action.swf7.ActionThrow; -import com.jpexs.decompiler.flash.action.swf7.ActionTry; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.tags.CSMTextSettingsTag; -import com.jpexs.decompiler.flash.tags.DebugIDTag; -import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag; -import com.jpexs.decompiler.flash.tags.DefineBitsTag; -import com.jpexs.decompiler.flash.tags.DefineButton2Tag; -import com.jpexs.decompiler.flash.tags.DefineButtonCxformTag; -import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag; -import com.jpexs.decompiler.flash.tags.DefineButtonTag; -import com.jpexs.decompiler.flash.tags.DefineEditTextTag; -import com.jpexs.decompiler.flash.tags.DefineFont2Tag; -import com.jpexs.decompiler.flash.tags.DefineFont3Tag; -import com.jpexs.decompiler.flash.tags.DefineFont4Tag; -import com.jpexs.decompiler.flash.tags.DefineFontAlignZonesTag; -import com.jpexs.decompiler.flash.tags.DefineFontInfo2Tag; -import com.jpexs.decompiler.flash.tags.DefineFontInfoTag; -import com.jpexs.decompiler.flash.tags.DefineFontNameTag; -import com.jpexs.decompiler.flash.tags.DefineFontTag; -import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag; -import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag; -import com.jpexs.decompiler.flash.tags.DefineScalingGridTag; -import com.jpexs.decompiler.flash.tags.DefineSceneAndFrameLabelDataTag; -import com.jpexs.decompiler.flash.tags.DefineShape2Tag; -import com.jpexs.decompiler.flash.tags.DefineShape3Tag; -import com.jpexs.decompiler.flash.tags.DefineShape4Tag; -import com.jpexs.decompiler.flash.tags.DefineShapeTag; -import com.jpexs.decompiler.flash.tags.DefineSoundTag; -import com.jpexs.decompiler.flash.tags.DefineSpriteTag; -import com.jpexs.decompiler.flash.tags.DefineText2Tag; -import com.jpexs.decompiler.flash.tags.DefineTextTag; -import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; -import com.jpexs.decompiler.flash.tags.DoABCDefineTag; -import com.jpexs.decompiler.flash.tags.DoABCTag; -import com.jpexs.decompiler.flash.tags.DoActionTag; -import com.jpexs.decompiler.flash.tags.DoInitActionTag; -import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag; -import com.jpexs.decompiler.flash.tags.EnableDebuggerTag; -import com.jpexs.decompiler.flash.tags.EnableTelemetryTag; -import com.jpexs.decompiler.flash.tags.EndTag; -import com.jpexs.decompiler.flash.tags.ExportAssetsTag; -import com.jpexs.decompiler.flash.tags.FileAttributesTag; -import com.jpexs.decompiler.flash.tags.FrameLabelTag; -import com.jpexs.decompiler.flash.tags.ImportAssets2Tag; -import com.jpexs.decompiler.flash.tags.ImportAssetsTag; -import com.jpexs.decompiler.flash.tags.JPEGTablesTag; -import com.jpexs.decompiler.flash.tags.MetadataTag; -import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; -import com.jpexs.decompiler.flash.tags.PlaceObject3Tag; -import com.jpexs.decompiler.flash.tags.PlaceObject4Tag; -import com.jpexs.decompiler.flash.tags.PlaceObjectTag; -import com.jpexs.decompiler.flash.tags.ProductInfoTag; -import com.jpexs.decompiler.flash.tags.ProtectTag; -import com.jpexs.decompiler.flash.tags.RemoveObject2Tag; -import com.jpexs.decompiler.flash.tags.RemoveObjectTag; -import com.jpexs.decompiler.flash.tags.ScriptLimitsTag; -import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; -import com.jpexs.decompiler.flash.tags.SetTabIndexTag; -import com.jpexs.decompiler.flash.tags.ShowFrameTag; -import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; -import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag; -import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag; -import com.jpexs.decompiler.flash.tags.StartSound2Tag; -import com.jpexs.decompiler.flash.tags.StartSoundTag; -import com.jpexs.decompiler.flash.tags.SymbolClassTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.UnknownTag; -import com.jpexs.decompiler.flash.tags.VideoFrameTag; -import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalGradient; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage2; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalSound; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalStreamSound; -import com.jpexs.decompiler.flash.tags.gfx.DefineGradientMap; -import com.jpexs.decompiler.flash.tags.gfx.DefineSubImage; -import com.jpexs.decompiler.flash.tags.gfx.ExporterInfoTag; -import com.jpexs.decompiler.flash.tags.gfx.FontTextureInfo; -import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; -import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA; -import com.jpexs.decompiler.flash.types.ARGB; -import com.jpexs.decompiler.flash.types.BITMAPDATA; -import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; -import com.jpexs.decompiler.flash.types.BUTTONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONS; -import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; -import com.jpexs.decompiler.flash.types.COLORMAPDATA; -import com.jpexs.decompiler.flash.types.CXFORM; -import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; -import com.jpexs.decompiler.flash.types.FILLSTYLE; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.FOCALGRADIENT; -import com.jpexs.decompiler.flash.types.GLYPHENTRY; -import com.jpexs.decompiler.flash.types.GRADIENT; -import com.jpexs.decompiler.flash.types.GRADRECORD; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.LINESTYLE; -import com.jpexs.decompiler.flash.types.LINESTYLE2; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADRECORD; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.PIX15; -import com.jpexs.decompiler.flash.types.PIX24; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.RGB; -import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; -import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import com.jpexs.decompiler.flash.types.TEXTRECORD; -import com.jpexs.decompiler.flash.types.ZONEDATA; -import com.jpexs.decompiler.flash.types.ZONERECORD; -import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.BLURFILTER; -import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER; -import com.jpexs.decompiler.flash.types.filters.CONVOLUTIONFILTER; -import com.jpexs.decompiler.flash.types.filters.DROPSHADOWFILTER; -import com.jpexs.decompiler.flash.types.filters.FILTER; -import com.jpexs.decompiler.flash.types.filters.GLOWFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTBEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTGLOWFILTER; -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -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.Helper; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.streams.SeekableInputStream; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.InflaterInputStream; - -/** - * Class for reading data from SWF file - * - * @author JPEXS - */ -public class SWFInputStream extends InputStream { - - private InputStream is; - private long pos; - private int version; - private static final Logger logger = Logger.getLogger(SWFInputStream.class.getName()); - private final List listeners = new ArrayList<>(); - private long percentMax; - private final List buffered = new ArrayList<>(); - private ByteArrayOutputStream buffer; - - public int getVersion() { - return version; - } - - public int getBufferLength() { - return buffer.size(); - } - - public void startBuffer() { - stopBuffer(); - buffer = new ByteArrayOutputStream(); - } - - public byte[] getBuffer() { - return buffer.toByteArray(); - } - - public byte[] stopBuffer() { - if (buffer != null) { - byte[] ret = buffer.toByteArray(); - buffered.add(ret); - buffer = null; - return ret; - } - return null; - } - - public void addPercentListener(ProgressListener listener) { - listeners.add(listener); - } - - public void removePercentListener(ProgressListener listener) { - int index = listeners.indexOf(listener); - if (index > -1) { - listeners.remove(index); - } - } - - public void setPercentMax(long percentMax) { - this.percentMax = percentMax; - } - - /** - * Constructor - * - * @param is Existing inputstream - * @param version Version of SWF to read - * @param startingPos - */ - public SWFInputStream(InputStream is, int version, long startingPos) { - this.version = version; - this.is = is; - pos = startingPos; - } - - /** - * Constructor - * - * @param is Existing inputstream - * @param version Version of SWF to read - */ - public SWFInputStream(InputStream is, int version) { - this(is, version, 0L); - } - - /** - * Gets position in bytes in the stream - * - * @return Number of bytes - */ - public long getPos() { - return pos; - } - - /** - * Sets position in bytes in the stream - * - * @param pos Number of bytes - * @throws java.io.IOException - */ - public void seek(long pos) throws IOException { - if (is instanceof SeekableInputStream) { - SeekableInputStream sis = (SeekableInputStream) is; - sis.seek(pos); - } else { - throw new IOException("Underlying stream is not a SeekableInputStream"); - } - } - - /** - * Reads one byte from the stream - * - * @return byte or -1 on error - * @throws IOException - */ - @Override - public int read() throws IOException { - bitPos = 0; - try { - return readNoBitReset(); - } catch (EOFException | EndOfStreamException ex) { - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, null, ex); - } - return -1; - } - - public int readEx() throws IOException { - bitPos = 0; - return readNoBitReset(); - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - int bytesRead = super.read(b, off, len); - bitPos = 0; - //pos += bytesRead; - return bytesRead; - } - - public void alignByte() { - bitPos = 0; - } - private int lastPercent = -1; - - private int readNoBitReset() throws IOException, EndOfStreamException { - pos++; - if (percentMax > 0) { - int percent = (int) (pos * 100 / percentMax); - if (lastPercent != percent) { - for (ProgressListener pl : listeners) { - pl.progress(percent); - } - lastPercent = percent; - } - } - int r = is.read(); - if (r == -1) { - throw new EndOfStreamException(); - } - return r; - } - - /** - * Reads one UI8 (Unsigned 8bit integer) value from the stream - * - * @return UI8 value or -1 on error - * @throws IOException - */ - public int readUI8() throws IOException { - return readEx(); - } - - /** - * Reads one string value from the stream - * - * @return String value - * @throws IOException - */ - public String readString() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int r; - while (true) { - r = readEx(); - if (r == 0) { - return new String(baos.toByteArray(), Utf8Helper.charset); - } - baos.write(r); - } - } - - /** - * Reads one UI32 (Unsigned 32bit integer) value from the stream - * - * @return UI32 value - * @throws IOException - */ - public long readUI32() throws IOException { - return (readEx() + (readEx() << 8) + (readEx() << 16) + (readEx() << 24)) & 0xffffffff; - } - - /** - * Reads one UI16 (Unsigned 16bit integer) value from the stream - * - * @return UI16 value - * @throws IOException - */ - public int readUI16() throws IOException { - return readEx() + (readEx() << 8); - } - - public int readUI24() throws IOException { - return readEx() + (readEx() << 8) + (readEx() << 16); - } - - /** - * Reads one SI32 (Signed 32bit integer) value from the stream - * - * @return SI32 value - * @throws IOException - */ - public long readSI32() throws IOException { - long uval = readEx() + (readEx() << 8) + (readEx() << 16) + (readEx() << 24); - if (uval >= 0x80000000) { - return -(((~uval) & 0xffffffff) + 1); - } else { - return uval; - } - } - - /** - * Reads one SI16 (Signed 16bit integer) value from the stream - * - * @return SI16 value - * @throws IOException - */ - public int readSI16() throws IOException { - int uval = readEx() + (readEx() << 8); - if (uval >= 0x8000) { - return -(((~uval) & 0xffff) + 1); - } else { - return uval; - } - } - - /** - * Reads one SI8 (Signed 8bit integer) value from the stream - * - * @return SI8 value - * @throws IOException - */ - public int readSI8() throws IOException { - int uval = readEx(); - if (uval >= 0x80) { - return -(((~uval) & 0xff) + 1); - } else { - return uval; - } - } - - /** - * Reads one FIXED (Fixed point 16.16) value from the stream - * - * @return FIXED value - * @throws IOException - */ - public double readFIXED() throws IOException { - int afterPoint = readUI16(); - int beforePoint = readUI16(); - return ((double) ((beforePoint << 16) + afterPoint)) / 65536; - } - - /** - * Reads one FIXED8 (Fixed point 8.8) value from the stream - * - * @return FIXED8 value - * @throws IOException - */ - public float readFIXED8() throws IOException { - int afterPoint = readEx(); - int beforePoint = readEx(); - return beforePoint + (((float) afterPoint) / 256); - } - - private long readLong() throws IOException { - byte[] readBuffer = readBytesEx(8); - return (((long) readBuffer[3] << 56) - + ((long) (readBuffer[2] & 255) << 48) - + ((long) (readBuffer[1] & 255) << 40) - + ((long) (readBuffer[0] & 255) << 32) - + ((long) (readBuffer[7] & 255) << 24) - + ((readBuffer[6] & 255) << 16) - + ((readBuffer[5] & 255) << 8) - + ((readBuffer[4] & 255))); - } - - /** - * Reads one DOUBLE (double precision floating point value) value from the - * stream - * - * @return DOUBLE value - * @throws IOException - */ - public double readDOUBLE() throws IOException { - long el = readLong(); - double ret = Double.longBitsToDouble(el); - return ret; - } - - /** - * Reads one FLOAT (single precision floating point value) value from the - * stream - * - * @return FLOAT value - * @throws IOException - */ - public float readFLOAT() throws IOException { - int val = (int) readUI32(); - float ret = Float.intBitsToFloat(val); - /*int sign = val >> 31; - int mantisa = val & 0x3FFFFF; - int exp = (val >> 22) & 0xFF; - float ret =(sign == 1 ? -1 : 1) * (float) Math.pow(2, exp)* (1+((mantisa)/ (float)(1<<23)));*/ - return ret; - } - - /** - * Reads one FLOAT16 (16bit floating point value) value from the stream - * - * @return FLOAT16 value - * @throws IOException - */ - public float readFLOAT16() throws IOException { - int val = readUI16(); - int sign = val >> 15; - int mantisa = val & 0x3FF; - int exp = (val >> 10) & 0x1F; - float ret = (sign == 1 ? -1 : 1) * (float) Math.pow(2, exp) * (1 + ((mantisa) / (float) (1 << 10))); - return ret; - } - - /** - * Reads bytes from the stream - * - * @param count Number of bytes to read - * @return Array of read bytes - * @throws IOException - */ - public byte[] readBytesEx(long count) throws IOException { - if (count <= 0) { - return new byte[0]; - } - byte[] ret = new byte[(int) count]; - for (int i = 0; i < count; i++) { - ret[i] = (byte) readEx(); - } - return ret; - } - - /** - * Reads bytes from the stream - * - * @param count Number of bytes to read - * @return Array of read bytes - * @throws IOException - */ - public byte[] readBytes(int count) throws IOException { - if (count <= 0) { - return new byte[0]; - } - byte[] ret = new byte[count]; - int i = 0; - try { - for (i = 0; i < count; i++) { - ret[i] = (byte) readEx(); - } - } catch (EOFException | EndOfStreamException ex) { - ret = Arrays.copyOf(ret, i); // truncate array - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, null, ex); - } - return ret; - } - - public byte[] readBytesZlib(long count) throws IOException { - byte[] data = readBytesEx(count); - InflaterInputStream dis = new InflaterInputStream(new ByteArrayInputStream(data)); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[4096]; - int c = 0; - while ((c = dis.read(buf)) > 0) { - baos.write(buf, 0, c); - } - return baos.toByteArray(); - } - - /** - * Reads one EncodedU32 (Encoded unsigned 32bit value) value from the stream - * - * @return U32 value - * @throws IOException - */ - public long readEncodedU32() throws IOException { - int result = readEx(); - if ((result & 0x00000080) == 0) { - return result; - } - result = (result & 0x0000007f) | (readEx()) << 7; - if ((result & 0x00004000) == 0) { - return result; - } - result = (result & 0x00003fff) | (readEx()) << 14; - if ((result & 0x00200000) == 0) { - return result; - } - result = (result & 0x001fffff) | (readEx()) << 21; - if ((result & 0x10000000) == 0) { - return result; - } - result = (result & 0x0fffffff) | (readEx()) << 28; - return result; - } - private int bitPos = 0; - private int tempByte = 0; - - /** - * Reads UB[nBits] (Unsigned-bit value) value from the stream - * - * @param nBits Number of bits which represent value - * @return Unsigned value - * @throws IOException - */ - public long readUB(int nBits) throws IOException { - if (nBits == 0) { - return 0; - } - long ret = 0; - if (bitPos == 0) { - tempByte = readNoBitReset(); - } - for (int bit = 0; bit < nBits; bit++) { - int nb = (tempByte >> (7 - bitPos)) & 1; - ret += (nb << (nBits - 1 - bit)); - bitPos++; - if (bitPos == 8) { - bitPos = 0; - if (bit != nBits - 1) { - tempByte = readNoBitReset(); - } - } - } - return ret; - } - - /** - * Reads SB[nBits] (Signed-bit value) value from the stream - * - * @param nBits Number of bits which represent value - * @return Signed value - * @throws IOException - */ - public long readSB(int nBits) throws IOException { - int uval = (int) readUB(nBits); - - int shift = 32 - nBits; - // sign extension - uval = (uval << shift) >> shift; - return uval; - } - - /** - * Reads FB[nBits] (Signed fixed-point bit value) value from the stream - * - * @param nBits Number of bits which represent value - * @return Fixed-point value - * @throws IOException - */ - public float readFB(int nBits) throws IOException { - if (nBits == 0) { - return 0; - } - float val = readSB(nBits); - float ret = val / 0x10000; - return ret; - } - - /** - * Reads one RECT value from the stream - * - * @return RECT value - * @throws IOException - */ - public RECT readRECT() throws IOException { - RECT ret = new RECT(); - int NBits = (int) readUB(5); - ret.Xmin = (int) readSB(NBits); - ret.Xmax = (int) readSB(NBits); - ret.Ymin = (int) readSB(NBits); - ret.Ymax = (int) readSB(NBits); - ret.nbits = NBits; - alignByte(); - return ret; - } - - private static void dumpTag(PrintStream out, int version, Tag tag, int level) { - StringBuilder sb = new StringBuilder(); - sb.append(Helper.formatHex((int) tag.getPos(), 8)); - sb.append(": "); - sb.append(Helper.indent(level, "", " ")); - sb.append(Helper.format(tag.toString(), 25 - 2 * level)); - sb.append(" tagId="); - sb.append(Helper.formatInt(tag.getId(), 3)); - sb.append(" len="); - sb.append(Helper.formatInt((int) tag.getOrigDataLength(), 8)); - sb.append(" "); - sb.append(Helper.bytesToHexString(64, tag.getData(), 0)); - out.println(sb.toString()); -// out.println(Utils.formatHex((int)tag.getPos(), 8) + ": " + Utils.indent(level, "") + Utils.format(tag.toString(), 25 - 2*level) + " tagId="+tag.getId()+" len="+tag.getOrigDataLength()+": "+Utils.bytesToHexString(64, tag.getData(version), 0)); - if (tag.hasSubTags()) { - for (Tag subTag : tag.getSubTags()) { - dumpTag(out, version, subTag, level + 1); - } - } - } - - private class TagResolutionTask implements Callable { - - private final Tag tag; - private final int level; - private final boolean parallel; - private final boolean skipUnusualTags; - private final SWF swf; - private final boolean gfx; - - public TagResolutionTask(SWF swf, Tag tag, int level, boolean parallel, boolean skipUnusualTags, boolean gfx) { - this.tag = tag; - this.level = level; - this.parallel = parallel; - this.skipUnusualTags = skipUnusualTags; - this.swf = swf; - this.gfx = gfx; - } - - @Override - public Tag call() throws Exception { - try { - return SWFInputStream.resolveTag(swf, tag, level, parallel, skipUnusualTags, gfx); - } catch (EndOfStreamException ex) { - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, null, ex); - return tag; - } - } - } - - /** - * Reads list of tags from the stream. Reading ends with End tag(=0) or end - * of the stream. Optionally can skip AS1/2 tags when file is AS3 - * - * @param swf - * @param timelined - * @param level - * @param parallel - * @param skipUnusualTags - * @param parseTags - * @param gfx - * @return List of tags - * @throws IOException - * @throws java.lang.InterruptedException - */ - public List readTagList(SWF swf, Timelined timelined, int level, boolean parallel, boolean skipUnusualTags, boolean parseTags, boolean gfx) throws IOException, InterruptedException { - ExecutorService executor = null; - List> futureResults = new ArrayList<>(); - if (parallel) { - executor = Executors.newFixedThreadPool(Configuration.parallelThreadCount.get()); - futureResults = new ArrayList<>(); - } - List tags = new ArrayList<>(); - Tag tag; - Tag previousTag = null; - boolean isAS3 = false; - while (true) { - long pos = getPos(); - try { - tag = readTag(swf, level, pos, parseTags && !parallel, parallel, skipUnusualTags, gfx); - } catch (EOFException | EndOfStreamException ex) { - tag = null; - } - if (tag == null) { - break; - } - - tag.setTimelined(timelined); - if (!parallel) { - tags.add(tag); - } - if (Configuration.dumpTags.get() && level == 0) { - dumpTag(System.out, version, tag, level); - } - tag.previousTag = previousTag; - previousTag = tag; - - boolean doParse; - if (!skipUnusualTags) { - doParse = true; - } else { - switch (tag.getId()) { - case FileAttributesTag.ID: //FileAttributes - FileAttributesTag fileAttributes = (FileAttributesTag) resolveTag(swf, tag, level, parallel, skipUnusualTags, gfx); - if (fileAttributes.actionScript3) { - isAS3 = true; - } - doParse = true; - break; - case DoActionTag.ID: - case DoInitActionTag.ID: - if (isAS3) { - doParse = false; - } else { - doParse = true; - } - break; - case ShowFrameTag.ID: - case PlaceObjectTag.ID: - case PlaceObject2Tag.ID: - case RemoveObjectTag.ID: - case RemoveObject2Tag.ID: - case PlaceObject3Tag.ID: //? - case StartSoundTag.ID: - case FrameLabelTag.ID: - case SoundStreamHeadTag.ID: - case SoundStreamHead2Tag.ID: - case SoundStreamBlockTag.ID: - case VideoFrameTag.ID: - case EndTag.ID: - doParse = true; - break; - default: - if (level > 0) { //No such tags in DefineSprite allowed - Logger.getLogger(SWFInputStream.class.getName()).log(Level.FINE, "Tag({0}) found in DefineSprite => Ignored", tag.getId()); - doParse = false; - } else { - doParse = true; - } - - } - } - if (!parseTags) { - doParse = false; - } - - if (doParse) { - if (parallel) { - Future future = executor.submit(new TagResolutionTask(swf, tag, level, parallel, skipUnusualTags, gfx)); - futureResults.add(future); - } - } - - if (tag.getId() == EndTag.ID) { - break; - } - } - - if (parallel) { - for (Future future : futureResults) { - try { - tags.add(future.get()); - } catch (InterruptedException ex) { - future.cancel(true); - } catch (ExecutionException e) { - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "Error during tag reading", e); - } - } - - executor.shutdown(); - } - return tags; - } - - public static Tag resolveTag(SWF swf, Tag tag, int level, boolean parallel, boolean skipUnusualTags, boolean gfx) throws InterruptedException { - Tag ret; - - byte[] data = tag.getData(); - byte[] headerData = tag.getOriginalHeaderData(); - long pos = tag.getPos(); - try { - switch (tag.getId()) { - case 0: - ret = new EndTag(swf, headerData, data, pos); - break; - case 1: - ret = new ShowFrameTag(swf, headerData, data, pos); - break; - case 2: - ret = new DefineShapeTag(swf, headerData, data, pos); - break; - //case 3: FreeCharacter - case 4: - ret = new PlaceObjectTag(swf, headerData, data, pos); - break; - case 5: - ret = new RemoveObjectTag(swf, headerData, data, pos); - break; - case 6: - ret = new DefineBitsTag(swf, headerData, data, pos); - break; - case 7: - ret = new DefineButtonTag(swf, headerData, data, pos); - break; - case 8: - ret = new JPEGTablesTag(swf, headerData, data, pos); - break; - case 9: - ret = new SetBackgroundColorTag(swf, headerData, data, pos); - break; - case 10: - ret = new DefineFontTag(swf, headerData, data, pos); - break; - case 11: - ret = new DefineTextTag(swf, headerData, data, pos); - break; - case 12: - ret = new DoActionTag(swf, headerData, data, pos); - break; - case 13: - ret = new DefineFontInfoTag(swf, headerData, data, pos); - break; - case 14: - ret = new DefineSoundTag(swf, headerData, data, pos); - break; - case 15: - ret = new StartSoundTag(swf, headerData, data, pos); - break; - //case 16: - case 17: - ret = new DefineButtonSoundTag(swf, headerData, data, pos); - break; - case 18: - ret = new SoundStreamHeadTag(swf, headerData, data, pos); - break; - case 19: - ret = new SoundStreamBlockTag(swf, headerData, data, pos); - break; - case 21: - ret = new DefineBitsJPEG2Tag(swf, headerData, data, pos); - break; - case 20: - ret = new DefineBitsLosslessTag(swf, headerData, data, pos); - break; - case 22: - ret = new DefineShape2Tag(swf, headerData, data, pos); - break; - case 23: - ret = new DefineButtonCxformTag(swf, headerData, data, pos); - break; - case 24: - ret = new ProtectTag(swf, headerData, data, pos); - break; - //case 25: PathsArePostscript - case 26: - ret = new PlaceObject2Tag(swf, headerData, data, pos); - break; - //case 27: - case 28: - ret = new RemoveObject2Tag(swf, headerData, data, pos); - break; - //case 29: SyncFrame - //case 30: - //case 31: FreeAll - case 32: - ret = new DefineShape3Tag(swf, headerData, data, pos); - break; - case 33: - ret = new DefineText2Tag(swf, headerData, data, pos); - break; - case 34: - ret = new DefineButton2Tag(swf, headerData, data, pos); - break; - case 35: - ret = new DefineBitsJPEG3Tag(swf, headerData, data, pos); - break; - case 36: - ret = new DefineBitsLossless2Tag(swf, headerData, data, pos); - break; - case 37: - ret = new DefineEditTextTag(swf, headerData, data, pos); - break; - //case 38: DefineVideo - case 39: - ret = new DefineSpriteTag(swf, headerData, data, level, pos, parallel, skipUnusualTags); - break; - //case 40: NameCharacter - case 41: - ret = new ProductInfoTag(swf, headerData, data, pos); - break; - //case 42: DefineTextFormat - case 43: - ret = new FrameLabelTag(swf, headerData, data, pos); - break; - //case 44: - case 45: - ret = new SoundStreamHead2Tag(swf, headerData, data, pos); - break; - case 46: - ret = new DefineMorphShapeTag(swf, headerData, data, pos); - break; - //case 47: GenerateFrame - case 48: - ret = new DefineFont2Tag(swf, headerData, data, pos); - break; - //case 49: GeneratorCommand - //case 50: DefineCommandObject - //case 51: CharacterSet - //case 52: ExternalFont - //case 53-55 - case 56: - ret = new ExportAssetsTag(swf, headerData, data, pos); - break; - case 57: - ret = new ImportAssetsTag(swf, headerData, data, pos); - break; - case 58: - ret = new EnableDebuggerTag(swf, headerData, data, pos); - break; - case 59: - ret = new DoInitActionTag(swf, headerData, data, pos); - break; - case 60: - ret = new DefineVideoStreamTag(swf, headerData, data, pos); - break; - case 61: - ret = new VideoFrameTag(swf, headerData, data, pos); - break; - case 62: - ret = new DefineFontInfo2Tag(swf, headerData, data, pos); - break; - case 63: - ret = new DebugIDTag(swf, headerData, data, pos); - break; - case 64: - ret = new EnableDebugger2Tag(swf, headerData, data, pos); - break; - case 65: - ret = new ScriptLimitsTag(swf, headerData, data, pos); - break; - case 66: - ret = new SetTabIndexTag(swf, headerData, data, pos); - break; - //case 67-68: - case 69: - ret = new FileAttributesTag(swf, headerData, data, pos); - break; - case 70: - ret = new PlaceObject3Tag(swf, headerData, data, pos); - break; - case 71: - ret = new ImportAssets2Tag(swf, headerData, data, pos); - break; - case 72: - ret = new DoABCTag(swf, headerData, data, pos); - break; - case 73: - ret = new DefineFontAlignZonesTag(swf, headerData, data, pos); - break; - case 74: - ret = new CSMTextSettingsTag(swf, headerData, data, pos); - break; - case 75: - ret = new DefineFont3Tag(swf, headerData, data, pos); - break; - case 76: - ret = new SymbolClassTag(swf, headerData, data, pos); - break; - case 77: - ret = new MetadataTag(swf, headerData, data, pos); - break; - case 78: - ret = new DefineScalingGridTag(swf, headerData, data, pos); - break; - //case 79-81: - case 82: - ret = new DoABCDefineTag(swf, headerData, data, pos); - break; - case 83: - ret = new DefineShape4Tag(swf, headerData, data, pos); - break; - case 84: - ret = new DefineMorphShape2Tag(swf, headerData, data, pos); - break; - //case 85: - case 86: - ret = new DefineSceneAndFrameLabelDataTag(swf, headerData, data, pos); - break; - case 87: - ret = new DefineBinaryDataTag(swf, headerData, data, pos); - break; - case 88: - ret = new DefineFontNameTag(swf, headerData, data, pos); - break; - case 89: - ret = new StartSound2Tag(swf, headerData, data, pos); - break; - case 90: - ret = new DefineBitsJPEG4Tag(swf, headerData, data, pos); - break; - case 91: - ret = new DefineFont4Tag(swf, headerData, data, pos); - break; - //case 92: certificate - case 93: - ret = new EnableTelemetryTag(swf, headerData, data, pos); - break; - case 94: - ret = new PlaceObject4Tag(swf, headerData, data, pos); - break; - default: - if (gfx) { //GFX tags only in GFX files. There may be incorrect GFX tags in non GFX files - switch (tag.getId()) { - case 1000: - ret = new ExporterInfoTag(swf, headerData, data, pos); - break; - case 1001: - ret = new DefineExternalImage(swf, headerData, data, pos); - break; - case 1002: - ret = new FontTextureInfo(swf, headerData, data, pos); - break; - case 1003: - ret = new DefineExternalGradient(swf, headerData, data, pos); - break; - case 1004: - ret = new DefineGradientMap(swf, headerData, data, pos); - break; - case 1005: - ret = new DefineCompactedFont(swf, headerData, data, pos); - break; - case 1006: - ret = new DefineExternalSound(swf, headerData, data, pos); - break; - case 1007: - ret = new DefineExternalStreamSound(swf, headerData, data, pos); - break; - case 1008: - ret = new DefineSubImage(swf, headerData, data, pos); - break; - case 1009: - ret = new DefineExternalImage2(swf, headerData, data, pos); - break; - default: - ret = new UnknownTag(swf, tag.getId(), headerData, data, pos); - } - } else { - ret = new UnknownTag(swf, tag.getId(), headerData, data, pos); - } - } - } catch (IOException ex) { - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "Error during tag reading", ex); - ret = new Tag(swf, tag.getId(), "ErrorTag", headerData, data, pos); - } - ret.previousTag = tag.previousTag; - ret.forceWriteAsLong = tag.forceWriteAsLong; - ret.setTimelined(tag.getTimelined()); - return ret; - } - - /** - * Reads one Tag from the stream with optional resolving (= reading tag - * content) - * - * @param swf - * @param level - * @param pos - * @param resolve - * @param parallel - * @param skipUnusualTags - * @param gfx - * @return Tag or null when End tag - * @throws IOException - * @throws java.lang.InterruptedException - */ - public Tag readTag(SWF swf, int level, long pos, boolean resolve, boolean parallel, boolean skipUnusualTags, boolean gfx) throws IOException, InterruptedException { - int tagIDTagLength = readUI16(); - int tagID = (tagIDTagLength) >> 6; - - logger.log(Level.INFO, "Reading tag. ID={0}, position: {1}", new Object[]{tagID, pos}); - - long tagLength = (tagIDTagLength & 0x003F); - boolean readLong = false; - if (tagLength == 0x3f) { - tagLength = readSI32(); - readLong = true; - } - byte[] data = readBytes((int) tagLength); - Tag ret = new Tag(swf, tagID, "Unresolved", Tag.getTagHeader(tagIDTagLength, tagLength, readLong, swf.version), data, pos); - ret.forceWriteAsLong = readLong; - - if (resolve) { - try { - ret = resolveTag(swf, ret, level, parallel, skipUnusualTags, gfx); - } catch (EndOfStreamException ex) { - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, null, ex); - } - - if (Configuration.debugMode.get()) { - byte[] dataNew = ret.getData(); - int ignoreFirst = 0; - for (int i = 0; i < data.length; i++) { - if (i >= dataNew.length) { - break; - } - if (dataNew[i] != data[i]) { - if (ignoreFirst > 0) { - ignoreFirst--; - continue; - } - String e = "TAG " + ret.toString() + " WRONG, "; - for (int j = i - 10; j <= i + 5; j++) { - while (j < 0) { - j++; - } - if (j >= data.length) { - break; - } - if (j >= dataNew.length) { - break; - } - if (j >= i) { - e += (Long.toHexString(data[j] & 0xff) + " ( is " + Long.toHexString(dataNew[j] & 0xff) + ") "); - } else { - e += (Long.toHexString(data[j] & 0xff) + " "); - } - } - logger.fine(e); - } - } - } - } - return ret; - } - - /** - * Reads one Action from the stream - * - * @param cpool - * @return Action or null when ActionEndFlag or end of the stream - * @throws IOException - */ - public Action readAction(ConstantPool cpool) throws IOException { - int actionCode = -1; - - try { - actionCode = readUI8(); - if (actionCode == 0) { - return new ActionEnd(); - } - if (actionCode == -1) { - return null; - } - int actionLength = 0; - if (actionCode >= 0x80) { - actionLength = readUI16(); - } - switch (actionCode) { - //SWF3 Actions - case 0x81: - return new ActionGotoFrame(actionLength, this); - case 0x83: - return new ActionGetURL(actionLength, this, version); - case 0x04: - return new ActionNextFrame(); - case 0x05: - return new ActionPrevFrame(); - case 0x06: - return new ActionPlay(); - case 0x07: - return new ActionStop(); - case 0x08: - return new ActionToggleQuality(); - case 0x09: - return new ActionStopSounds(); - case 0x8A: - return new ActionWaitForFrame(actionLength, this, cpool); - case 0x8B: - return new ActionSetTarget(actionLength, this, version); - case 0x8C: - return new ActionGoToLabel(actionLength, this, version); - //SWF4 Actions - case 0x96: - return new ActionPush(actionLength, this, version); - case 0x17: - return new ActionPop(); - case 0x0A: - return new ActionAdd(); - case 0x0B: - return new ActionSubtract(); - case 0x0C: - return new ActionMultiply(); - case 0x0D: - return new ActionDivide(); - case 0x0E: - return new ActionEquals(); - case 0x0F: - return new ActionLess(); - case 0x10: - return new ActionAnd(); - case 0x11: - return new ActionOr(); - case 0x12: - return new ActionNot(); - case 0x13: - return new ActionStringEquals(); - case 0x14: - return new ActionStringLength(); - case 0x21: - return new ActionStringAdd(); - case 0x15: - return new ActionStringExtract(); - case 0x29: - return new ActionStringLess(); - case 0x31: - return new ActionMBStringLength(); - case 0x35: - return new ActionMBStringExtract(); - case 0x18: - return new ActionToInteger(); - case 0x32: - return new ActionCharToAscii(); - case 0x33: - return new ActionAsciiToChar(); - case 0x36: - return new ActionMBCharToAscii(); - case 0x37: - return new ActionMBAsciiToChar(); - case 0x99: - return new ActionJump(actionLength, this); - case 0x9D: - return new ActionIf(actionLength, this); - case 0x9E: - return new ActionCall(actionLength); - case 0x1C: - return new ActionGetVariable(); - case 0x1D: - return new ActionSetVariable(); - case 0x9A: - return new ActionGetURL2(actionLength, this); - case 0x9F: - return new ActionGotoFrame2(actionLength, this); - case 0x20: - return new ActionSetTarget2(); - case 0x22: - return new ActionGetProperty(); - case 0x23: - return new ActionSetProperty(); - case 0x24: - return new ActionCloneSprite(); - case 0x25: - return new ActionRemoveSprite(); - case 0x27: - return new ActionStartDrag(); - case 0x28: - return new ActionEndDrag(); - case 0x8D: - return new ActionWaitForFrame2(actionLength, this, cpool); - case 0x26: - return new ActionTrace(); - case 0x34: - return new ActionGetTime(); - case 0x30: - return new ActionRandomNumber(); - //SWF5 Actions - case 0x3D: - return new ActionCallFunction(); - case 0x52: - return new ActionCallMethod(); - case 0x88: - return new ActionConstantPool(actionLength, this, version); - case 0x9B: - return new ActionDefineFunction(actionLength, this, version); - case 0x3C: - return new ActionDefineLocal(); - case 0x41: - return new ActionDefineLocal2(); - case 0x3A: - return new ActionDelete(); - case 0x3B: - return new ActionDelete2(); - case 0x46: - return new ActionEnumerate(); - case 0x49: - return new ActionEquals2(); - case 0x4E: - return new ActionGetMember(); - case 0x42: - return new ActionInitArray(); - case 0x43: - return new ActionInitObject(); - case 0x53: - return new ActionNewMethod(); - case 0x40: - return new ActionNewObject(); - case 0x4F: - return new ActionSetMember(); - case 0x45: - return new ActionTargetPath(); - case 0x94: - return new ActionWith(actionLength, this, version); - case 0x4A: - return new ActionToNumber(); - case 0x4B: - return new ActionToString(); - case 0x44: - return new ActionTypeOf(); - case 0x47: - return new ActionAdd2(); - case 0x48: - return new ActionLess2(); - case 0x3F: - return new ActionModulo(); - case 0x60: - return new ActionBitAnd(); - case 0x63: - return new ActionBitLShift(); - case 0x61: - return new ActionBitOr(); - case 0x64: - return new ActionBitRShift(); - case 0x65: - return new ActionBitURShift(); - case 0x62: - return new ActionBitXor(); - case 0x51: - return new ActionDecrement(); - case 0x50: - return new ActionIncrement(); - case 0x4C: - return new ActionPushDuplicate(); - case 0x3E: - return new ActionReturn(); - case 0x4D: - return new ActionStackSwap(); - case 0x87: - return new ActionStoreRegister(actionLength, this); - //SWF6 Actions - case 0x54: - return new ActionInstanceOf(); - case 0x55: - return new ActionEnumerate2(); - case 0x66: - return new ActionStrictEquals(); - case 0x67: - return new ActionGreater(); - case 0x68: - return new ActionStringGreater(); - //SWF7 Actions - case 0x8E: - return new ActionDefineFunction2(actionLength, this, version); - case 0x69: - return new ActionExtends(); - case 0x2B: - return new ActionCastOp(); - case 0x2C: - return new ActionImplementsOp(); - case 0x8F: - return new ActionTry(actionLength, this, version); - case 0x2A: - return new ActionThrow(); - default: - /*if (actionLength > 0) { - //skip(actionLength); - }*/ - //throw new UnknownActionException(actionCode); - Action r = new ActionNop(); - r.actionCode = actionCode; - r.actionLength = actionLength; - return r; - //return new Action(actionCode, actionLength); - } - } catch (EndOfStreamException | ArrayIndexOutOfBoundsException eos) { - return null; - } - } - - /** - * Reads one MATRIX value from the stream - * - * @return MATRIX value - * @throws IOException - */ - public MATRIX readMatrix() throws IOException { - MATRIX ret = new MATRIX(); - ret.hasScale = readUB(1) == 1; - if (ret.hasScale) { - int NScaleBits = (int) readUB(5); - ret.scaleX = (int) readSB(NScaleBits); - ret.scaleY = (int) readSB(NScaleBits); - ret.nScaleBits = NScaleBits; - } - ret.hasRotate = readUB(1) == 1; - if (ret.hasRotate) { - int NRotateBits = (int) readUB(5); - ret.rotateSkew0 = (int) readSB(NRotateBits); - ret.rotateSkew1 = (int) readSB(NRotateBits); - ret.nRotateBits = NRotateBits; - } - int NTranslateBits = (int) readUB(5); - ret.translateX = (int) readSB(NTranslateBits); - ret.translateY = (int) readSB(NTranslateBits); - ret.nTranslateBits = NTranslateBits; - alignByte(); - return ret; - } - - /** - * Reads one CXFORMWITHALPHA value from the stream - * - * @return CXFORMWITHALPHA value - * @throws IOException - */ - public CXFORMWITHALPHA readCXFORMWITHALPHA() throws IOException { - CXFORMWITHALPHA ret = new CXFORMWITHALPHA(); - ret.hasAddTerms = readUB(1) == 1; - ret.hasMultTerms = readUB(1) == 1; - int Nbits = (int) readUB(4); - ret.nbits = Nbits; - if (ret.hasMultTerms) { - ret.redMultTerm = (int) readSB(Nbits); - ret.greenMultTerm = (int) readSB(Nbits); - ret.blueMultTerm = (int) readSB(Nbits); - ret.alphaMultTerm = (int) readSB(Nbits); - } - if (ret.hasAddTerms) { - ret.redAddTerm = (int) readSB(Nbits); - ret.greenAddTerm = (int) readSB(Nbits); - ret.blueAddTerm = (int) readSB(Nbits); - ret.alphaAddTerm = (int) readSB(Nbits); - } - alignByte(); - return ret; - } - - /** - * Reads one CXFORM value from the stream - * - * @return CXFORM value - * @throws IOException - */ - public CXFORM readCXFORM() throws IOException { - CXFORM ret = new CXFORM(); - ret.hasAddTerms = readUB(1) == 1; - ret.hasMultTerms = readUB(1) == 1; - int Nbits = (int) readUB(4); - ret.nbits = Nbits; - if (ret.hasMultTerms) { - ret.redMultTerm = (int) readSB(Nbits); - ret.greenMultTerm = (int) readSB(Nbits); - ret.blueMultTerm = (int) readSB(Nbits); - } - if (ret.hasAddTerms) { - ret.redAddTerm = (int) readSB(Nbits); - ret.greenAddTerm = (int) readSB(Nbits); - ret.blueAddTerm = (int) readSB(Nbits); - } - alignByte(); - return ret; - } - - /** - * Reads one CLIPEVENTFLAGS value from the stream - * - * @return CLIPEVENTFLAGS value - * @throws IOException - */ - public CLIPEVENTFLAGS readCLIPEVENTFLAGS() throws IOException { - CLIPEVENTFLAGS ret = new CLIPEVENTFLAGS(); - ret.clipEventKeyUp = readUB(1) == 1; - ret.clipEventKeyDown = readUB(1) == 1; - ret.clipEventMouseUp = readUB(1) == 1; - ret.clipEventMouseDown = readUB(1) == 1; - ret.clipEventMouseMove = readUB(1) == 1; - ret.clipEventUnload = readUB(1) == 1; - ret.clipEventEnterFrame = readUB(1) == 1; - ret.clipEventLoad = readUB(1) == 1; - ret.clipEventDragOver = readUB(1) == 1; - ret.clipEventRollOut = readUB(1) == 1; - ret.clipEventRollOver = readUB(1) == 1; - ret.clipEventReleaseOutside = readUB(1) == 1; - ret.clipEventRelease = readUB(1) == 1; - ret.clipEventPress = readUB(1) == 1; - ret.clipEventInitialize = readUB(1) == 1; - ret.clipEventData = readUB(1) == 1; - if (version >= 6) { - ret.reserved = (int) readUB(5); - ret.clipEventConstruct = readUB(1) == 1; - ret.clipEventKeyPress = readUB(1) == 1; - ret.clipEventDragOut = readUB(1) == 1; - ret.reserved2 = (int) readUB(8); - } - return ret; - } - - /** - * Reads one CLIPACTIONRECORD value from the stream - * - * @param swf - * @param tag - * @return CLIPACTIONRECORD value - * @throws IOException - */ - public CLIPACTIONRECORD readCLIPACTIONRECORD(SWF swf, Tag tag) throws IOException { - CLIPACTIONRECORD ret = new CLIPACTIONRECORD(swf, this, getPos(), tag); - if (ret.eventFlags.isClear()) { - return null; - } - //ret.actions = (new SWFInputStream(new ByteArrayInputStream(readBytes(actionRecordSize)), version)).readActionList(); - return ret; - } - - /** - * Reads one CLIPACTIONS value from the stream - * - * @param swf - * @param tag - * @return CLIPACTIONS value - * @throws IOException - */ - public CLIPACTIONS readCLIPACTIONS(SWF swf, Tag tag) throws IOException { - CLIPACTIONS ret = new CLIPACTIONS(); - ret.reserved = readUI16(); - ret.allEventFlags = readCLIPEVENTFLAGS(); - CLIPACTIONRECORD cr; - ret.clipActionRecords = new ArrayList<>(); - while ((cr = readCLIPACTIONRECORD(swf, tag)) != null) { - ret.clipActionRecords.add(cr); - } - return ret; - } - - /** - * Reads one COLORMATRIXFILTER value from the stream - * - * @return COLORMATRIXFILTER value - * @throws IOException - */ - public COLORMATRIXFILTER readCOLORMATRIXFILTER() throws IOException { - COLORMATRIXFILTER ret = new COLORMATRIXFILTER(); - ret.matrix = new float[20]; - for (int i = 0; i < 20; i++) { - ret.matrix[i] = readFLOAT(); - } - return ret; - } - - /** - * Reads one RGBA value from the stream - * - * @return RGBA value - * @throws IOException - */ - public RGBA readRGBA() throws IOException { - RGBA ret = new RGBA(); - ret.red = readUI8(); - ret.green = readUI8(); - ret.blue = readUI8(); - ret.alpha = readUI8(); - return ret; - } - - /** - * Reads one ARGB value from the stream - * - * @return ARGB value - * @throws IOException - */ - public ARGB readARGB() throws IOException { - ARGB ret = new ARGB(); - ret.alpha = readUI8(); - ret.red = readUI8(); - ret.green = readUI8(); - ret.blue = readUI8(); - return ret; - } - - /** - * Reads one RGB value from the stream - * - * @return RGB value - * @throws IOException - */ - public RGB readRGB() throws IOException { - RGB ret = new RGB(); - ret.red = readUI8(); - ret.green = readUI8(); - ret.blue = readUI8(); - return ret; - } - - /** - * Reads one CONVOLUTIONFILTER value from the stream - * - * @return CONVOLUTIONFILTER value - * @throws IOException - */ - public CONVOLUTIONFILTER readCONVOLUTIONFILTER() throws IOException { - CONVOLUTIONFILTER ret = new CONVOLUTIONFILTER(); - ret.matrixX = readUI8(); - ret.matrixY = readUI8(); - ret.divisor = readFLOAT(); - ret.bias = readFLOAT(); - ret.matrix = new float[ret.matrixX][ret.matrixY]; - for (int x = 0; x < ret.matrixX; x++) { - for (int y = 0; y < ret.matrixY; y++) { - ret.matrix[x][y] = readFLOAT(); - } - } - ret.defaultColor = readRGBA(); - ret.reserved = (int) readUB(6); - ret.clamp = readUB(1) == 1; - ret.preserveAlpha = readUB(1) == 1; - return ret; - } - - /** - * Reads one BLURFILTER value from the stream - * - * @return BLURFILTER value - * @throws IOException - */ - public BLURFILTER readBLURFILTER() throws IOException { - BLURFILTER ret = new BLURFILTER(); - ret.blurX = readFIXED(); - ret.blurY = readFIXED(); - ret.passes = (int) readUB(5); - ret.reserved = (int) readUB(3); - return ret; - } - - /** - * Reads one DROPSHADOWFILTER value from the stream - * - * @return DROPSHADOWFILTER value - * @throws IOException - */ - public DROPSHADOWFILTER readDROPSHADOWFILTER() throws IOException { - DROPSHADOWFILTER ret = new DROPSHADOWFILTER(); - ret.dropShadowColor = readRGBA(); - ret.blurX = readFIXED(); - ret.blurY = readFIXED(); - ret.angle = readFIXED(); - ret.distance = readFIXED(); - ret.strength = readFIXED8(); - ret.innerShadow = readUB(1) == 1; - ret.knockout = readUB(1) == 1; - ret.compositeSource = readUB(1) == 1; - ret.passes = (int) readUB(5); - return ret; - } - - /** - * Reads one GLOWFILTER value from the stream - * - * @return GLOWFILTER value - * @throws IOException - */ - public GLOWFILTER readGLOWFILTER() throws IOException { - GLOWFILTER ret = new GLOWFILTER(); - ret.glowColor = readRGBA(); - ret.blurX = readFIXED(); - ret.blurY = readFIXED(); - ret.strength = readFIXED8(); - ret.innerGlow = readUB(1) == 1; - ret.knockout = readUB(1) == 1; - ret.compositeSource = readUB(1) == 1; - ret.passes = (int) readUB(5); - return ret; - } - - /** - * Reads one BEVELFILTER value from the stream - * - * @return BEVELFILTER value - * @throws IOException - */ - public BEVELFILTER readBEVELFILTER() throws IOException { - BEVELFILTER ret = new BEVELFILTER(); - ret.highlightColor = readRGBA(); //Highlight color first. It it opposite of the documentation - ret.shadowColor = readRGBA(); - ret.blurX = readFIXED(); - ret.blurY = readFIXED(); - ret.angle = readFIXED(); - ret.distance = readFIXED(); - ret.strength = readFIXED8(); - ret.innerShadow = readUB(1) == 1; - ret.knockout = readUB(1) == 1; - ret.compositeSource = readUB(1) == 1; - ret.onTop = readUB(1) == 1; - ret.passes = (int) readUB(4); - return ret; - } - - /** - * Reads one GRADIENTGLOWFILTER value from the stream - * - * @return GRADIENTGLOWFILTER value - * @throws IOException - */ - public GRADIENTGLOWFILTER readGRADIENTGLOWFILTER() throws IOException { - GRADIENTGLOWFILTER ret = new GRADIENTGLOWFILTER(); - int numColors = readUI8(); - ret.gradientColors = new RGBA[numColors]; - ret.gradientRatio = new int[numColors]; - for (int i = 0; i < numColors; i++) { - ret.gradientColors[i] = readRGBA(); - } - for (int i = 0; i < numColors; i++) { - ret.gradientRatio[i] = readUI8(); - } - ret.blurX = readFIXED(); - ret.blurY = readFIXED(); - ret.angle = readFIXED(); - ret.distance = readFIXED(); - ret.strength = readFIXED8(); - ret.innerShadow = readUB(1) == 1; - ret.knockout = readUB(1) == 1; - ret.compositeSource = readUB(1) == 1; - ret.onTop = readUB(1) == 1; - ret.passes = (int) readUB(4); - return ret; - } - - /** - * Reads one GRADIENTBEVELFILTER value from the stream - * - * @return GRADIENTBEVELFILTER value - * @throws IOException - */ - public GRADIENTBEVELFILTER readGRADIENTBEVELFILTER() throws IOException { - GRADIENTBEVELFILTER ret = new GRADIENTBEVELFILTER(); - int numColors = readUI8(); - ret.gradientColors = new RGBA[numColors]; - ret.gradientRatio = new int[numColors]; - for (int i = 0; i < numColors; i++) { - ret.gradientColors[i] = readRGBA(); - } - for (int i = 0; i < numColors; i++) { - ret.gradientRatio[i] = readUI8(); - } - ret.blurX = readFIXED(); - ret.blurY = readFIXED(); - ret.angle = readFIXED(); - ret.distance = readFIXED(); - ret.strength = readFIXED8(); - ret.innerShadow = readUB(1) == 1; - ret.knockout = readUB(1) == 1; - ret.compositeSource = readUB(1) == 1; - ret.onTop = readUB(1) == 1; - ret.passes = (int) readUB(4); - return ret; - } - - /** - * Reads list of FILTER values from the stream - * - * @return List of FILTER values - * @throws IOException - */ - public List readFILTERLIST() throws IOException { - List ret = new ArrayList<>(); - int numberOfFilters = readUI8(); - for (int i = 0; i < numberOfFilters; i++) { - ret.add(readFILTER()); - } - return ret; - } - - /** - * Reads one FILTER value from the stream - * - * @return FILTER value - * @throws IOException - */ - public FILTER readFILTER() throws IOException { - int filterId = readUI8(); - switch (filterId) { - case 0: - return readDROPSHADOWFILTER(); - case 1: - return readBLURFILTER(); - case 2: - return readGLOWFILTER(); - case 3: - return readBEVELFILTER(); - case 4: - return readGRADIENTGLOWFILTER(); - case 5: - return readCONVOLUTIONFILTER(); - case 6: - return readCOLORMATRIXFILTER(); - case 7: - return readGRADIENTBEVELFILTER(); - default: - return null; - } - } - - /** - * Reads list of BUTTONRECORD values from the stream - * - * @param inDefineButton2 Whether read from inside of DefineButton2Tag or - * not - * @return List of BUTTONRECORD values - * @throws IOException - */ - public List readBUTTONRECORDList(boolean inDefineButton2) throws IOException { - List ret = new ArrayList<>(); - BUTTONRECORD br; - while ((br = readBUTTONRECORD(inDefineButton2)) != null) { - ret.add(br); - } - return ret; - } - - /** - * Reads one BUTTONRECORD value from the stream - * - * @param inDefineButton2 True when in DefineButton2 - * @return BUTTONRECORD value - * @throws IOException - */ - public BUTTONRECORD readBUTTONRECORD(boolean inDefineButton2) throws IOException { - BUTTONRECORD ret = new BUTTONRECORD(); - ret.reserved = (int) readUB(2); - ret.buttonHasBlendMode = readUB(1) == 1; - ret.buttonHasFilterList = readUB(1) == 1; - ret.buttonStateHitTest = readUB(1) == 1; - ret.buttonStateDown = readUB(1) == 1; - ret.buttonStateOver = readUB(1) == 1; - ret.buttonStateUp = readUB(1) == 1; - - if (!ret.buttonHasBlendMode && !ret.buttonHasFilterList - && !ret.buttonStateHitTest && !ret.buttonStateDown - && !ret.buttonStateOver && !ret.buttonStateUp && ret.reserved == 0) { - return null; - } - - ret.characterId = readUI16(); - ret.placeDepth = readUI16(); - ret.placeMatrix = readMatrix(); - if (inDefineButton2) { - ret.colorTransform = readCXFORMWITHALPHA(); - if (ret.buttonHasFilterList) { - ret.filterList = readFILTERLIST(); - } - if (ret.buttonHasBlendMode) { - ret.blendMode = readUI8(); - } - } - return ret; - } - - /** - * Reads list of BUTTONCONDACTION values from the stream - * - * @param swf - * @param tag - * @return List of BUTTONCONDACTION values - * @throws IOException - */ - public List readBUTTONCONDACTIONList(SWF swf, Tag tag) throws IOException { - List ret = new ArrayList<>(); - BUTTONCONDACTION bc; - while (!(bc = readBUTTONCONDACTION(swf, tag)).isLast) { - ret.add(bc); - } - ret.add(bc); - return ret; - } - - /** - * Reads one BUTTONCONDACTION value from the stream - * - * @param swf - * @param tag - * @return BUTTONCONDACTION value - * @throws IOException - */ - public BUTTONCONDACTION readBUTTONCONDACTION(SWF swf, Tag tag) throws IOException { - BUTTONCONDACTION ret = new BUTTONCONDACTION(swf, this, getPos(), tag); - //ret.actions = readActionList(); - return ret; - } - - /** - * Reads one GRADRECORD value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return GRADRECORD value - * @throws IOException - */ - public GRADRECORD readGRADRECORD(int shapeNum) throws IOException { - GRADRECORD ret = new GRADRECORD(); - ret.ratio = readUI8(); - if (shapeNum >= 3) { - ret.color = readRGBA(); - } else { - ret.color = readRGB(); - } - return ret; - } - - /** - * Reads one GRADIENT value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return GRADIENT value - * @throws IOException - */ - public GRADIENT readGRADIENT(int shapeNum) throws IOException { - GRADIENT ret = new GRADIENT(); - ret.spreadMode = (int) readUB(2); - ret.interpolationMode = (int) readUB(2); - int numGradients = (int) readUB(4); - ret.gradientRecords = new GRADRECORD[numGradients]; - for (int i = 0; i < numGradients; i++) { - ret.gradientRecords[i] = readGRADRECORD(shapeNum); - - } - return ret; - } - - /** - * Reads one FOCALGRADIENT value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return FOCALGRADIENT value - * @throws IOException - */ - public FOCALGRADIENT readFOCALGRADIENT(int shapeNum) throws IOException { - FOCALGRADIENT ret = new FOCALGRADIENT(); - ret.spreadMode = (int) readUB(2); - ret.interpolationMode = (int) readUB(2); - int numGradients = (int) readUB(4); - ret.gradientRecords = new GRADRECORD[numGradients]; - for (int i = 0; i < numGradients; i++) { - ret.gradientRecords[i] = readGRADRECORD(shapeNum); - } - ret.focalPoint = readFIXED8(); - return ret; - } - - /** - * Reads one FILLSTYLE value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return FILLSTYLE value - * @throws IOException - */ - public FILLSTYLE readFILLSTYLE(int shapeNum) throws IOException { - FILLSTYLE ret = new FILLSTYLE(); - ret.fillStyleType = readUI8(); - if (ret.fillStyleType == FILLSTYLE.SOLID) { - if (shapeNum >= 3) { - ret.color = readRGBA(); - } else { - ret.color = readRGB(); - } - } - if ((ret.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) - || (ret.fillStyleType == FILLSTYLE.RADIAL_GRADIENT) - || (ret.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT)) { - ret.gradientMatrix = readMatrix(); - } - if ((ret.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) - || (ret.fillStyleType == FILLSTYLE.RADIAL_GRADIENT)) { - ret.gradient = readGRADIENT(shapeNum); - } - if (ret.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT) { - ret.gradient = readFOCALGRADIENT(shapeNum); - } - - if ((ret.fillStyleType == FILLSTYLE.REPEATING_BITMAP) - || (ret.fillStyleType == FILLSTYLE.CLIPPED_BITMAP) - || (ret.fillStyleType == FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) - || (ret.fillStyleType == FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { - ret.bitmapId = readUI16(); - ret.bitmapMatrix = readMatrix(); - } - return ret; - } - - /** - * Reads one FILLSTYLEARRAY value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return FILLSTYLEARRAY value - * @throws IOException - */ - public FILLSTYLEARRAY readFILLSTYLEARRAY(int shapeNum) throws IOException { - - FILLSTYLEARRAY ret = new FILLSTYLEARRAY(); - int fillStyleCount = readUI8(); - if (((shapeNum == 2) || (shapeNum == 3) || (shapeNum == 4/*?*/)) && (fillStyleCount == 0xff)) { - fillStyleCount = readUI16(); - } - ret.fillStyles = new FILLSTYLE[fillStyleCount]; - for (int i = 0; i < fillStyleCount; i++) { - ret.fillStyles[i] = readFILLSTYLE(shapeNum); - } - return ret; - } - - /** - * Reads one LINESTYLE value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return LINESTYLE value - * @throws IOException - */ - public LINESTYLE readLINESTYLE(int shapeNum) throws IOException { - LINESTYLE ret = new LINESTYLE(); - ret.width = readUI16(); - if ((shapeNum == 1) || (shapeNum == 2)) { - ret.color = readRGB(); - } - if (shapeNum == 3) { - ret.color = readRGBA(); - } - return ret; - } - - /** - * Reads one LINESTYLE2 value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return LINESTYLE2 value - * @throws IOException - */ - public LINESTYLE2 readLINESTYLE2(int shapeNum) throws IOException { - LINESTYLE2 ret = new LINESTYLE2(); - ret.width = readUI16(); - ret.startCapStyle = (int) readUB(2); - ret.joinStyle = (int) readUB(2); - ret.hasFillFlag = (int) readUB(1) == 1; - ret.noHScaleFlag = (int) readUB(1) == 1; - ret.noVScaleFlag = (int) readUB(1) == 1; - ret.pixelHintingFlag = (int) readUB(1) == 1; - ret.reserved = (int) readUB(5); - ret.noClose = (int) readUB(1) == 1; - ret.endCapStyle = (int) readUB(2); - if (ret.joinStyle == LINESTYLE2.MITER_JOIN) { - ret.miterLimitFactor = readUI16(); - } - if (!ret.hasFillFlag) { - ret.color = readRGBA(); - } else { - ret.fillType = readFILLSTYLE(shapeNum); - } - return ret; - } - - /** - * Reads one LINESTYLEARRAY value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return LINESTYLEARRAY value - * @throws IOException - */ - public LINESTYLEARRAY readLINESTYLEARRAY(int shapeNum) throws IOException { - LINESTYLEARRAY ret = new LINESTYLEARRAY(); - int lineStyleCount = readUI8(); - if (lineStyleCount == 0xff) { - lineStyleCount = readUI16(); - } - if ((shapeNum == 1 || shapeNum == 2 || shapeNum == 3)) { - ret.lineStyles = new LINESTYLE[lineStyleCount]; - for (int i = 0; i < lineStyleCount; i++) { - ret.lineStyles[i] = readLINESTYLE(shapeNum); - } - } else if (shapeNum == 4) { - ret.lineStyles = new LINESTYLE2[lineStyleCount]; - for (int i = 0; i < lineStyleCount; i++) { - ret.lineStyles[i] = readLINESTYLE2(shapeNum); - } - } - return ret; - } - - /** - * Reads one SHAPERECORD value from the stream - * - * @param fillBits - * @param lineBits - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @return SHAPERECORD value - * @throws IOException - */ - private SHAPERECORD readSHAPERECORD(int fillBits, int lineBits, int shapeNum, boolean morphShape) throws IOException { - SHAPERECORD ret; - int typeFlag = (int) readUB(1); - if (typeFlag == 0) { - boolean stateNewStyles = readUB(1) == 1; - boolean stateLineStyle = readUB(1) == 1; - boolean stateFillStyle1 = readUB(1) == 1; - boolean stateFillStyle0 = readUB(1) == 1; - boolean stateMoveTo = readUB(1) == 1; - if ((!stateNewStyles) && (!stateLineStyle) && (!stateFillStyle1) && (!stateFillStyle0) && (!stateMoveTo)) { - ret = new EndShapeRecord(); - } else { - StyleChangeRecord scr = new StyleChangeRecord(); - scr.stateNewStyles = stateNewStyles; - scr.stateLineStyle = stateLineStyle; - scr.stateFillStyle0 = stateFillStyle0; - scr.stateFillStyle1 = stateFillStyle1; - scr.stateMoveTo = stateMoveTo; - if (stateMoveTo) { - scr.moveBits = (int) readUB(5); - scr.moveDeltaX = (int) readSB(scr.moveBits); - scr.moveDeltaY = (int) readSB(scr.moveBits); - } - if (stateFillStyle0) { - scr.fillStyle0 = (int) readUB(fillBits); - } - if (stateFillStyle1) { - scr.fillStyle1 = (int) readUB(fillBits); - } - if (stateLineStyle) { - scr.lineStyle = (int) readUB(lineBits); - } - if (stateNewStyles) { - if (morphShape) { - //This should never happen - } else { - scr.fillStyles = readFILLSTYLEARRAY(shapeNum); - scr.lineStyles = readLINESTYLEARRAY(shapeNum); - } - scr.numFillBits = (int) readUB(4); - scr.numLineBits = (int) readUB(4); - } - ret = scr; - } - } else {//typeFlag==1 - int straightFlag = (int) readUB(1); - if (straightFlag == 1) { - StraightEdgeRecord ser = new StraightEdgeRecord(); - ser.numBits = (int) readUB(4); - ser.generalLineFlag = readUB(1) == 1; - if (!ser.generalLineFlag) { - ser.vertLineFlag = readUB(1) == 1; - } - if (ser.generalLineFlag || (!ser.vertLineFlag)) { - ser.deltaX = (int) readSB(ser.numBits + 2); - } - if (ser.generalLineFlag || (ser.vertLineFlag)) { - ser.deltaY = (int) readSB(ser.numBits + 2); - } - ret = ser; - } else { - CurvedEdgeRecord cer = new CurvedEdgeRecord(); - cer.numBits = (int) readUB(4); - cer.controlDeltaX = (int) readSB(cer.numBits + 2); - cer.controlDeltaY = (int) readSB(cer.numBits + 2); - cer.anchorDeltaX = (int) readSB(cer.numBits + 2); - cer.anchorDeltaY = (int) readSB(cer.numBits + 2); - ret = cer; - } - } - return ret; - } - - /** - * Reads one SHAPE value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param morphShape - * @return SHAPE value - * @throws IOException - */ - public SHAPE readSHAPE(int shapeNum, boolean morphShape) throws IOException { - SHAPE ret = new SHAPE(); - ret.numFillBits = (int) readUB(4); - ret.numLineBits = (int) readUB(4); - ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits, morphShape); - return ret; - } - - /** - * Reads one SHAPEWITHSTYLE value from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param morphShape - * @return SHAPEWITHSTYLE value - * @throws IOException - */ - public SHAPEWITHSTYLE readSHAPEWITHSTYLE(int shapeNum, boolean morphShape) throws IOException { - SHAPEWITHSTYLE ret = new SHAPEWITHSTYLE(); - ret.fillStyles = readFILLSTYLEARRAY(shapeNum); - ret.lineStyles = readLINESTYLEARRAY(shapeNum); - ret.numFillBits = (int) readUB(4); - ret.numLineBits = (int) readUB(4); - ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits, morphShape); - return ret; - } - - /** - * Reads list of SHAPERECORDs from the stream - * - * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param fillBits - * @param lineBits - * @return SHAPERECORDs array - * @throws IOException - */ - private List readSHAPERECORDS(int shapeNum, int fillBits, int lineBits, boolean morphShape) throws IOException { - List ret = new ArrayList<>(); - SHAPERECORD rec; - do { - rec = readSHAPERECORD(fillBits, lineBits, shapeNum, morphShape); - if (rec instanceof StyleChangeRecord) { - StyleChangeRecord scRec = (StyleChangeRecord) rec; - if (scRec.stateNewStyles) { - fillBits = scRec.numFillBits; - lineBits = scRec.numLineBits; - } - } - ret.add(rec); - } while (!(rec instanceof EndShapeRecord)); - alignByte(); - return ret; - } - - /** - * Reads one SOUNDINFO value from the stream - * - * @return SOUNDINFO value - * @throws IOException - */ - public SOUNDINFO readSOUNDINFO() throws IOException { - SOUNDINFO ret = new SOUNDINFO(); - ret.reserved = (int) readUB(2); - ret.syncStop = readUB(1) == 1; - ret.syncNoMultiple = readUB(1) == 1; - ret.hasEnvelope = readUB(1) == 1; - ret.hasLoops = readUB(1) == 1; - ret.hasOutPoint = readUB(1) == 1; - ret.hasInPoint = readUB(1) == 1; - if (ret.hasInPoint) { - ret.inPoint = readUI32(); - } - if (ret.hasOutPoint) { - ret.outPoint = readUI32(); - } - if (ret.hasLoops) { - ret.loopCount = readUI16(); - } - if (ret.hasEnvelope) { - int envPoints = readUI8(); - ret.envelopeRecords = new SOUNDENVELOPE[envPoints]; - for (int i = 0; i < envPoints; i++) { - ret.envelopeRecords[i] = readSOUNDENVELOPE(); - } - } - return ret; - } - - /** - * Reads one SOUNDENVELOPE value from the stream - * - * @return SOUNDENVELOPE value - * @throws IOException - */ - public SOUNDENVELOPE readSOUNDENVELOPE() throws IOException { - SOUNDENVELOPE ret = new SOUNDENVELOPE(); - ret.pos44 = readUI32(); - ret.leftLevel = readUI16(); - ret.rightLevel = readUI16(); - return ret; - } - - /** - * Reads one GLYPHENTRY value from the stream - * - * @param glyphBits - * @param advanceBits - * @return GLYPHENTRY value - * @throws IOException - */ - public GLYPHENTRY readGLYPHENTRY(int glyphBits, int advanceBits) throws IOException { - GLYPHENTRY ret = new GLYPHENTRY(); - ret.glyphIndex = (int) readUB(glyphBits); - ret.glyphAdvance = (int) readUB(advanceBits); - return ret; - } - - /** - * Reads one TEXTRECORD value from the stream - * - * @param inDefineText2 - * @param glyphBits - * @param advanceBits - * @return TEXTRECORD value - * @throws IOException - */ - public TEXTRECORD readTEXTRECORD(boolean inDefineText2, int glyphBits, int advanceBits) throws IOException { - TEXTRECORD ret = new TEXTRECORD(); - int first = (int) readUB(1); //always 1 - readUB(3); //always 0 - ret.styleFlagsHasFont = readUB(1) == 1; - ret.styleFlagsHasColor = readUB(1) == 1; - ret.styleFlagsHasYOffset = readUB(1) == 1; - ret.styleFlagsHasXOffset = readUB(1) == 1; - if ((!ret.styleFlagsHasFont) && (!ret.styleFlagsHasColor) && (!ret.styleFlagsHasYOffset) && (!ret.styleFlagsHasXOffset) && (first == 0)) { //final text record - return null; - } - if (ret.styleFlagsHasFont) { - ret.fontId = readUI16(); - } - if (ret.styleFlagsHasColor) { - if (inDefineText2) { - ret.textColorA = readRGBA(); - } else { - ret.textColor = readRGB(); - } - } - if (ret.styleFlagsHasXOffset) { - ret.xOffset = readSI16(); - } - if (ret.styleFlagsHasYOffset) { - ret.yOffset = readSI16(); - } - if (ret.styleFlagsHasFont) { - ret.textHeight = readUI16(); - } - int glyphCount = readUI8(); - ret.glyphEntries = new GLYPHENTRY[glyphCount]; - for (int i = 0; i < glyphCount; i++) { - ret.glyphEntries[i] = readGLYPHENTRY(glyphBits, advanceBits); - } - alignByte(); - return ret; - } - - /** - * Reads one MORPHGRADRECORD value from the stream - * - * @return MORPHGRADRECORD value - * @throws IOException - */ - public MORPHGRADRECORD readMORPHGRADRECORD() throws IOException { - MORPHGRADRECORD ret = new MORPHGRADRECORD(); - ret.startRatio = readUI8(); - ret.startColor = readRGBA(); - ret.endRatio = readUI8(); - ret.endColor = readRGBA(); - return ret; - } - - /** - * Reads one MORPHGRADIENT value from the stream - * - * @return MORPHGRADIENT value - * @throws IOException - */ - public MORPHGRADIENT readMORPHGRADIENT() throws IOException { - MORPHGRADIENT ret = new MORPHGRADIENT(); - //Despite of documentation (UI8 1-8), there are two fields - // spreadMode and interPolationMode which are same as in GRADIENT - ret.spreadMode = (int) readUB(2); - ret.interPolationMode = (int) readUB(2); - int numGradients = (int) readUB(4); - ret.gradientRecords = new MORPHGRADRECORD[numGradients]; - for (int i = 0; i < numGradients; i++) { - ret.gradientRecords[i] = readMORPHGRADRECORD(); - } - return ret; - } - - /** - * Reads one MORPHFOCALGRADIENT value from the stream - * - * This is undocumented feature - * - * @return MORPHGRADIENT value - * @throws IOException - */ - public MORPHFOCALGRADIENT readMORPHFOCALGRADIENT() throws IOException { - MORPHFOCALGRADIENT ret = new MORPHFOCALGRADIENT(); - ret.spreadMode = (int) readUB(2); - ret.interPolationMode = (int) readUB(2); - int numGradients = (int) readUB(4); - ret.gradientRecords = new MORPHGRADRECORD[numGradients]; - for (int i = 0; i < numGradients; i++) { - ret.gradientRecords[i] = readMORPHGRADRECORD(); - } - ret.startFocalPoint = readFIXED8(); - ret.endFocalPoint = readFIXED8(); - return ret; - } - - /** - * Reads one MORPHFILLSTYLE value from the stream - * - * @return MORPHFILLSTYLE value - * @throws IOException - */ - public MORPHFILLSTYLE readMORPHFILLSTYLE() throws IOException { - MORPHFILLSTYLE ret = new MORPHFILLSTYLE(); - ret.fillStyleType = readUI8(); - if (ret.fillStyleType == MORPHFILLSTYLE.SOLID) { - ret.startColor = readRGBA(); - ret.endColor = readRGBA(); - } - if ((ret.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) - || (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT) - || (ret.fillStyleType == MORPHFILLSTYLE.FOCAL_RADIAL_GRADIENT)) { - ret.startGradientMatrix = readMatrix(); - ret.endGradientMatrix = readMatrix(); - } - if ((ret.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) - || (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) { - ret.gradient = readMORPHGRADIENT(); - } - if (ret.fillStyleType == MORPHFILLSTYLE.FOCAL_RADIAL_GRADIENT) { - ret.gradient = readMORPHFOCALGRADIENT(); - } - - if ((ret.fillStyleType == MORPHFILLSTYLE.REPEATING_BITMAP) - || (ret.fillStyleType == MORPHFILLSTYLE.CLIPPED_BITMAP) - || (ret.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) - || (ret.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { - ret.bitmapId = readUI16(); - ret.startBitmapMatrix = readMatrix(); - ret.endBitmapMatrix = readMatrix(); - } - return ret; - } - - /** - * Reads one MORPHFILLSTYLEARRAY value from the stream - * - * @return MORPHFILLSTYLEARRAY value - * @throws IOException - */ - public MORPHFILLSTYLEARRAY readMORPHFILLSTYLEARRAY() throws IOException { - - MORPHFILLSTYLEARRAY ret = new MORPHFILLSTYLEARRAY(); - int fillStyleCount = readUI8(); - if (fillStyleCount == 0xff) { - fillStyleCount = readUI16(); - } - ret.fillStyles = new MORPHFILLSTYLE[fillStyleCount]; - for (int i = 0; i < fillStyleCount; i++) { - ret.fillStyles[i] = readMORPHFILLSTYLE(); - } - return ret; - } - - /** - * Reads one MORPHLINESTYLE value from the stream - * - * @return MORPHLINESTYLE value - * @throws IOException - */ - public MORPHLINESTYLE readMORPHLINESTYLE() throws IOException { - MORPHLINESTYLE ret = new MORPHLINESTYLE(); - ret.startWidth = readUI16(); - ret.endWidth = readUI16(); - ret.startColor = readRGBA(); - ret.endColor = readRGBA(); - return ret; - } - - /** - * Reads one MORPHLINESTYLE2 value from the stream - * - * @return MORPHLINESTYLE2 value - * @throws IOException - */ - public MORPHLINESTYLE2 readMORPHLINESTYLE2() throws IOException { - MORPHLINESTYLE2 ret = new MORPHLINESTYLE2(); - ret.startWidth = readUI16(); - ret.endWidth = readUI16(); - ret.startCapStyle = (int) readUB(2); - ret.joinStyle = (int) readUB(2); - ret.hasFillFlag = (int) readUB(1) == 1; - ret.noHScaleFlag = (int) readUB(1) == 1; - ret.noVScaleFlag = (int) readUB(1) == 1; - ret.pixelHintingFlag = (int) readUB(1) == 1; - ret.reserved = (int) readUB(5); - ret.noClose = (int) readUB(1) == 1; - ret.endCapStyle = (int) readUB(2); - if (ret.joinStyle == LINESTYLE2.MITER_JOIN) { - ret.miterLimitFactor = readUI16(); - } - if (!ret.hasFillFlag) { - ret.startColor = readRGBA(); - ret.endColor = readRGBA(); - } else { - ret.fillType = readMORPHFILLSTYLE(); - } - return ret; - } - - /** - * Reads one MORPHLINESTYLEARRAY value from the stream - * - * @param morphShapeNum 1 on DefineMorphShape, 2 on DefineMorphShape2 - * @return MORPHLINESTYLEARRAY value - * @throws IOException - */ - public MORPHLINESTYLEARRAY readMORPHLINESTYLEARRAY(int morphShapeNum) throws IOException { - MORPHLINESTYLEARRAY ret = new MORPHLINESTYLEARRAY(); - int lineStyleCount = readUI8(); - if (lineStyleCount == 0xff) { - lineStyleCount = readUI16(); - } - if (morphShapeNum == 1) { - ret.lineStyles = new MORPHLINESTYLE[lineStyleCount]; - for (int i = 0; i < lineStyleCount; i++) { - ret.lineStyles[i] = readMORPHLINESTYLE(); - } - } else if (morphShapeNum == 2) { - ret.lineStyles2 = new MORPHLINESTYLE2[lineStyleCount]; - for (int i = 0; i < lineStyleCount; i++) { - ret.lineStyles2[i] = readMORPHLINESTYLE2(); - } - } - return ret; - } - - /** - * Reads one KERNINGRECORD value from the stream - * - * @param fontFlagsWideCodes - * @return KERNINGRECORD value - * @throws IOException - */ - public KERNINGRECORD readKERNINGRECORD(boolean fontFlagsWideCodes) throws IOException { - KERNINGRECORD ret = new KERNINGRECORD(); - if (fontFlagsWideCodes) { - ret.fontKerningCode1 = readUI16(); - ret.fontKerningCode2 = readUI16(); - } else { - ret.fontKerningCode1 = readUI8(); - ret.fontKerningCode2 = readUI8(); - } - ret.fontKerningAdjustment = readSI16(); - return ret; - } - - /** - * Reads one LANGCODE value from the stream - * - * @return LANGCODE value - * @throws IOException - */ - public LANGCODE readLANGCODE() throws IOException { - LANGCODE ret = new LANGCODE(); - ret.languageCode = readUI8(); - return ret; - } - - /** - * Reads one ZONERECORD value from the stream - * - * @return ZONERECORD value - * @throws IOException - */ - public ZONERECORD readZONERECORD() throws IOException { - ZONERECORD ret = new ZONERECORD(); - int numZoneData = readUI8(); - ret.zonedata = new ZONEDATA[numZoneData]; - for (int i = 0; i < numZoneData; i++) { - ret.zonedata[i] = readZONEDATA(); - } - readUB(6); - ret.zoneMaskY = readUB(1) == 1; - ret.zoneMaskX = readUB(1) == 1; - return ret; - } - - /** - * Reads one ZONEDATA value from the stream - * - * @return ZONEDATA value - * @throws IOException - */ - public ZONEDATA readZONEDATA() throws IOException { - ZONEDATA ret = new ZONEDATA(); - ret.alignmentCoordinate = readUI16(); - ret.range = readUI16(); - return ret; - } - - /** - * Reads one PIX15 value from the stream - * - * @return PIX15 value - * @throws IOException - */ - public PIX15 readPIX15() throws IOException { - PIX15 ret = new PIX15(); - readUB(1); - ret.red = (int) readUB(5); - ret.green = (int) readUB(5); - ret.blue = (int) readUB(5); - return ret; - } - - /** - * Reads one PIX24 value from the stream - * - * @return PIX24 value - * @throws IOException - */ - public PIX24 readPIX24() throws IOException { - PIX24 ret = new PIX24(); - ret.reserved = readUI8(); - ret.red = readUI8(); - ret.green = readUI8(); - ret.blue = readUI8(); - return ret; - } - - /** - * Reads one COLORMAPDATA value from the stream - * - * @param colorTableSize - * @param bitmapWidth - * @param bitmapHeight - * @return COLORMAPDATA value - * @throws IOException - */ - public COLORMAPDATA readCOLORMAPDATA(int colorTableSize, int bitmapWidth, int bitmapHeight) throws IOException { - COLORMAPDATA ret = new COLORMAPDATA(); - ret.colorTableRGB = new RGB[colorTableSize + 1]; - for (int i = 0; i < colorTableSize + 1; i++) { - ret.colorTableRGB[i] = readRGB(); - } - int dataLen = 0; - for (int y = 0; y < bitmapHeight; y++) { - int x = 0; - for (; x < bitmapWidth; x++) { - dataLen++; - } - while ((x % 4) != 0) { - dataLen++; - x++; - } - } - ret.colorMapPixelData = readBytesEx(dataLen); - return ret; - } - - /** - * Reads one BITMAPDATA value from the stream - * - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight - * @return COLORMAPDATA value - * @throws IOException - */ - public BITMAPDATA readBITMAPDATA(int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { - BITMAPDATA ret = new BITMAPDATA(); - List pix15 = new ArrayList<>(); - List pix24 = new ArrayList<>(); - int dataLen = 0; - for (int y = 0; y < bitmapHeight; y++) { - int x = 0; - for (; x < bitmapWidth; x++) { - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { - dataLen += 2; - pix15.add(readPIX15()); - } - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { - dataLen += 4; - pix24.add(readPIX24()); - } - } - while ((dataLen % 4) != 0) { - dataLen++; - readUI8(); - } - } - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { - ret.bitmapPixelDataPix15 = pix15.toArray(new PIX15[pix15.size()]); - } else if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { - ret.bitmapPixelDataPix24 = pix24.toArray(new PIX24[pix24.size()]); - } - return ret; - } - - /** - * Reads one BITMAPDATA value from the stream - * - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight - * @return COLORMAPDATA value - * @throws IOException - */ - public ALPHABITMAPDATA readALPHABITMAPDATA(int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { - ALPHABITMAPDATA ret = new ALPHABITMAPDATA(); - ret.bitmapPixelData = new ARGB[bitmapWidth * bitmapHeight]; - for (int y = 0; y < bitmapHeight; y++) { - for (int x = 0; x < bitmapWidth; x++) { - ret.bitmapPixelData[y * bitmapWidth + x] = readARGB(); - } - } - return ret; - } - - /** - * Reads one ALPHACOLORMAPDATA value from the stream - * - * @param colorTableSize - * @param bitmapWidth - * @param bitmapHeight - * @return ALPHACOLORMAPDATA value - * @throws IOException - */ - public ALPHACOLORMAPDATA readALPHACOLORMAPDATA(int colorTableSize, int bitmapWidth, int bitmapHeight) throws IOException { - ALPHACOLORMAPDATA ret = new ALPHACOLORMAPDATA(); - ret.colorTableRGB = new RGBA[colorTableSize + 1]; - for (int i = 0; i < colorTableSize + 1; i++) { - ret.colorTableRGB[i] = readRGBA(); - } - int dataLen = 0; - for (int y = 0; y < bitmapHeight; y++) { - int x = 0; - for (; x < bitmapWidth; x++) { - dataLen++; - } - while ((x % 4) != 0) { - dataLen++; - x++; - } - } - ret.colorMapPixelData = readBytesEx(dataLen); - return ret; - } - - @Override - public int available() throws IOException { - return is.available(); - } - - public long availableBits() throws IOException { - if (bitPos > 0) { - return available() * 8 + (8 - bitPos); - } - return available() * 8; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionNop; +import com.jpexs.decompiler.flash.action.swf3.ActionGetURL; +import com.jpexs.decompiler.flash.action.swf3.ActionGoToLabel; +import com.jpexs.decompiler.flash.action.swf3.ActionGotoFrame; +import com.jpexs.decompiler.flash.action.swf3.ActionNextFrame; +import com.jpexs.decompiler.flash.action.swf3.ActionPlay; +import com.jpexs.decompiler.flash.action.swf3.ActionPrevFrame; +import com.jpexs.decompiler.flash.action.swf3.ActionSetTarget; +import com.jpexs.decompiler.flash.action.swf3.ActionStop; +import com.jpexs.decompiler.flash.action.swf3.ActionStopSounds; +import com.jpexs.decompiler.flash.action.swf3.ActionToggleQuality; +import com.jpexs.decompiler.flash.action.swf3.ActionWaitForFrame; +import com.jpexs.decompiler.flash.action.swf4.ActionAdd; +import com.jpexs.decompiler.flash.action.swf4.ActionAnd; +import com.jpexs.decompiler.flash.action.swf4.ActionAsciiToChar; +import com.jpexs.decompiler.flash.action.swf4.ActionCall; +import com.jpexs.decompiler.flash.action.swf4.ActionCharToAscii; +import com.jpexs.decompiler.flash.action.swf4.ActionCloneSprite; +import com.jpexs.decompiler.flash.action.swf4.ActionDivide; +import com.jpexs.decompiler.flash.action.swf4.ActionEndDrag; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionGetProperty; +import com.jpexs.decompiler.flash.action.swf4.ActionGetTime; +import com.jpexs.decompiler.flash.action.swf4.ActionGetURL2; +import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionGotoFrame2; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionLess; +import com.jpexs.decompiler.flash.action.swf4.ActionMBAsciiToChar; +import com.jpexs.decompiler.flash.action.swf4.ActionMBCharToAscii; +import com.jpexs.decompiler.flash.action.swf4.ActionMBStringExtract; +import com.jpexs.decompiler.flash.action.swf4.ActionMBStringLength; +import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionOr; +import com.jpexs.decompiler.flash.action.swf4.ActionPop; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionRandomNumber; +import com.jpexs.decompiler.flash.action.swf4.ActionRemoveSprite; +import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; +import com.jpexs.decompiler.flash.action.swf4.ActionSetTarget2; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.ActionStartDrag; +import com.jpexs.decompiler.flash.action.swf4.ActionStringAdd; +import com.jpexs.decompiler.flash.action.swf4.ActionStringEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionStringExtract; +import com.jpexs.decompiler.flash.action.swf4.ActionStringLength; +import com.jpexs.decompiler.flash.action.swf4.ActionStringLess; +import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; +import com.jpexs.decompiler.flash.action.swf4.ActionToInteger; +import com.jpexs.decompiler.flash.action.swf4.ActionTrace; +import com.jpexs.decompiler.flash.action.swf4.ActionWaitForFrame2; +import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; +import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; +import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; +import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitURShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; +import com.jpexs.decompiler.flash.action.swf5.ActionDelete; +import com.jpexs.decompiler.flash.action.swf5.ActionDelete2; +import com.jpexs.decompiler.flash.action.swf5.ActionEnumerate; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; +import com.jpexs.decompiler.flash.action.swf5.ActionInitArray; +import com.jpexs.decompiler.flash.action.swf5.ActionInitObject; +import com.jpexs.decompiler.flash.action.swf5.ActionLess2; +import com.jpexs.decompiler.flash.action.swf5.ActionModulo; +import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; +import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; +import com.jpexs.decompiler.flash.action.swf5.ActionReturn; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf5.ActionTargetPath; +import com.jpexs.decompiler.flash.action.swf5.ActionToNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionToString; +import com.jpexs.decompiler.flash.action.swf5.ActionTypeOf; +import com.jpexs.decompiler.flash.action.swf5.ActionWith; +import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; +import com.jpexs.decompiler.flash.action.swf6.ActionGreater; +import com.jpexs.decompiler.flash.action.swf6.ActionInstanceOf; +import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater; +import com.jpexs.decompiler.flash.action.swf7.ActionCastOp; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.action.swf7.ActionExtends; +import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; +import com.jpexs.decompiler.flash.action.swf7.ActionThrow; +import com.jpexs.decompiler.flash.action.swf7.ActionTry; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.tags.CSMTextSettingsTag; +import com.jpexs.decompiler.flash.tags.DebugIDTag; +import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; +import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag; +import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; +import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; +import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag; +import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag; +import com.jpexs.decompiler.flash.tags.DefineBitsTag; +import com.jpexs.decompiler.flash.tags.DefineButton2Tag; +import com.jpexs.decompiler.flash.tags.DefineButtonCxformTag; +import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag; +import com.jpexs.decompiler.flash.tags.DefineButtonTag; +import com.jpexs.decompiler.flash.tags.DefineEditTextTag; +import com.jpexs.decompiler.flash.tags.DefineFont2Tag; +import com.jpexs.decompiler.flash.tags.DefineFont3Tag; +import com.jpexs.decompiler.flash.tags.DefineFont4Tag; +import com.jpexs.decompiler.flash.tags.DefineFontAlignZonesTag; +import com.jpexs.decompiler.flash.tags.DefineFontInfo2Tag; +import com.jpexs.decompiler.flash.tags.DefineFontInfoTag; +import com.jpexs.decompiler.flash.tags.DefineFontNameTag; +import com.jpexs.decompiler.flash.tags.DefineFontTag; +import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag; +import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag; +import com.jpexs.decompiler.flash.tags.DefineScalingGridTag; +import com.jpexs.decompiler.flash.tags.DefineSceneAndFrameLabelDataTag; +import com.jpexs.decompiler.flash.tags.DefineShape2Tag; +import com.jpexs.decompiler.flash.tags.DefineShape3Tag; +import com.jpexs.decompiler.flash.tags.DefineShape4Tag; +import com.jpexs.decompiler.flash.tags.DefineShapeTag; +import com.jpexs.decompiler.flash.tags.DefineSoundTag; +import com.jpexs.decompiler.flash.tags.DefineSpriteTag; +import com.jpexs.decompiler.flash.tags.DefineText2Tag; +import com.jpexs.decompiler.flash.tags.DefineTextTag; +import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; +import com.jpexs.decompiler.flash.tags.DoABCDefineTag; +import com.jpexs.decompiler.flash.tags.DoABCTag; +import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.DoInitActionTag; +import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag; +import com.jpexs.decompiler.flash.tags.EnableDebuggerTag; +import com.jpexs.decompiler.flash.tags.EnableTelemetryTag; +import com.jpexs.decompiler.flash.tags.EndTag; +import com.jpexs.decompiler.flash.tags.ExportAssetsTag; +import com.jpexs.decompiler.flash.tags.FileAttributesTag; +import com.jpexs.decompiler.flash.tags.FrameLabelTag; +import com.jpexs.decompiler.flash.tags.ImportAssets2Tag; +import com.jpexs.decompiler.flash.tags.ImportAssetsTag; +import com.jpexs.decompiler.flash.tags.JPEGTablesTag; +import com.jpexs.decompiler.flash.tags.MetadataTag; +import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; +import com.jpexs.decompiler.flash.tags.PlaceObject3Tag; +import com.jpexs.decompiler.flash.tags.PlaceObject4Tag; +import com.jpexs.decompiler.flash.tags.PlaceObjectTag; +import com.jpexs.decompiler.flash.tags.ProductInfoTag; +import com.jpexs.decompiler.flash.tags.ProtectTag; +import com.jpexs.decompiler.flash.tags.RemoveObject2Tag; +import com.jpexs.decompiler.flash.tags.RemoveObjectTag; +import com.jpexs.decompiler.flash.tags.ScriptLimitsTag; +import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; +import com.jpexs.decompiler.flash.tags.SetTabIndexTag; +import com.jpexs.decompiler.flash.tags.ShowFrameTag; +import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; +import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag; +import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag; +import com.jpexs.decompiler.flash.tags.StartSound2Tag; +import com.jpexs.decompiler.flash.tags.StartSoundTag; +import com.jpexs.decompiler.flash.tags.SymbolClassTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.UnknownTag; +import com.jpexs.decompiler.flash.tags.VideoFrameTag; +import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; +import com.jpexs.decompiler.flash.tags.gfx.DefineExternalGradient; +import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage; +import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage2; +import com.jpexs.decompiler.flash.tags.gfx.DefineExternalSound; +import com.jpexs.decompiler.flash.tags.gfx.DefineExternalStreamSound; +import com.jpexs.decompiler.flash.tags.gfx.DefineGradientMap; +import com.jpexs.decompiler.flash.tags.gfx.DefineSubImage; +import com.jpexs.decompiler.flash.tags.gfx.ExporterInfoTag; +import com.jpexs.decompiler.flash.tags.gfx.FontTextureInfo; +import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; +import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA; +import com.jpexs.decompiler.flash.types.ARGB; +import com.jpexs.decompiler.flash.types.BITMAPDATA; +import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; +import com.jpexs.decompiler.flash.types.BUTTONRECORD; +import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; +import com.jpexs.decompiler.flash.types.CLIPACTIONS; +import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; +import com.jpexs.decompiler.flash.types.COLORMAPDATA; +import com.jpexs.decompiler.flash.types.CXFORM; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.FILLSTYLE; +import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.FOCALGRADIENT; +import com.jpexs.decompiler.flash.types.GLYPHENTRY; +import com.jpexs.decompiler.flash.types.GRADIENT; +import com.jpexs.decompiler.flash.types.GRADRECORD; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.LINESTYLE; +import com.jpexs.decompiler.flash.types.LINESTYLE2; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE; +import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT; +import com.jpexs.decompiler.flash.types.MORPHGRADIENT; +import com.jpexs.decompiler.flash.types.MORPHGRADRECORD; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLE; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.PIX15; +import com.jpexs.decompiler.flash.types.PIX24; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.RGB; +import com.jpexs.decompiler.flash.types.RGBA; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; +import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; +import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.TEXTRECORD; +import com.jpexs.decompiler.flash.types.ZONEDATA; +import com.jpexs.decompiler.flash.types.ZONERECORD; +import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; +import com.jpexs.decompiler.flash.types.filters.BLURFILTER; +import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER; +import com.jpexs.decompiler.flash.types.filters.CONVOLUTIONFILTER; +import com.jpexs.decompiler.flash.types.filters.DROPSHADOWFILTER; +import com.jpexs.decompiler.flash.types.filters.FILTER; +import com.jpexs.decompiler.flash.types.filters.GLOWFILTER; +import com.jpexs.decompiler.flash.types.filters.GRADIENTBEVELFILTER; +import com.jpexs.decompiler.flash.types.filters.GRADIENTGLOWFILTER; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +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.Helper; +import com.jpexs.helpers.MemoryInputStream; +import com.jpexs.helpers.ProgressListener; +import com.jpexs.helpers.streams.SeekableInputStream; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.InflaterInputStream; + +/** + * Class for reading data from SWF file + * + * @author JPEXS + */ +public class SWFInputStream implements AutoCloseable { + + private SeekableInputStream is; + private long pos; + private int version; + private static final Logger logger = Logger.getLogger(SWFInputStream.class.getName()); + private final List listeners = new ArrayList<>(); + private long percentMax; + + public int getVersion() { + return version; + } + + public void addPercentListener(ProgressListener listener) { + listeners.add(listener); + } + + public void removePercentListener(ProgressListener listener) { + int index = listeners.indexOf(listener); + if (index > -1) { + listeners.remove(index); + } + } + + public void setPercentMax(long percentMax) { + this.percentMax = percentMax; + } + + /** + * Constructor + * + * @param data SWF data + * @param version Version of SWF to read + * @param startingPos + */ + public SWFInputStream(byte[] data, int version, long startingPos) { + this.version = version; + this.is = new MemoryInputStream(data); + pos = startingPos; + } + + /** + * Constructor + * + * @param data SWF data + * @param version Version of SWF to read + */ + public SWFInputStream(byte[] data, int version) { + this(data, version, 0L); + } + + /** + * Constructor + * + * @param is Existing inputstream + * @param version Version of SWF to read + * @param startingPos + */ + public SWFInputStream(SeekableInputStream is, int version, long startingPos) { + this.version = version; + this.is = is; + pos = startingPos; + } + + /** + * Constructor + * + * @param is Existing inputstream + * @param version Version of SWF to read + */ + public SWFInputStream(SeekableInputStream is, int version) { + this(is, version, 0L); + } + + /** + * Gets position in bytes in the stream + * + * @return Number of bytes + */ + public long getPos() { + return pos; + } + + /** + * Sets position in bytes in the stream + * + * @param pos Number of bytes + * @throws java.io.IOException + */ + public void seek(long pos) throws IOException { + if (is instanceof SeekableInputStream) { + SeekableInputStream sis = (SeekableInputStream) is; + sis.seek(pos); + } else { + throw new IOException("Underlying stream is not a SeekableInputStream"); + } + } + + /** + * Reads one byte from the stream + * + * @return byte or -1 on error + * @throws IOException + */ + public int read() throws IOException { + bitPos = 0; + try { + return readNoBitReset(); + } catch (EOFException | EndOfStreamException ex) { + logger.log(Level.SEVERE, null, ex); + } + return -1; + } + + public int readEx() throws IOException { + bitPos = 0; + return readNoBitReset(); + } + + public int read(byte[] b, int off, int len) throws IOException { + int bytesRead = is.read(b, off, len); + bitPos = 0; + pos += bytesRead; + return bytesRead; + } + + public void alignByte() { + bitPos = 0; + } + private int lastPercent = -1; + + private int readNoBitReset() throws IOException, EndOfStreamException { + pos++; + if (percentMax > 0) { + int percent = (int) (pos * 100 / percentMax); + if (lastPercent != percent) { + for (ProgressListener pl : listeners) { + pl.progress(percent); + } + lastPercent = percent; + } + } + int r = is.read(); + if (r == -1) { + throw new EndOfStreamException(); + } + return r; + } + + /** + * Reads one UI8 (Unsigned 8bit integer) value from the stream + * + * @return UI8 value or -1 on error + * @throws IOException + */ + public int readUI8() throws IOException { + return readEx(); + } + + /** + * Reads one string value from the stream + * + * @return String value + * @throws IOException + */ + public String readString() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int r; + while (true) { + r = readEx(); + if (r == 0) { + return new String(baos.toByteArray(), Utf8Helper.charset); + } + baos.write(r); + } + } + + /** + * Reads one UI32 (Unsigned 32bit integer) value from the stream + * + * @return UI32 value + * @throws IOException + */ + public long readUI32() throws IOException { + return (readEx() + (readEx() << 8) + (readEx() << 16) + (readEx() << 24)) & 0xffffffff; + } + + /** + * Reads one UI16 (Unsigned 16bit integer) value from the stream + * + * @return UI16 value + * @throws IOException + */ + public int readUI16() throws IOException { + return readEx() + (readEx() << 8); + } + + public int readUI24() throws IOException { + return readEx() + (readEx() << 8) + (readEx() << 16); + } + + /** + * Reads one SI32 (Signed 32bit integer) value from the stream + * + * @return SI32 value + * @throws IOException + */ + public long readSI32() throws IOException { + long uval = readEx() + (readEx() << 8) + (readEx() << 16) + (readEx() << 24); + if (uval >= 0x80000000) { + return -(((~uval) & 0xffffffff) + 1); + } else { + return uval; + } + } + + /** + * Reads one SI16 (Signed 16bit integer) value from the stream + * + * @return SI16 value + * @throws IOException + */ + public int readSI16() throws IOException { + int uval = readEx() + (readEx() << 8); + if (uval >= 0x8000) { + return -(((~uval) & 0xffff) + 1); + } else { + return uval; + } + } + + /** + * Reads one SI8 (Signed 8bit integer) value from the stream + * + * @return SI8 value + * @throws IOException + */ + public int readSI8() throws IOException { + int uval = readEx(); + if (uval >= 0x80) { + return -(((~uval) & 0xff) + 1); + } else { + return uval; + } + } + + /** + * Reads one FIXED (Fixed point 16.16) value from the stream + * + * @return FIXED value + * @throws IOException + */ + public double readFIXED() throws IOException { + int afterPoint = readUI16(); + int beforePoint = readUI16(); + return ((double) ((beforePoint << 16) + afterPoint)) / 65536; + } + + /** + * Reads one FIXED8 (Fixed point 8.8) value from the stream + * + * @return FIXED8 value + * @throws IOException + */ + public float readFIXED8() throws IOException { + int afterPoint = readEx(); + int beforePoint = readEx(); + return beforePoint + (((float) afterPoint) / 256); + } + + private long readLong() throws IOException { + byte[] readBuffer = readBytesEx(8); + return (((long) readBuffer[3] << 56) + + ((long) (readBuffer[2] & 255) << 48) + + ((long) (readBuffer[1] & 255) << 40) + + ((long) (readBuffer[0] & 255) << 32) + + ((long) (readBuffer[7] & 255) << 24) + + ((readBuffer[6] & 255) << 16) + + ((readBuffer[5] & 255) << 8) + + ((readBuffer[4] & 255))); + } + + /** + * Reads one DOUBLE (double precision floating point value) value from the + * stream + * + * @return DOUBLE value + * @throws IOException + */ + public double readDOUBLE() throws IOException { + long el = readLong(); + double ret = Double.longBitsToDouble(el); + return ret; + } + + /** + * Reads one FLOAT (single precision floating point value) value from the + * stream + * + * @return FLOAT value + * @throws IOException + */ + public float readFLOAT() throws IOException { + int val = (int) readUI32(); + float ret = Float.intBitsToFloat(val); + /*int sign = val >> 31; + int mantisa = val & 0x3FFFFF; + int exp = (val >> 22) & 0xFF; + float ret =(sign == 1 ? -1 : 1) * (float) Math.pow(2, exp)* (1+((mantisa)/ (float)(1<<23)));*/ + return ret; + } + + /** + * Reads one FLOAT16 (16bit floating point value) value from the stream + * + * @return FLOAT16 value + * @throws IOException + */ + public float readFLOAT16() throws IOException { + int val = readUI16(); + int sign = val >> 15; + int mantisa = val & 0x3FF; + int exp = (val >> 10) & 0x1F; + float ret = (sign == 1 ? -1 : 1) * (float) Math.pow(2, exp) * (1 + ((mantisa) / (float) (1 << 10))); + return ret; + } + + /** + * Reads bytes from the stream + * + * @param count Number of bytes to read + * @return Array of read bytes + * @throws IOException + */ + public byte[] readBytesEx(long count) throws IOException { + if (count <= 0) { + return new byte[0]; + } + byte[] ret = new byte[(int) count]; + for (int i = 0; i < count; i++) { + ret[i] = (byte) readEx(); + } + return ret; + } + + /** + * Skip bytes from the stream + * + * @param count Number of bytes to skip + * @throws IOException + */ + public void skipBytes(int count) throws IOException { + try { + bitPos = 0; + for (int i = 0; i < count; i++) { + readNoBitReset(); + } + } catch (EOFException | EndOfStreamException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + /** + * Reads bytes from the stream + * + * @param count Number of bytes to read + * @return Array of read bytes + * @throws IOException + */ + public byte[] readBytes(int count) throws IOException { + if (count <= 0) { + return new byte[0]; + } + byte[] ret = new byte[count]; + int i = 0; + try { + for (i = 0; i < count; i++) { + ret[i] = (byte) readEx(); + } + } catch (EOFException | EndOfStreamException ex) { + ret = Arrays.copyOf(ret, i); // truncate array + logger.log(Level.SEVERE, null, ex); + } + return ret; + } + + public byte[] readBytesZlib(long count) throws IOException { + byte[] data = readBytesEx(count); + InflaterInputStream dis = new InflaterInputStream(new ByteArrayInputStream(data)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[4096]; + int c = 0; + while ((c = dis.read(buf)) > 0) { + baos.write(buf, 0, c); + } + return baos.toByteArray(); + } + + /** + * Reads one EncodedU32 (Encoded unsigned 32bit value) value from the stream + * + * @return U32 value + * @throws IOException + */ + public long readEncodedU32() throws IOException { + int result = readEx(); + if ((result & 0x00000080) == 0) { + return result; + } + result = (result & 0x0000007f) | (readEx()) << 7; + if ((result & 0x00004000) == 0) { + return result; + } + result = (result & 0x00003fff) | (readEx()) << 14; + if ((result & 0x00200000) == 0) { + return result; + } + result = (result & 0x001fffff) | (readEx()) << 21; + if ((result & 0x10000000) == 0) { + return result; + } + result = (result & 0x0fffffff) | (readEx()) << 28; + return result; + } + private int bitPos = 0; + private int tempByte = 0; + + /** + * Reads UB[nBits] (Unsigned-bit value) value from the stream + * + * @param nBits Number of bits which represent value + * @return Unsigned value + * @throws IOException + */ + public long readUB(int nBits) throws IOException { + if (nBits == 0) { + return 0; + } + long ret = 0; + if (bitPos == 0) { + tempByte = readNoBitReset(); + } + for (int bit = 0; bit < nBits; bit++) { + int nb = (tempByte >> (7 - bitPos)) & 1; + ret += (nb << (nBits - 1 - bit)); + bitPos++; + if (bitPos == 8) { + bitPos = 0; + if (bit != nBits - 1) { + tempByte = readNoBitReset(); + } + } + } + return ret; + } + + /** + * Reads SB[nBits] (Signed-bit value) value from the stream + * + * @param nBits Number of bits which represent value + * @return Signed value + * @throws IOException + */ + public long readSB(int nBits) throws IOException { + int uval = (int) readUB(nBits); + + int shift = 32 - nBits; + // sign extension + uval = (uval << shift) >> shift; + return uval; + } + + /** + * Reads FB[nBits] (Signed fixed-point bit value) value from the stream + * + * @param nBits Number of bits which represent value + * @return Fixed-point value + * @throws IOException + */ + public float readFB(int nBits) throws IOException { + if (nBits == 0) { + return 0; + } + float val = readSB(nBits); + float ret = val / 0x10000; + return ret; + } + + /** + * Reads one RECT value from the stream + * + * @return RECT value + * @throws IOException + */ + public RECT readRECT() throws IOException { + RECT ret = new RECT(); + int NBits = (int) readUB(5); + ret.Xmin = (int) readSB(NBits); + ret.Xmax = (int) readSB(NBits); + ret.Ymin = (int) readSB(NBits); + ret.Ymax = (int) readSB(NBits); + ret.nbits = NBits; + alignByte(); + return ret; + } + + private static void dumpTag(PrintStream out, int version, Tag tag, int level) { + StringBuilder sb = new StringBuilder(); + sb.append(Helper.formatHex((int) tag.getPos(), 8)); + sb.append(": "); + sb.append(Helper.indent(level, "", " ")); + sb.append(Helper.format(tag.toString(), 25 - 2 * level)); + sb.append(" tagId="); + sb.append(Helper.formatInt(tag.getId(), 3)); + sb.append(" len="); + sb.append(Helper.formatInt(tag.getOriginalDataLength(), 8)); + sb.append(" "); + sb.append(Helper.bytesToHexString(64, tag.getData(), 0)); + out.println(sb.toString()); +// out.println(Utils.formatHex((int)tag.getPos(), 8) + ": " + Utils.indent(level, "") + Utils.format(tag.toString(), 25 - 2*level) + " tagId="+tag.getId()+" len="+tag.getOrigDataLength()+": "+Utils.bytesToHexString(64, tag.getData(version), 0)); + if (tag.hasSubTags()) { + for (Tag subTag : tag.getSubTags()) { + dumpTag(out, version, subTag, level + 1); + } + } + } + + @Override + public void close() { + } + + private class TagResolutionTask implements Callable { + + private final Tag tag; + private final int level; + private final boolean parallel; + private final boolean skipUnusualTags; + private final SWF swf; + private final boolean gfx; + + public TagResolutionTask(SWF swf, Tag tag, int level, boolean parallel, boolean skipUnusualTags, boolean gfx) { + this.tag = tag; + this.level = level; + this.parallel = parallel; + this.skipUnusualTags = skipUnusualTags; + this.swf = swf; + this.gfx = gfx; + } + + @Override + public Tag call() throws Exception { + try { + return resolveTag(swf, tag, level, parallel, skipUnusualTags, gfx); + } catch (EndOfStreamException ex) { + logger.log(Level.SEVERE, null, ex); + return tag; + } + } + } + + /** + * Reads list of tags from the stream. Reading ends with End tag(=0) or end + * of the stream. Optionally can skip AS1/2 tags when file is AS3 + * + * @param swf + * @param timelined + * @param level + * @param parallel + * @param skipUnusualTags + * @param parseTags + * @param gfx + * @return List of tags + * @throws IOException + * @throws java.lang.InterruptedException + */ + public List readTagList(SWF swf, Timelined timelined, int level, boolean parallel, boolean skipUnusualTags, boolean parseTags, boolean gfx) throws IOException, InterruptedException { + ExecutorService executor = null; + List> futureResults = new ArrayList<>(); + if (parallel) { + executor = Executors.newFixedThreadPool(Configuration.parallelThreadCount.get()); + futureResults = new ArrayList<>(); + } + List tags = new ArrayList<>(); + Tag tag; + boolean isAS3 = false; + while (true) { + long pos = getPos(); + try { + tag = readTag(swf, level, pos, parseTags && !parallel, parallel, skipUnusualTags, gfx); + } catch (EOFException | EndOfStreamException ex) { + tag = null; + } + if (tag == null) { + break; + } + + tag.setTimelined(timelined); + if (!parallel) { + tags.add(tag); + } + if (Configuration.dumpTags.get() && level == 0) { + dumpTag(System.out, version, tag, level); + } + + boolean doParse; + if (!skipUnusualTags) { + doParse = true; + } else { + switch (tag.getId()) { + case FileAttributesTag.ID: //FileAttributes + FileAttributesTag fileAttributes = (FileAttributesTag) resolveTag(swf, tag, level, parallel, skipUnusualTags, gfx); + if (fileAttributes.actionScript3) { + isAS3 = true; + } + doParse = true; + break; + case DoActionTag.ID: + case DoInitActionTag.ID: + if (isAS3) { + doParse = false; + } else { + doParse = true; + } + break; + case ShowFrameTag.ID: + case PlaceObjectTag.ID: + case PlaceObject2Tag.ID: + case RemoveObjectTag.ID: + case RemoveObject2Tag.ID: + case PlaceObject3Tag.ID: //? + case StartSoundTag.ID: + case FrameLabelTag.ID: + case SoundStreamHeadTag.ID: + case SoundStreamHead2Tag.ID: + case SoundStreamBlockTag.ID: + case VideoFrameTag.ID: + case EndTag.ID: + doParse = true; + break; + default: + if (level > 0) { //No such tags in DefineSprite allowed + logger.log(Level.FINE, "Tag({0}) found in DefineSprite => Ignored", tag.getId()); + doParse = false; + } else { + doParse = true; + } + + } + } + if (parseTags && doParse) { + if (parallel) { + Future future = executor.submit(new TagResolutionTask(swf, tag, level, parallel, skipUnusualTags, gfx)); + futureResults.add(future); + } + } + + if (tag.getId() == EndTag.ID) { + break; + } + } + + if (parallel) { + for (Future future : futureResults) { + try { + tags.add(future.get()); + } catch (InterruptedException ex) { + future.cancel(true); + } catch (ExecutionException e) { + logger.log(Level.SEVERE, "Error during tag reading", e); + } + } + + executor.shutdown(); + } + return tags; + } + + public static Tag resolveTag(SWF swf, Tag tag, int level, boolean parallel, boolean skipUnusualTags, boolean gfx) throws InterruptedException { + Tag ret; + + byte[] data = tag.getData(); + long pos = tag.getPos(); + int length = tag.getOriginalLength(); + SWFLimitedInputStream sis = new SWFLimitedInputStream(swf, new SWFInputStream(data, swf.version), length); + + try { + switch (tag.getId()) { + case 0: + ret = new EndTag(swf, pos, length); + break; + case 1: + ret = new ShowFrameTag(swf, pos, length); + break; + case 2: + ret = new DefineShapeTag(sis, pos, length); + break; + //case 3: FreeCharacter + case 4: + ret = new PlaceObjectTag(sis, pos, length); + break; + case 5: + ret = new RemoveObjectTag(sis, pos, length); + break; + case 6: + ret = new DefineBitsTag(sis, pos, length); + break; + case 7: + ret = new DefineButtonTag(sis, pos, length); + break; + case 8: + ret = new JPEGTablesTag(sis, pos, length); + break; + case 9: + ret = new SetBackgroundColorTag(sis, pos, length); + break; + case 10: + ret = new DefineFontTag(sis, pos, length); + break; + case 11: + ret = new DefineTextTag(sis, pos, length); + break; + case 12: + ret = new DoActionTag(sis, pos, length); + break; + case 13: + ret = new DefineFontInfoTag(sis, pos, length); + break; + case 14: + ret = new DefineSoundTag(sis, pos, length); + break; + case 15: + ret = new StartSoundTag(sis, pos, length); + break; + //case 16: + case 17: + ret = new DefineButtonSoundTag(sis, pos, length); + break; + case 18: + ret = new SoundStreamHeadTag(sis, pos, length); + break; + case 19: + ret = new SoundStreamBlockTag(sis, pos, length); + break; + case 21: + ret = new DefineBitsJPEG2Tag(sis, pos, length); + break; + case 20: + ret = new DefineBitsLosslessTag(sis, pos, length); + break; + case 22: + ret = new DefineShape2Tag(sis, pos, length); + break; + case 23: + ret = new DefineButtonCxformTag(sis, pos, length); + break; + case 24: + ret = new ProtectTag(sis, pos, length); + break; + //case 25: PathsArePostscript + case 26: + ret = new PlaceObject2Tag(sis, pos, length); + break; + //case 27: + case 28: + ret = new RemoveObject2Tag(sis, pos, length); + break; + //case 29: SyncFrame + //case 30: + //case 31: FreeAll + case 32: + ret = new DefineShape3Tag(sis, pos, length); + break; + case 33: + ret = new DefineText2Tag(sis, pos, length); + break; + case 34: + ret = new DefineButton2Tag(sis, pos, length); + break; + case 35: + ret = new DefineBitsJPEG3Tag(sis, pos, length); + break; + case 36: + ret = new DefineBitsLossless2Tag(sis, pos, length); + break; + case 37: + ret = new DefineEditTextTag(sis, pos, length); + break; + //case 38: DefineVideo + case 39: + ret = new DefineSpriteTag(sis, level, pos, length, parallel, skipUnusualTags); + break; + //case 40: NameCharacter + case 41: + ret = new ProductInfoTag(sis, pos, length); + break; + //case 42: DefineTextFormat + case 43: + ret = new FrameLabelTag(sis, pos, length); + break; + //case 44: + case 45: + ret = new SoundStreamHead2Tag(sis, pos, length); + break; + case 46: + ret = new DefineMorphShapeTag(sis, pos, length); + break; + //case 47: GenerateFrame + case 48: + ret = new DefineFont2Tag(sis, pos, length); + break; + //case 49: GeneratorCommand + //case 50: DefineCommandObject + //case 51: CharacterSet + //case 52: ExternalFont + //case 53-55 + case 56: + ret = new ExportAssetsTag(sis, pos, length); + break; + case 57: + ret = new ImportAssetsTag(sis, pos, length); + break; + case 58: + ret = new EnableDebuggerTag(sis, pos, length); + break; + case 59: + ret = new DoInitActionTag(sis, pos, length); + break; + case 60: + ret = new DefineVideoStreamTag(sis, pos, length); + break; + case 61: + ret = new VideoFrameTag(sis, pos, length); + break; + case 62: + ret = new DefineFontInfo2Tag(sis, pos, length); + break; + case 63: + ret = new DebugIDTag(sis, pos, length); + break; + case 64: + ret = new EnableDebugger2Tag(sis, pos, length); + break; + case 65: + ret = new ScriptLimitsTag(sis, pos, length); + break; + case 66: + ret = new SetTabIndexTag(sis, pos, length); + break; + //case 67-68: + case 69: + ret = new FileAttributesTag(sis, pos, length); + break; + case 70: + ret = new PlaceObject3Tag(sis, pos, length); + break; + case 71: + ret = new ImportAssets2Tag(sis, pos, length); + break; + case 72: + ret = new DoABCTag(sis, pos, length); + break; + case 73: + ret = new DefineFontAlignZonesTag(sis, pos, length); + break; + case 74: + ret = new CSMTextSettingsTag(sis, pos, length); + break; + case 75: + ret = new DefineFont3Tag(sis, pos, length); + break; + case 76: + ret = new SymbolClassTag(sis, pos, length); + break; + case 77: + ret = new MetadataTag(sis, pos, length); + break; + case 78: + ret = new DefineScalingGridTag(sis, pos, length); + break; + //case 79-81: + case 82: + ret = new DoABCDefineTag(sis, pos, length); + break; + case 83: + ret = new DefineShape4Tag(sis, pos, length); + break; + case 84: + ret = new DefineMorphShape2Tag(sis, pos, length); + break; + //case 85: + case 86: + ret = new DefineSceneAndFrameLabelDataTag(sis, pos, length); + break; + case 87: + ret = new DefineBinaryDataTag(sis, pos, length); + break; + case 88: + ret = new DefineFontNameTag(sis, pos, length); + break; + case 89: + ret = new StartSound2Tag(sis, pos, length); + break; + case 90: + ret = new DefineBitsJPEG4Tag(sis, pos, length); + break; + case 91: + ret = new DefineFont4Tag(sis, pos, length); + break; + //case 92: certificate + case 93: + ret = new EnableTelemetryTag(sis, pos, length); + break; + case 94: + ret = new PlaceObject4Tag(sis, pos, length); + break; + default: + if (gfx) { //GFX tags only in GFX files. There may be incorrect GFX tags in non GFX files + switch (tag.getId()) { + case 1000: + ret = new ExporterInfoTag(sis, pos, length); + break; + case 1001: + ret = new DefineExternalImage(sis, pos, length); + break; + case 1002: + ret = new FontTextureInfo(sis, pos, length); + break; + case 1003: + ret = new DefineExternalGradient(sis, pos, length); + break; + case 1004: + ret = new DefineGradientMap(sis, pos, length); + break; + case 1005: + ret = new DefineCompactedFont(sis, pos, length); + break; + case 1006: + ret = new DefineExternalSound(sis, pos, length); + break; + case 1007: + ret = new DefineExternalStreamSound(sis, pos, length); + break; + case 1008: + ret = new DefineSubImage(sis, pos, length); + break; + case 1009: + ret = new DefineExternalImage2(sis, pos, length); + break; + default: + ret = new UnknownTag(swf, tag.getId(), pos, length); + } + } else { + ret = new UnknownTag(swf, tag.getId(), pos, length); + } + } + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error during tag reading", ex); + ret = new Tag(swf, tag.getId(), "ErrorTag", pos, length); + } + ret.forceWriteAsLong = tag.forceWriteAsLong; + ret.setTimelined(tag.getTimelined()); + return ret; + } + + /** + * Reads one Tag from the stream with optional resolving (= reading tag + * content) + * + * @param swf + * @param level + * @param pos + * @param resolve + * @param parallel + * @param skipUnusualTags + * @param gfx + * @return Tag or null when End tag + * @throws IOException + * @throws java.lang.InterruptedException + */ + public Tag readTag(SWF swf, int level, long pos, boolean resolve, boolean parallel, boolean skipUnusualTags, boolean gfx) throws IOException, InterruptedException { + int tagIDTagLength = readUI16(); + int tagID = (tagIDTagLength) >> 6; + + logger.log(Level.INFO, "Reading tag. ID={0}, position: {1}", new Object[]{tagID, pos}); + + long tagLength = (tagIDTagLength & 0x003F); + boolean readLong = false; + if (tagLength == 0x3f) { + tagLength = readSI32(); + readLong = true; + } + skipBytes((int) tagLength); + Tag ret = new Tag(swf, tagID, "Unresolved", pos, (int) (tagLength + (readLong ? 6 : 2))); + ret.forceWriteAsLong = readLong; + + if (resolve) { + try { + ret = resolveTag(swf, ret, level, parallel, skipUnusualTags, gfx); + } catch (EndOfStreamException ex) { + logger.log(Level.SEVERE, null, ex); + } + + if (Configuration.debugMode.get()) { + byte[] data = ret.getOriginalData(); + byte[] dataNew = ret.getData(); + int ignoreFirst = 0; + for (int i = 0; i < data.length; i++) { + if (i >= dataNew.length) { + break; + } + if (dataNew[i] != data[i]) { + if (ignoreFirst > 0) { + ignoreFirst--; + continue; + } + String e = "TAG " + ret.toString() + " WRONG, "; + for (int j = i - 10; j <= i + 5; j++) { + while (j < 0) { + j++; + } + if (j >= data.length) { + break; + } + if (j >= dataNew.length) { + break; + } + if (j >= i) { + e += (Long.toHexString(data[j] & 0xff) + " ( is " + Long.toHexString(dataNew[j] & 0xff) + ") "); + } else { + e += (Long.toHexString(data[j] & 0xff) + " "); + } + } + logger.fine(e); + } + } + } + } + return ret; + } + + /** + * Reads one Action from the stream + * + * @param cpool + * @return Action or null when ActionEndFlag or end of the stream + * @throws IOException + */ + public Action readAction(ConstantPool cpool) throws IOException { + int actionCode = -1; + + try { + actionCode = readUI8(); + if (actionCode == 0) { + return new ActionEnd(); + } + if (actionCode == -1) { + return null; + } + int actionLength = 0; + if (actionCode >= 0x80) { + actionLength = readUI16(); + } + switch (actionCode) { + //SWF3 Actions + case 0x81: + return new ActionGotoFrame(actionLength, this); + case 0x83: + return new ActionGetURL(actionLength, this, version); + case 0x04: + return new ActionNextFrame(); + case 0x05: + return new ActionPrevFrame(); + case 0x06: + return new ActionPlay(); + case 0x07: + return new ActionStop(); + case 0x08: + return new ActionToggleQuality(); + case 0x09: + return new ActionStopSounds(); + case 0x8A: + return new ActionWaitForFrame(actionLength, this, cpool); + case 0x8B: + return new ActionSetTarget(actionLength, this, version); + case 0x8C: + return new ActionGoToLabel(actionLength, this, version); + //SWF4 Actions + case 0x96: + return new ActionPush(actionLength, this, version); + case 0x17: + return new ActionPop(); + case 0x0A: + return new ActionAdd(); + case 0x0B: + return new ActionSubtract(); + case 0x0C: + return new ActionMultiply(); + case 0x0D: + return new ActionDivide(); + case 0x0E: + return new ActionEquals(); + case 0x0F: + return new ActionLess(); + case 0x10: + return new ActionAnd(); + case 0x11: + return new ActionOr(); + case 0x12: + return new ActionNot(); + case 0x13: + return new ActionStringEquals(); + case 0x14: + return new ActionStringLength(); + case 0x21: + return new ActionStringAdd(); + case 0x15: + return new ActionStringExtract(); + case 0x29: + return new ActionStringLess(); + case 0x31: + return new ActionMBStringLength(); + case 0x35: + return new ActionMBStringExtract(); + case 0x18: + return new ActionToInteger(); + case 0x32: + return new ActionCharToAscii(); + case 0x33: + return new ActionAsciiToChar(); + case 0x36: + return new ActionMBCharToAscii(); + case 0x37: + return new ActionMBAsciiToChar(); + case 0x99: + return new ActionJump(actionLength, this); + case 0x9D: + return new ActionIf(actionLength, this); + case 0x9E: + return new ActionCall(actionLength); + case 0x1C: + return new ActionGetVariable(); + case 0x1D: + return new ActionSetVariable(); + case 0x9A: + return new ActionGetURL2(actionLength, this); + case 0x9F: + return new ActionGotoFrame2(actionLength, this); + case 0x20: + return new ActionSetTarget2(); + case 0x22: + return new ActionGetProperty(); + case 0x23: + return new ActionSetProperty(); + case 0x24: + return new ActionCloneSprite(); + case 0x25: + return new ActionRemoveSprite(); + case 0x27: + return new ActionStartDrag(); + case 0x28: + return new ActionEndDrag(); + case 0x8D: + return new ActionWaitForFrame2(actionLength, this, cpool); + case 0x26: + return new ActionTrace(); + case 0x34: + return new ActionGetTime(); + case 0x30: + return new ActionRandomNumber(); + //SWF5 Actions + case 0x3D: + return new ActionCallFunction(); + case 0x52: + return new ActionCallMethod(); + case 0x88: + return new ActionConstantPool(actionLength, this, version); + case 0x9B: + return new ActionDefineFunction(actionLength, this, version); + case 0x3C: + return new ActionDefineLocal(); + case 0x41: + return new ActionDefineLocal2(); + case 0x3A: + return new ActionDelete(); + case 0x3B: + return new ActionDelete2(); + case 0x46: + return new ActionEnumerate(); + case 0x49: + return new ActionEquals2(); + case 0x4E: + return new ActionGetMember(); + case 0x42: + return new ActionInitArray(); + case 0x43: + return new ActionInitObject(); + case 0x53: + return new ActionNewMethod(); + case 0x40: + return new ActionNewObject(); + case 0x4F: + return new ActionSetMember(); + case 0x45: + return new ActionTargetPath(); + case 0x94: + return new ActionWith(actionLength, this, version); + case 0x4A: + return new ActionToNumber(); + case 0x4B: + return new ActionToString(); + case 0x44: + return new ActionTypeOf(); + case 0x47: + return new ActionAdd2(); + case 0x48: + return new ActionLess2(); + case 0x3F: + return new ActionModulo(); + case 0x60: + return new ActionBitAnd(); + case 0x63: + return new ActionBitLShift(); + case 0x61: + return new ActionBitOr(); + case 0x64: + return new ActionBitRShift(); + case 0x65: + return new ActionBitURShift(); + case 0x62: + return new ActionBitXor(); + case 0x51: + return new ActionDecrement(); + case 0x50: + return new ActionIncrement(); + case 0x4C: + return new ActionPushDuplicate(); + case 0x3E: + return new ActionReturn(); + case 0x4D: + return new ActionStackSwap(); + case 0x87: + return new ActionStoreRegister(actionLength, this); + //SWF6 Actions + case 0x54: + return new ActionInstanceOf(); + case 0x55: + return new ActionEnumerate2(); + case 0x66: + return new ActionStrictEquals(); + case 0x67: + return new ActionGreater(); + case 0x68: + return new ActionStringGreater(); + //SWF7 Actions + case 0x8E: + return new ActionDefineFunction2(actionLength, this, version); + case 0x69: + return new ActionExtends(); + case 0x2B: + return new ActionCastOp(); + case 0x2C: + return new ActionImplementsOp(); + case 0x8F: + return new ActionTry(actionLength, this, version); + case 0x2A: + return new ActionThrow(); + default: + /*if (actionLength > 0) { + //skip(actionLength); + }*/ + //throw new UnknownActionException(actionCode); + Action r = new ActionNop(); + r.actionCode = actionCode; + r.actionLength = actionLength; + return r; + //return new Action(actionCode, actionLength); + } + } catch (EndOfStreamException | ArrayIndexOutOfBoundsException eos) { + return null; + } + } + + /** + * Reads one MATRIX value from the stream + * + * @return MATRIX value + * @throws IOException + */ + public MATRIX readMatrix() throws IOException { + MATRIX ret = new MATRIX(); + ret.hasScale = readUB(1) == 1; + if (ret.hasScale) { + int NScaleBits = (int) readUB(5); + ret.scaleX = (int) readSB(NScaleBits); + ret.scaleY = (int) readSB(NScaleBits); + ret.nScaleBits = NScaleBits; + } + ret.hasRotate = readUB(1) == 1; + if (ret.hasRotate) { + int NRotateBits = (int) readUB(5); + ret.rotateSkew0 = (int) readSB(NRotateBits); + ret.rotateSkew1 = (int) readSB(NRotateBits); + ret.nRotateBits = NRotateBits; + } + int NTranslateBits = (int) readUB(5); + ret.translateX = (int) readSB(NTranslateBits); + ret.translateY = (int) readSB(NTranslateBits); + ret.nTranslateBits = NTranslateBits; + alignByte(); + return ret; + } + + /** + * Reads one CXFORMWITHALPHA value from the stream + * + * @return CXFORMWITHALPHA value + * @throws IOException + */ + public CXFORMWITHALPHA readCXFORMWITHALPHA() throws IOException { + CXFORMWITHALPHA ret = new CXFORMWITHALPHA(); + ret.hasAddTerms = readUB(1) == 1; + ret.hasMultTerms = readUB(1) == 1; + int Nbits = (int) readUB(4); + ret.nbits = Nbits; + if (ret.hasMultTerms) { + ret.redMultTerm = (int) readSB(Nbits); + ret.greenMultTerm = (int) readSB(Nbits); + ret.blueMultTerm = (int) readSB(Nbits); + ret.alphaMultTerm = (int) readSB(Nbits); + } + if (ret.hasAddTerms) { + ret.redAddTerm = (int) readSB(Nbits); + ret.greenAddTerm = (int) readSB(Nbits); + ret.blueAddTerm = (int) readSB(Nbits); + ret.alphaAddTerm = (int) readSB(Nbits); + } + alignByte(); + return ret; + } + + /** + * Reads one CXFORM value from the stream + * + * @return CXFORM value + * @throws IOException + */ + public CXFORM readCXFORM() throws IOException { + CXFORM ret = new CXFORM(); + ret.hasAddTerms = readUB(1) == 1; + ret.hasMultTerms = readUB(1) == 1; + int Nbits = (int) readUB(4); + ret.nbits = Nbits; + if (ret.hasMultTerms) { + ret.redMultTerm = (int) readSB(Nbits); + ret.greenMultTerm = (int) readSB(Nbits); + ret.blueMultTerm = (int) readSB(Nbits); + } + if (ret.hasAddTerms) { + ret.redAddTerm = (int) readSB(Nbits); + ret.greenAddTerm = (int) readSB(Nbits); + ret.blueAddTerm = (int) readSB(Nbits); + } + alignByte(); + return ret; + } + + /** + * Reads one CLIPEVENTFLAGS value from the stream + * + * @return CLIPEVENTFLAGS value + * @throws IOException + */ + public CLIPEVENTFLAGS readCLIPEVENTFLAGS() throws IOException { + CLIPEVENTFLAGS ret = new CLIPEVENTFLAGS(); + ret.clipEventKeyUp = readUB(1) == 1; + ret.clipEventKeyDown = readUB(1) == 1; + ret.clipEventMouseUp = readUB(1) == 1; + ret.clipEventMouseDown = readUB(1) == 1; + ret.clipEventMouseMove = readUB(1) == 1; + ret.clipEventUnload = readUB(1) == 1; + ret.clipEventEnterFrame = readUB(1) == 1; + ret.clipEventLoad = readUB(1) == 1; + ret.clipEventDragOver = readUB(1) == 1; + ret.clipEventRollOut = readUB(1) == 1; + ret.clipEventRollOver = readUB(1) == 1; + ret.clipEventReleaseOutside = readUB(1) == 1; + ret.clipEventRelease = readUB(1) == 1; + ret.clipEventPress = readUB(1) == 1; + ret.clipEventInitialize = readUB(1) == 1; + ret.clipEventData = readUB(1) == 1; + if (version >= 6) { + ret.reserved = (int) readUB(5); + ret.clipEventConstruct = readUB(1) == 1; + ret.clipEventKeyPress = readUB(1) == 1; + ret.clipEventDragOut = readUB(1) == 1; + ret.reserved2 = (int) readUB(8); + } + return ret; + } + + /** + * Reads one CLIPACTIONRECORD value from the stream + * + * @param swf + * @param tag + * @return CLIPACTIONRECORD value + * @throws IOException + */ + public CLIPACTIONRECORD readCLIPACTIONRECORD(SWF swf, Tag tag) throws IOException { + CLIPACTIONRECORD ret = new CLIPACTIONRECORD(swf, this, getPos(), tag); + if (ret.eventFlags.isClear()) { + return null; + } + return ret; + } + + /** + * Reads one CLIPACTIONS value from the stream + * + * @param swf + * @param tag + * @return CLIPACTIONS value + * @throws IOException + */ + public CLIPACTIONS readCLIPACTIONS(SWF swf, Tag tag) throws IOException { + CLIPACTIONS ret = new CLIPACTIONS(); + ret.reserved = readUI16(); + ret.allEventFlags = readCLIPEVENTFLAGS(); + CLIPACTIONRECORD cr; + ret.clipActionRecords = new ArrayList<>(); + while ((cr = readCLIPACTIONRECORD(swf, tag)) != null) { + ret.clipActionRecords.add(cr); + } + return ret; + } + + /** + * Reads one COLORMATRIXFILTER value from the stream + * + * @return COLORMATRIXFILTER value + * @throws IOException + */ + public COLORMATRIXFILTER readCOLORMATRIXFILTER() throws IOException { + COLORMATRIXFILTER ret = new COLORMATRIXFILTER(); + ret.matrix = new float[20]; + for (int i = 0; i < 20; i++) { + ret.matrix[i] = readFLOAT(); + } + return ret; + } + + /** + * Reads one RGBA value from the stream + * + * @return RGBA value + * @throws IOException + */ + public RGBA readRGBA() throws IOException { + RGBA ret = new RGBA(); + ret.red = readUI8(); + ret.green = readUI8(); + ret.blue = readUI8(); + ret.alpha = readUI8(); + return ret; + } + + /** + * Reads one ARGB value from the stream + * + * @return ARGB value + * @throws IOException + */ + public ARGB readARGB() throws IOException { + ARGB ret = new ARGB(); + ret.alpha = readUI8(); + ret.red = readUI8(); + ret.green = readUI8(); + ret.blue = readUI8(); + return ret; + } + + /** + * Reads one RGB value from the stream + * + * @return RGB value + * @throws IOException + */ + public RGB readRGB() throws IOException { + RGB ret = new RGB(); + ret.red = readUI8(); + ret.green = readUI8(); + ret.blue = readUI8(); + return ret; + } + + /** + * Reads one CONVOLUTIONFILTER value from the stream + * + * @return CONVOLUTIONFILTER value + * @throws IOException + */ + public CONVOLUTIONFILTER readCONVOLUTIONFILTER() throws IOException { + CONVOLUTIONFILTER ret = new CONVOLUTIONFILTER(); + ret.matrixX = readUI8(); + ret.matrixY = readUI8(); + ret.divisor = readFLOAT(); + ret.bias = readFLOAT(); + ret.matrix = new float[ret.matrixX][ret.matrixY]; + for (int x = 0; x < ret.matrixX; x++) { + for (int y = 0; y < ret.matrixY; y++) { + ret.matrix[x][y] = readFLOAT(); + } + } + ret.defaultColor = readRGBA(); + ret.reserved = (int) readUB(6); + ret.clamp = readUB(1) == 1; + ret.preserveAlpha = readUB(1) == 1; + return ret; + } + + /** + * Reads one BLURFILTER value from the stream + * + * @return BLURFILTER value + * @throws IOException + */ + public BLURFILTER readBLURFILTER() throws IOException { + BLURFILTER ret = new BLURFILTER(); + ret.blurX = readFIXED(); + ret.blurY = readFIXED(); + ret.passes = (int) readUB(5); + ret.reserved = (int) readUB(3); + return ret; + } + + /** + * Reads one DROPSHADOWFILTER value from the stream + * + * @return DROPSHADOWFILTER value + * @throws IOException + */ + public DROPSHADOWFILTER readDROPSHADOWFILTER() throws IOException { + DROPSHADOWFILTER ret = new DROPSHADOWFILTER(); + ret.dropShadowColor = readRGBA(); + ret.blurX = readFIXED(); + ret.blurY = readFIXED(); + ret.angle = readFIXED(); + ret.distance = readFIXED(); + ret.strength = readFIXED8(); + ret.innerShadow = readUB(1) == 1; + ret.knockout = readUB(1) == 1; + ret.compositeSource = readUB(1) == 1; + ret.passes = (int) readUB(5); + return ret; + } + + /** + * Reads one GLOWFILTER value from the stream + * + * @return GLOWFILTER value + * @throws IOException + */ + public GLOWFILTER readGLOWFILTER() throws IOException { + GLOWFILTER ret = new GLOWFILTER(); + ret.glowColor = readRGBA(); + ret.blurX = readFIXED(); + ret.blurY = readFIXED(); + ret.strength = readFIXED8(); + ret.innerGlow = readUB(1) == 1; + ret.knockout = readUB(1) == 1; + ret.compositeSource = readUB(1) == 1; + ret.passes = (int) readUB(5); + return ret; + } + + /** + * Reads one BEVELFILTER value from the stream + * + * @return BEVELFILTER value + * @throws IOException + */ + public BEVELFILTER readBEVELFILTER() throws IOException { + BEVELFILTER ret = new BEVELFILTER(); + ret.highlightColor = readRGBA(); //Highlight color first. It it opposite of the documentation + ret.shadowColor = readRGBA(); + ret.blurX = readFIXED(); + ret.blurY = readFIXED(); + ret.angle = readFIXED(); + ret.distance = readFIXED(); + ret.strength = readFIXED8(); + ret.innerShadow = readUB(1) == 1; + ret.knockout = readUB(1) == 1; + ret.compositeSource = readUB(1) == 1; + ret.onTop = readUB(1) == 1; + ret.passes = (int) readUB(4); + return ret; + } + + /** + * Reads one GRADIENTGLOWFILTER value from the stream + * + * @return GRADIENTGLOWFILTER value + * @throws IOException + */ + public GRADIENTGLOWFILTER readGRADIENTGLOWFILTER() throws IOException { + GRADIENTGLOWFILTER ret = new GRADIENTGLOWFILTER(); + int numColors = readUI8(); + ret.gradientColors = new RGBA[numColors]; + ret.gradientRatio = new int[numColors]; + for (int i = 0; i < numColors; i++) { + ret.gradientColors[i] = readRGBA(); + } + for (int i = 0; i < numColors; i++) { + ret.gradientRatio[i] = readUI8(); + } + ret.blurX = readFIXED(); + ret.blurY = readFIXED(); + ret.angle = readFIXED(); + ret.distance = readFIXED(); + ret.strength = readFIXED8(); + ret.innerShadow = readUB(1) == 1; + ret.knockout = readUB(1) == 1; + ret.compositeSource = readUB(1) == 1; + ret.onTop = readUB(1) == 1; + ret.passes = (int) readUB(4); + return ret; + } + + /** + * Reads one GRADIENTBEVELFILTER value from the stream + * + * @return GRADIENTBEVELFILTER value + * @throws IOException + */ + public GRADIENTBEVELFILTER readGRADIENTBEVELFILTER() throws IOException { + GRADIENTBEVELFILTER ret = new GRADIENTBEVELFILTER(); + int numColors = readUI8(); + ret.gradientColors = new RGBA[numColors]; + ret.gradientRatio = new int[numColors]; + for (int i = 0; i < numColors; i++) { + ret.gradientColors[i] = readRGBA(); + } + for (int i = 0; i < numColors; i++) { + ret.gradientRatio[i] = readUI8(); + } + ret.blurX = readFIXED(); + ret.blurY = readFIXED(); + ret.angle = readFIXED(); + ret.distance = readFIXED(); + ret.strength = readFIXED8(); + ret.innerShadow = readUB(1) == 1; + ret.knockout = readUB(1) == 1; + ret.compositeSource = readUB(1) == 1; + ret.onTop = readUB(1) == 1; + ret.passes = (int) readUB(4); + return ret; + } + + /** + * Reads list of FILTER values from the stream + * + * @return List of FILTER values + * @throws IOException + */ + public List readFILTERLIST() throws IOException { + List ret = new ArrayList<>(); + int numberOfFilters = readUI8(); + for (int i = 0; i < numberOfFilters; i++) { + ret.add(readFILTER()); + } + return ret; + } + + /** + * Reads one FILTER value from the stream + * + * @return FILTER value + * @throws IOException + */ + public FILTER readFILTER() throws IOException { + int filterId = readUI8(); + switch (filterId) { + case 0: + return readDROPSHADOWFILTER(); + case 1: + return readBLURFILTER(); + case 2: + return readGLOWFILTER(); + case 3: + return readBEVELFILTER(); + case 4: + return readGRADIENTGLOWFILTER(); + case 5: + return readCONVOLUTIONFILTER(); + case 6: + return readCOLORMATRIXFILTER(); + case 7: + return readGRADIENTBEVELFILTER(); + default: + return null; + } + } + + /** + * Reads list of BUTTONRECORD values from the stream + * + * @param inDefineButton2 Whether read from inside of DefineButton2Tag or + * not + * @return List of BUTTONRECORD values + * @throws IOException + */ + public List readBUTTONRECORDList(boolean inDefineButton2) throws IOException { + List ret = new ArrayList<>(); + BUTTONRECORD br; + while ((br = readBUTTONRECORD(inDefineButton2)) != null) { + ret.add(br); + } + return ret; + } + + /** + * Reads one BUTTONRECORD value from the stream + * + * @param inDefineButton2 True when in DefineButton2 + * @return BUTTONRECORD value + * @throws IOException + */ + public BUTTONRECORD readBUTTONRECORD(boolean inDefineButton2) throws IOException { + BUTTONRECORD ret = new BUTTONRECORD(); + ret.reserved = (int) readUB(2); + ret.buttonHasBlendMode = readUB(1) == 1; + ret.buttonHasFilterList = readUB(1) == 1; + ret.buttonStateHitTest = readUB(1) == 1; + ret.buttonStateDown = readUB(1) == 1; + ret.buttonStateOver = readUB(1) == 1; + ret.buttonStateUp = readUB(1) == 1; + + if (!ret.buttonHasBlendMode && !ret.buttonHasFilterList + && !ret.buttonStateHitTest && !ret.buttonStateDown + && !ret.buttonStateOver && !ret.buttonStateUp && ret.reserved == 0) { + return null; + } + + ret.characterId = readUI16(); + ret.placeDepth = readUI16(); + ret.placeMatrix = readMatrix(); + if (inDefineButton2) { + ret.colorTransform = readCXFORMWITHALPHA(); + if (ret.buttonHasFilterList) { + ret.filterList = readFILTERLIST(); + } + if (ret.buttonHasBlendMode) { + ret.blendMode = readUI8(); + } + } + return ret; + } + + /** + * Reads list of BUTTONCONDACTION values from the stream + * + * @param swf + * @param tag + * @return List of BUTTONCONDACTION values + * @throws IOException + */ + public List readBUTTONCONDACTIONList(SWF swf, Tag tag) throws IOException { + List ret = new ArrayList<>(); + BUTTONCONDACTION bc; + while (!(bc = readBUTTONCONDACTION(swf, tag)).isLast) { + ret.add(bc); + } + ret.add(bc); + return ret; + } + + /** + * Reads one BUTTONCONDACTION value from the stream + * + * @param swf + * @param tag + * @return BUTTONCONDACTION value + * @throws IOException + */ + public BUTTONCONDACTION readBUTTONCONDACTION(SWF swf, Tag tag) throws IOException { + BUTTONCONDACTION ret = new BUTTONCONDACTION(swf, this, getPos(), tag); + //ret.actions = readActionList(); + return ret; + } + + /** + * Reads one GRADRECORD value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return GRADRECORD value + * @throws IOException + */ + public GRADRECORD readGRADRECORD(int shapeNum) throws IOException { + GRADRECORD ret = new GRADRECORD(); + ret.ratio = readUI8(); + if (shapeNum >= 3) { + ret.color = readRGBA(); + } else { + ret.color = readRGB(); + } + return ret; + } + + /** + * Reads one GRADIENT value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return GRADIENT value + * @throws IOException + */ + public GRADIENT readGRADIENT(int shapeNum) throws IOException { + GRADIENT ret = new GRADIENT(); + ret.spreadMode = (int) readUB(2); + ret.interpolationMode = (int) readUB(2); + int numGradients = (int) readUB(4); + ret.gradientRecords = new GRADRECORD[numGradients]; + for (int i = 0; i < numGradients; i++) { + ret.gradientRecords[i] = readGRADRECORD(shapeNum); + + } + return ret; + } + + /** + * Reads one FOCALGRADIENT value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return FOCALGRADIENT value + * @throws IOException + */ + public FOCALGRADIENT readFOCALGRADIENT(int shapeNum) throws IOException { + FOCALGRADIENT ret = new FOCALGRADIENT(); + ret.spreadMode = (int) readUB(2); + ret.interpolationMode = (int) readUB(2); + int numGradients = (int) readUB(4); + ret.gradientRecords = new GRADRECORD[numGradients]; + for (int i = 0; i < numGradients; i++) { + ret.gradientRecords[i] = readGRADRECORD(shapeNum); + } + ret.focalPoint = readFIXED8(); + return ret; + } + + /** + * Reads one FILLSTYLE value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return FILLSTYLE value + * @throws IOException + */ + public FILLSTYLE readFILLSTYLE(int shapeNum) throws IOException { + FILLSTYLE ret = new FILLSTYLE(); + ret.fillStyleType = readUI8(); + if (ret.fillStyleType == FILLSTYLE.SOLID) { + if (shapeNum >= 3) { + ret.color = readRGBA(); + } else { + ret.color = readRGB(); + } + } + if ((ret.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) + || (ret.fillStyleType == FILLSTYLE.RADIAL_GRADIENT) + || (ret.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT)) { + ret.gradientMatrix = readMatrix(); + } + if ((ret.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) + || (ret.fillStyleType == FILLSTYLE.RADIAL_GRADIENT)) { + ret.gradient = readGRADIENT(shapeNum); + } + if (ret.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT) { + ret.gradient = readFOCALGRADIENT(shapeNum); + } + + if ((ret.fillStyleType == FILLSTYLE.REPEATING_BITMAP) + || (ret.fillStyleType == FILLSTYLE.CLIPPED_BITMAP) + || (ret.fillStyleType == FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) + || (ret.fillStyleType == FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { + ret.bitmapId = readUI16(); + ret.bitmapMatrix = readMatrix(); + } + return ret; + } + + /** + * Reads one FILLSTYLEARRAY value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return FILLSTYLEARRAY value + * @throws IOException + */ + public FILLSTYLEARRAY readFILLSTYLEARRAY(int shapeNum) throws IOException { + + FILLSTYLEARRAY ret = new FILLSTYLEARRAY(); + int fillStyleCount = readUI8(); + if (((shapeNum == 2) || (shapeNum == 3) || (shapeNum == 4/*?*/)) && (fillStyleCount == 0xff)) { + fillStyleCount = readUI16(); + } + ret.fillStyles = new FILLSTYLE[fillStyleCount]; + for (int i = 0; i < fillStyleCount; i++) { + ret.fillStyles[i] = readFILLSTYLE(shapeNum); + } + return ret; + } + + /** + * Reads one LINESTYLE value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return LINESTYLE value + * @throws IOException + */ + public LINESTYLE readLINESTYLE(int shapeNum) throws IOException { + LINESTYLE ret = new LINESTYLE(); + ret.width = readUI16(); + if ((shapeNum == 1) || (shapeNum == 2)) { + ret.color = readRGB(); + } + if (shapeNum == 3) { + ret.color = readRGBA(); + } + return ret; + } + + /** + * Reads one LINESTYLE2 value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return LINESTYLE2 value + * @throws IOException + */ + public LINESTYLE2 readLINESTYLE2(int shapeNum) throws IOException { + LINESTYLE2 ret = new LINESTYLE2(); + ret.width = readUI16(); + ret.startCapStyle = (int) readUB(2); + ret.joinStyle = (int) readUB(2); + ret.hasFillFlag = (int) readUB(1) == 1; + ret.noHScaleFlag = (int) readUB(1) == 1; + ret.noVScaleFlag = (int) readUB(1) == 1; + ret.pixelHintingFlag = (int) readUB(1) == 1; + ret.reserved = (int) readUB(5); + ret.noClose = (int) readUB(1) == 1; + ret.endCapStyle = (int) readUB(2); + if (ret.joinStyle == LINESTYLE2.MITER_JOIN) { + ret.miterLimitFactor = readUI16(); + } + if (!ret.hasFillFlag) { + ret.color = readRGBA(); + } else { + ret.fillType = readFILLSTYLE(shapeNum); + } + return ret; + } + + /** + * Reads one LINESTYLEARRAY value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return LINESTYLEARRAY value + * @throws IOException + */ + public LINESTYLEARRAY readLINESTYLEARRAY(int shapeNum) throws IOException { + LINESTYLEARRAY ret = new LINESTYLEARRAY(); + int lineStyleCount = readUI8(); + if (lineStyleCount == 0xff) { + lineStyleCount = readUI16(); + } + if ((shapeNum == 1 || shapeNum == 2 || shapeNum == 3)) { + ret.lineStyles = new LINESTYLE[lineStyleCount]; + for (int i = 0; i < lineStyleCount; i++) { + ret.lineStyles[i] = readLINESTYLE(shapeNum); + } + } else if (shapeNum == 4) { + ret.lineStyles = new LINESTYLE2[lineStyleCount]; + for (int i = 0; i < lineStyleCount; i++) { + ret.lineStyles[i] = readLINESTYLE2(shapeNum); + } + } + return ret; + } + + /** + * Reads one SHAPERECORD value from the stream + * + * @param fillBits + * @param lineBits + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @return SHAPERECORD value + * @throws IOException + */ + private SHAPERECORD readSHAPERECORD(int fillBits, int lineBits, int shapeNum, boolean morphShape) throws IOException { + SHAPERECORD ret; + int typeFlag = (int) readUB(1); + if (typeFlag == 0) { + boolean stateNewStyles = readUB(1) == 1; + boolean stateLineStyle = readUB(1) == 1; + boolean stateFillStyle1 = readUB(1) == 1; + boolean stateFillStyle0 = readUB(1) == 1; + boolean stateMoveTo = readUB(1) == 1; + if ((!stateNewStyles) && (!stateLineStyle) && (!stateFillStyle1) && (!stateFillStyle0) && (!stateMoveTo)) { + ret = new EndShapeRecord(); + } else { + StyleChangeRecord scr = new StyleChangeRecord(); + scr.stateNewStyles = stateNewStyles; + scr.stateLineStyle = stateLineStyle; + scr.stateFillStyle0 = stateFillStyle0; + scr.stateFillStyle1 = stateFillStyle1; + scr.stateMoveTo = stateMoveTo; + if (stateMoveTo) { + scr.moveBits = (int) readUB(5); + scr.moveDeltaX = (int) readSB(scr.moveBits); + scr.moveDeltaY = (int) readSB(scr.moveBits); + } + if (stateFillStyle0) { + scr.fillStyle0 = (int) readUB(fillBits); + } + if (stateFillStyle1) { + scr.fillStyle1 = (int) readUB(fillBits); + } + if (stateLineStyle) { + scr.lineStyle = (int) readUB(lineBits); + } + if (stateNewStyles) { + if (morphShape) { + //This should never happen + } else { + scr.fillStyles = readFILLSTYLEARRAY(shapeNum); + scr.lineStyles = readLINESTYLEARRAY(shapeNum); + } + scr.numFillBits = (int) readUB(4); + scr.numLineBits = (int) readUB(4); + } + ret = scr; + } + } else {//typeFlag==1 + int straightFlag = (int) readUB(1); + if (straightFlag == 1) { + StraightEdgeRecord ser = new StraightEdgeRecord(); + ser.numBits = (int) readUB(4); + ser.generalLineFlag = readUB(1) == 1; + if (!ser.generalLineFlag) { + ser.vertLineFlag = readUB(1) == 1; + } + if (ser.generalLineFlag || (!ser.vertLineFlag)) { + ser.deltaX = (int) readSB(ser.numBits + 2); + } + if (ser.generalLineFlag || (ser.vertLineFlag)) { + ser.deltaY = (int) readSB(ser.numBits + 2); + } + ret = ser; + } else { + CurvedEdgeRecord cer = new CurvedEdgeRecord(); + cer.numBits = (int) readUB(4); + cer.controlDeltaX = (int) readSB(cer.numBits + 2); + cer.controlDeltaY = (int) readSB(cer.numBits + 2); + cer.anchorDeltaX = (int) readSB(cer.numBits + 2); + cer.anchorDeltaY = (int) readSB(cer.numBits + 2); + ret = cer; + } + } + return ret; + } + + /** + * Reads one SHAPE value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @param morphShape + * @return SHAPE value + * @throws IOException + */ + public SHAPE readSHAPE(int shapeNum, boolean morphShape) throws IOException { + SHAPE ret = new SHAPE(); + ret.numFillBits = (int) readUB(4); + ret.numLineBits = (int) readUB(4); + ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits, morphShape); + return ret; + } + + /** + * Reads one SHAPEWITHSTYLE value from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @param morphShape + * @return SHAPEWITHSTYLE value + * @throws IOException + */ + public SHAPEWITHSTYLE readSHAPEWITHSTYLE(int shapeNum, boolean morphShape) throws IOException { + SHAPEWITHSTYLE ret = new SHAPEWITHSTYLE(); + ret.fillStyles = readFILLSTYLEARRAY(shapeNum); + ret.lineStyles = readLINESTYLEARRAY(shapeNum); + ret.numFillBits = (int) readUB(4); + ret.numLineBits = (int) readUB(4); + ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits, morphShape); + return ret; + } + + /** + * Reads list of SHAPERECORDs from the stream + * + * @param shapeNum 1 in DefineShape, 2 in DefineShape2... + * @param fillBits + * @param lineBits + * @return SHAPERECORDs array + * @throws IOException + */ + private List readSHAPERECORDS(int shapeNum, int fillBits, int lineBits, boolean morphShape) throws IOException { + List ret = new ArrayList<>(); + SHAPERECORD rec; + do { + rec = readSHAPERECORD(fillBits, lineBits, shapeNum, morphShape); + if (rec instanceof StyleChangeRecord) { + StyleChangeRecord scRec = (StyleChangeRecord) rec; + if (scRec.stateNewStyles) { + fillBits = scRec.numFillBits; + lineBits = scRec.numLineBits; + } + } + ret.add(rec); + } while (!(rec instanceof EndShapeRecord)); + alignByte(); + return ret; + } + + /** + * Reads one SOUNDINFO value from the stream + * + * @return SOUNDINFO value + * @throws IOException + */ + public SOUNDINFO readSOUNDINFO() throws IOException { + SOUNDINFO ret = new SOUNDINFO(); + ret.reserved = (int) readUB(2); + ret.syncStop = readUB(1) == 1; + ret.syncNoMultiple = readUB(1) == 1; + ret.hasEnvelope = readUB(1) == 1; + ret.hasLoops = readUB(1) == 1; + ret.hasOutPoint = readUB(1) == 1; + ret.hasInPoint = readUB(1) == 1; + if (ret.hasInPoint) { + ret.inPoint = readUI32(); + } + if (ret.hasOutPoint) { + ret.outPoint = readUI32(); + } + if (ret.hasLoops) { + ret.loopCount = readUI16(); + } + if (ret.hasEnvelope) { + int envPoints = readUI8(); + ret.envelopeRecords = new SOUNDENVELOPE[envPoints]; + for (int i = 0; i < envPoints; i++) { + ret.envelopeRecords[i] = readSOUNDENVELOPE(); + } + } + return ret; + } + + /** + * Reads one SOUNDENVELOPE value from the stream + * + * @return SOUNDENVELOPE value + * @throws IOException + */ + public SOUNDENVELOPE readSOUNDENVELOPE() throws IOException { + SOUNDENVELOPE ret = new SOUNDENVELOPE(); + ret.pos44 = readUI32(); + ret.leftLevel = readUI16(); + ret.rightLevel = readUI16(); + return ret; + } + + /** + * Reads one GLYPHENTRY value from the stream + * + * @param glyphBits + * @param advanceBits + * @return GLYPHENTRY value + * @throws IOException + */ + public GLYPHENTRY readGLYPHENTRY(int glyphBits, int advanceBits) throws IOException { + GLYPHENTRY ret = new GLYPHENTRY(); + ret.glyphIndex = (int) readUB(glyphBits); + ret.glyphAdvance = (int) readUB(advanceBits); + return ret; + } + + /** + * Reads one TEXTRECORD value from the stream + * + * @param inDefineText2 + * @param glyphBits + * @param advanceBits + * @return TEXTRECORD value + * @throws IOException + */ + public TEXTRECORD readTEXTRECORD(boolean inDefineText2, int glyphBits, int advanceBits) throws IOException { + TEXTRECORD ret = new TEXTRECORD(); + int first = (int) readUB(1); //always 1 + readUB(3); //always 0 + ret.styleFlagsHasFont = readUB(1) == 1; + ret.styleFlagsHasColor = readUB(1) == 1; + ret.styleFlagsHasYOffset = readUB(1) == 1; + ret.styleFlagsHasXOffset = readUB(1) == 1; + if ((!ret.styleFlagsHasFont) && (!ret.styleFlagsHasColor) && (!ret.styleFlagsHasYOffset) && (!ret.styleFlagsHasXOffset) && (first == 0)) { //final text record + return null; + } + if (ret.styleFlagsHasFont) { + ret.fontId = readUI16(); + } + if (ret.styleFlagsHasColor) { + if (inDefineText2) { + ret.textColorA = readRGBA(); + } else { + ret.textColor = readRGB(); + } + } + if (ret.styleFlagsHasXOffset) { + ret.xOffset = readSI16(); + } + if (ret.styleFlagsHasYOffset) { + ret.yOffset = readSI16(); + } + if (ret.styleFlagsHasFont) { + ret.textHeight = readUI16(); + } + int glyphCount = readUI8(); + ret.glyphEntries = new GLYPHENTRY[glyphCount]; + for (int i = 0; i < glyphCount; i++) { + ret.glyphEntries[i] = readGLYPHENTRY(glyphBits, advanceBits); + } + alignByte(); + return ret; + } + + /** + * Reads one MORPHGRADRECORD value from the stream + * + * @return MORPHGRADRECORD value + * @throws IOException + */ + public MORPHGRADRECORD readMORPHGRADRECORD() throws IOException { + MORPHGRADRECORD ret = new MORPHGRADRECORD(); + ret.startRatio = readUI8(); + ret.startColor = readRGBA(); + ret.endRatio = readUI8(); + ret.endColor = readRGBA(); + return ret; + } + + /** + * Reads one MORPHGRADIENT value from the stream + * + * @return MORPHGRADIENT value + * @throws IOException + */ + public MORPHGRADIENT readMORPHGRADIENT() throws IOException { + MORPHGRADIENT ret = new MORPHGRADIENT(); + //Despite of documentation (UI8 1-8), there are two fields + // spreadMode and interPolationMode which are same as in GRADIENT + ret.spreadMode = (int) readUB(2); + ret.interPolationMode = (int) readUB(2); + int numGradients = (int) readUB(4); + ret.gradientRecords = new MORPHGRADRECORD[numGradients]; + for (int i = 0; i < numGradients; i++) { + ret.gradientRecords[i] = readMORPHGRADRECORD(); + } + return ret; + } + + /** + * Reads one MORPHFOCALGRADIENT value from the stream + * + * This is undocumented feature + * + * @return MORPHGRADIENT value + * @throws IOException + */ + public MORPHFOCALGRADIENT readMORPHFOCALGRADIENT() throws IOException { + MORPHFOCALGRADIENT ret = new MORPHFOCALGRADIENT(); + ret.spreadMode = (int) readUB(2); + ret.interPolationMode = (int) readUB(2); + int numGradients = (int) readUB(4); + ret.gradientRecords = new MORPHGRADRECORD[numGradients]; + for (int i = 0; i < numGradients; i++) { + ret.gradientRecords[i] = readMORPHGRADRECORD(); + } + ret.startFocalPoint = readFIXED8(); + ret.endFocalPoint = readFIXED8(); + return ret; + } + + /** + * Reads one MORPHFILLSTYLE value from the stream + * + * @return MORPHFILLSTYLE value + * @throws IOException + */ + public MORPHFILLSTYLE readMORPHFILLSTYLE() throws IOException { + MORPHFILLSTYLE ret = new MORPHFILLSTYLE(); + ret.fillStyleType = readUI8(); + if (ret.fillStyleType == MORPHFILLSTYLE.SOLID) { + ret.startColor = readRGBA(); + ret.endColor = readRGBA(); + } + if ((ret.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) + || (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT) + || (ret.fillStyleType == MORPHFILLSTYLE.FOCAL_RADIAL_GRADIENT)) { + ret.startGradientMatrix = readMatrix(); + ret.endGradientMatrix = readMatrix(); + } + if ((ret.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) + || (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) { + ret.gradient = readMORPHGRADIENT(); + } + if (ret.fillStyleType == MORPHFILLSTYLE.FOCAL_RADIAL_GRADIENT) { + ret.gradient = readMORPHFOCALGRADIENT(); + } + + if ((ret.fillStyleType == MORPHFILLSTYLE.REPEATING_BITMAP) + || (ret.fillStyleType == MORPHFILLSTYLE.CLIPPED_BITMAP) + || (ret.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) + || (ret.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { + ret.bitmapId = readUI16(); + ret.startBitmapMatrix = readMatrix(); + ret.endBitmapMatrix = readMatrix(); + } + return ret; + } + + /** + * Reads one MORPHFILLSTYLEARRAY value from the stream + * + * @return MORPHFILLSTYLEARRAY value + * @throws IOException + */ + public MORPHFILLSTYLEARRAY readMORPHFILLSTYLEARRAY() throws IOException { + + MORPHFILLSTYLEARRAY ret = new MORPHFILLSTYLEARRAY(); + int fillStyleCount = readUI8(); + if (fillStyleCount == 0xff) { + fillStyleCount = readUI16(); + } + ret.fillStyles = new MORPHFILLSTYLE[fillStyleCount]; + for (int i = 0; i < fillStyleCount; i++) { + ret.fillStyles[i] = readMORPHFILLSTYLE(); + } + return ret; + } + + /** + * Reads one MORPHLINESTYLE value from the stream + * + * @return MORPHLINESTYLE value + * @throws IOException + */ + public MORPHLINESTYLE readMORPHLINESTYLE() throws IOException { + MORPHLINESTYLE ret = new MORPHLINESTYLE(); + ret.startWidth = readUI16(); + ret.endWidth = readUI16(); + ret.startColor = readRGBA(); + ret.endColor = readRGBA(); + return ret; + } + + /** + * Reads one MORPHLINESTYLE2 value from the stream + * + * @return MORPHLINESTYLE2 value + * @throws IOException + */ + public MORPHLINESTYLE2 readMORPHLINESTYLE2() throws IOException { + MORPHLINESTYLE2 ret = new MORPHLINESTYLE2(); + ret.startWidth = readUI16(); + ret.endWidth = readUI16(); + ret.startCapStyle = (int) readUB(2); + ret.joinStyle = (int) readUB(2); + ret.hasFillFlag = (int) readUB(1) == 1; + ret.noHScaleFlag = (int) readUB(1) == 1; + ret.noVScaleFlag = (int) readUB(1) == 1; + ret.pixelHintingFlag = (int) readUB(1) == 1; + ret.reserved = (int) readUB(5); + ret.noClose = (int) readUB(1) == 1; + ret.endCapStyle = (int) readUB(2); + if (ret.joinStyle == LINESTYLE2.MITER_JOIN) { + ret.miterLimitFactor = readUI16(); + } + if (!ret.hasFillFlag) { + ret.startColor = readRGBA(); + ret.endColor = readRGBA(); + } else { + ret.fillType = readMORPHFILLSTYLE(); + } + return ret; + } + + /** + * Reads one MORPHLINESTYLEARRAY value from the stream + * + * @param morphShapeNum 1 on DefineMorphShape, 2 on DefineMorphShape2 + * @return MORPHLINESTYLEARRAY value + * @throws IOException + */ + public MORPHLINESTYLEARRAY readMORPHLINESTYLEARRAY(int morphShapeNum) throws IOException { + MORPHLINESTYLEARRAY ret = new MORPHLINESTYLEARRAY(); + int lineStyleCount = readUI8(); + if (lineStyleCount == 0xff) { + lineStyleCount = readUI16(); + } + if (morphShapeNum == 1) { + ret.lineStyles = new MORPHLINESTYLE[lineStyleCount]; + for (int i = 0; i < lineStyleCount; i++) { + ret.lineStyles[i] = readMORPHLINESTYLE(); + } + } else if (morphShapeNum == 2) { + ret.lineStyles2 = new MORPHLINESTYLE2[lineStyleCount]; + for (int i = 0; i < lineStyleCount; i++) { + ret.lineStyles2[i] = readMORPHLINESTYLE2(); + } + } + return ret; + } + + /** + * Reads one KERNINGRECORD value from the stream + * + * @param fontFlagsWideCodes + * @return KERNINGRECORD value + * @throws IOException + */ + public KERNINGRECORD readKERNINGRECORD(boolean fontFlagsWideCodes) throws IOException { + KERNINGRECORD ret = new KERNINGRECORD(); + if (fontFlagsWideCodes) { + ret.fontKerningCode1 = readUI16(); + ret.fontKerningCode2 = readUI16(); + } else { + ret.fontKerningCode1 = readUI8(); + ret.fontKerningCode2 = readUI8(); + } + ret.fontKerningAdjustment = readSI16(); + return ret; + } + + /** + * Reads one LANGCODE value from the stream + * + * @return LANGCODE value + * @throws IOException + */ + public LANGCODE readLANGCODE() throws IOException { + LANGCODE ret = new LANGCODE(); + ret.languageCode = readUI8(); + return ret; + } + + /** + * Reads one ZONERECORD value from the stream + * + * @return ZONERECORD value + * @throws IOException + */ + public ZONERECORD readZONERECORD() throws IOException { + ZONERECORD ret = new ZONERECORD(); + int numZoneData = readUI8(); + ret.zonedata = new ZONEDATA[numZoneData]; + for (int i = 0; i < numZoneData; i++) { + ret.zonedata[i] = readZONEDATA(); + } + readUB(6); + ret.zoneMaskY = readUB(1) == 1; + ret.zoneMaskX = readUB(1) == 1; + return ret; + } + + /** + * Reads one ZONEDATA value from the stream + * + * @return ZONEDATA value + * @throws IOException + */ + public ZONEDATA readZONEDATA() throws IOException { + ZONEDATA ret = new ZONEDATA(); + ret.alignmentCoordinate = readUI16(); + ret.range = readUI16(); + return ret; + } + + /** + * Reads one PIX15 value from the stream + * + * @return PIX15 value + * @throws IOException + */ + public PIX15 readPIX15() throws IOException { + PIX15 ret = new PIX15(); + readUB(1); + ret.red = (int) readUB(5); + ret.green = (int) readUB(5); + ret.blue = (int) readUB(5); + return ret; + } + + /** + * Reads one PIX24 value from the stream + * + * @return PIX24 value + * @throws IOException + */ + public PIX24 readPIX24() throws IOException { + PIX24 ret = new PIX24(); + ret.reserved = readUI8(); + ret.red = readUI8(); + ret.green = readUI8(); + ret.blue = readUI8(); + return ret; + } + + /** + * Reads one COLORMAPDATA value from the stream + * + * @param colorTableSize + * @param bitmapWidth + * @param bitmapHeight + * @return COLORMAPDATA value + * @throws IOException + */ + public COLORMAPDATA readCOLORMAPDATA(int colorTableSize, int bitmapWidth, int bitmapHeight) throws IOException { + COLORMAPDATA ret = new COLORMAPDATA(); + ret.colorTableRGB = new RGB[colorTableSize + 1]; + for (int i = 0; i < colorTableSize + 1; i++) { + ret.colorTableRGB[i] = readRGB(); + } + int dataLen = 0; + for (int y = 0; y < bitmapHeight; y++) { + int x = 0; + for (; x < bitmapWidth; x++) { + dataLen++; + } + while ((x % 4) != 0) { + dataLen++; + x++; + } + } + ret.colorMapPixelData = readBytesEx(dataLen); + return ret; + } + + /** + * Reads one BITMAPDATA value from the stream + * + * @param bitmapFormat + * @param bitmapWidth + * @param bitmapHeight + * @return COLORMAPDATA value + * @throws IOException + */ + public BITMAPDATA readBITMAPDATA(int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { + BITMAPDATA ret = new BITMAPDATA(); + List pix15 = new ArrayList<>(); + List pix24 = new ArrayList<>(); + int dataLen = 0; + for (int y = 0; y < bitmapHeight; y++) { + int x = 0; + for (; x < bitmapWidth; x++) { + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { + dataLen += 2; + pix15.add(readPIX15()); + } + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { + dataLen += 4; + pix24.add(readPIX24()); + } + } + while ((dataLen % 4) != 0) { + dataLen++; + readUI8(); + } + } + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { + ret.bitmapPixelDataPix15 = pix15.toArray(new PIX15[pix15.size()]); + } else if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { + ret.bitmapPixelDataPix24 = pix24.toArray(new PIX24[pix24.size()]); + } + return ret; + } + + /** + * Reads one BITMAPDATA value from the stream + * + * @param bitmapFormat + * @param bitmapWidth + * @param bitmapHeight + * @return COLORMAPDATA value + * @throws IOException + */ + public ALPHABITMAPDATA readALPHABITMAPDATA(int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { + ALPHABITMAPDATA ret = new ALPHABITMAPDATA(); + ret.bitmapPixelData = new ARGB[bitmapWidth * bitmapHeight]; + for (int y = 0; y < bitmapHeight; y++) { + for (int x = 0; x < bitmapWidth; x++) { + ret.bitmapPixelData[y * bitmapWidth + x] = readARGB(); + } + } + return ret; + } + + /** + * Reads one ALPHACOLORMAPDATA value from the stream + * + * @param colorTableSize + * @param bitmapWidth + * @param bitmapHeight + * @return ALPHACOLORMAPDATA value + * @throws IOException + */ + public ALPHACOLORMAPDATA readALPHACOLORMAPDATA(int colorTableSize, int bitmapWidth, int bitmapHeight) throws IOException { + ALPHACOLORMAPDATA ret = new ALPHACOLORMAPDATA(); + ret.colorTableRGB = new RGBA[colorTableSize + 1]; + for (int i = 0; i < colorTableSize + 1; i++) { + ret.colorTableRGB[i] = readRGBA(); + } + int dataLen = 0; + for (int y = 0; y < bitmapHeight; y++) { + int x = 0; + for (; x < bitmapWidth; x++) { + dataLen++; + } + while ((x % 4) != 0) { + dataLen++; + x++; + } + } + ret.colorMapPixelData = readBytesEx(dataLen); + return ret; + } + + public int available() throws IOException { + return is.available(); + } + + public long availableBits() throws IOException { + if (bitPos > 0) { + return available() * 8 + (8 - bitPos); + } + return available() * 8; + } + + public SeekableInputStream getBaseStream() { + return is; + } +} diff --git a/src/com/jpexs/decompiler/flash/SWFLimitedInputStream.java b/src/com/jpexs/decompiler/flash/SWFLimitedInputStream.java new file mode 100644 index 000000000..190ae9bba --- /dev/null +++ b/src/com/jpexs/decompiler/flash/SWFLimitedInputStream.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.tags.DefineButton2Tag; +import com.jpexs.decompiler.flash.tags.DefineSpriteTag; +import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; +import com.jpexs.decompiler.flash.types.BUTTONRECORD; +import com.jpexs.decompiler.flash.types.CLIPACTIONS; +import com.jpexs.decompiler.flash.types.CXFORM; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.RGB; +import com.jpexs.decompiler.flash.types.RGBA; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; +import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.TEXTRECORD; +import com.jpexs.decompiler.flash.types.ZONERECORD; +import com.jpexs.decompiler.flash.types.filters.FILTER; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class SWFLimitedInputStream { + + private SWFInputStream sis; + public SWF swf; + + public SWFLimitedInputStream(SWF swf, SWFInputStream sis, long limit) { + this.swf = swf; + this.sis = sis; + } + + public int available() throws IOException { + return sis.available(); + } + + public long readUB(int nBits) throws IOException { + return sis.readUB(nBits); + } + + public int readUI8() throws IOException { + return sis.readUI8(); + } + + public int readUI16() throws IOException { + return sis.readUI16(); + } + + public long readUI32() throws IOException { + return sis.readUI32(); + } + + public int readSI16() throws IOException { + return sis.readSI16(); + } + + public long readEncodedU32() throws IOException { + return sis.readEncodedU32(); + } + + public float readFLOAT() throws IOException { + return sis.readFLOAT(); + } + + public byte[] readBytesEx(long count) throws IOException { + return sis.readBytesEx(count); + } + + public byte[] readBytesZlib(long count) throws IOException { + return sis.readBytesZlib(count); + } + + public String readString() throws IOException { + return sis.readString(); + } + + public MATRIX readMatrix() throws IOException { + return sis.readMatrix(); + } + + public List readTagList(SWF swf, Timelined timelined, int level, boolean parallel, boolean skipUnusualTags, boolean parseTags, boolean gfx) throws IOException, InterruptedException { + return sis.readTagList(swf, timelined, level, parallel, skipUnusualTags, parseTags, gfx); + } + + public List readBUTTONRECORDList(boolean inDefineButton2) throws IOException { + return sis.readBUTTONRECORDList(inDefineButton2); + } + + public List readBUTTONCONDACTIONList(SWF swf, Tag tag) throws IOException { + return sis.readBUTTONCONDACTIONList(swf, tag); + } + + public CLIPACTIONS readCLIPACTIONS(SWF swf, Tag tag) throws IOException { + return sis.readCLIPACTIONS(swf, tag); + } + + public CXFORM readCXFORM() throws IOException { + return sis.readCXFORM(); + } + + public CXFORMWITHALPHA readCXFORMWITHALPHA() throws IOException { + return sis.readCXFORMWITHALPHA(); + } + + public List readFILTERLIST() throws IOException { + return sis.readFILTERLIST(); + } + + public LANGCODE readLANGCODE() throws IOException { + return sis.readLANGCODE(); + } + + public MORPHFILLSTYLEARRAY readMORPHFILLSTYLEARRAY() throws IOException { + return sis.readMORPHFILLSTYLEARRAY(); + } + + public MORPHLINESTYLEARRAY readMORPHLINESTYLEARRAY(int morphShapeNum) throws IOException { + return sis.readMORPHLINESTYLEARRAY(morphShapeNum); + } + + public RGB readRGB() throws IOException { + return sis.readRGB(); + } + + public RGBA readRGBA() throws IOException { + return sis.readRGBA(); + } + + public SHAPE readSHAPE(int shapeNum, boolean morphShape) throws IOException { + return sis.readSHAPE(shapeNum, morphShape); + } + + public SHAPEWITHSTYLE readSHAPEWITHSTYLE(int shapeNum, boolean morphShape) throws IOException { + return sis.readSHAPEWITHSTYLE(shapeNum, morphShape); + } + + public KERNINGRECORD readKERNINGRECORD(boolean fontFlagsWideCodes) throws IOException { + return sis.readKERNINGRECORD(fontFlagsWideCodes); + } + + public TEXTRECORD readTEXTRECORD(boolean inDefineText2, int glyphBits, int advanceBits) throws IOException { + return sis.readTEXTRECORD(inDefineText2, glyphBits, advanceBits); + } + + public RECT readRECT() throws IOException { + return sis.readRECT(); + } + + public SOUNDINFO readSOUNDINFO() throws IOException { + return sis.readSOUNDINFO(); + } + + public ZONERECORD readZONERECORD() throws IOException { + return sis.readZONERECORD(); + } + + public long getPos() { + return sis.getPos(); + } + + public InputStream getBaseStream() { + return sis.getBaseStream(); + } + +} diff --git a/src/com/jpexs/decompiler/flash/SWFOutputStream.java b/src/com/jpexs/decompiler/flash/SWFOutputStream.java index 9a2e84dad..ac4ff0092 100644 --- a/src/com/jpexs/decompiler/flash/SWFOutputStream.java +++ b/src/com/jpexs/decompiler/flash/SWFOutputStream.java @@ -1,1756 +1,1751 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; -import com.jpexs.decompiler.flash.types.ARGB; -import com.jpexs.decompiler.flash.types.BITMAPDATA; -import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; -import com.jpexs.decompiler.flash.types.BUTTONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONS; -import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; -import com.jpexs.decompiler.flash.types.CXFORM; -import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; -import com.jpexs.decompiler.flash.types.FILLSTYLE; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.FOCALGRADIENT; -import com.jpexs.decompiler.flash.types.GLYPHENTRY; -import com.jpexs.decompiler.flash.types.GRADIENT; -import com.jpexs.decompiler.flash.types.GRADRECORD; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.LINESTYLE; -import com.jpexs.decompiler.flash.types.LINESTYLE2; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADRECORD; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.PIX15; -import com.jpexs.decompiler.flash.types.PIX24; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.RGB; -import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; -import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import com.jpexs.decompiler.flash.types.TEXTRECORD; -import com.jpexs.decompiler.flash.types.ZONEDATA; -import com.jpexs.decompiler.flash.types.ZONERECORD; -import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.BLURFILTER; -import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER; -import com.jpexs.decompiler.flash.types.filters.CONVOLUTIONFILTER; -import com.jpexs.decompiler.flash.types.filters.DROPSHADOWFILTER; -import com.jpexs.decompiler.flash.types.filters.FILTER; -import com.jpexs.decompiler.flash.types.filters.GLOWFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTBEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTGLOWFILTER; -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -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.utf8.Utf8Helper; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.List; -import java.util.zip.Deflater; -import java.util.zip.DeflaterOutputStream; - -/** - * Class for writing data into SWF file - * - * @author JPEXS - */ -public class SWFOutputStream extends OutputStream { - - private final OutputStream os; - private final int version; - private long pos = 0; - private int bitPos = 0; - private int tempByte = 0; - - public long getPos() { - return pos; - } - - /** - * Constructor - * - * @param os OutputStream for writing data - * @param version Version of SWF - */ - public SWFOutputStream(OutputStream os, int version) { - this.version = version; - this.os = os; - } - - /** - * Writes byte to the stream - * - * @param b byte to write - * @throws IOException - */ - @Override - public void write(int b) throws IOException { - alignByte(); - os.write(b); - pos++; - } - - private void alignByte() throws IOException { - if (bitPos > 0) { - bitPos = 0; - write(tempByte); - tempByte = 0; - } - } - - /** - * Writes UI8 (Unsigned 8bit integer) value to the stream - * - * @param val UI8 value to write - * @throws IOException - */ - public void writeUI8(int val) throws IOException { - write(val); - } - - /** - * Writes String value to the stream - * - * @param value String value - * @throws IOException - */ - public void writeString(String value) throws IOException { - write(Utf8Helper.getBytes(value)); - write(0); - } - - /** - * Writes UI32 (Unsigned 32bit integer) value to the stream - * - * @param value UI32 value - * @throws IOException - */ - public void writeUI32(long value) throws IOException { - write((int) (value & 0xff)); - write((int) ((value >> 8) & 0xff)); - write((int) ((value >> 16) & 0xff)); - write((int) ((value >> 24) & 0xff)); - } - - /** - * Writes UI16 (Unsigned 16bit integer) value to the stream - * - * @param value UI16 value - * @throws IOException - */ - public void writeUI16(int value) throws IOException { - write((int) (value & 0xff)); - write((int) ((value >> 8) & 0xff)); - } - - /** - * Writes SI32 (Signed 32bit integer) value to the stream - * - * @param value SI32 value - * @throws IOException - */ - public void writeSI32(long value) throws IOException { - writeUI32(value); - } - - /** - * Writes SI16 (Signed 16bit integer) value to the stream - * - * @param value SI16 value - * @throws IOException - */ - public void writeSI16(int value) throws IOException { - writeUI16(value); - } - - /** - * Writes SI8 (Signed 8bit integer) value to the stream - * - * @param value SI8 value - * @throws IOException - */ - public void writeSI8(int value) throws IOException { - writeUI8(value); - } - - /** - * Writes FIXED (Fixed point 16.16) value to the stream - * - * @param value FIXED value - * @throws IOException - */ - public void writeFIXED(double value) throws IOException { - long valueLong = (long) (value * (1 << 16)); - int beforePoint = (int) valueLong >> 16; - - int afterPoint = (int) valueLong % (1 << 16); - writeUI16(afterPoint); - writeUI16(beforePoint); - } - - /** - * Writes FIXED8 (Fixed point 8.8) value to the stream - * - * @param value FIXED8 value - * @throws IOException - */ - public void writeFIXED8(float value) throws IOException { - int beforePoint = (int) getIntPart(value); - int afterPoint = (int) getIntPart((value + (value < 0 ? beforePoint : -beforePoint)) * 256); - writeUI8(afterPoint); - writeUI8(beforePoint); - } - - private void writeLong(long value) throws IOException { - byte[] writeBuffer = new byte[8]; - writeBuffer[3] = (byte) (value >>> 56); - writeBuffer[2] = (byte) (value >>> 48); - writeBuffer[1] = (byte) (value >>> 40); - writeBuffer[0] = (byte) (value >>> 32); - writeBuffer[7] = (byte) (value >>> 24); - writeBuffer[6] = (byte) (value >>> 16); - writeBuffer[5] = (byte) (value >>> 8); - writeBuffer[4] = (byte) (value); - write(writeBuffer); - } - - /** - * Writes DOUBLE (double precision floating point value) value to the stream - * - * @param value DOUBLE value - * @throws IOException - */ - public void writeDOUBLE(double value) throws IOException { - writeLong(Double.doubleToLongBits(value)); - } - - /** - * Writes FLOAT (single precision floating point value) value to the stream - * - * @param value FLOAT value - * @throws IOException - */ - public void writeFLOAT(float value) throws IOException { - writeUI32(Float.floatToIntBits(value)); - } - - /** - * Writes FLOAT16 (16bit floating point value) value to the stream - * - * @param value FLOAT16 value - * @throws IOException - */ - public void writeFLOAT16(float value) throws IOException { - int bits = Float.floatToRawIntBits(value); - int sign = bits >> 31; - int exponent = (bits >> 22) & 0xff; - int mantisa = bits & 0x3FFFFF; - mantisa >>= 13; - writeUI16((sign << 15) + (exponent << 10) + mantisa); - } - - /** - * Writes EncodedU32 (Encoded unsigned 32bit value) value to the stream - * - * @param value U32 value - * @throws IOException - */ - public void writeEncodedU32(long value) throws IOException { - boolean loop = true; - value &= 0xFFFFFFFF; - do { - int ret = (int) (value & 0x7F); - if (value < 0x80) { - loop = false; - } - if (value > 0x7F) { - ret += 0x80; - } - write(ret); - value >>= 7; - } while (loop); - } - - /** - * Flushes data to underlying stream - * - * @throws IOException - */ - @Override - public void flush() throws IOException { - if (bitPos > 0) { - bitPos = 0; - write(tempByte); - tempByte = 0; - } - os.flush(); - } - - /** - * Closes the stream - * - * @throws IOException - */ - @Override - public void close() throws IOException { - flush(); - os.close(); - } - - /** - * Writes UB[nBits] (Unsigned-bit value) value to the stream - * - * @param nBits Number of bits which represent value - * @param value Unsigned value to write - * @throws IOException - */ - public void writeUB(int nBits, long value) throws IOException { - for (int bit = 0; bit < nBits; bit++) { - int nb = (int) ((value >> (nBits - 1 - bit)) & 1); - tempByte += nb * (1 << (7 - bitPos)); - bitPos++; - if (bitPos == 8) { - bitPos = 0; - write(tempByte); - tempByte = 0; - } - } - } - - /** - * Writes SB[nBits] (Signed-bit value) value to the stream - * - * @param nBits Number of bits which represent value - * @param value Signed value to write - * @throws IOException - */ - public void writeSB(int nBits, long value) throws IOException { - writeUB(nBits, value); - } - - /** - * Writes FB[nBits] (Signed fixed-point bit value) value to the stream - * - * @param nBits Number of bits which represent value - * @param value Double value to write - * @throws IOException - */ - public void writeFB(int nBits, double value) throws IOException { - if (nBits == 0) { - return; - } - long longVal = (long) (value * (1 << 16)); - writeSB(nBits, longVal); - } - - /** - * Writes RECT value to the stream - * - * @param value RECT value - * @throws IOException - */ - public void writeRECT(RECT value) throws IOException { - int nBits = 0; - int xMin = truncateTo31Bit(value.Xmin); - int xMax = truncateTo31Bit(value.Xmax); - int yMin = truncateTo31Bit(value.Ymin); - int yMax = truncateTo31Bit(value.Ymax); - nBits = enlargeBitCountS(nBits, xMin); - nBits = enlargeBitCountS(nBits, xMax); - nBits = enlargeBitCountS(nBits, yMin); - nBits = enlargeBitCountS(nBits, yMax); - writeUB(5, nBits); - writeSB(nBits, xMin); - writeSB(nBits, xMax); - writeSB(nBits, yMin); - writeSB(nBits, yMax); - alignByte(); - } - - private int truncateTo31Bit(int value) { - if (value > 0x3fffffff) { - value = 0x3fffffff; - } - if (value < -0x3fffffff) { - value = -0x3fffffff; - } - return value; - } - - /** - * Writes list of Tag values to the stream - * - * @param tags List of tag values - * @throws IOException - */ - public void writeTags(List tags) throws IOException { - for (Tag tag : tags) { - //try { - tag.writeTag(this); - /*} catch (NotSameException nse) { - throw new RuntimeException("error in tag "+tag+" at pos "+Helper.formatHex((int)tag.getPos(), 8), nse); - }*/ - //NotSameException must be processed in order to catch it elsewhere - } - } - - /** - * Calculates number of bits needed for representing unsigned value - * - * @param value Unsigned value - * @return Number of bits - */ - public static int getNeededBitsU(int value) { - value = Math.abs(value); - long x = 1; - int nBits; - - for (nBits = 1; nBits <= 64; nBits++) { - x <<= 1; - if (x > value) { - break; - } - } - return nBits; - } - - /** - * Calculates number of bits needed for representing signed value - * - * @param v Signed value - * @return Number of bits - */ - public static int getNeededBitsS(int v) { - int counter = 32; - int mask = 0x80000000; - final int val = (v < 0) ? -v : v; - while (((val & mask) == 0) && (counter > 0)) { - mask >>>= 1; - counter -= 1; - } - return counter + 1; - } - - /** - * Calculates number of bits needed for representing signed values - * - * @param first First Signed value - * @param params Next Signed values - * @return Number of bits - */ - public static int getNeededBitsS(int first, int... params) { - int nBits = 0; - nBits = enlargeBitCountS(nBits, first); - for (int i = 0; i < params.length; i++) { - nBits = enlargeBitCountS(nBits, params[i]); - } - return nBits; - } - - public static int getNeededBitsU(int first, int... params) { - int nBits = 0; - nBits = enlargeBitCountU(nBits, first); - for (int i = 0; i < params.length; i++) { - nBits = enlargeBitCountU(nBits, params[i]); - } - return nBits; - } - - private static long getIntPart(double value) { - if (value < 0) { - return (long) Math.ceil(value); - } - return (long) Math.floor(value); - } - - public static int unsignedSize(final int value) { - - final int val = (value < 0) ? -value - 1 : value; - int counter = 32; - int mask = 0x80000000; - - while (((val & mask) == 0) && (counter > 0)) { - mask >>>= 1; - counter -= 1; - } - return counter; - } - - /** - * Calculates number of bits needed for representing fixed-point value - * - * @param value Fixed-point value - * @return Number of bits - */ - public static int getNeededBitsF(float value) { - //0.26213074 16bits - //0.5 17bits - //1.3476715 18bits - int k = (int) value; - return getNeededBitsS(k) + 16; - } - - public static int enlargeBitCountS(int currentBitCount, int value) { - int neededNew = getNeededBitsS(value); - if (neededNew > currentBitCount) { - return neededNew; - } - return currentBitCount; - } - - public static int enlargeBitCountU(int currentBitCount, int value) { - int neededNew = getNeededBitsU(value); - if (neededNew > currentBitCount) { - return neededNew; - } - return currentBitCount; - } - - /** - * Writes MATRIX value to the stream - * - * @param value MATRIX value - * @throws IOException - */ - public void writeMatrix(MATRIX value) throws IOException { - writeUB(1, value.hasScale ? 1 : 0); - if (value.hasScale) { - int nBits = 0; - nBits = enlargeBitCountS(nBits, value.scaleX); - nBits = enlargeBitCountS(nBits, value.scaleY); - writeUB(5, nBits); - writeSB(nBits, value.scaleX); - writeSB(nBits, value.scaleY); - } - writeUB(1, value.hasRotate ? 1 : 0); - if (value.hasRotate) { - int nBits = 0; - nBits = enlargeBitCountS(nBits, value.rotateSkew0); - nBits = enlargeBitCountS(nBits, value.rotateSkew1); - writeUB(5, nBits); - writeSB(nBits, value.rotateSkew0); - writeSB(nBits, value.rotateSkew1); - } - int NTranslateBits = 0; - NTranslateBits = enlargeBitCountS(NTranslateBits, value.translateX); - NTranslateBits = enlargeBitCountS(NTranslateBits, value.translateY); - - writeUB(5, NTranslateBits); - - writeSB(NTranslateBits, value.translateX); - writeSB(NTranslateBits, value.translateY); - alignByte(); - - } - - /** - * Writes CXFORM value to the stream - * - * @param value CXFORM value - * @throws IOException - */ - public void writeCXFORM(CXFORM value) throws IOException { - writeUB(1, value.hasAddTerms ? 1 : 0); - writeUB(1, value.hasMultTerms ? 1 : 0); - int Nbits = 1; - if (value.hasMultTerms) { - Nbits = enlargeBitCountS(Nbits, value.redMultTerm); - Nbits = enlargeBitCountS(Nbits, value.greenMultTerm); - Nbits = enlargeBitCountS(Nbits, value.blueMultTerm); - } - if (value.hasAddTerms) { - Nbits = enlargeBitCountS(Nbits, value.redAddTerm); - Nbits = enlargeBitCountS(Nbits, value.greenAddTerm); - Nbits = enlargeBitCountS(Nbits, value.blueAddTerm); - } - writeUB(4, Nbits); - if (value.hasMultTerms) { - writeSB(Nbits, value.redMultTerm); - writeSB(Nbits, value.greenMultTerm); - writeSB(Nbits, value.blueMultTerm); - } - if (value.hasAddTerms) { - writeSB(Nbits, value.redAddTerm); - writeSB(Nbits, value.greenAddTerm); - writeSB(Nbits, value.blueAddTerm); - } - alignByte(); - } - - /** - * Writes CXFORMWITHALPHA value to the stream - * - * @param value CXFORMWITHALPHA value - * @throws IOException - */ - public void writeCXFORMWITHALPHA(CXFORMWITHALPHA value) throws IOException { - writeUB(1, value.hasAddTerms ? 1 : 0); - writeUB(1, value.hasMultTerms ? 1 : 0); - int Nbits = 1; - if (value.hasMultTerms) { - Nbits = enlargeBitCountS(Nbits, value.redMultTerm); - Nbits = enlargeBitCountS(Nbits, value.greenMultTerm); - Nbits = enlargeBitCountS(Nbits, value.blueMultTerm); - Nbits = enlargeBitCountS(Nbits, value.alphaMultTerm); - } - if (value.hasAddTerms) { - Nbits = enlargeBitCountS(Nbits, value.redAddTerm); - Nbits = enlargeBitCountS(Nbits, value.greenAddTerm); - Nbits = enlargeBitCountS(Nbits, value.blueAddTerm); - Nbits = enlargeBitCountS(Nbits, value.alphaAddTerm); - } - writeUB(4, Nbits); - if (value.hasMultTerms) { - writeSB(Nbits, value.redMultTerm); - writeSB(Nbits, value.greenMultTerm); - writeSB(Nbits, value.blueMultTerm); - writeSB(Nbits, value.alphaMultTerm); - } - if (value.hasAddTerms) { - writeSB(Nbits, value.redAddTerm); - writeSB(Nbits, value.greenAddTerm); - writeSB(Nbits, value.blueAddTerm); - writeSB(Nbits, value.alphaAddTerm); - } - alignByte(); - } - - /** - * Writes CLIPEVENTFLAGS value to the stream - * - * @param value CLIPEVENTFLAGS value - * @throws IOException - */ - public void writeCLIPEVENTFLAGS(CLIPEVENTFLAGS value) throws IOException { - writeUB(1, value.clipEventKeyUp ? 1 : 0); - writeUB(1, value.clipEventKeyDown ? 1 : 0); - writeUB(1, value.clipEventMouseUp ? 1 : 0); - writeUB(1, value.clipEventMouseDown ? 1 : 0); - writeUB(1, value.clipEventMouseMove ? 1 : 0); - writeUB(1, value.clipEventUnload ? 1 : 0); - writeUB(1, value.clipEventEnterFrame ? 1 : 0); - writeUB(1, value.clipEventLoad ? 1 : 0); - writeUB(1, value.clipEventDragOver ? 1 : 0); - writeUB(1, value.clipEventRollOut ? 1 : 0); - writeUB(1, value.clipEventRollOver ? 1 : 0); - writeUB(1, value.clipEventReleaseOutside ? 1 : 0); - writeUB(1, value.clipEventRelease ? 1 : 0); - writeUB(1, value.clipEventPress ? 1 : 0); - writeUB(1, value.clipEventInitialize ? 1 : 0); - writeUB(1, value.clipEventData ? 1 : 0); - if (version >= 6) { - writeUB(5, value.reserved); - writeUB(1, value.clipEventConstruct ? 1 : 0); - writeUB(1, value.clipEventKeyPress ? 1 : 0); - writeUB(1, value.clipEventDragOut ? 1 : 0); - writeUB(8, value.reserved2); - } - } - - /** - * Writes CLIPACTIONRECORD value to the stream - * - * @param value CLIPACTIONRECORD value - * @throws IOException - */ - public void writeCLIPACTIONRECORD(CLIPACTIONRECORD value) throws IOException { - writeCLIPEVENTFLAGS(value.eventFlags); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (SWFOutputStream sos = new SWFOutputStream(baos, version)) { - if (value.eventFlags.clipEventKeyPress) { - sos.writeUI8(value.keyCode); - } - sos.write(value.actionBytes); - } - byte[] data = baos.toByteArray(); - writeUI32(data.length); //actionRecordSize - write(data); - } - - /** - * Writes CLIPACTIONS value to the stream - * - * @param value CLIPACTIONS value - * @throws IOException - */ - public void writeCLIPACTIONS(CLIPACTIONS value) throws IOException { - writeUI16(value.reserved); - writeCLIPEVENTFLAGS(value.allEventFlags); - for (CLIPACTIONRECORD car : value.clipActionRecords) { - writeCLIPACTIONRECORD(car); - } - if (version <= 5) { - writeUI16(0); - } else { - writeUI32(0); - } - } - - /** - * Writes COLORMATRIXFILTER value to the stream - * - * @param value COLORMATRIXFILTER value - * @throws IOException - */ - public void writeCOLORMATRIXFILTER(COLORMATRIXFILTER value) throws IOException { - for (int i = 0; i < 20; i++) { - writeFLOAT(value.matrix[i]); - } - } - - /** - * Writes RGBA value to the stream - * - * @param value RGBA value - * @throws IOException - */ - public void writeRGBA(RGBA value) throws IOException { - writeUI8(value.red); - writeUI8(value.green); - writeUI8(value.blue); - writeUI8(value.alpha); - } - - /** - * Writes ARGB value to the stream - * - * @param value ARGB value - * @throws IOException - */ - public void writeARGB(ARGB value) throws IOException { - writeUI8(value.alpha); - writeUI8(value.red); - writeUI8(value.green); - writeUI8(value.blue); - } - - /** - * Writes RGB value to the stream - * - * @param value RGB value - * @throws IOException - */ - public void writeRGB(RGB value) throws IOException { - writeUI8(value.red); - writeUI8(value.green); - writeUI8(value.blue); - } - - /** - * Writes CONVOLUTIONFILTER value to the stream - * - * @param value CONVOLUTIONFILTER value - * @throws IOException - */ - public void writeCONVOLUTIONFILTER(CONVOLUTIONFILTER value) throws IOException { - writeUI8(value.matrixX); - writeUI8(value.matrixY); - writeFLOAT(value.divisor); - writeFLOAT(value.bias); - for (int x = 0; x < value.matrixX; x++) { - for (int y = 0; y < value.matrixY; y++) { - writeFLOAT(value.matrix[x][y]); - } - } - writeRGBA(value.defaultColor); - writeUB(6, value.reserved); - writeUB(1, value.clamp ? 1 : 0); - writeUB(1, value.preserveAlpha ? 1 : 0); - } - - /** - * Writes BLURFILTER value to the stream - * - * @param value BLURFILTER value - * @throws IOException - */ - public void writeBLURFILTER(BLURFILTER value) throws IOException { - writeFIXED(value.blurX); - writeFIXED(value.blurY); - writeUB(5, value.passes); - writeUB(3, value.reserved); - } - - /** - * Writes DROPSHADOWFILTER value to the stream - * - * @param value DROPSHADOWFILTER value - * @throws IOException - */ - public void writeDROPSHADOWFILTER(DROPSHADOWFILTER value) throws IOException { - writeRGBA(value.dropShadowColor); - writeFIXED(value.blurX); - writeFIXED(value.blurY); - writeFIXED(value.angle); - writeFIXED(value.distance); - writeFIXED8(value.strength); - writeUB(1, value.innerShadow ? 1 : 0); - writeUB(1, value.knockout ? 1 : 0); - writeUB(1, value.compositeSource ? 1 : 0); - writeUB(5, value.passes); - } - - /** - * Writes GLOWFILTER value to the stream - * - * @param value GLOWFILTER value - * @throws IOException - */ - public void writeGLOWFILTER(GLOWFILTER value) throws IOException { - writeRGBA(value.glowColor); - writeFIXED(value.blurX); - writeFIXED(value.blurY); - writeFIXED8(value.strength); - writeUB(1, value.innerGlow ? 1 : 0); - writeUB(1, value.knockout ? 1 : 0); - writeUB(1, value.compositeSource ? 1 : 0); - writeUB(5, value.passes); - } - - /** - * Writes BEVELFILTER value to the stream - * - * @param value BEVELFILTER value - * @throws IOException - */ - public void writeBEVELFILTER(BEVELFILTER value) throws IOException { - writeRGBA(value.highlightColor); - writeRGBA(value.shadowColor); - writeFIXED(value.blurX); - writeFIXED(value.blurY); - writeFIXED(value.angle); - writeFIXED(value.distance); - writeFIXED8(value.strength); - writeUB(1, value.innerShadow ? 1 : 0); - writeUB(1, value.knockout ? 1 : 0); - writeUB(1, value.compositeSource ? 1 : 0); - writeUB(1, value.onTop ? 1 : 0); - writeUB(4, value.passes); - } - - /** - * Writes GRADIENTGLOWFILTER value to the stream - * - * @param value GRADIENTGLOWFILTER value - * @throws IOException - */ - public void writeGRADIENTGLOWFILTER(GRADIENTGLOWFILTER value) throws IOException { - writeUI8(value.gradientColors.length); - for (int i = 0; i < value.gradientColors.length; i++) { - writeRGBA(value.gradientColors[i]); - } - for (int i = 0; i < value.gradientColors.length; i++) { - writeUI8(value.gradientRatio[i]); - } - writeFIXED(value.blurX); - writeFIXED(value.blurY); - writeFIXED(value.angle); - writeFIXED(value.distance); - writeFIXED8(value.strength); - writeUB(1, value.innerShadow ? 1 : 0); - writeUB(1, value.knockout ? 1 : 0); - writeUB(1, value.compositeSource ? 1 : 0); - writeUB(1, value.onTop ? 1 : 0); - writeUB(4, value.passes); - } - - /** - * Writes GRADIENTBEVELFILTER value to the stream - * - * @param value GRADIENTBEVELFILTER value - * @throws IOException - */ - public void writeGRADIENTBEVELFILTER(GRADIENTBEVELFILTER value) throws IOException { - writeUI8(value.gradientColors.length); - for (int i = 0; i < value.gradientColors.length; i++) { - writeRGBA(value.gradientColors[i]); - } - for (int i = 0; i < value.gradientColors.length; i++) { - writeUI8(value.gradientRatio[i]); - } - writeFIXED(value.blurX); - writeFIXED(value.blurY); - writeFIXED(value.angle); - writeFIXED(value.distance); - writeFIXED8(value.strength); - writeUB(1, value.innerShadow ? 1 : 0); - writeUB(1, value.knockout ? 1 : 0); - writeUB(1, value.compositeSource ? 1 : 0); - writeUB(1, value.onTop ? 1 : 0); - writeUB(4, value.passes); - } - - /** - * Writes list of FILTER values to the stream - * - * @param list List of FILTER values - * @throws IOException - */ - public void writeFILTERLIST(List list) throws IOException { - writeUI8(list.size()); - for (int i = 0; i < list.size(); i++) { - writeFILTER(list.get(i)); - } - } - - /** - * Writes FILTER value to the stream - * - * @param value FILTER value - * @throws IOException - */ - public void writeFILTER(FILTER value) throws IOException { - writeUI8(value.id); - if (value instanceof DROPSHADOWFILTER) { - writeDROPSHADOWFILTER((DROPSHADOWFILTER) value); - } - if (value instanceof BLURFILTER) { - writeBLURFILTER((BLURFILTER) value); - } - if (value instanceof GLOWFILTER) { - writeGLOWFILTER((GLOWFILTER) value); - } - if (value instanceof BEVELFILTER) { - writeBEVELFILTER((BEVELFILTER) value); - } - if (value instanceof GRADIENTGLOWFILTER) { - writeGRADIENTGLOWFILTER((GRADIENTGLOWFILTER) value); - } - if (value instanceof CONVOLUTIONFILTER) { - writeCONVOLUTIONFILTER((CONVOLUTIONFILTER) value); - } - if (value instanceof COLORMATRIXFILTER) { - writeCOLORMATRIXFILTER((COLORMATRIXFILTER) value); - } - if (value instanceof GRADIENTBEVELFILTER) { - writeGRADIENTBEVELFILTER((GRADIENTBEVELFILTER) value); - } - } - - /** - * Writes list of BUTTONRECORD values to the stream - * - * @param list List of BUTTONRECORD values - * @param inDefineButton2 Whether write inside of DefineButton2Tag or not - * @throws IOException - */ - public void writeBUTTONRECORDList(List list, boolean inDefineButton2) throws IOException { - for (BUTTONRECORD brec : list) { - writeBUTTONRECORD(brec, inDefineButton2); - } - writeUI8(0); - } - - /** - * Writes BUTTONRECORD value to the stream - * - * @param value BUTTONRECORD value - * @param inDefineButton2 Whether write inside of DefineButton2Tag or not - * @throws IOException - */ - public void writeBUTTONRECORD(BUTTONRECORD value, boolean inDefineButton2) throws IOException { - writeUB(2, value.reserved); - writeUB(1, value.buttonHasBlendMode ? 1 : 0); - writeUB(1, value.buttonHasFilterList ? 1 : 0); - writeUB(1, value.buttonStateHitTest ? 1 : 0); - writeUB(1, value.buttonStateDown ? 1 : 0); - writeUB(1, value.buttonStateOver ? 1 : 0); - writeUB(1, value.buttonStateUp ? 1 : 0); - writeUI16(value.characterId); - writeUI16(value.placeDepth); - writeMatrix(value.placeMatrix); - if (inDefineButton2) { - writeCXFORMWITHALPHA(value.colorTransform); - if (value.buttonHasFilterList) { - writeFILTERLIST(value.filterList); - } - if (value.buttonHasBlendMode) { - writeUI8(value.blendMode); - } - } - } - - /** - * Writes list of BUTTONCONDACTION values to the stream - * - * @param list List of BUTTONCONDACTION values - * @throws IOException - */ - public void writeBUTTONCONDACTIONList(List list) throws IOException { - for (int i = 0; i < list.size(); i++) { - writeBUTTONCONDACTION(list.get(i), i == list.size() - 1); - } - } - - /** - * Writes BUTTONCONDACTION value to the stream - * - * @param value BUTTONCONDACTION value - * @param isLast True if it is last on the list - * @throws IOException - */ - public void writeBUTTONCONDACTION(BUTTONCONDACTION value, boolean isLast) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (SWFOutputStream sos = new SWFOutputStream(baos, version)) { - sos.writeUB(1, value.condIdleToOverDown ? 1 : 0); - sos.writeUB(1, value.condOutDownToIdle ? 1 : 0); - sos.writeUB(1, value.condOutDownToOverDown ? 1 : 0); - sos.writeUB(1, value.condOverDownToOutDown ? 1 : 0); - sos.writeUB(1, value.condOverDownToOverUp ? 1 : 0); - sos.writeUB(1, value.condOverUpToOverDown ? 1 : 0); - sos.writeUB(1, value.condOverUpToIddle ? 1 : 0); - sos.writeUB(1, value.condIdleToOverUp ? 1 : 0); - sos.writeUB(7, value.condKeyPress); - sos.writeUB(1, value.condOverDownToIddle ? 1 : 0); - sos.write(value.actionBytes); - } - byte[] data = baos.toByteArray(); - if (isLast) { - writeUI16(0); - } else { - writeUI16(data.length + 2); - } - write(data); - } - - /** - * Writes FILLSTYLE value to the stream - * - * @param value FILLSTYLE value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeFILLSTYLE(FILLSTYLE value, int shapeNum) throws IOException { - writeUI8(value.fillStyleType); - if (value.fillStyleType == FILLSTYLE.SOLID) { - if (shapeNum >= 3) { - writeRGBA((RGBA) value.color); - } else if (shapeNum == 1 || shapeNum == 2) { - writeRGB(value.color); - } - } - if ((value.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) - || (value.fillStyleType == FILLSTYLE.RADIAL_GRADIENT) - || (value.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT)) { - writeMatrix(value.gradientMatrix); - } - if ((value.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) - || (value.fillStyleType == FILLSTYLE.RADIAL_GRADIENT)) { - writeGRADIENT(value.gradient, shapeNum); - } - if (value.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT) { - writeFOCALGRADIENT((FOCALGRADIENT) value.gradient, shapeNum); - } - - if ((value.fillStyleType == FILLSTYLE.REPEATING_BITMAP) - || (value.fillStyleType == FILLSTYLE.CLIPPED_BITMAP) - || (value.fillStyleType == FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) - || (value.fillStyleType == FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { - writeUI16(value.bitmapId); - writeMatrix(value.bitmapMatrix); - } - } - - /** - * Writes FILLSTYLEARRAY value to the stream - * - * @param value FILLSTYLEARRAY value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeFILLSTYLEARRAY(FILLSTYLEARRAY value, int shapeNum) throws IOException { - int fillStyleCount = value.fillStyles.length; - if (shapeNum == 2 || shapeNum == 3) { - if (fillStyleCount >= 0xff) { - writeUI8(0xff); - writeUI16(fillStyleCount); - } else { - writeUI8(fillStyleCount); - } - } else { - writeUI8(fillStyleCount); - } - for (int i = 0; i < value.fillStyles.length; i++) { - writeFILLSTYLE(value.fillStyles[i], shapeNum); - } - } - - /** - * Writes FOCALGRADIENT value to the stream - * - * @param value FILLSTYLEARRAY value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeFOCALGRADIENT(FOCALGRADIENT value, int shapeNum) throws IOException { - writeUB(2, value.spreadMode); - writeUB(2, value.interpolationMode); - writeUB(4, value.gradientRecords.length); - for (int i = 0; i < value.gradientRecords.length; i++) { - writeGRADRECORD(value.gradientRecords[i], shapeNum); - } - writeFIXED8(value.focalPoint); - } - - /** - * Writes GRADIENT value to the stream - * - * @param value GRADIENT value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeGRADIENT(GRADIENT value, int shapeNum) throws IOException { - writeUB(2, value.spreadMode); - writeUB(2, value.interpolationMode); - writeUB(4, value.gradientRecords.length); - for (int i = 0; i < value.gradientRecords.length; i++) { - writeGRADRECORD(value.gradientRecords[i], shapeNum); - } - } - - /** - * Writes GRADRECORD value to the stream - * - * @param value GRADRECORD value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeGRADRECORD(GRADRECORD value, int shapeNum) throws IOException { - writeUI8(value.ratio); - if (shapeNum == 1 || shapeNum == 2) { - writeRGB(value.color); - } else if (shapeNum == 3) { - writeRGBA((RGBA) value.color); - } - } - - /** - * Writes LINESTYLE value to the stream - * - * @param value LINESTYLE value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeLINESTYLE(LINESTYLE value, int shapeNum) throws IOException { - writeUI16(value.width); - if (shapeNum == 1 || shapeNum == 2) { - writeRGB(value.color); - } else if (shapeNum == 3) { - writeRGBA((RGBA) value.color); - } - } - - /** - * Writes LINESTYLE2 value to the stream - * - * @param value LINESTYLE2 value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeLINESTYLE2(LINESTYLE2 value, int shapeNum) throws IOException { - writeUI16(value.width); - writeUB(2, value.startCapStyle); - writeUB(2, value.joinStyle); - writeUB(1, value.hasFillFlag ? 1 : 0); - writeUB(1, value.noHScaleFlag ? 1 : 0); - writeUB(1, value.noVScaleFlag ? 1 : 0); - writeUB(1, value.pixelHintingFlag ? 1 : 0); - writeUB(5, value.reserved); - writeUB(1, value.noClose ? 1 : 0); - writeUB(2, value.endCapStyle); - if (value.joinStyle == LINESTYLE2.MITER_JOIN) { - writeUI16(value.miterLimitFactor); - } - if (!value.hasFillFlag) { - writeRGBA((RGBA) value.color); - } else { - writeFILLSTYLE(value.fillType, shapeNum); - } - } - - /** - * Writes LINESTYLEARRAY value to the stream - * - * @param value FILLSTYLEARRAY value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeLINESTYLEARRAY(LINESTYLEARRAY value, int shapeNum) throws IOException { - int lineStyleCount; - if (shapeNum == 1 || shapeNum == 2 || shapeNum == 3) { - lineStyleCount = value.lineStyles.length; - if (lineStyleCount >= 0xff) { - writeUI8(0xff); - writeUI16(lineStyleCount); - } else { - writeUI8(lineStyleCount); - } - for (int i = 0; i < lineStyleCount; i++) { - writeLINESTYLE(value.lineStyles[i], shapeNum); - } - } else if (shapeNum == 4) { - lineStyleCount = value.lineStyles.length; - if (lineStyleCount >= 0xff) { - writeUI8(0xff); - writeUI16(lineStyleCount); - } else { - writeUI8(lineStyleCount); - } - for (int i = 0; i < lineStyleCount; i++) { - writeLINESTYLE2((LINESTYLE2) value.lineStyles[i], shapeNum); - } - } - } - - /** - * Writes SHAPE value to the stream - * - * @param value SHAPE value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeSHAPE(SHAPE value, int shapeNum) throws IOException { - writeUB(4, value.numFillBits); - writeUB(4, value.numLineBits); - writeSHAPERECORDS(value.shapeRecords, value.numFillBits, value.numLineBits, shapeNum); - } - - /** - * Writes SHAPEWITHSTYLE value to the stream - * - * @param value SHAPEWITHSTYLE value - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - public void writeSHAPEWITHSTYLE(SHAPEWITHSTYLE value, int shapeNum) throws IOException { - writeFILLSTYLEARRAY(value.fillStyles, shapeNum); - writeLINESTYLEARRAY(value.lineStyles, shapeNum); - writeUB(4, value.numFillBits); - writeUB(4, value.numLineBits); - writeSHAPERECORDS(value.shapeRecords, value.numFillBits, value.numLineBits, shapeNum); - } - - /** - * Writes SHAPERECORDs value to the stream - * - * @param value SHAPERECORDS value - * @param fillBits - * @param lineBits - * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... - * @throws IOException - */ - private void writeSHAPERECORDS(List value, int fillBits, int lineBits, int shapeNum) throws IOException { - for (SHAPERECORD sh : value) { - if (sh instanceof CurvedEdgeRecord) { - CurvedEdgeRecord cer = (CurvedEdgeRecord) sh; - writeUB(1, 1); //typeFlag - writeUB(1, 0);//curvedEdge - writeUB(4, cer.numBits); - writeUB(cer.numBits + 2, cer.controlDeltaX); - writeUB(cer.numBits + 2, cer.controlDeltaY); - writeUB(cer.numBits + 2, cer.anchorDeltaX); - writeUB(cer.numBits + 2, cer.anchorDeltaY); - } else if (sh instanceof StraightEdgeRecord) { - StraightEdgeRecord ser = (StraightEdgeRecord) sh; - writeUB(1, 1); //typeFlag - writeUB(1, 1);//straightEdge - writeUB(4, ser.numBits); - writeUB(1, ser.generalLineFlag ? 1 : 0); - if (!ser.generalLineFlag) { - writeUB(1, ser.vertLineFlag ? 1 : 0); - } - if (ser.generalLineFlag || (!ser.vertLineFlag)) { - writeSB(ser.numBits + 2, ser.deltaX); - } - if (ser.generalLineFlag || ser.vertLineFlag) { - writeSB(ser.numBits + 2, ser.deltaY); - } - } else if (sh instanceof StyleChangeRecord) { - StyleChangeRecord scr = (StyleChangeRecord) sh; - writeUB(1, 0); //typeFlag - writeUB(1, scr.stateNewStyles ? 1 : 0); - writeUB(1, scr.stateLineStyle ? 1 : 0); - writeUB(1, scr.stateFillStyle1 ? 1 : 0); - writeUB(1, scr.stateFillStyle0 ? 1 : 0); - writeUB(1, scr.stateMoveTo ? 1 : 0); - if (scr.stateMoveTo) { - writeUB(5, scr.moveBits); - writeUB(scr.moveBits, scr.moveDeltaX); - writeUB(scr.moveBits, scr.moveDeltaY); - } - if (scr.stateFillStyle0) { - writeUB(fillBits, scr.fillStyle0); - } - if (scr.stateFillStyle1) { - writeUB(fillBits, scr.fillStyle1); - } - if (scr.stateLineStyle) { - writeUB(lineBits, scr.lineStyle); - } - if (scr.stateNewStyles) { - writeFILLSTYLEARRAY(scr.fillStyles, shapeNum); - writeLINESTYLEARRAY(scr.lineStyles, shapeNum); - writeUB(4, scr.numFillBits); - writeUB(4, scr.numLineBits); - } - - } else if (sh instanceof EndShapeRecord) { - writeUB(1, 0); //typeFlag - writeUB(5, 0); //end of shape flag - } - } - alignByte(); - } - - /** - * Writes SOUNDINFO value to the stream - * - * @param value SOUNDINFO value - * @throws IOException - */ - public void writeSOUNDINFO(SOUNDINFO value) throws IOException { - writeUB(2, value.reserved); - writeUB(1, value.syncStop ? 1 : 0); - writeUB(1, value.syncNoMultiple ? 1 : 0); - writeUB(1, value.hasEnvelope ? 1 : 0); - writeUB(1, value.hasLoops ? 1 : 0); - writeUB(1, value.hasOutPoint ? 1 : 0); - writeUB(1, value.hasInPoint ? 1 : 0); - if (value.hasInPoint) { - writeUI32(value.inPoint); - } - if (value.hasOutPoint) { - writeUI32(value.outPoint); - } - if (value.hasLoops) { - writeUI16(value.loopCount); - } - if (value.hasEnvelope) { - writeUI8(value.envelopeRecords.length); - for (SOUNDENVELOPE env : value.envelopeRecords) { - writeSOUNDENVELOPE(env); - } - } - } - - /** - * Writes SOUNDENVELOPE value to the stream - * - * @param value SOUNDENVELOPE value - * @throws IOException - */ - public void writeSOUNDENVELOPE(SOUNDENVELOPE value) throws IOException { - writeUI32(value.pos44); - writeUI16(value.leftLevel); - writeUI16(value.rightLevel); - } - - /** - * Writes TEXTRECORD value to the stream - * - * @param value TEXTRECORD value - * @param inDefineText2 - * @param glyphBits - * @param advanceBits - * @throws IOException - */ - public void writeTEXTRECORD(TEXTRECORD value, boolean inDefineText2, int glyphBits, int advanceBits) throws IOException { - writeUB(1, 1); - writeUB(3, 0); - writeUB(1, value.styleFlagsHasFont ? 1 : 0); - writeUB(1, value.styleFlagsHasColor ? 1 : 0); - writeUB(1, value.styleFlagsHasYOffset ? 1 : 0); - writeUB(1, value.styleFlagsHasXOffset ? 1 : 0); - if (value.styleFlagsHasFont) { - writeUI16(value.fontId); - } - if (value.styleFlagsHasColor) { - if (inDefineText2) { - writeRGBA(value.textColorA); - } else { - writeRGB(value.textColor); - } - } - if (value.styleFlagsHasXOffset) { - writeSI16(value.xOffset); - } - if (value.styleFlagsHasYOffset) { - writeSI16(value.yOffset); - } - if (value.styleFlagsHasFont) { - writeUI16(value.textHeight); - } - writeUI8(value.glyphEntries.length); - for (GLYPHENTRY ge : value.glyphEntries) { - writeGLYPHENTRY(ge, glyphBits, advanceBits); - } - alignByte(); - } - - /** - * Writes GLYPHENTRY value to the stream - * - * @param value GLYPHENTRY value - * @param glyphBits - * @param advanceBits - * @throws IOException - */ - public void writeGLYPHENTRY(GLYPHENTRY value, int glyphBits, int advanceBits) throws IOException { - writeUB(glyphBits, value.glyphIndex); - writeSB(advanceBits, value.glyphAdvance); - } - - /** - * Writes MORPHFILLSTYLE value to the stream - * - * @param value MORPHFILLSTYLE value - * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... - * @throws IOException - */ - public void writeMORPHFILLSTYLE(MORPHFILLSTYLE value, int shapeNum) throws IOException { - writeUI8(value.fillStyleType); - if (value.fillStyleType == MORPHFILLSTYLE.SOLID) { - writeRGBA(value.startColor); - writeRGBA(value.endColor); - } - if ((value.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) - || (value.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) { - writeMatrix(value.startGradientMatrix); - writeMatrix(value.endGradientMatrix); - } - if ((value.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) - || (value.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) { - writeMORPHGRADIENT(value.gradient, shapeNum); - } - - if ((value.fillStyleType == MORPHFILLSTYLE.REPEATING_BITMAP) - || (value.fillStyleType == MORPHFILLSTYLE.CLIPPED_BITMAP) - || (value.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) - || (value.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { - writeUI16(value.bitmapId); - writeMatrix(value.startBitmapMatrix); - writeMatrix(value.endBitmapMatrix); - } - } - - /** - * WritesMORPH FILLSTYLEARRAY value to the stream - * - * @param value MORPHFILLSTYLEARRAY value - * @param morphShapeNum 1 on DefineMorphShape, 2 on DefineMorphShape - * @throws IOException - */ - public void writeMORPHFILLSTYLEARRAY(MORPHFILLSTYLEARRAY value, int morphShapeNum) throws IOException { - int fillStyleCount = value.fillStyles.length; - if (fillStyleCount >= 0xff) { - writeUI8(0xff); - writeUI16(fillStyleCount); - } else { - writeUI8(fillStyleCount); - } - for (int i = 0; i < value.fillStyles.length; i++) { - writeMORPHFILLSTYLE(value.fillStyles[i], morphShapeNum); - } - } - - /** - * Writes MORPHGRADIENT value to the stream - * - * @param value MORPHGRADIENT value - * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... - * @throws IOException - */ - public void writeMORPHGRADIENT(MORPHGRADIENT value, int shapeNum) throws IOException { - //Despite of documentation (UI8 1-8), there are two fields - // spreadMode and interPolationMode which are same as in GRADIENT - writeUB(2, value.spreadMode); - writeUB(2, value.interPolationMode); - writeUB(4, value.gradientRecords.length); - for (int i = 0; i < value.gradientRecords.length; i++) { - writeMORPHGRADRECORD(value.gradientRecords[i]); - } - } - - /** - * Writes MORPHFOCALGRADIENT value to the stream - * - * Undocumented feature - * - * @param value MORPHGRADIENT value - * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... - * @throws IOException - */ - public void writeMORPHFOCALGRADIENT(MORPHFOCALGRADIENT value, int shapeNum) throws IOException { - writeUB(2, value.spreadMode); - writeUB(2, value.interPolationMode); - writeUB(4, value.gradientRecords.length); - for (int i = 0; i < value.gradientRecords.length; i++) { - writeMORPHGRADRECORD(value.gradientRecords[i]); - } - writeFIXED8(value.startFocalPoint); - writeFIXED8(value.endFocalPoint); - } - - /** - * Writes MORPHGRADRECORD value to the stream - * - * @param value MORPHGRADRECORD value - * @throws IOException - */ - public void writeMORPHGRADRECORD(MORPHGRADRECORD value) throws IOException { - writeUI8(value.startRatio); - writeRGBA(value.startColor); - writeUI8(value.endRatio); - writeRGBA(value.endColor); - } - - /** - * Writes MORPHLINESTYLE value to the stream - * - * @param value LINESTYLE value - * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... - * @throws IOException - */ - public void writeMORPHLINESTYLE(MORPHLINESTYLE value, int shapeNum) throws IOException { - writeUI16(value.startWidth); - writeUI16(value.endWidth); - writeRGBA(value.startColor); - writeRGBA(value.endColor); - - } - - /** - * Writes MORPHLINESTYLE2 value to the stream - * - * @param value MORPHLINESTYLE2 value - * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... - * @throws IOException - */ - public void writeMORPHLINESTYLE2(MORPHLINESTYLE2 value, int shapeNum) throws IOException { - writeUI16(value.startWidth); - writeUI16(value.endWidth); - writeUB(2, value.startCapStyle); - writeUB(2, value.joinStyle); - writeUB(1, value.hasFillFlag ? 1 : 0); - writeUB(1, value.noHScaleFlag ? 1 : 0); - writeUB(1, value.noVScaleFlag ? 1 : 0); - writeUB(1, value.pixelHintingFlag ? 1 : 0); - writeUB(5, value.reserved); - writeUB(1, value.noClose ? 1 : 0); - writeUB(2, value.endCapStyle); - if (value.joinStyle == LINESTYLE2.MITER_JOIN) { - writeUI16(value.miterLimitFactor); - } - if (!value.hasFillFlag) { - writeRGBA(value.startColor); - writeRGBA(value.endColor); - } else { - writeMORPHFILLSTYLE(value.fillType, shapeNum); - } - } - - /** - * Writes MORPHLINESTYLEARRAY value to the stream - * - * @param value MORPHFILLSTYLEARRAY value - * @param morphShapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... - * @throws IOException - */ - public void writeMORPHLINESTYLEARRAY(MORPHLINESTYLEARRAY value, int morphShapeNum) throws IOException { - int lineStyleCount; - if (morphShapeNum == 1) { - lineStyleCount = value.lineStyles.length; - if (lineStyleCount >= 0xff) { - writeUI8(0xff); - writeUI16(lineStyleCount); - } else { - writeUI8(lineStyleCount); - } - for (int i = 0; i < lineStyleCount; i++) { - writeMORPHLINESTYLE(value.lineStyles[i], morphShapeNum); - } - } else if (morphShapeNum == 2) { - lineStyleCount = value.lineStyles2.length; - if (lineStyleCount >= 0xff) { - writeUI8(0xff); - writeUI16(lineStyleCount); - } else { - writeUI8(lineStyleCount); - } - for (int i = 0; i < lineStyleCount; i++) { - writeMORPHLINESTYLE2(value.lineStyles2[i], morphShapeNum); - } - } - } - - /** - * Writes KERNINGRECORD value to the stream - * - * @param value KERNINGRECORD value - * @param fontFlagsWideCodes - * @throws IOException - */ - public void writeKERNINGRECORD(KERNINGRECORD value, boolean fontFlagsWideCodes) throws IOException { - if (fontFlagsWideCodes) { - writeUI16(value.fontKerningCode1); - writeUI16(value.fontKerningCode2); - } else { - writeUI8(value.fontKerningCode1); - writeUI8(value.fontKerningCode2); - } - writeSI16(value.fontKerningAdjustment); - } - - /** - * Writes LANGCODE value to the stream - * - * @param value LANGCODE value - * @throws IOException - */ - public void writeLANGCODE(LANGCODE value) throws IOException { - writeUI8(value.languageCode); - } - - /** - * Writes ZONERECORD value to the stream - * - * @param value ZONERECORD value - * @throws IOException - */ - public void writeZONERECORD(ZONERECORD value) throws IOException { - writeUI8(value.zonedata.length); - for (int i = 0; i < value.zonedata.length; i++) { - writeZONEDATA(value.zonedata[i]); - } - writeUB(6, 0); - writeUB(1, value.zoneMaskY ? 1 : 0); - writeUB(1, value.zoneMaskX ? 1 : 0); - } - - /** - * Writes ZONEDATA value to the stream - * - * @param value ZONEDATA value - * @throws IOException - */ - public void writeZONEDATA(ZONEDATA value) throws IOException { - writeUI16(value.alignmentCoordinate); - writeUI16(value.range); - } - - public void writeBytesZlib(byte[] data) throws IOException { - DeflaterOutputStream deflater = new DeflaterOutputStream(this, new Deflater(9)); - deflater.write(data); - deflater.finish(); - } - - /** - * Reads one BITMAPDATA value from the stream - * - * @param value - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight - * @throws IOException - */ - public void writeBITMAPDATA(BITMAPDATA value, int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { - int dataLen = 0; - int pos = 0; - for (int y = 0; y < bitmapHeight; y++) { - int x = 0; - for (; x < bitmapWidth; x++) { - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { - dataLen += 2; - writePIX15(value.bitmapPixelDataPix15[pos]); - } - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { - dataLen += 4; - writePIX24(value.bitmapPixelDataPix24[pos]); - } - pos++; - } - while ((dataLen % 4) != 0) { - dataLen++; - writeUI8(0); - } - } - } - - /** - * Reads one ALPHABITMAPDATA value from the stream - * - * @param value - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight - * @throws IOException - */ - public void writeALPHABITMAPDATA(ALPHABITMAPDATA value, int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { - int pos = 0; - for (int y = 0; y < bitmapHeight; y++) { - for (int x = 0; x < bitmapWidth; x++) { - writeARGB(value.bitmapPixelData[pos]); - pos++; - } - } - } - - /** - * Writes PIX24 value to the stream - * - * @param value PIX24 value - * @throws IOException - */ - public void writePIX24(PIX24 value) throws IOException { - writeUI8(value.reserved); - writeUI8(value.red); - writeUI8(value.green); - writeUI8(value.blue); - } - - /** - * Writes PIX15 value to the stream - * - * @param value PIX15 value - * @throws IOException - */ - public void writePIX15(PIX15 value) throws IOException { - writeUB(1, 0); - writeUB(5, value.red); - writeUB(5, value.green); - writeUB(5, value.blue); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; +import com.jpexs.decompiler.flash.types.ARGB; +import com.jpexs.decompiler.flash.types.BITMAPDATA; +import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; +import com.jpexs.decompiler.flash.types.BUTTONRECORD; +import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; +import com.jpexs.decompiler.flash.types.CLIPACTIONS; +import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; +import com.jpexs.decompiler.flash.types.CXFORM; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.FILLSTYLE; +import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.FOCALGRADIENT; +import com.jpexs.decompiler.flash.types.GLYPHENTRY; +import com.jpexs.decompiler.flash.types.GRADIENT; +import com.jpexs.decompiler.flash.types.GRADRECORD; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.LINESTYLE; +import com.jpexs.decompiler.flash.types.LINESTYLE2; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE; +import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT; +import com.jpexs.decompiler.flash.types.MORPHGRADIENT; +import com.jpexs.decompiler.flash.types.MORPHGRADRECORD; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLE; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2; +import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.PIX15; +import com.jpexs.decompiler.flash.types.PIX24; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.RGB; +import com.jpexs.decompiler.flash.types.RGBA; +import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; +import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; +import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.TEXTRECORD; +import com.jpexs.decompiler.flash.types.ZONEDATA; +import com.jpexs.decompiler.flash.types.ZONERECORD; +import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; +import com.jpexs.decompiler.flash.types.filters.BLURFILTER; +import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER; +import com.jpexs.decompiler.flash.types.filters.CONVOLUTIONFILTER; +import com.jpexs.decompiler.flash.types.filters.DROPSHADOWFILTER; +import com.jpexs.decompiler.flash.types.filters.FILTER; +import com.jpexs.decompiler.flash.types.filters.GLOWFILTER; +import com.jpexs.decompiler.flash.types.filters.GRADIENTBEVELFILTER; +import com.jpexs.decompiler.flash.types.filters.GRADIENTGLOWFILTER; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +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.utf8.Utf8Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +/** + * Class for writing data into SWF file + * + * @author JPEXS + */ +public class SWFOutputStream extends OutputStream { + + private final OutputStream os; + private final int version; + private long pos = 0; + private int bitPos = 0; + private int tempByte = 0; + + public long getPos() { + return pos; + } + + /** + * Constructor + * + * @param os OutputStream for writing data + * @param version Version of SWF + */ + public SWFOutputStream(OutputStream os, int version) { + this.version = version; + this.os = os; + } + + /** + * Writes byte to the stream + * + * @param b byte to write + * @throws IOException + */ + @Override + public void write(int b) throws IOException { + alignByte(); + os.write(b); + pos++; + } + + private void alignByte() throws IOException { + if (bitPos > 0) { + bitPos = 0; + write(tempByte); + tempByte = 0; + } + } + + /** + * Writes UI8 (Unsigned 8bit integer) value to the stream + * + * @param val UI8 value to write + * @throws IOException + */ + public void writeUI8(int val) throws IOException { + write(val); + } + + /** + * Writes String value to the stream + * + * @param value String value + * @throws IOException + */ + public void writeString(String value) throws IOException { + write(Utf8Helper.getBytes(value)); + write(0); + } + + /** + * Writes UI32 (Unsigned 32bit integer) value to the stream + * + * @param value UI32 value + * @throws IOException + */ + public void writeUI32(long value) throws IOException { + write((int) (value & 0xff)); + write((int) ((value >> 8) & 0xff)); + write((int) ((value >> 16) & 0xff)); + write((int) ((value >> 24) & 0xff)); + } + + /** + * Writes UI16 (Unsigned 16bit integer) value to the stream + * + * @param value UI16 value + * @throws IOException + */ + public void writeUI16(int value) throws IOException { + write((int) (value & 0xff)); + write((int) ((value >> 8) & 0xff)); + } + + /** + * Writes SI32 (Signed 32bit integer) value to the stream + * + * @param value SI32 value + * @throws IOException + */ + public void writeSI32(long value) throws IOException { + writeUI32(value); + } + + /** + * Writes SI16 (Signed 16bit integer) value to the stream + * + * @param value SI16 value + * @throws IOException + */ + public void writeSI16(int value) throws IOException { + writeUI16(value); + } + + /** + * Writes SI8 (Signed 8bit integer) value to the stream + * + * @param value SI8 value + * @throws IOException + */ + public void writeSI8(int value) throws IOException { + writeUI8(value); + } + + /** + * Writes FIXED (Fixed point 16.16) value to the stream + * + * @param value FIXED value + * @throws IOException + */ + public void writeFIXED(double value) throws IOException { + long valueLong = (long) (value * (1 << 16)); + int beforePoint = (int) valueLong >> 16; + + int afterPoint = (int) valueLong % (1 << 16); + writeUI16(afterPoint); + writeUI16(beforePoint); + } + + /** + * Writes FIXED8 (Fixed point 8.8) value to the stream + * + * @param value FIXED8 value + * @throws IOException + */ + public void writeFIXED8(float value) throws IOException { + int beforePoint = (int) getIntPart(value); + int afterPoint = (int) getIntPart((value + (value < 0 ? beforePoint : -beforePoint)) * 256); + writeUI8(afterPoint); + writeUI8(beforePoint); + } + + private void writeLong(long value) throws IOException { + byte[] writeBuffer = new byte[8]; + writeBuffer[3] = (byte) (value >>> 56); + writeBuffer[2] = (byte) (value >>> 48); + writeBuffer[1] = (byte) (value >>> 40); + writeBuffer[0] = (byte) (value >>> 32); + writeBuffer[7] = (byte) (value >>> 24); + writeBuffer[6] = (byte) (value >>> 16); + writeBuffer[5] = (byte) (value >>> 8); + writeBuffer[4] = (byte) (value); + write(writeBuffer); + } + + /** + * Writes DOUBLE (double precision floating point value) value to the stream + * + * @param value DOUBLE value + * @throws IOException + */ + public void writeDOUBLE(double value) throws IOException { + writeLong(Double.doubleToLongBits(value)); + } + + /** + * Writes FLOAT (single precision floating point value) value to the stream + * + * @param value FLOAT value + * @throws IOException + */ + public void writeFLOAT(float value) throws IOException { + writeUI32(Float.floatToIntBits(value)); + } + + /** + * Writes FLOAT16 (16bit floating point value) value to the stream + * + * @param value FLOAT16 value + * @throws IOException + */ + public void writeFLOAT16(float value) throws IOException { + int bits = Float.floatToRawIntBits(value); + int sign = bits >> 31; + int exponent = (bits >> 22) & 0xff; + int mantisa = bits & 0x3FFFFF; + mantisa >>= 13; + writeUI16((sign << 15) + (exponent << 10) + mantisa); + } + + /** + * Writes EncodedU32 (Encoded unsigned 32bit value) value to the stream + * + * @param value U32 value + * @throws IOException + */ + public void writeEncodedU32(long value) throws IOException { + boolean loop = true; + value &= 0xFFFFFFFF; + do { + int ret = (int) (value & 0x7F); + if (value < 0x80) { + loop = false; + } + if (value > 0x7F) { + ret += 0x80; + } + write(ret); + value >>= 7; + } while (loop); + } + + /** + * Flushes data to underlying stream + * + * @throws IOException + */ + @Override + public void flush() throws IOException { + if (bitPos > 0) { + bitPos = 0; + write(tempByte); + tempByte = 0; + } + os.flush(); + } + + /** + * Closes the stream + * + * @throws IOException + */ + @Override + public void close() throws IOException { + flush(); + os.close(); + } + + /** + * Writes UB[nBits] (Unsigned-bit value) value to the stream + * + * @param nBits Number of bits which represent value + * @param value Unsigned value to write + * @throws IOException + */ + public void writeUB(int nBits, long value) throws IOException { + for (int bit = 0; bit < nBits; bit++) { + int nb = (int) ((value >> (nBits - 1 - bit)) & 1); + tempByte += nb * (1 << (7 - bitPos)); + bitPos++; + if (bitPos == 8) { + bitPos = 0; + write(tempByte); + tempByte = 0; + } + } + } + + /** + * Writes SB[nBits] (Signed-bit value) value to the stream + * + * @param nBits Number of bits which represent value + * @param value Signed value to write + * @throws IOException + */ + public void writeSB(int nBits, long value) throws IOException { + writeUB(nBits, value); + } + + /** + * Writes FB[nBits] (Signed fixed-point bit value) value to the stream + * + * @param nBits Number of bits which represent value + * @param value Double value to write + * @throws IOException + */ + public void writeFB(int nBits, double value) throws IOException { + if (nBits == 0) { + return; + } + long longVal = (long) (value * (1 << 16)); + writeSB(nBits, longVal); + } + + /** + * Writes RECT value to the stream + * + * @param value RECT value + * @throws IOException + */ + public void writeRECT(RECT value) throws IOException { + int nBits = 0; + int xMin = truncateTo31Bit(value.Xmin); + int xMax = truncateTo31Bit(value.Xmax); + int yMin = truncateTo31Bit(value.Ymin); + int yMax = truncateTo31Bit(value.Ymax); + nBits = enlargeBitCountS(nBits, xMin); + nBits = enlargeBitCountS(nBits, xMax); + nBits = enlargeBitCountS(nBits, yMin); + nBits = enlargeBitCountS(nBits, yMax); + writeUB(5, nBits); + writeSB(nBits, xMin); + writeSB(nBits, xMax); + writeSB(nBits, yMin); + writeSB(nBits, yMax); + alignByte(); + } + + private int truncateTo31Bit(int value) { + if (value > 0x3fffffff) { + value = 0x3fffffff; + } + if (value < -0x3fffffff) { + value = -0x3fffffff; + } + return value; + } + + /** + * Writes list of Tag values to the stream + * + * @param tags List of tag values + * @throws IOException + */ + public void writeTags(List tags) throws IOException { + for (Tag tag : tags) { + tag.writeTag(this); + } + } + + /** + * Calculates number of bits needed for representing unsigned value + * + * @param value Unsigned value + * @return Number of bits + */ + public static int getNeededBitsU(int value) { + value = Math.abs(value); + long x = 1; + int nBits; + + for (nBits = 1; nBits <= 64; nBits++) { + x <<= 1; + if (x > value) { + break; + } + } + return nBits; + } + + /** + * Calculates number of bits needed for representing signed value + * + * @param v Signed value + * @return Number of bits + */ + public static int getNeededBitsS(int v) { + int counter = 32; + int mask = 0x80000000; + final int val = (v < 0) ? -v : v; + while (((val & mask) == 0) && (counter > 0)) { + mask >>>= 1; + counter -= 1; + } + return counter + 1; + } + + /** + * Calculates number of bits needed for representing signed values + * + * @param first First Signed value + * @param params Next Signed values + * @return Number of bits + */ + public static int getNeededBitsS(int first, int... params) { + int nBits = 0; + nBits = enlargeBitCountS(nBits, first); + for (int i = 0; i < params.length; i++) { + nBits = enlargeBitCountS(nBits, params[i]); + } + return nBits; + } + + public static int getNeededBitsU(int first, int... params) { + int nBits = 0; + nBits = enlargeBitCountU(nBits, first); + for (int i = 0; i < params.length; i++) { + nBits = enlargeBitCountU(nBits, params[i]); + } + return nBits; + } + + private static long getIntPart(double value) { + if (value < 0) { + return (long) Math.ceil(value); + } + return (long) Math.floor(value); + } + + public static int unsignedSize(final int value) { + + final int val = (value < 0) ? -value - 1 : value; + int counter = 32; + int mask = 0x80000000; + + while (((val & mask) == 0) && (counter > 0)) { + mask >>>= 1; + counter -= 1; + } + return counter; + } + + /** + * Calculates number of bits needed for representing fixed-point value + * + * @param value Fixed-point value + * @return Number of bits + */ + public static int getNeededBitsF(float value) { + //0.26213074 16bits + //0.5 17bits + //1.3476715 18bits + int k = (int) value; + return getNeededBitsS(k) + 16; + } + + public static int enlargeBitCountS(int currentBitCount, int value) { + int neededNew = getNeededBitsS(value); + if (neededNew > currentBitCount) { + return neededNew; + } + return currentBitCount; + } + + public static int enlargeBitCountU(int currentBitCount, int value) { + int neededNew = getNeededBitsU(value); + if (neededNew > currentBitCount) { + return neededNew; + } + return currentBitCount; + } + + /** + * Writes MATRIX value to the stream + * + * @param value MATRIX value + * @throws IOException + */ + public void writeMatrix(MATRIX value) throws IOException { + writeUB(1, value.hasScale ? 1 : 0); + if (value.hasScale) { + int nBits = 0; + nBits = enlargeBitCountS(nBits, value.scaleX); + nBits = enlargeBitCountS(nBits, value.scaleY); + writeUB(5, nBits); + writeSB(nBits, value.scaleX); + writeSB(nBits, value.scaleY); + } + writeUB(1, value.hasRotate ? 1 : 0); + if (value.hasRotate) { + int nBits = 0; + nBits = enlargeBitCountS(nBits, value.rotateSkew0); + nBits = enlargeBitCountS(nBits, value.rotateSkew1); + writeUB(5, nBits); + writeSB(nBits, value.rotateSkew0); + writeSB(nBits, value.rotateSkew1); + } + int NTranslateBits = 0; + NTranslateBits = enlargeBitCountS(NTranslateBits, value.translateX); + NTranslateBits = enlargeBitCountS(NTranslateBits, value.translateY); + + writeUB(5, NTranslateBits); + + writeSB(NTranslateBits, value.translateX); + writeSB(NTranslateBits, value.translateY); + alignByte(); + + } + + /** + * Writes CXFORM value to the stream + * + * @param value CXFORM value + * @throws IOException + */ + public void writeCXFORM(CXFORM value) throws IOException { + writeUB(1, value.hasAddTerms ? 1 : 0); + writeUB(1, value.hasMultTerms ? 1 : 0); + int Nbits = 1; + if (value.hasMultTerms) { + Nbits = enlargeBitCountS(Nbits, value.redMultTerm); + Nbits = enlargeBitCountS(Nbits, value.greenMultTerm); + Nbits = enlargeBitCountS(Nbits, value.blueMultTerm); + } + if (value.hasAddTerms) { + Nbits = enlargeBitCountS(Nbits, value.redAddTerm); + Nbits = enlargeBitCountS(Nbits, value.greenAddTerm); + Nbits = enlargeBitCountS(Nbits, value.blueAddTerm); + } + writeUB(4, Nbits); + if (value.hasMultTerms) { + writeSB(Nbits, value.redMultTerm); + writeSB(Nbits, value.greenMultTerm); + writeSB(Nbits, value.blueMultTerm); + } + if (value.hasAddTerms) { + writeSB(Nbits, value.redAddTerm); + writeSB(Nbits, value.greenAddTerm); + writeSB(Nbits, value.blueAddTerm); + } + alignByte(); + } + + /** + * Writes CXFORMWITHALPHA value to the stream + * + * @param value CXFORMWITHALPHA value + * @throws IOException + */ + public void writeCXFORMWITHALPHA(CXFORMWITHALPHA value) throws IOException { + writeUB(1, value.hasAddTerms ? 1 : 0); + writeUB(1, value.hasMultTerms ? 1 : 0); + int Nbits = 1; + if (value.hasMultTerms) { + Nbits = enlargeBitCountS(Nbits, value.redMultTerm); + Nbits = enlargeBitCountS(Nbits, value.greenMultTerm); + Nbits = enlargeBitCountS(Nbits, value.blueMultTerm); + Nbits = enlargeBitCountS(Nbits, value.alphaMultTerm); + } + if (value.hasAddTerms) { + Nbits = enlargeBitCountS(Nbits, value.redAddTerm); + Nbits = enlargeBitCountS(Nbits, value.greenAddTerm); + Nbits = enlargeBitCountS(Nbits, value.blueAddTerm); + Nbits = enlargeBitCountS(Nbits, value.alphaAddTerm); + } + writeUB(4, Nbits); + if (value.hasMultTerms) { + writeSB(Nbits, value.redMultTerm); + writeSB(Nbits, value.greenMultTerm); + writeSB(Nbits, value.blueMultTerm); + writeSB(Nbits, value.alphaMultTerm); + } + if (value.hasAddTerms) { + writeSB(Nbits, value.redAddTerm); + writeSB(Nbits, value.greenAddTerm); + writeSB(Nbits, value.blueAddTerm); + writeSB(Nbits, value.alphaAddTerm); + } + alignByte(); + } + + /** + * Writes CLIPEVENTFLAGS value to the stream + * + * @param value CLIPEVENTFLAGS value + * @throws IOException + */ + public void writeCLIPEVENTFLAGS(CLIPEVENTFLAGS value) throws IOException { + writeUB(1, value.clipEventKeyUp ? 1 : 0); + writeUB(1, value.clipEventKeyDown ? 1 : 0); + writeUB(1, value.clipEventMouseUp ? 1 : 0); + writeUB(1, value.clipEventMouseDown ? 1 : 0); + writeUB(1, value.clipEventMouseMove ? 1 : 0); + writeUB(1, value.clipEventUnload ? 1 : 0); + writeUB(1, value.clipEventEnterFrame ? 1 : 0); + writeUB(1, value.clipEventLoad ? 1 : 0); + writeUB(1, value.clipEventDragOver ? 1 : 0); + writeUB(1, value.clipEventRollOut ? 1 : 0); + writeUB(1, value.clipEventRollOver ? 1 : 0); + writeUB(1, value.clipEventReleaseOutside ? 1 : 0); + writeUB(1, value.clipEventRelease ? 1 : 0); + writeUB(1, value.clipEventPress ? 1 : 0); + writeUB(1, value.clipEventInitialize ? 1 : 0); + writeUB(1, value.clipEventData ? 1 : 0); + if (version >= 6) { + writeUB(5, value.reserved); + writeUB(1, value.clipEventConstruct ? 1 : 0); + writeUB(1, value.clipEventKeyPress ? 1 : 0); + writeUB(1, value.clipEventDragOut ? 1 : 0); + writeUB(8, value.reserved2); + } + } + + /** + * Writes CLIPACTIONRECORD value to the stream + * + * @param value CLIPACTIONRECORD value + * @throws IOException + */ + public void writeCLIPACTIONRECORD(CLIPACTIONRECORD value) throws IOException { + writeCLIPEVENTFLAGS(value.eventFlags); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (SWFOutputStream sos = new SWFOutputStream(baos, version)) { + if (value.eventFlags.clipEventKeyPress) { + sos.writeUI8(value.keyCode); + } + sos.write(value.actionBytes); + } + byte[] data = baos.toByteArray(); + writeUI32(data.length); //actionRecordSize + write(data); + } + + /** + * Writes CLIPACTIONS value to the stream + * + * @param value CLIPACTIONS value + * @throws IOException + */ + public void writeCLIPACTIONS(CLIPACTIONS value) throws IOException { + writeUI16(value.reserved); + writeCLIPEVENTFLAGS(value.allEventFlags); + for (CLIPACTIONRECORD car : value.clipActionRecords) { + writeCLIPACTIONRECORD(car); + } + if (version <= 5) { + writeUI16(0); + } else { + writeUI32(0); + } + } + + /** + * Writes COLORMATRIXFILTER value to the stream + * + * @param value COLORMATRIXFILTER value + * @throws IOException + */ + public void writeCOLORMATRIXFILTER(COLORMATRIXFILTER value) throws IOException { + for (int i = 0; i < 20; i++) { + writeFLOAT(value.matrix[i]); + } + } + + /** + * Writes RGBA value to the stream + * + * @param value RGBA value + * @throws IOException + */ + public void writeRGBA(RGBA value) throws IOException { + writeUI8(value.red); + writeUI8(value.green); + writeUI8(value.blue); + writeUI8(value.alpha); + } + + /** + * Writes ARGB value to the stream + * + * @param value ARGB value + * @throws IOException + */ + public void writeARGB(ARGB value) throws IOException { + writeUI8(value.alpha); + writeUI8(value.red); + writeUI8(value.green); + writeUI8(value.blue); + } + + /** + * Writes RGB value to the stream + * + * @param value RGB value + * @throws IOException + */ + public void writeRGB(RGB value) throws IOException { + writeUI8(value.red); + writeUI8(value.green); + writeUI8(value.blue); + } + + /** + * Writes CONVOLUTIONFILTER value to the stream + * + * @param value CONVOLUTIONFILTER value + * @throws IOException + */ + public void writeCONVOLUTIONFILTER(CONVOLUTIONFILTER value) throws IOException { + writeUI8(value.matrixX); + writeUI8(value.matrixY); + writeFLOAT(value.divisor); + writeFLOAT(value.bias); + for (int x = 0; x < value.matrixX; x++) { + for (int y = 0; y < value.matrixY; y++) { + writeFLOAT(value.matrix[x][y]); + } + } + writeRGBA(value.defaultColor); + writeUB(6, value.reserved); + writeUB(1, value.clamp ? 1 : 0); + writeUB(1, value.preserveAlpha ? 1 : 0); + } + + /** + * Writes BLURFILTER value to the stream + * + * @param value BLURFILTER value + * @throws IOException + */ + public void writeBLURFILTER(BLURFILTER value) throws IOException { + writeFIXED(value.blurX); + writeFIXED(value.blurY); + writeUB(5, value.passes); + writeUB(3, value.reserved); + } + + /** + * Writes DROPSHADOWFILTER value to the stream + * + * @param value DROPSHADOWFILTER value + * @throws IOException + */ + public void writeDROPSHADOWFILTER(DROPSHADOWFILTER value) throws IOException { + writeRGBA(value.dropShadowColor); + writeFIXED(value.blurX); + writeFIXED(value.blurY); + writeFIXED(value.angle); + writeFIXED(value.distance); + writeFIXED8(value.strength); + writeUB(1, value.innerShadow ? 1 : 0); + writeUB(1, value.knockout ? 1 : 0); + writeUB(1, value.compositeSource ? 1 : 0); + writeUB(5, value.passes); + } + + /** + * Writes GLOWFILTER value to the stream + * + * @param value GLOWFILTER value + * @throws IOException + */ + public void writeGLOWFILTER(GLOWFILTER value) throws IOException { + writeRGBA(value.glowColor); + writeFIXED(value.blurX); + writeFIXED(value.blurY); + writeFIXED8(value.strength); + writeUB(1, value.innerGlow ? 1 : 0); + writeUB(1, value.knockout ? 1 : 0); + writeUB(1, value.compositeSource ? 1 : 0); + writeUB(5, value.passes); + } + + /** + * Writes BEVELFILTER value to the stream + * + * @param value BEVELFILTER value + * @throws IOException + */ + public void writeBEVELFILTER(BEVELFILTER value) throws IOException { + writeRGBA(value.highlightColor); + writeRGBA(value.shadowColor); + writeFIXED(value.blurX); + writeFIXED(value.blurY); + writeFIXED(value.angle); + writeFIXED(value.distance); + writeFIXED8(value.strength); + writeUB(1, value.innerShadow ? 1 : 0); + writeUB(1, value.knockout ? 1 : 0); + writeUB(1, value.compositeSource ? 1 : 0); + writeUB(1, value.onTop ? 1 : 0); + writeUB(4, value.passes); + } + + /** + * Writes GRADIENTGLOWFILTER value to the stream + * + * @param value GRADIENTGLOWFILTER value + * @throws IOException + */ + public void writeGRADIENTGLOWFILTER(GRADIENTGLOWFILTER value) throws IOException { + writeUI8(value.gradientColors.length); + for (int i = 0; i < value.gradientColors.length; i++) { + writeRGBA(value.gradientColors[i]); + } + for (int i = 0; i < value.gradientColors.length; i++) { + writeUI8(value.gradientRatio[i]); + } + writeFIXED(value.blurX); + writeFIXED(value.blurY); + writeFIXED(value.angle); + writeFIXED(value.distance); + writeFIXED8(value.strength); + writeUB(1, value.innerShadow ? 1 : 0); + writeUB(1, value.knockout ? 1 : 0); + writeUB(1, value.compositeSource ? 1 : 0); + writeUB(1, value.onTop ? 1 : 0); + writeUB(4, value.passes); + } + + /** + * Writes GRADIENTBEVELFILTER value to the stream + * + * @param value GRADIENTBEVELFILTER value + * @throws IOException + */ + public void writeGRADIENTBEVELFILTER(GRADIENTBEVELFILTER value) throws IOException { + writeUI8(value.gradientColors.length); + for (int i = 0; i < value.gradientColors.length; i++) { + writeRGBA(value.gradientColors[i]); + } + for (int i = 0; i < value.gradientColors.length; i++) { + writeUI8(value.gradientRatio[i]); + } + writeFIXED(value.blurX); + writeFIXED(value.blurY); + writeFIXED(value.angle); + writeFIXED(value.distance); + writeFIXED8(value.strength); + writeUB(1, value.innerShadow ? 1 : 0); + writeUB(1, value.knockout ? 1 : 0); + writeUB(1, value.compositeSource ? 1 : 0); + writeUB(1, value.onTop ? 1 : 0); + writeUB(4, value.passes); + } + + /** + * Writes list of FILTER values to the stream + * + * @param list List of FILTER values + * @throws IOException + */ + public void writeFILTERLIST(List list) throws IOException { + writeUI8(list.size()); + for (int i = 0; i < list.size(); i++) { + writeFILTER(list.get(i)); + } + } + + /** + * Writes FILTER value to the stream + * + * @param value FILTER value + * @throws IOException + */ + public void writeFILTER(FILTER value) throws IOException { + writeUI8(value.id); + if (value instanceof DROPSHADOWFILTER) { + writeDROPSHADOWFILTER((DROPSHADOWFILTER) value); + } + if (value instanceof BLURFILTER) { + writeBLURFILTER((BLURFILTER) value); + } + if (value instanceof GLOWFILTER) { + writeGLOWFILTER((GLOWFILTER) value); + } + if (value instanceof BEVELFILTER) { + writeBEVELFILTER((BEVELFILTER) value); + } + if (value instanceof GRADIENTGLOWFILTER) { + writeGRADIENTGLOWFILTER((GRADIENTGLOWFILTER) value); + } + if (value instanceof CONVOLUTIONFILTER) { + writeCONVOLUTIONFILTER((CONVOLUTIONFILTER) value); + } + if (value instanceof COLORMATRIXFILTER) { + writeCOLORMATRIXFILTER((COLORMATRIXFILTER) value); + } + if (value instanceof GRADIENTBEVELFILTER) { + writeGRADIENTBEVELFILTER((GRADIENTBEVELFILTER) value); + } + } + + /** + * Writes list of BUTTONRECORD values to the stream + * + * @param list List of BUTTONRECORD values + * @param inDefineButton2 Whether write inside of DefineButton2Tag or not + * @throws IOException + */ + public void writeBUTTONRECORDList(List list, boolean inDefineButton2) throws IOException { + for (BUTTONRECORD brec : list) { + writeBUTTONRECORD(brec, inDefineButton2); + } + writeUI8(0); + } + + /** + * Writes BUTTONRECORD value to the stream + * + * @param value BUTTONRECORD value + * @param inDefineButton2 Whether write inside of DefineButton2Tag or not + * @throws IOException + */ + public void writeBUTTONRECORD(BUTTONRECORD value, boolean inDefineButton2) throws IOException { + writeUB(2, value.reserved); + writeUB(1, value.buttonHasBlendMode ? 1 : 0); + writeUB(1, value.buttonHasFilterList ? 1 : 0); + writeUB(1, value.buttonStateHitTest ? 1 : 0); + writeUB(1, value.buttonStateDown ? 1 : 0); + writeUB(1, value.buttonStateOver ? 1 : 0); + writeUB(1, value.buttonStateUp ? 1 : 0); + writeUI16(value.characterId); + writeUI16(value.placeDepth); + writeMatrix(value.placeMatrix); + if (inDefineButton2) { + writeCXFORMWITHALPHA(value.colorTransform); + if (value.buttonHasFilterList) { + writeFILTERLIST(value.filterList); + } + if (value.buttonHasBlendMode) { + writeUI8(value.blendMode); + } + } + } + + /** + * Writes list of BUTTONCONDACTION values to the stream + * + * @param list List of BUTTONCONDACTION values + * @throws IOException + */ + public void writeBUTTONCONDACTIONList(List list) throws IOException { + for (int i = 0; i < list.size(); i++) { + writeBUTTONCONDACTION(list.get(i), i == list.size() - 1); + } + } + + /** + * Writes BUTTONCONDACTION value to the stream + * + * @param value BUTTONCONDACTION value + * @param isLast True if it is last on the list + * @throws IOException + */ + public void writeBUTTONCONDACTION(BUTTONCONDACTION value, boolean isLast) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (SWFOutputStream sos = new SWFOutputStream(baos, version)) { + sos.writeUB(1, value.condIdleToOverDown ? 1 : 0); + sos.writeUB(1, value.condOutDownToIdle ? 1 : 0); + sos.writeUB(1, value.condOutDownToOverDown ? 1 : 0); + sos.writeUB(1, value.condOverDownToOutDown ? 1 : 0); + sos.writeUB(1, value.condOverDownToOverUp ? 1 : 0); + sos.writeUB(1, value.condOverUpToOverDown ? 1 : 0); + sos.writeUB(1, value.condOverUpToIddle ? 1 : 0); + sos.writeUB(1, value.condIdleToOverUp ? 1 : 0); + sos.writeUB(7, value.condKeyPress); + sos.writeUB(1, value.condOverDownToIddle ? 1 : 0); + sos.write(value.actionBytes); + } + byte[] data = baos.toByteArray(); + if (isLast) { + writeUI16(0); + } else { + writeUI16(data.length + 2); + } + write(data); + } + + /** + * Writes FILLSTYLE value to the stream + * + * @param value FILLSTYLE value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeFILLSTYLE(FILLSTYLE value, int shapeNum) throws IOException { + writeUI8(value.fillStyleType); + if (value.fillStyleType == FILLSTYLE.SOLID) { + if (shapeNum >= 3) { + writeRGBA((RGBA) value.color); + } else if (shapeNum == 1 || shapeNum == 2) { + writeRGB(value.color); + } + } + if ((value.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) + || (value.fillStyleType == FILLSTYLE.RADIAL_GRADIENT) + || (value.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT)) { + writeMatrix(value.gradientMatrix); + } + if ((value.fillStyleType == FILLSTYLE.LINEAR_GRADIENT) + || (value.fillStyleType == FILLSTYLE.RADIAL_GRADIENT)) { + writeGRADIENT(value.gradient, shapeNum); + } + if (value.fillStyleType == FILLSTYLE.FOCAL_RADIAL_GRADIENT) { + writeFOCALGRADIENT((FOCALGRADIENT) value.gradient, shapeNum); + } + + if ((value.fillStyleType == FILLSTYLE.REPEATING_BITMAP) + || (value.fillStyleType == FILLSTYLE.CLIPPED_BITMAP) + || (value.fillStyleType == FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) + || (value.fillStyleType == FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { + writeUI16(value.bitmapId); + writeMatrix(value.bitmapMatrix); + } + } + + /** + * Writes FILLSTYLEARRAY value to the stream + * + * @param value FILLSTYLEARRAY value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeFILLSTYLEARRAY(FILLSTYLEARRAY value, int shapeNum) throws IOException { + int fillStyleCount = value.fillStyles.length; + if (shapeNum == 2 || shapeNum == 3) { + if (fillStyleCount >= 0xff) { + writeUI8(0xff); + writeUI16(fillStyleCount); + } else { + writeUI8(fillStyleCount); + } + } else { + writeUI8(fillStyleCount); + } + for (int i = 0; i < value.fillStyles.length; i++) { + writeFILLSTYLE(value.fillStyles[i], shapeNum); + } + } + + /** + * Writes FOCALGRADIENT value to the stream + * + * @param value FILLSTYLEARRAY value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeFOCALGRADIENT(FOCALGRADIENT value, int shapeNum) throws IOException { + writeUB(2, value.spreadMode); + writeUB(2, value.interpolationMode); + writeUB(4, value.gradientRecords.length); + for (int i = 0; i < value.gradientRecords.length; i++) { + writeGRADRECORD(value.gradientRecords[i], shapeNum); + } + writeFIXED8(value.focalPoint); + } + + /** + * Writes GRADIENT value to the stream + * + * @param value GRADIENT value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeGRADIENT(GRADIENT value, int shapeNum) throws IOException { + writeUB(2, value.spreadMode); + writeUB(2, value.interpolationMode); + writeUB(4, value.gradientRecords.length); + for (int i = 0; i < value.gradientRecords.length; i++) { + writeGRADRECORD(value.gradientRecords[i], shapeNum); + } + } + + /** + * Writes GRADRECORD value to the stream + * + * @param value GRADRECORD value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeGRADRECORD(GRADRECORD value, int shapeNum) throws IOException { + writeUI8(value.ratio); + if (shapeNum == 1 || shapeNum == 2) { + writeRGB(value.color); + } else if (shapeNum == 3) { + writeRGBA((RGBA) value.color); + } + } + + /** + * Writes LINESTYLE value to the stream + * + * @param value LINESTYLE value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeLINESTYLE(LINESTYLE value, int shapeNum) throws IOException { + writeUI16(value.width); + if (shapeNum == 1 || shapeNum == 2) { + writeRGB(value.color); + } else if (shapeNum == 3) { + writeRGBA((RGBA) value.color); + } + } + + /** + * Writes LINESTYLE2 value to the stream + * + * @param value LINESTYLE2 value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeLINESTYLE2(LINESTYLE2 value, int shapeNum) throws IOException { + writeUI16(value.width); + writeUB(2, value.startCapStyle); + writeUB(2, value.joinStyle); + writeUB(1, value.hasFillFlag ? 1 : 0); + writeUB(1, value.noHScaleFlag ? 1 : 0); + writeUB(1, value.noVScaleFlag ? 1 : 0); + writeUB(1, value.pixelHintingFlag ? 1 : 0); + writeUB(5, value.reserved); + writeUB(1, value.noClose ? 1 : 0); + writeUB(2, value.endCapStyle); + if (value.joinStyle == LINESTYLE2.MITER_JOIN) { + writeUI16(value.miterLimitFactor); + } + if (!value.hasFillFlag) { + writeRGBA((RGBA) value.color); + } else { + writeFILLSTYLE(value.fillType, shapeNum); + } + } + + /** + * Writes LINESTYLEARRAY value to the stream + * + * @param value FILLSTYLEARRAY value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeLINESTYLEARRAY(LINESTYLEARRAY value, int shapeNum) throws IOException { + int lineStyleCount; + if (shapeNum == 1 || shapeNum == 2 || shapeNum == 3) { + lineStyleCount = value.lineStyles.length; + if (lineStyleCount >= 0xff) { + writeUI8(0xff); + writeUI16(lineStyleCount); + } else { + writeUI8(lineStyleCount); + } + for (int i = 0; i < lineStyleCount; i++) { + writeLINESTYLE(value.lineStyles[i], shapeNum); + } + } else if (shapeNum == 4) { + lineStyleCount = value.lineStyles.length; + if (lineStyleCount >= 0xff) { + writeUI8(0xff); + writeUI16(lineStyleCount); + } else { + writeUI8(lineStyleCount); + } + for (int i = 0; i < lineStyleCount; i++) { + writeLINESTYLE2((LINESTYLE2) value.lineStyles[i], shapeNum); + } + } + } + + /** + * Writes SHAPE value to the stream + * + * @param value SHAPE value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeSHAPE(SHAPE value, int shapeNum) throws IOException { + writeUB(4, value.numFillBits); + writeUB(4, value.numLineBits); + writeSHAPERECORDS(value.shapeRecords, value.numFillBits, value.numLineBits, shapeNum); + } + + /** + * Writes SHAPEWITHSTYLE value to the stream + * + * @param value SHAPEWITHSTYLE value + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + public void writeSHAPEWITHSTYLE(SHAPEWITHSTYLE value, int shapeNum) throws IOException { + writeFILLSTYLEARRAY(value.fillStyles, shapeNum); + writeLINESTYLEARRAY(value.lineStyles, shapeNum); + writeUB(4, value.numFillBits); + writeUB(4, value.numLineBits); + writeSHAPERECORDS(value.shapeRecords, value.numFillBits, value.numLineBits, shapeNum); + } + + /** + * Writes SHAPERECORDs value to the stream + * + * @param value SHAPERECORDS value + * @param fillBits + * @param lineBits + * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... + * @throws IOException + */ + private void writeSHAPERECORDS(List value, int fillBits, int lineBits, int shapeNum) throws IOException { + for (SHAPERECORD sh : value) { + if (sh instanceof CurvedEdgeRecord) { + CurvedEdgeRecord cer = (CurvedEdgeRecord) sh; + writeUB(1, 1); //typeFlag + writeUB(1, 0);//curvedEdge + writeUB(4, cer.numBits); + writeUB(cer.numBits + 2, cer.controlDeltaX); + writeUB(cer.numBits + 2, cer.controlDeltaY); + writeUB(cer.numBits + 2, cer.anchorDeltaX); + writeUB(cer.numBits + 2, cer.anchorDeltaY); + } else if (sh instanceof StraightEdgeRecord) { + StraightEdgeRecord ser = (StraightEdgeRecord) sh; + writeUB(1, 1); //typeFlag + writeUB(1, 1);//straightEdge + writeUB(4, ser.numBits); + writeUB(1, ser.generalLineFlag ? 1 : 0); + if (!ser.generalLineFlag) { + writeUB(1, ser.vertLineFlag ? 1 : 0); + } + if (ser.generalLineFlag || (!ser.vertLineFlag)) { + writeSB(ser.numBits + 2, ser.deltaX); + } + if (ser.generalLineFlag || ser.vertLineFlag) { + writeSB(ser.numBits + 2, ser.deltaY); + } + } else if (sh instanceof StyleChangeRecord) { + StyleChangeRecord scr = (StyleChangeRecord) sh; + writeUB(1, 0); //typeFlag + writeUB(1, scr.stateNewStyles ? 1 : 0); + writeUB(1, scr.stateLineStyle ? 1 : 0); + writeUB(1, scr.stateFillStyle1 ? 1 : 0); + writeUB(1, scr.stateFillStyle0 ? 1 : 0); + writeUB(1, scr.stateMoveTo ? 1 : 0); + if (scr.stateMoveTo) { + writeUB(5, scr.moveBits); + writeUB(scr.moveBits, scr.moveDeltaX); + writeUB(scr.moveBits, scr.moveDeltaY); + } + if (scr.stateFillStyle0) { + writeUB(fillBits, scr.fillStyle0); + } + if (scr.stateFillStyle1) { + writeUB(fillBits, scr.fillStyle1); + } + if (scr.stateLineStyle) { + writeUB(lineBits, scr.lineStyle); + } + if (scr.stateNewStyles) { + writeFILLSTYLEARRAY(scr.fillStyles, shapeNum); + writeLINESTYLEARRAY(scr.lineStyles, shapeNum); + writeUB(4, scr.numFillBits); + writeUB(4, scr.numLineBits); + } + + } else if (sh instanceof EndShapeRecord) { + writeUB(1, 0); //typeFlag + writeUB(5, 0); //end of shape flag + } + } + alignByte(); + } + + /** + * Writes SOUNDINFO value to the stream + * + * @param value SOUNDINFO value + * @throws IOException + */ + public void writeSOUNDINFO(SOUNDINFO value) throws IOException { + writeUB(2, value.reserved); + writeUB(1, value.syncStop ? 1 : 0); + writeUB(1, value.syncNoMultiple ? 1 : 0); + writeUB(1, value.hasEnvelope ? 1 : 0); + writeUB(1, value.hasLoops ? 1 : 0); + writeUB(1, value.hasOutPoint ? 1 : 0); + writeUB(1, value.hasInPoint ? 1 : 0); + if (value.hasInPoint) { + writeUI32(value.inPoint); + } + if (value.hasOutPoint) { + writeUI32(value.outPoint); + } + if (value.hasLoops) { + writeUI16(value.loopCount); + } + if (value.hasEnvelope) { + writeUI8(value.envelopeRecords.length); + for (SOUNDENVELOPE env : value.envelopeRecords) { + writeSOUNDENVELOPE(env); + } + } + } + + /** + * Writes SOUNDENVELOPE value to the stream + * + * @param value SOUNDENVELOPE value + * @throws IOException + */ + public void writeSOUNDENVELOPE(SOUNDENVELOPE value) throws IOException { + writeUI32(value.pos44); + writeUI16(value.leftLevel); + writeUI16(value.rightLevel); + } + + /** + * Writes TEXTRECORD value to the stream + * + * @param value TEXTRECORD value + * @param inDefineText2 + * @param glyphBits + * @param advanceBits + * @throws IOException + */ + public void writeTEXTRECORD(TEXTRECORD value, boolean inDefineText2, int glyphBits, int advanceBits) throws IOException { + writeUB(1, 1); + writeUB(3, 0); + writeUB(1, value.styleFlagsHasFont ? 1 : 0); + writeUB(1, value.styleFlagsHasColor ? 1 : 0); + writeUB(1, value.styleFlagsHasYOffset ? 1 : 0); + writeUB(1, value.styleFlagsHasXOffset ? 1 : 0); + if (value.styleFlagsHasFont) { + writeUI16(value.fontId); + } + if (value.styleFlagsHasColor) { + if (inDefineText2) { + writeRGBA(value.textColorA); + } else { + writeRGB(value.textColor); + } + } + if (value.styleFlagsHasXOffset) { + writeSI16(value.xOffset); + } + if (value.styleFlagsHasYOffset) { + writeSI16(value.yOffset); + } + if (value.styleFlagsHasFont) { + writeUI16(value.textHeight); + } + writeUI8(value.glyphEntries.length); + for (GLYPHENTRY ge : value.glyphEntries) { + writeGLYPHENTRY(ge, glyphBits, advanceBits); + } + alignByte(); + } + + /** + * Writes GLYPHENTRY value to the stream + * + * @param value GLYPHENTRY value + * @param glyphBits + * @param advanceBits + * @throws IOException + */ + public void writeGLYPHENTRY(GLYPHENTRY value, int glyphBits, int advanceBits) throws IOException { + writeUB(glyphBits, value.glyphIndex); + writeSB(advanceBits, value.glyphAdvance); + } + + /** + * Writes MORPHFILLSTYLE value to the stream + * + * @param value MORPHFILLSTYLE value + * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... + * @throws IOException + */ + public void writeMORPHFILLSTYLE(MORPHFILLSTYLE value, int shapeNum) throws IOException { + writeUI8(value.fillStyleType); + if (value.fillStyleType == MORPHFILLSTYLE.SOLID) { + writeRGBA(value.startColor); + writeRGBA(value.endColor); + } + if ((value.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) + || (value.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) { + writeMatrix(value.startGradientMatrix); + writeMatrix(value.endGradientMatrix); + } + if ((value.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT) + || (value.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) { + writeMORPHGRADIENT(value.gradient, shapeNum); + } + + if ((value.fillStyleType == MORPHFILLSTYLE.REPEATING_BITMAP) + || (value.fillStyleType == MORPHFILLSTYLE.CLIPPED_BITMAP) + || (value.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP) + || (value.fillStyleType == MORPHFILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP)) { + writeUI16(value.bitmapId); + writeMatrix(value.startBitmapMatrix); + writeMatrix(value.endBitmapMatrix); + } + } + + /** + * WritesMORPH FILLSTYLEARRAY value to the stream + * + * @param value MORPHFILLSTYLEARRAY value + * @param morphShapeNum 1 on DefineMorphShape, 2 on DefineMorphShape + * @throws IOException + */ + public void writeMORPHFILLSTYLEARRAY(MORPHFILLSTYLEARRAY value, int morphShapeNum) throws IOException { + int fillStyleCount = value.fillStyles.length; + if (fillStyleCount >= 0xff) { + writeUI8(0xff); + writeUI16(fillStyleCount); + } else { + writeUI8(fillStyleCount); + } + for (int i = 0; i < value.fillStyles.length; i++) { + writeMORPHFILLSTYLE(value.fillStyles[i], morphShapeNum); + } + } + + /** + * Writes MORPHGRADIENT value to the stream + * + * @param value MORPHGRADIENT value + * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... + * @throws IOException + */ + public void writeMORPHGRADIENT(MORPHGRADIENT value, int shapeNum) throws IOException { + //Despite of documentation (UI8 1-8), there are two fields + // spreadMode and interPolationMode which are same as in GRADIENT + writeUB(2, value.spreadMode); + writeUB(2, value.interPolationMode); + writeUB(4, value.gradientRecords.length); + for (int i = 0; i < value.gradientRecords.length; i++) { + writeMORPHGRADRECORD(value.gradientRecords[i]); + } + } + + /** + * Writes MORPHFOCALGRADIENT value to the stream + * + * Undocumented feature + * + * @param value MORPHGRADIENT value + * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... + * @throws IOException + */ + public void writeMORPHFOCALGRADIENT(MORPHFOCALGRADIENT value, int shapeNum) throws IOException { + writeUB(2, value.spreadMode); + writeUB(2, value.interPolationMode); + writeUB(4, value.gradientRecords.length); + for (int i = 0; i < value.gradientRecords.length; i++) { + writeMORPHGRADRECORD(value.gradientRecords[i]); + } + writeFIXED8(value.startFocalPoint); + writeFIXED8(value.endFocalPoint); + } + + /** + * Writes MORPHGRADRECORD value to the stream + * + * @param value MORPHGRADRECORD value + * @throws IOException + */ + public void writeMORPHGRADRECORD(MORPHGRADRECORD value) throws IOException { + writeUI8(value.startRatio); + writeRGBA(value.startColor); + writeUI8(value.endRatio); + writeRGBA(value.endColor); + } + + /** + * Writes MORPHLINESTYLE value to the stream + * + * @param value LINESTYLE value + * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... + * @throws IOException + */ + public void writeMORPHLINESTYLE(MORPHLINESTYLE value, int shapeNum) throws IOException { + writeUI16(value.startWidth); + writeUI16(value.endWidth); + writeRGBA(value.startColor); + writeRGBA(value.endColor); + + } + + /** + * Writes MORPHLINESTYLE2 value to the stream + * + * @param value MORPHLINESTYLE2 value + * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... + * @throws IOException + */ + public void writeMORPHLINESTYLE2(MORPHLINESTYLE2 value, int shapeNum) throws IOException { + writeUI16(value.startWidth); + writeUI16(value.endWidth); + writeUB(2, value.startCapStyle); + writeUB(2, value.joinStyle); + writeUB(1, value.hasFillFlag ? 1 : 0); + writeUB(1, value.noHScaleFlag ? 1 : 0); + writeUB(1, value.noVScaleFlag ? 1 : 0); + writeUB(1, value.pixelHintingFlag ? 1 : 0); + writeUB(5, value.reserved); + writeUB(1, value.noClose ? 1 : 0); + writeUB(2, value.endCapStyle); + if (value.joinStyle == LINESTYLE2.MITER_JOIN) { + writeUI16(value.miterLimitFactor); + } + if (!value.hasFillFlag) { + writeRGBA(value.startColor); + writeRGBA(value.endColor); + } else { + writeMORPHFILLSTYLE(value.fillType, shapeNum); + } + } + + /** + * Writes MORPHLINESTYLEARRAY value to the stream + * + * @param value MORPHFILLSTYLEARRAY value + * @param morphShapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... + * @throws IOException + */ + public void writeMORPHLINESTYLEARRAY(MORPHLINESTYLEARRAY value, int morphShapeNum) throws IOException { + int lineStyleCount; + if (morphShapeNum == 1) { + lineStyleCount = value.lineStyles.length; + if (lineStyleCount >= 0xff) { + writeUI8(0xff); + writeUI16(lineStyleCount); + } else { + writeUI8(lineStyleCount); + } + for (int i = 0; i < lineStyleCount; i++) { + writeMORPHLINESTYLE(value.lineStyles[i], morphShapeNum); + } + } else if (morphShapeNum == 2) { + lineStyleCount = value.lineStyles2.length; + if (lineStyleCount >= 0xff) { + writeUI8(0xff); + writeUI16(lineStyleCount); + } else { + writeUI8(lineStyleCount); + } + for (int i = 0; i < lineStyleCount; i++) { + writeMORPHLINESTYLE2(value.lineStyles2[i], morphShapeNum); + } + } + } + + /** + * Writes KERNINGRECORD value to the stream + * + * @param value KERNINGRECORD value + * @param fontFlagsWideCodes + * @throws IOException + */ + public void writeKERNINGRECORD(KERNINGRECORD value, boolean fontFlagsWideCodes) throws IOException { + if (fontFlagsWideCodes) { + writeUI16(value.fontKerningCode1); + writeUI16(value.fontKerningCode2); + } else { + writeUI8(value.fontKerningCode1); + writeUI8(value.fontKerningCode2); + } + writeSI16(value.fontKerningAdjustment); + } + + /** + * Writes LANGCODE value to the stream + * + * @param value LANGCODE value + * @throws IOException + */ + public void writeLANGCODE(LANGCODE value) throws IOException { + writeUI8(value.languageCode); + } + + /** + * Writes ZONERECORD value to the stream + * + * @param value ZONERECORD value + * @throws IOException + */ + public void writeZONERECORD(ZONERECORD value) throws IOException { + writeUI8(value.zonedata.length); + for (int i = 0; i < value.zonedata.length; i++) { + writeZONEDATA(value.zonedata[i]); + } + writeUB(6, 0); + writeUB(1, value.zoneMaskY ? 1 : 0); + writeUB(1, value.zoneMaskX ? 1 : 0); + } + + /** + * Writes ZONEDATA value to the stream + * + * @param value ZONEDATA value + * @throws IOException + */ + public void writeZONEDATA(ZONEDATA value) throws IOException { + writeUI16(value.alignmentCoordinate); + writeUI16(value.range); + } + + public void writeBytesZlib(byte[] data) throws IOException { + DeflaterOutputStream deflater = new DeflaterOutputStream(this, new Deflater(9)); + deflater.write(data); + deflater.finish(); + } + + /** + * Reads one BITMAPDATA value from the stream + * + * @param value + * @param bitmapFormat + * @param bitmapWidth + * @param bitmapHeight + * @throws IOException + */ + public void writeBITMAPDATA(BITMAPDATA value, int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { + int dataLen = 0; + int pos = 0; + for (int y = 0; y < bitmapHeight; y++) { + int x = 0; + for (; x < bitmapWidth; x++) { + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { + dataLen += 2; + writePIX15(value.bitmapPixelDataPix15[pos]); + } + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { + dataLen += 4; + writePIX24(value.bitmapPixelDataPix24[pos]); + } + pos++; + } + while ((dataLen % 4) != 0) { + dataLen++; + writeUI8(0); + } + } + } + + /** + * Reads one ALPHABITMAPDATA value from the stream + * + * @param value + * @param bitmapFormat + * @param bitmapWidth + * @param bitmapHeight + * @throws IOException + */ + public void writeALPHABITMAPDATA(ALPHABITMAPDATA value, int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { + int pos = 0; + for (int y = 0; y < bitmapHeight; y++) { + for (int x = 0; x < bitmapWidth; x++) { + writeARGB(value.bitmapPixelData[pos]); + pos++; + } + } + } + + /** + * Writes PIX24 value to the stream + * + * @param value PIX24 value + * @throws IOException + */ + public void writePIX24(PIX24 value) throws IOException { + writeUI8(value.reserved); + writeUI8(value.red); + writeUI8(value.green); + writeUI8(value.blue); + } + + /** + * Writes PIX15 value to the stream + * + * @param value PIX15 value + * @throws IOException + */ + public void writePIX15(PIX15 value) throws IOException { + writeUB(1, 0); + writeUB(5, value.red); + writeUB(5, value.green); + writeUB(5, value.blue); + } +} diff --git a/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java b/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java index f51f868f3..a810e20eb 100644 --- a/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java +++ b/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java @@ -1,110 +1,109 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.MemoryInputStream; -import com.jpexs.helpers.ReReadableInputStream; -import com.jpexs.helpers.streams.SeekableInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * - * @author JPEXS - */ -public class ZippedSWFBundle implements SWFBundle { - - protected Set keySet = new HashSet<>(); - private final Map cachedSWFs = new HashMap<>(); - protected ReReadableInputStream is; - - public ZippedSWFBundle(InputStream is) { - this.is = new ReReadableInputStream(is); - ZipInputStream zip = new ZipInputStream(this.is); - ZipEntry entry; - try { - while ((entry = zip.getNextEntry()) != null) { - if (entry.getName().toLowerCase().endsWith(".swf") - || entry.getName().toLowerCase().endsWith(".gfx")) { - keySet.add(entry.getName()); - } - //streamMap.put(, is) - } - } catch (IOException ex) { - Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex); - } - } - - @Override - public int length() { - return keySet.size(); - } - - @Override - public Set getKeys() { - return keySet; - } - - @Override - public SeekableInputStream getSWF(String key) throws IOException { - if (!keySet.contains(key)) { - return null; - } - if (!cachedSWFs.containsKey(key)) { - - this.is.reset(); - ZipInputStream zip = new ZipInputStream(this.is); - ZipEntry entry; - try { - while ((entry = zip.getNextEntry()) != null) { - if (entry.getName().equals(key)) { - MemoryInputStream mis = new MemoryInputStream(Helper.readStream(zip)); - cachedSWFs.put(key, mis); - break; - } - zip.closeEntry(); - } - } catch (IOException ex) { - Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex); - } - - } - return cachedSWFs.get(key); - } - - @Override - public Map getAll() throws IOException { - for (String key : getKeys()) { //cache everything first - getSWF(key); - } - return cachedSWFs; - } - - @Override - public String getExtension() { - return "zip"; - } -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.MemoryInputStream; +import com.jpexs.helpers.ReReadableInputStream; +import com.jpexs.helpers.streams.SeekableInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * + * @author JPEXS + */ +public class ZippedSWFBundle implements SWFBundle { + + protected Set keySet = new HashSet<>(); + private final Map cachedSWFs = new HashMap<>(); + protected ReReadableInputStream is; + + public ZippedSWFBundle(InputStream is) { + this.is = new ReReadableInputStream(is); + ZipInputStream zip = new ZipInputStream(this.is); + ZipEntry entry; + try { + while ((entry = zip.getNextEntry()) != null) { + if (entry.getName().toLowerCase().endsWith(".swf") + || entry.getName().toLowerCase().endsWith(".gfx")) { + keySet.add(entry.getName()); + } + } + } catch (IOException ex) { + Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex); + } + } + + @Override + public int length() { + return keySet.size(); + } + + @Override + public Set getKeys() { + return keySet; + } + + @Override + public SeekableInputStream getSWF(String key) throws IOException { + if (!keySet.contains(key)) { + return null; + } + if (!cachedSWFs.containsKey(key)) { + + this.is.reset(); + ZipInputStream zip = new ZipInputStream(this.is); + ZipEntry entry; + try { + while ((entry = zip.getNextEntry()) != null) { + if (entry.getName().equals(key)) { + MemoryInputStream mis = new MemoryInputStream(Helper.readStream(zip)); + cachedSWFs.put(key, mis); + break; + } + zip.closeEntry(); + } + } catch (IOException ex) { + Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex); + } + + } + return cachedSWFs.get(key); + } + + @Override + public Map getAll() throws IOException { + for (String key : getKeys()) { //cache everything first + getSWF(key); + } + return cachedSWFs; + } + + @Override + public String getExtension() { + return "zip"; + } +} diff --git a/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index e9ddec268..ed4f38d8b 100644 --- a/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -1,372 +1,372 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.action.swf4; - -import com.jpexs.decompiler.flash.EndOfStreamException; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.TemporaryRegister; -import com.jpexs.decompiler.flash.action.parser.ParseException; -import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; -import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.ecma.Undefined; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.helpers.Helper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Stack; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class ActionPush extends Action { - - public List values; - public List replacement; - public List constantPool; - public List ignoredParts = new ArrayList<>(); - - @Override - public boolean isIgnored() { - return ignoredParts.size() == values.size(); - } - - @Override - public void setIgnored(boolean ignored, int pos) { - if (ignored) { - if (!ignoredParts.contains(pos)) { - ignoredParts.add(pos); - if (ignoredParts.size() == values.size()) { - super.setIgnored(ignored, 0); - } - } - } else { - if (ignoredParts.contains(pos)) { - ignoredParts.remove(pos); - super.setIgnored(false, 0); - } - } - - } - - public ActionPush(int actionLength, SWFInputStream sis, int version) throws IOException { - super(0x96, actionLength); - int type; - values = new ArrayList<>(); - sis = new SWFInputStream(new ByteArrayInputStream(sis.readBytesEx(actionLength)), version); - try { - while (sis.available() > 0) { - type = sis.readUI8(); - switch (type) { - case 0: - values.add(sis.readString()); - break; - case 1: - values.add(sis.readFLOAT()); - break; - case 2: - values.add(new Null()); - break; - case 3: - values.add(new Undefined()); - break; - case 4: - values.add(new RegisterNumber(sis.readUI8())); - break; - case 5: - int b = sis.readUI8(); - if (b == 0) { - values.add((Boolean) false); - } else { - values.add((Boolean) true); - } - - break; - case 6: - values.add(sis.readDOUBLE()); - break; - case 7: - long el = sis.readSI32(); - values.add((Long) el); - break; - case 8: - values.add(new ConstantIndex(sis.readUI8())); - break; - case 9: - values.add(new ConstantIndex(sis.readUI16())); - break; - } - } - } catch (EndOfStreamException ex) { - } - } - - @Override - public byte[] getBytes(int version) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, version); - try { - for (Object o : values) { - if (o instanceof String) { - sos.writeUI8(0); - sos.writeString((String) o); - } - if (o instanceof Float) { - sos.writeUI8(1); - sos.writeFLOAT((Float) o); - } - if (o instanceof Null) { - sos.writeUI8(2); - } - if (o instanceof Undefined) { - sos.writeUI8(3); - } - if (o instanceof RegisterNumber) { - sos.writeUI8(4); - sos.writeUI8(((RegisterNumber) o).number); - } - if (o instanceof Boolean) { - sos.writeUI8(5); - sos.writeUI8((Boolean) o ? 1 : 0); - } - if (o instanceof Double) { - sos.writeUI8(6); - sos.writeDOUBLE((Double) o); - } - if (o instanceof Long) { - sos.writeUI8(7); - sos.writeSI32((Long) o); - } - if (o instanceof ConstantIndex) { - int cIndex = ((ConstantIndex) o).index; - if (cIndex < 256) { - sos.writeUI8(8); - sos.writeUI8(cIndex); - } else { - sos.writeUI8(9); - sos.writeUI16(cIndex); - } - } - } - sos.close(); - } catch (IOException e) { - Logger.getLogger(ActionPush.class.getName()).log(Level.SEVERE, "Error during push to bytes", e); - } - return surroundWithAction(baos.toByteArray(), version); - } - - public ActionPush(Object value) { - super(0x96, 0); - this.values = new ArrayList<>(); - this.values.add(value); - } - - public ActionPush(FlasmLexer lexer, List constantPool) throws IOException, ParseException { - super(0x96, 0); - this.constantPool = constantPool; - values = new ArrayList<>(); - int count = 0; - loop: - while (true) { - ASMParsedSymbol symb = lexer.yylex(); - switch (symb.type) { - case ASMParsedSymbol.TYPE_STRING: - count++; - if (constantPool.contains((String) symb.value)) { - values.add(new ConstantIndex(constantPool.indexOf(symb.value), constantPool)); - } else { - values.add(symb.value); - } - break; - case ASMParsedSymbol.TYPE_FLOAT: - case ASMParsedSymbol.TYPE_NULL: - case ASMParsedSymbol.TYPE_UNDEFINED: - case ASMParsedSymbol.TYPE_REGISTER: - case ASMParsedSymbol.TYPE_BOOLEAN: - case ASMParsedSymbol.TYPE_INTEGER: - case ASMParsedSymbol.TYPE_CONSTANT: - count++; - values.add(symb.value); - break; - case ASMParsedSymbol.TYPE_EOL: - case ASMParsedSymbol.TYPE_EOF: - if (count == 0) { - throw new ParseException("Arguments expected", lexer.yyline()); - } else { - break loop; - } - case ASMParsedSymbol.TYPE_COMMENT: - break; - default: - throw new ParseException("Arguments expected, " + symb.type + " " + symb.value + " found", lexer.yyline()); - } - } - } - - @Override - public GraphTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - if (replacement == null || replacement.size() < values.size()) { - return toString(writer); - } - List oldVal = values; - values = replacement; - toString(writer); - values = oldVal; - return writer; - } - - public GraphTextWriter paramsToStringReplaced(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - if (replacement == null || replacement.size() < values.size()) { - return paramsToString(writer); - } - List oldVal = values; - values = replacement; - paramsToString(writer); - values = oldVal; - return writer; - } - - public String toStringNoQ(int i) { - String ret = ""; - if (values.get(i) instanceof ConstantIndex) { - ((ConstantIndex) values.get(i)).constantPool = constantPool; - ret += ((ConstantIndex) values.get(i)).toStringNoQ(); - } else if (values.get(i) instanceof String) { - ret += (String) values.get(i); - } else if (values.get(i) instanceof RegisterNumber) { - ret += ((RegisterNumber) values.get(i)).toStringNoName(); - } else { - ret += values.get(i).toString(); - } - return ret; - } - - public String toString(int i) { - String ret = ""; - if (values.get(i) instanceof ConstantIndex) { - ((ConstantIndex) values.get(i)).constantPool = constantPool; - ret += ((ConstantIndex) values.get(i)).toString(); - } else if (values.get(i) instanceof String) { - ret += "\"" + Helper.escapeString((String) values.get(i)) + "\""; - } else if (values.get(i) instanceof RegisterNumber) { - ret += ((RegisterNumber) values.get(i)).toStringNoName(); - } else { - ret += values.get(i).toString(); - } - return ret; - } - - public GraphTextWriter paramsToString(GraphTextWriter writer) { - int pos = 0; - for (int i = 0; i < values.size(); i++) { - if (ignoredParts.contains(i)) { - continue; - } - if (pos > 0) { - writer.appendNoHilight(" "); - } - writer.append(toString(i), getAddress() + pos + 1); - pos++; - } - return writer; - } - - @Override - public String toString() { - HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), false); - toString(writer); - return writer.toString(); - } - - public GraphTextWriter toString(GraphTextWriter writer) { - writer.appendNoHilight("Push "); - paramsToString(writer); - return writer; - } - - @Override - public void translate(Stack stack, List output, java.util.HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - int pos = 0; - for (Object o : values) { - if (ignoredParts.contains(pos)) { - pos++; - continue; - } - if (o instanceof ConstantIndex) { - if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) { - o = "CONSTANT" + ((ConstantIndex) o).index; - } else { - o = constantPool.get(((ConstantIndex) o).index); - } - } - /*if (o instanceof RegisterNumber) { - if (regNames.containsKey(((RegisterNumber) o).number)) { - ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); - } else if (output.size() >= 2) { //chained assignments:, ignore for class prototype assignment - GraphTargetItem last = output.get(output.size() - 1); - GraphTargetItem prev = output.get(output.size() - 2); - if (last instanceof SetTypeActionItem) { - if (prev instanceof StoreRegisterActionItem) { - StoreRegisterActionItem str = (StoreRegisterActionItem) prev; - if (str.register.number == ((RegisterNumber) o).number) { - SetTypeActionItem stt = (SetTypeActionItem) last; - stt.setTempRegister(((RegisterNumber) o).number); - if ((stt.getValue() instanceof IncrementActionItem) && (((IncrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { - stack.push(new PreIncrementActionItem(this, stt.getObject())); - } else if ((stt.getValue() instanceof DecrementActionItem) && (((DecrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { - stack.push(new PreDecrementActionItem(this, stt.getObject())); - } else { - //stack.push(last); - continue; - } - output.remove(output.size() - 1); - output.remove(output.size() - 1); - pos++; - continue; - } - } - } - } - }*/ - DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool); - - if (o instanceof RegisterNumber) {//TemporaryRegister - dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); - if (regNames.containsKey(((RegisterNumber) o).number)) { - ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); - } - } - if (dvt.computedRegValue instanceof TemporaryRegister) { - stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); - } else { - stack.push(dvt); - } - pos++; - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.action.swf4; + +import com.jpexs.decompiler.flash.EndOfStreamException; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.TemporaryRegister; +import com.jpexs.decompiler.flash.action.parser.ParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.helpers.Helper; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ActionPush extends Action { + + public List values; + public List replacement; + public List constantPool; + public List ignoredParts = new ArrayList<>(); + + @Override + public boolean isIgnored() { + return ignoredParts.size() == values.size(); + } + + @Override + public void setIgnored(boolean ignored, int pos) { + if (ignored) { + if (!ignoredParts.contains(pos)) { + ignoredParts.add(pos); + if (ignoredParts.size() == values.size()) { + super.setIgnored(ignored, 0); + } + } + } else { + if (ignoredParts.contains(pos)) { + ignoredParts.remove(pos); + super.setIgnored(false, 0); + } + } + + } + + public ActionPush(int actionLength, SWFInputStream sis, int version) throws IOException { + super(0x96, actionLength); + int type; + values = new ArrayList<>(); + sis = new SWFInputStream(sis.readBytesEx(actionLength), version); + try { + while (sis.available() > 0) { + type = sis.readUI8(); + switch (type) { + case 0: + values.add(sis.readString()); + break; + case 1: + values.add(sis.readFLOAT()); + break; + case 2: + values.add(new Null()); + break; + case 3: + values.add(new Undefined()); + break; + case 4: + values.add(new RegisterNumber(sis.readUI8())); + break; + case 5: + int b = sis.readUI8(); + if (b == 0) { + values.add((Boolean) false); + } else { + values.add((Boolean) true); + } + + break; + case 6: + values.add(sis.readDOUBLE()); + break; + case 7: + long el = sis.readSI32(); + values.add((Long) el); + break; + case 8: + values.add(new ConstantIndex(sis.readUI8())); + break; + case 9: + values.add(new ConstantIndex(sis.readUI16())); + break; + } + } + } catch (EndOfStreamException ex) { + } + } + + @Override + public byte[] getBytes(int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, version); + try { + for (Object o : values) { + if (o instanceof String) { + sos.writeUI8(0); + sos.writeString((String) o); + } + if (o instanceof Float) { + sos.writeUI8(1); + sos.writeFLOAT((Float) o); + } + if (o instanceof Null) { + sos.writeUI8(2); + } + if (o instanceof Undefined) { + sos.writeUI8(3); + } + if (o instanceof RegisterNumber) { + sos.writeUI8(4); + sos.writeUI8(((RegisterNumber) o).number); + } + if (o instanceof Boolean) { + sos.writeUI8(5); + sos.writeUI8((Boolean) o ? 1 : 0); + } + if (o instanceof Double) { + sos.writeUI8(6); + sos.writeDOUBLE((Double) o); + } + if (o instanceof Long) { + sos.writeUI8(7); + sos.writeSI32((Long) o); + } + if (o instanceof ConstantIndex) { + int cIndex = ((ConstantIndex) o).index; + if (cIndex < 256) { + sos.writeUI8(8); + sos.writeUI8(cIndex); + } else { + sos.writeUI8(9); + sos.writeUI16(cIndex); + } + } + } + sos.close(); + } catch (IOException e) { + Logger.getLogger(ActionPush.class.getName()).log(Level.SEVERE, "Error during push to bytes", e); + } + return surroundWithAction(baos.toByteArray(), version); + } + + public ActionPush(Object value) { + super(0x96, 0); + this.values = new ArrayList<>(); + this.values.add(value); + } + + public ActionPush(FlasmLexer lexer, List constantPool) throws IOException, ParseException { + super(0x96, 0); + this.constantPool = constantPool; + values = new ArrayList<>(); + int count = 0; + loop: + while (true) { + ASMParsedSymbol symb = lexer.yylex(); + switch (symb.type) { + case ASMParsedSymbol.TYPE_STRING: + count++; + if (constantPool.contains((String) symb.value)) { + values.add(new ConstantIndex(constantPool.indexOf(symb.value), constantPool)); + } else { + values.add(symb.value); + } + break; + case ASMParsedSymbol.TYPE_FLOAT: + case ASMParsedSymbol.TYPE_NULL: + case ASMParsedSymbol.TYPE_UNDEFINED: + case ASMParsedSymbol.TYPE_REGISTER: + case ASMParsedSymbol.TYPE_BOOLEAN: + case ASMParsedSymbol.TYPE_INTEGER: + case ASMParsedSymbol.TYPE_CONSTANT: + count++; + values.add(symb.value); + break; + case ASMParsedSymbol.TYPE_EOL: + case ASMParsedSymbol.TYPE_EOF: + if (count == 0) { + throw new ParseException("Arguments expected", lexer.yyline()); + } else { + break loop; + } + case ASMParsedSymbol.TYPE_COMMENT: + break; + default: + throw new ParseException("Arguments expected, " + symb.type + " " + symb.value + " found", lexer.yyline()); + } + } + } + + @Override + public GraphTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + if (replacement == null || replacement.size() < values.size()) { + return toString(writer); + } + List oldVal = values; + values = replacement; + toString(writer); + values = oldVal; + return writer; + } + + public GraphTextWriter paramsToStringReplaced(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + if (replacement == null || replacement.size() < values.size()) { + return paramsToString(writer); + } + List oldVal = values; + values = replacement; + paramsToString(writer); + values = oldVal; + return writer; + } + + public String toStringNoQ(int i) { + String ret = ""; + if (values.get(i) instanceof ConstantIndex) { + ((ConstantIndex) values.get(i)).constantPool = constantPool; + ret += ((ConstantIndex) values.get(i)).toStringNoQ(); + } else if (values.get(i) instanceof String) { + ret += (String) values.get(i); + } else if (values.get(i) instanceof RegisterNumber) { + ret += ((RegisterNumber) values.get(i)).toStringNoName(); + } else { + ret += values.get(i).toString(); + } + return ret; + } + + public String toString(int i) { + String ret = ""; + if (values.get(i) instanceof ConstantIndex) { + ((ConstantIndex) values.get(i)).constantPool = constantPool; + ret += ((ConstantIndex) values.get(i)).toString(); + } else if (values.get(i) instanceof String) { + ret += "\"" + Helper.escapeString((String) values.get(i)) + "\""; + } else if (values.get(i) instanceof RegisterNumber) { + ret += ((RegisterNumber) values.get(i)).toStringNoName(); + } else { + ret += values.get(i).toString(); + } + return ret; + } + + public GraphTextWriter paramsToString(GraphTextWriter writer) { + int pos = 0; + for (int i = 0; i < values.size(); i++) { + if (ignoredParts.contains(i)) { + continue; + } + if (pos > 0) { + writer.appendNoHilight(" "); + } + writer.append(toString(i), getAddress() + pos + 1); + pos++; + } + return writer; + } + + @Override + public String toString() { + HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), false); + toString(writer); + return writer.toString(); + } + + public GraphTextWriter toString(GraphTextWriter writer) { + writer.appendNoHilight("Push "); + paramsToString(writer); + return writer; + } + + @Override + public void translate(Stack stack, List output, java.util.HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { + int pos = 0; + for (Object o : values) { + if (ignoredParts.contains(pos)) { + pos++; + continue; + } + if (o instanceof ConstantIndex) { + if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) { + o = "CONSTANT" + ((ConstantIndex) o).index; + } else { + o = constantPool.get(((ConstantIndex) o).index); + } + } + /*if (o instanceof RegisterNumber) { + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + } else if (output.size() >= 2) { //chained assignments:, ignore for class prototype assignment + GraphTargetItem last = output.get(output.size() - 1); + GraphTargetItem prev = output.get(output.size() - 2); + if (last instanceof SetTypeActionItem) { + if (prev instanceof StoreRegisterActionItem) { + StoreRegisterActionItem str = (StoreRegisterActionItem) prev; + if (str.register.number == ((RegisterNumber) o).number) { + SetTypeActionItem stt = (SetTypeActionItem) last; + stt.setTempRegister(((RegisterNumber) o).number); + if ((stt.getValue() instanceof IncrementActionItem) && (((IncrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { + stack.push(new PreIncrementActionItem(this, stt.getObject())); + } else if ((stt.getValue() instanceof DecrementActionItem) && (((DecrementActionItem) stt.getValue()).object.equals(stt.getObject()))) { + stack.push(new PreDecrementActionItem(this, stt.getObject())); + } else { + //stack.push(last); + continue; + } + output.remove(output.size() - 1); + output.remove(output.size() - 1); + pos++; + continue; + } + } + } + } + }*/ + DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool); + + if (o instanceof RegisterNumber) {//TemporaryRegister + dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); + } + } + if (dvt.computedRegValue instanceof TemporaryRegister) { + stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value)); + } else { + stack.push(dvt); + } + pos++; + } + } +} diff --git a/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java b/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java new file mode 100644 index 000000000..f31a78a41 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.dumpview; + +/** + * + * @author JPEXS + */ +public class DumpInfo { + + public String name; + + public Object previewValue; + + public int startByte; + + public int startBit; + + public int lengthBytes; + + public int lengthBits; + + public DumpInfo(int startByte, int lengthBytes) { + + this.startByte = startByte; + this.lengthBytes = lengthBytes; + } + + public DumpInfo(int startByte, int startBit, int lengthBytes, int lengthBits) { + + this.startByte = startByte; + this.lengthBytes = lengthBytes; + this.startBit = startBit; + this.lengthBits = lengthBits; + } +} diff --git a/src/com/jpexs/decompiler/flash/dumpview/Dumpable.java b/src/com/jpexs/decompiler/flash/dumpview/Dumpable.java new file mode 100644 index 000000000..4f97c46a9 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/dumpview/Dumpable.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.dumpview; + +import java.util.List; + +/** + * + * @author JPEXS + */ +public interface Dumpable { + + public List getNeededCharacters(); +} diff --git a/src/com/jpexs/decompiler/flash/dumpview/DumpableItem.java b/src/com/jpexs/decompiler/flash/dumpview/DumpableItem.java new file mode 100644 index 000000000..96fd98158 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/dumpview/DumpableItem.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.dumpview; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.treeitems.TreeItem; + +/** + * + * @author JPEXS + */ +public class DumpableItem implements TreeItem { + + private final SWF swf; + + public DumpableItem(SWF swf) { + this.swf = swf; + } + + @Override + public SWF getSwf() { + return swf; + } + +} diff --git a/src/com/jpexs/decompiler/flash/dumpview/DumpableNode.java b/src/com/jpexs/decompiler/flash/dumpview/DumpableNode.java new file mode 100644 index 000000000..a348cf116 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/dumpview/DumpableNode.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.dumpview; + +import com.jpexs.decompiler.flash.treenodes.TreeNode; + +/** + * + * @author JPEXS + */ +public class DumpableNode extends TreeNode { + + public DumpableNode(DumpableItem item) { + super(item); + } + + @Override + public DumpableItem getItem() { + return (DumpableItem) item; + } + +} diff --git a/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java b/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java index bc7592281..e5f668791 100644 --- a/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java +++ b/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java @@ -1,171 +1,171 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.exporters; - -import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; -import com.jpexs.decompiler.flash.RetryTask; -import com.jpexs.decompiler.flash.RunnableIOEx; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; -import com.jpexs.decompiler.flash.exporters.settings.MovieExportSettings; -import com.jpexs.decompiler.flash.flv.FLVOutputStream; -import com.jpexs.decompiler.flash.flv.FLVTAG; -import com.jpexs.decompiler.flash.flv.VIDEODATA; -import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.VideoFrameTag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class MovieExporter { - - public List exportMovies(AbortRetryIgnoreHandler handler, String outdir, List tags, final MovieExportSettings settings) throws IOException { - List ret = new ArrayList<>(); - if (tags.isEmpty()) { - return ret; - } - File foutdir = new File(outdir); - if (!foutdir.exists()) { - if (!foutdir.mkdirs()) { - if (!foutdir.exists()) { - throw new IOException("Cannot create directory " + outdir); - } - } - } - for (Tag t : tags) { - if (t instanceof DefineVideoStreamTag) { - final DefineVideoStreamTag videoStream = (DefineVideoStreamTag) t; - final File file = new File(outdir + File.separator + ((DefineVideoStreamTag) t).getCharacterExportFileName() + ".flv"); - new RetryTask(new RunnableIOEx() { - @Override - public void run() throws IOException { - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(exportMovie(videoStream, settings.mode)); - } - } - }, handler).run(); - - } - } - return ret; - } - - public byte[] exportMovie(DefineVideoStreamTag videoStream, MovieExportMode mode) throws IOException { - SWF swf = videoStream.getSwf(); - HashMap frames = new HashMap<>(); - SWF.populateVideoFrames(videoStream.characterID, swf.tags, frames); - if (frames.isEmpty()) { - return new byte[0]; - } - - //double ms = 1000.0f / ((float) frameRate); - ByteArrayOutputStream fos = new ByteArrayOutputStream(); - //CopyOutputStream cos = new CopyOutputStream(fos, new FileInputStream("f:\\trunk\\testdata\\xfl\\xfl\\_obj\\streamvideo 7.flv")); - OutputStream tos = fos; - FLVOutputStream flv = new FLVOutputStream(tos); - flv.writeHeader(false, true); - //flv.writeTag(new FLVTAG(0, SCRIPTDATA.onMetaData(ms * frames.size() / 1000.0, videoStream.width, videoStream.height, 0, frameRate, videoStream.codecID, 0, 0, false, 0, fileSize))); - int horizontalAdjustment = 0; - int verticalAdjustment = 0; - for (int i = 0; i < frames.size(); i++) { - VideoFrameTag tag = frames.get(i); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - int frameType = 1; - - if ((videoStream.codecID == DefineVideoStreamTag.CODEC_VP6) - || (videoStream.codecID == DefineVideoStreamTag.CODEC_VP6_ALPHA)) { - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(tag.videoData), swf.version); - if (videoStream.codecID == DefineVideoStreamTag.CODEC_VP6_ALPHA) { - sis.readUI24(); //offsetToAlpha - } - int frameMode = (int) sis.readUB(1); - - if (frameMode == 0) { - frameType = 1; //intra - } else { - frameType = 2; //inter - } - sis.readUB(6); //qp - int marker = (int) sis.readUB(1); - if (frameMode == 0) { - int version = (int) sis.readUB(5); - int version2 = (int) sis.readUB(2); - sis.readUB(1);//interlace - if (marker == 1 || version2 == 0) { - sis.readUI16();//offset - } - int dim_y = sis.readUI8(); - int dim_x = sis.readUI8(); - sis.readUI8(); //render_y - sis.readUI8(); //render_x - horizontalAdjustment = (int) (dim_x * Math.ceil(((double) videoStream.width) / (double) dim_x)) - videoStream.width; - verticalAdjustment = (int) (dim_y * Math.ceil(((double) videoStream.height) / (double) dim_y)) - videoStream.height; - - } - - SWFOutputStream sos = new SWFOutputStream(baos, swf.version); - sos.writeUB(4, horizontalAdjustment); - sos.writeUB(4, verticalAdjustment); - } - if (videoStream.codecID == DefineVideoStreamTag.CODEC_SORENSON_H263) { - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(tag.videoData), swf.version); - sis.readUB(17);//pictureStartCode - sis.readUB(5); //version - sis.readUB(8); //temporalReference - int pictureSize = (int) sis.readUB(3); //pictureSize - if (pictureSize == 0) { - sis.readUB(8); //customWidth - sis.readUB(8); //customHeight - } - if (pictureSize == 1) { - sis.readUB(16); //customWidth - sis.readUB(16); //customHeight - } - int pictureType = (int) sis.readUB(2); - switch (pictureType) { - case 0: //intra - frameType = 1; //keyframe - break; - case 1://inter - frameType = 2; - break; - case 2: //disposable - frameType = 3; - break; - } - } - - baos.write(tag.videoData); - flv.writeTag(new FLVTAG((int) Math.floor(i * 1000.0f / ((float) swf.frameRate)), new VIDEODATA(frameType, videoStream.codecID, baos.toByteArray()))); - } - return fos.toByteArray(); - } -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.exporters; + +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.RunnableIOEx; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; +import com.jpexs.decompiler.flash.exporters.settings.MovieExportSettings; +import com.jpexs.decompiler.flash.flv.FLVOutputStream; +import com.jpexs.decompiler.flash.flv.FLVTAG; +import com.jpexs.decompiler.flash.flv.VIDEODATA; +import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.VideoFrameTag; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class MovieExporter { + + public List exportMovies(AbortRetryIgnoreHandler handler, String outdir, List tags, final MovieExportSettings settings) throws IOException { + List ret = new ArrayList<>(); + if (tags.isEmpty()) { + return ret; + } + File foutdir = new File(outdir); + if (!foutdir.exists()) { + if (!foutdir.mkdirs()) { + if (!foutdir.exists()) { + throw new IOException("Cannot create directory " + outdir); + } + } + } + for (Tag t : tags) { + if (t instanceof DefineVideoStreamTag) { + final DefineVideoStreamTag videoStream = (DefineVideoStreamTag) t; + final File file = new File(outdir + File.separator + ((DefineVideoStreamTag) t).getCharacterExportFileName() + ".flv"); + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(exportMovie(videoStream, settings.mode)); + } + } + }, handler).run(); + + } + } + return ret; + } + + public byte[] exportMovie(DefineVideoStreamTag videoStream, MovieExportMode mode) throws IOException { + SWF swf = videoStream.getSwf(); + HashMap frames = new HashMap<>(); + SWF.populateVideoFrames(videoStream.characterID, swf.tags, frames); + if (frames.isEmpty()) { + return new byte[0]; + } + + //double ms = 1000.0f / ((float) frameRate); + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + //CopyOutputStream cos = new CopyOutputStream(fos, new FileInputStream("f:\\trunk\\testdata\\xfl\\xfl\\_obj\\streamvideo 7.flv")); + OutputStream tos = fos; + FLVOutputStream flv = new FLVOutputStream(tos); + flv.writeHeader(false, true); + //flv.writeTag(new FLVTAG(0, SCRIPTDATA.onMetaData(ms * frames.size() / 1000.0, videoStream.width, videoStream.height, 0, frameRate, videoStream.codecID, 0, 0, false, 0, fileSize))); + int horizontalAdjustment = 0; + int verticalAdjustment = 0; + for (int i = 0; i < frames.size(); i++) { + VideoFrameTag tag = frames.get(i); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + int frameType = 1; + + if ((videoStream.codecID == DefineVideoStreamTag.CODEC_VP6) + || (videoStream.codecID == DefineVideoStreamTag.CODEC_VP6_ALPHA)) { + SWFInputStream sis = new SWFInputStream(tag.videoData, swf.version); + if (videoStream.codecID == DefineVideoStreamTag.CODEC_VP6_ALPHA) { + sis.readUI24(); //offsetToAlpha + } + int frameMode = (int) sis.readUB(1); + + if (frameMode == 0) { + frameType = 1; //intra + } else { + frameType = 2; //inter + } + sis.readUB(6); //qp + int marker = (int) sis.readUB(1); + if (frameMode == 0) { + int version = (int) sis.readUB(5); + int version2 = (int) sis.readUB(2); + sis.readUB(1);//interlace + if (marker == 1 || version2 == 0) { + sis.readUI16();//offset + } + int dim_y = sis.readUI8(); + int dim_x = sis.readUI8(); + sis.readUI8(); //render_y + sis.readUI8(); //render_x + horizontalAdjustment = (int) (dim_x * Math.ceil(((double) videoStream.width) / (double) dim_x)) - videoStream.width; + verticalAdjustment = (int) (dim_y * Math.ceil(((double) videoStream.height) / (double) dim_y)) - videoStream.height; + + } + + SWFOutputStream sos = new SWFOutputStream(baos, swf.version); + sos.writeUB(4, horizontalAdjustment); + sos.writeUB(4, verticalAdjustment); + } + if (videoStream.codecID == DefineVideoStreamTag.CODEC_SORENSON_H263) { + SWFInputStream sis = new SWFInputStream(tag.videoData, swf.version); + sis.readUB(17);//pictureStartCode + sis.readUB(5); //version + sis.readUB(8); //temporalReference + int pictureSize = (int) sis.readUB(3); //pictureSize + if (pictureSize == 0) { + sis.readUB(8); //customWidth + sis.readUB(8); //customHeight + } + if (pictureSize == 1) { + sis.readUB(16); //customWidth + sis.readUB(16); //customHeight + } + int pictureType = (int) sis.readUB(2); + switch (pictureType) { + case 0: //intra + frameType = 1; //keyframe + break; + case 1://inter + frameType = 2; + break; + case 2: //disposable + frameType = 3; + break; + } + } + + baos.write(tag.videoData); + flv.writeTag(new FLVTAG((int) Math.floor(i * 1000.0f / ((float) swf.frameRate)), new VIDEODATA(frameType, videoStream.codecID, baos.toByteArray()))); + } + return fos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java b/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java index cded3d21f..9c95d31b5 100644 --- a/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java +++ b/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java @@ -1,147 +1,147 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.exporters; - -import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; -import com.jpexs.decompiler.flash.RetryTask; -import com.jpexs.decompiler.flash.RunnableIOEx; -import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode; -import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings; -import com.jpexs.decompiler.flash.flv.AUDIODATA; -import com.jpexs.decompiler.flash.flv.FLVOutputStream; -import com.jpexs.decompiler.flash.flv.FLVTAG; -import com.jpexs.decompiler.flash.tags.DefineSoundTag; -import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; -import com.jpexs.decompiler.flash.tags.base.SoundTag; -import com.jpexs.decompiler.flash.types.sound.SoundFormat; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class SoundExporter { - - public List exportSounds(AbortRetryIgnoreHandler handler, String outdir, List tags, final SoundExportSettings settings) throws IOException { - List ret = new ArrayList<>(); - if (tags.isEmpty()) { - return ret; - } - File foutdir = new File(outdir); - if (!foutdir.exists()) { - if (!foutdir.mkdirs()) { - if (!foutdir.exists()) { - throw new IOException("Cannot create directory " + outdir); - } - } - } - for (Tag t : tags) { - File newfile = null; - int id = 0; - if (t instanceof DefineSoundTag) { - id = ((DefineSoundTag) t).soundId; - } - - if (t instanceof SoundTag) { - final SoundTag st = (SoundTag) t; - - String ext = "wav"; - SoundFormat fmt = st.getSoundFormat(); - switch (fmt.getNativeExportFormat()) { - case SoundFormat.EXPORT_MP3: - if (settings.mode.hasMP3()) { - ext = "mp3"; - } - break; - case SoundFormat.EXPORT_FLV: - if (settings.mode.hasFlv()) { - ext = "flv"; - } - break; - } - if (settings.mode == SoundExportMode.FLV) { - ext = "flv"; - } - - final File file = new File(outdir + File.separator + st.getCharacterExportFileName() + "." + ext); - newfile = file; - new RetryTask(new RunnableIOEx() { - @Override - public void run() throws IOException { - try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) { - exportSound(os, st, settings.mode); - } - } - }, handler).run(); - - ret.add(newfile); - - } - - } - return ret; - } - - public byte[] exportSound(SoundTag t, SoundExportMode mode) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - exportSound(baos, t, mode); - return baos.toByteArray(); - } - - public void exportSound(OutputStream fos, SoundTag st, SoundExportMode mode) throws IOException { - SoundFormat fmt = st.getSoundFormat(); - int nativeFormat = fmt.getNativeExportFormat(); - - if (nativeFormat == SoundFormat.EXPORT_MP3 && mode.hasMP3()) { - fos.write(st.getRawSoundData()); - } else if ((nativeFormat == SoundFormat.EXPORT_FLV && mode.hasFlv()) || mode == SoundExportMode.FLV) { - if (st instanceof DefineSoundTag) { - FLVOutputStream flv = new FLVOutputStream(fos); - flv.writeHeader(true, false); - flv.writeTag(new FLVTAG(0, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), st.getRawSoundData()))); - } else if (st instanceof SoundStreamHeadTypeTag) { - SoundStreamHeadTypeTag sh = (SoundStreamHeadTypeTag) st; - FLVOutputStream flv = new FLVOutputStream(fos); - flv.writeHeader(true, false); - List blocks = sh.getBlocks(); - - int ms = (int) (1000.0f / ((float) ((Tag) st).getSwf().frameRate)); - for (int b = 0; b < blocks.size(); b++) { - byte[] data = blocks.get(b).getData(); - if (st.getSoundFormatId() == 2) { //MP3 - data = Arrays.copyOfRange(data, 4, data.length); - } - flv.writeTag(new FLVTAG(ms * b, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), data))); - } - } - } else { - fmt.createWav(new ByteArrayInputStream(st.getRawSoundData()), fos); - } - } - -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.exporters; + +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.RunnableIOEx; +import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode; +import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings; +import com.jpexs.decompiler.flash.flv.AUDIODATA; +import com.jpexs.decompiler.flash.flv.FLVOutputStream; +import com.jpexs.decompiler.flash.flv.FLVTAG; +import com.jpexs.decompiler.flash.tags.DefineSoundTag; +import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; +import com.jpexs.decompiler.flash.tags.base.SoundTag; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class SoundExporter { + + public List exportSounds(AbortRetryIgnoreHandler handler, String outdir, List tags, final SoundExportSettings settings) throws IOException { + List ret = new ArrayList<>(); + if (tags.isEmpty()) { + return ret; + } + File foutdir = new File(outdir); + if (!foutdir.exists()) { + if (!foutdir.mkdirs()) { + if (!foutdir.exists()) { + throw new IOException("Cannot create directory " + outdir); + } + } + } + for (Tag t : tags) { + File newfile = null; + int id = 0; + if (t instanceof DefineSoundTag) { + id = ((DefineSoundTag) t).soundId; + } + + if (t instanceof SoundTag) { + final SoundTag st = (SoundTag) t; + + String ext = "wav"; + SoundFormat fmt = st.getSoundFormat(); + switch (fmt.getNativeExportFormat()) { + case SoundFormat.EXPORT_MP3: + if (settings.mode.hasMP3()) { + ext = "mp3"; + } + break; + case SoundFormat.EXPORT_FLV: + if (settings.mode.hasFlv()) { + ext = "flv"; + } + break; + } + if (settings.mode == SoundExportMode.FLV) { + ext = "flv"; + } + + final File file = new File(outdir + File.separator + st.getCharacterExportFileName() + "." + ext); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) { + exportSound(os, st, settings.mode); + } + } + }, handler).run(); + + ret.add(newfile); + + } + + } + return ret; + } + + public byte[] exportSound(SoundTag t, SoundExportMode mode) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + exportSound(baos, t, mode); + return baos.toByteArray(); + } + + public void exportSound(OutputStream fos, SoundTag st, SoundExportMode mode) throws IOException { + SoundFormat fmt = st.getSoundFormat(); + int nativeFormat = fmt.getNativeExportFormat(); + + if (nativeFormat == SoundFormat.EXPORT_MP3 && mode.hasMP3()) { + fos.write(st.getRawSoundData()); + } else if ((nativeFormat == SoundFormat.EXPORT_FLV && mode.hasFlv()) || mode == SoundExportMode.FLV) { + if (st instanceof DefineSoundTag) { + FLVOutputStream flv = new FLVOutputStream(fos); + flv.writeHeader(true, false); + flv.writeTag(new FLVTAG(0, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), st.getRawSoundData()))); + } else if (st instanceof SoundStreamHeadTypeTag) { + SoundStreamHeadTypeTag sh = (SoundStreamHeadTypeTag) st; + FLVOutputStream flv = new FLVOutputStream(fos); + flv.writeHeader(true, false); + List blocks = sh.getBlocks(); + + int ms = (int) (1000.0f / ((float) ((Tag) st).getSwf().frameRate)); + for (int b = 0; b < blocks.size(); b++) { + byte[] data = blocks.get(b).streamSoundData; + if (st.getSoundFormatId() == 2) { //MP3 + data = Arrays.copyOfRange(data, 4, data.length); + } + flv.writeTag(new FLVTAG(ms * b, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), data))); + } + } + } else { + fmt.createWav(st.getRawSoundData(), fos); + } + } + +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java index 602bf0a98..1e7a11a75 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameClassicMenu.java @@ -500,11 +500,13 @@ public class MainFrameClassicMenu implements MainFrameMenu, ActionListener { View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE); } } + swf.clearModified(); } break; case ACTION_SAVE_AS: { SWF swf = mainFrame.panel.getCurrentSwf(); saveAs(swf, SaveFileMode.SAVEAS); + swf.clearModified(); } break; case ACTION_SAVE_AS_EXE: { diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index 7d19d58b0..c90141f7f 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -539,15 +539,6 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { } } - private void clearModified(SWF swf) { - for (Tag tag : swf.tags) { - if (tag.isModified()) { - tag.createOriginalData(); - tag.setModified(false); - } - } - } - @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { @@ -689,13 +680,13 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener { View.showMessageDialog(null, translate("error.file.save"), translate("error"), JOptionPane.ERROR_MESSAGE); } } - clearModified(swf); + swf.clearModified(); } break; case ACTION_SAVE_AS: { SWF swf = mainFrame.panel.getCurrentSwf(); saveAs(swf, SaveFileMode.SAVEAS); - clearModified(swf); + swf.clearModified(); } break; case ACTION_SAVE_AS_EXE: { diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 62cc5ed92..9bc89fc9a 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2222,7 +2222,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec try { SWF swf = it.getSwf(); if (it instanceof DefineBitsTag) { - DefineBitsJPEG2Tag jpeg2Tag = new DefineBitsJPEG2Tag(swf, it.getOriginalHeaderData(), it.getOriginalData(), it.getPos(), it.getCharacterId(), data); + DefineBitsJPEG2Tag jpeg2Tag = new DefineBitsJPEG2Tag(swf, it.getPos(), it.getOriginalLength(), it.getCharacterId(), data); jpeg2Tag.setModified(true); swf.tags.set(swf.tags.indexOf(it), jpeg2Tag); swf.updateCharacters(); diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 019b52b9a..9f0ad034e 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -515,7 +515,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { byte[] data; try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - SWFOutputStream sos2 = new SWFOutputStream(baos, 10); + SWFOutputStream sos2 = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); int width = swf.displayRect.Xmax - swf.displayRect.Xmin; int height = swf.displayRect.Ymax - swf.displayRect.Ymin; sos2.writeRECT(swf.displayRect); @@ -684,7 +684,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener { List actions; DoActionTag doa; - doa = new DoActionTag(swf, new byte[0], new byte[0], 0); + doa = new DoActionTag(swf, 0, 0); actions = ASMParser.parse(0, 0, false, "ConstantPool \"_root\" \"my_sound\" \"Sound\" \"my_define_sound\" \"attachSound\"\n" + "Push \"_root\"\n" diff --git a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java index de566a073..77db9564f 100644 --- a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java +++ b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java @@ -1,211 +1,210 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.gui; - -import com.jpexs.decompiler.flash.gui.player.MediaDisplay; -import com.jpexs.decompiler.flash.tags.base.SoundTag; -import com.jpexs.helpers.SoundPlayer; -import java.awt.Color; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.UnsupportedAudioFileException; - -/** - * - * @author JPEXS - */ -public class SoundTagPlayer implements MediaDisplay { - - private final SoundPlayer player; - - private Thread thr; - private int actualPos = 0; - private final SoundTag tag; - private final List listeners = new ArrayList<>(); - - public void addListener(PlayerListener l) { - listeners.add(l); - } - - public void removeListener(PlayerListener l) { - listeners.remove(l); - } - - public void fireFinished() { - for (PlayerListener l : listeners) { - l.playingFinished(); - } - } - - private static final int FRAME_DIVISOR = 8000; - - private int loops; - private boolean paused = true; - private final Object playLock = new Object(); - - public SoundTagPlayer(SoundTag tag, int loops) throws LineUnavailableException, IOException, UnsupportedAudioFileException { - this.tag = tag; - this.loops = loops; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ByteArrayInputStream bais = new ByteArrayInputStream(tag.getRawSoundData()); - tag.getSoundFormat().createWav(bais, baos); - player = new SoundPlayer(new ByteArrayInputStream(baos.toByteArray())); - } - - @Override - public synchronized int getCurrentFrame() { - - synchronized (playLock) { - if (isPlaying()) { - actualPos = (int) (player.getSamplePosition() / FRAME_DIVISOR); - } - return actualPos; - } - } - - @Override - public synchronized int getTotalFrames() { - - int ret = (int) (player.samplesCount() / FRAME_DIVISOR); - return ret; - } - - @Override - public synchronized void pause() { - if (!isPlaying()) { - paused = true; - return; - } - - synchronized (playLock) { - actualPos = (int) (player.getSamplePosition() / FRAME_DIVISOR); - } - - waitStop(); - } - - private void waitStop() { - synchronized (playLock) { - if (!paused) { - paused = true; - player.stop(); - try { - playLock.wait(); - } catch (InterruptedException ex) { - Logger.getLogger(SoundTagPlayer.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - } - - public void play(boolean async) { - - waitStop(); - Runnable r = new Runnable() { - - @Override - public void run() { - boolean playAgain = true; - while (playAgain) { - int startPos = 0; - synchronized (playLock) { - startPos = actualPos * FRAME_DIVISOR; - } - player.setPosition(startPos); - player.play(); - - synchronized (playLock) { - playAgain = !paused && loops > 0; - if (!paused) { - if (loops == 0) { - paused = true; - } else if (loops != Integer.MAX_VALUE) { - loops--; - } - } - if (playAgain) { - actualPos = 0; - } - } - } - - fireFinished(); - synchronized (playLock) { - playLock.notifyAll(); - } - } - }; - synchronized (playLock) { - paused = false; - } - if (async) { - thr = new Thread(r); - thr.start(); - } else { - r.run(); - } - - } - - @Override - public synchronized void play() { - play(true); - } - - @Override - public void rewind() { - gotoFrame(0); - } - - @Override - public boolean isPlaying() { - return player.isPlaying(); - } - - @Override - public synchronized void gotoFrame(int frame) { - pause(); - synchronized (playLock) { - actualPos = frame; - } - } - - @Override - public void setBackground(Color color) { - - } - - @Override - public int getFrameRate() { - if (player == null) { - return 1; - } - return (int) (player.getFrameRate() / FRAME_DIVISOR); - } - - @Override - public boolean isLoaded() { - return true; - } - -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.gui.player.MediaDisplay; +import com.jpexs.decompiler.flash.tags.base.SoundTag; +import com.jpexs.helpers.SoundPlayer; +import java.awt.Color; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * + * @author JPEXS + */ +public class SoundTagPlayer implements MediaDisplay { + + private final SoundPlayer player; + + private Thread thr; + private int actualPos = 0; + private final SoundTag tag; + private final List listeners = new ArrayList<>(); + + public void addListener(PlayerListener l) { + listeners.add(l); + } + + public void removeListener(PlayerListener l) { + listeners.remove(l); + } + + public void fireFinished() { + for (PlayerListener l : listeners) { + l.playingFinished(); + } + } + + private static final int FRAME_DIVISOR = 8000; + + private int loops; + private boolean paused = true; + private final Object playLock = new Object(); + + public SoundTagPlayer(SoundTag tag, int loops) throws LineUnavailableException, IOException, UnsupportedAudioFileException { + this.tag = tag; + this.loops = loops; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + tag.getSoundFormat().createWav(tag.getRawSoundData(), baos); + player = new SoundPlayer(new ByteArrayInputStream(baos.toByteArray())); + } + + @Override + public synchronized int getCurrentFrame() { + + synchronized (playLock) { + if (isPlaying()) { + actualPos = (int) (player.getSamplePosition() / FRAME_DIVISOR); + } + return actualPos; + } + } + + @Override + public synchronized int getTotalFrames() { + + int ret = (int) (player.samplesCount() / FRAME_DIVISOR); + return ret; + } + + @Override + public synchronized void pause() { + if (!isPlaying()) { + paused = true; + return; + } + + synchronized (playLock) { + actualPos = (int) (player.getSamplePosition() / FRAME_DIVISOR); + } + + waitStop(); + } + + private void waitStop() { + synchronized (playLock) { + if (!paused) { + paused = true; + player.stop(); + try { + playLock.wait(); + } catch (InterruptedException ex) { + Logger.getLogger(SoundTagPlayer.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + } + + public void play(boolean async) { + + waitStop(); + Runnable r = new Runnable() { + + @Override + public void run() { + boolean playAgain = true; + while (playAgain) { + int startPos = 0; + synchronized (playLock) { + startPos = actualPos * FRAME_DIVISOR; + } + player.setPosition(startPos); + player.play(); + + synchronized (playLock) { + playAgain = !paused && loops > 0; + if (!paused) { + if (loops == 0) { + paused = true; + } else if (loops != Integer.MAX_VALUE) { + loops--; + } + } + if (playAgain) { + actualPos = 0; + } + } + } + + fireFinished(); + synchronized (playLock) { + playLock.notifyAll(); + } + } + }; + synchronized (playLock) { + paused = false; + } + if (async) { + thr = new Thread(r); + thr.start(); + } else { + r.run(); + } + + } + + @Override + public synchronized void play() { + play(true); + } + + @Override + public void rewind() { + gotoFrame(0); + } + + @Override + public boolean isPlaying() { + return player.isPlaying(); + } + + @Override + public synchronized void gotoFrame(int frame) { + pause(); + synchronized (playLock) { + actualPos = frame; + } + } + + @Override + public void setBackground(Color color) { + + } + + @Override + public int getFrameRate() { + if (player == null) { + return 1; + } + return (int) (player.getFrameRate() / FRAME_DIVISOR); + } + + @Override + public boolean isLoaded() { + return true; + } + +} diff --git a/src/com/jpexs/decompiler/flash/tags/CSMTextSettingsTag.java b/src/com/jpexs/decompiler/flash/tags/CSMTextSettingsTag.java index 81b9d402a..cca2bd1ab 100644 --- a/src/com/jpexs/decompiler/flash/tags/CSMTextSettingsTag.java +++ b/src/com/jpexs/decompiler/flash/tags/CSMTextSettingsTag.java @@ -1,115 +1,112 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class CSMTextSettingsTag extends Tag { - - @SWFType(BasicType.UI16) - public int textID; - - @SWFType(value = BasicType.UB, count = 2) - public int useFlashType; - - @SWFType(value = BasicType.UB, count = 3) - public int gridFit; - - @Reserved - @SWFType(value = BasicType.UB, count = 3) - public int reserved; - - @SWFType(value = BasicType.FLOAT) //F32 = FLOAT - public float thickness; - - @SWFType(value = BasicType.FLOAT) //F32 = FLOAT - public float sharpness; - - @Reserved - @SWFType(BasicType.UI8) - public int reserved2; - - public static final int ID = 74; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(textID); - sos.writeUB(2, useFlashType); - sos.writeUB(3, gridFit); - sos.writeUB(3, reserved); - sos.writeFLOAT(thickness); //F32 = FLOAT - sos.writeFLOAT(sharpness); //F32 = FLOAT - sos.writeUI8(reserved2); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public CSMTextSettingsTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "CSMTextSettings", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - textID = sis.readUI16(); - useFlashType = (int) sis.readUB(2); - gridFit = (int) sis.readUB(3); - reserved = (int) sis.readUB(3); - thickness = sis.readFLOAT(); //F32 = FLOAT - sharpness = sis.readFLOAT(); //F32 = FLOAT - reserved2 = sis.readUI8(); //reserved - } - - /** - * Returns string representation of the object - * - * @return String representation of the object - */ - @Override - public String toString() { - return "CSMTextSettings"; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class CSMTextSettingsTag extends Tag { + + @SWFType(BasicType.UI16) + public int textID; + + @SWFType(value = BasicType.UB, count = 2) + public int useFlashType; + + @SWFType(value = BasicType.UB, count = 3) + public int gridFit; + + @Reserved + @SWFType(value = BasicType.UB, count = 3) + public int reserved; + + @SWFType(value = BasicType.FLOAT) //F32 = FLOAT + public float thickness; + + @SWFType(value = BasicType.FLOAT) //F32 = FLOAT + public float sharpness; + + @Reserved + @SWFType(BasicType.UI8) + public int reserved2; + + public static final int ID = 74; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(textID); + sos.writeUB(2, useFlashType); + sos.writeUB(3, gridFit); + sos.writeUB(3, reserved); + sos.writeFLOAT(thickness); //F32 = FLOAT + sos.writeFLOAT(sharpness); //F32 = FLOAT + sos.writeUI8(reserved2); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public CSMTextSettingsTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "CSMTextSettings", pos, length); + textID = sis.readUI16(); + useFlashType = (int) sis.readUB(2); + gridFit = (int) sis.readUB(3); + reserved = (int) sis.readUB(3); + thickness = sis.readFLOAT(); //F32 = FLOAT + sharpness = sis.readFLOAT(); //F32 = FLOAT + reserved2 = sis.readUI8(); //reserved + } + + /** + * Returns string representation of the object + * + * @return String representation of the object + */ + @Override + public String toString() { + return "CSMTextSettings"; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java b/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java index 7297e22c6..8fe8e7bea 100644 --- a/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DebugIDTag.java @@ -1,72 +1,69 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DebugIDTag extends Tag { - - @SWFType(value = BasicType.UI8, count = 16) - public byte[] debugId; - - public static final int ID = 63; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.write(debugId); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DebugIDTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DebugID", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - debugId = sis.readBytesEx(16); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DebugIDTag extends Tag { + + @SWFType(value = BasicType.UI8, count = 16) + public byte[] debugId; + + public static final int ID = 63; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.write(debugId); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DebugIDTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DebugID", pos, length); + debugId = sis.readBytesEx(16); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java b/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java index 1cc7e87b9..5ddd9cf1b 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java @@ -1,75 +1,72 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class DefineBinaryDataTag extends CharacterTag { - - @SWFType(BasicType.UI16) - public int tag; - - public byte[] binaryData; - - @Reserved - @SWFType(BasicType.UI32) - public long reserved; - - public static final int ID = 87; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(tag); - sos.writeUI32(reserved); - sos.write(binaryData); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - public DefineBinaryDataTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBinaryData", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - tag = sis.readUI16(); - reserved = sis.readUI32(); - binaryData = sis.readBytesEx(sis.available()); - } - - @Override - public int getCharacterId() { - return tag; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class DefineBinaryDataTag extends CharacterTag { + + @SWFType(BasicType.UI16) + public int tag; + + public byte[] binaryData; + + @Reserved + @SWFType(BasicType.UI32) + public long reserved; + + public static final int ID = 87; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(tag); + sos.writeUI32(reserved); + sos.write(binaryData); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + public DefineBinaryDataTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBinaryData", pos, length); + tag = sis.readUI16(); + reserved = sis.readUI32(); + binaryData = sis.readBytesEx(sis.available()); + } + + @Override + public int getCharacterId() { + return tag; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG2Tag.java index d307caf91..fd207d221 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG2Tag.java @@ -1,102 +1,101 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.AloneTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import javax.imageio.ImageIO; - -public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI8) - public byte[] imageData; - - public static final int ID = 21; - - @Override - public int getCharacterId() { - return characterID; - } - - @Override - public String getImageFormat() { - return ImageTag.getImageFormat(imageData); - } - - @Override - public InputStream getImageData() { - if (SWF.hasErrorHeader(imageData)) { - return new ByteArrayInputStream(imageData, 4, imageData.length - 4); - } - return new ByteArrayInputStream(imageData); - } - - @Override - public SerializableImage getImage() { - try { - return new SerializableImage(ImageIO.read(getImageData())); - } catch (IOException ex) { - } - return null; - } - - public DefineBitsJPEG2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBitsJPEG2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - imageData = sis.readBytesEx(sis.available()); - } - - public DefineBitsJPEG2Tag(SWF swf, byte[] headerData, byte[] data, long pos, int characterID, byte[] imageData) throws IOException { - super(swf, ID, "DefineBitsJPEG2", headerData, data, pos); - this.characterID = characterID; - this.imageData = imageData; - } - - @Override - public void setImage(byte[] data) { - imageData = data; - setModified(true); - } - - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.write(imageData); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.AloneTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.SerializableImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.imageio.ImageIO; + +public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI8) + public byte[] imageData; + + public static final int ID = 21; + + @Override + public int getCharacterId() { + return characterID; + } + + @Override + public String getImageFormat() { + return ImageTag.getImageFormat(imageData); + } + + @Override + public InputStream getImageData() { + if (SWF.hasErrorHeader(imageData)) { + return new ByteArrayInputStream(imageData, 4, imageData.length - 4); + } + return new ByteArrayInputStream(imageData); + } + + @Override + public SerializableImage getImage() { + try { + return new SerializableImage(ImageIO.read(getImageData())); + } catch (IOException ex) { + } + return null; + } + + public DefineBitsJPEG2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBitsJPEG2", pos, length); + characterID = sis.readUI16(); + imageData = sis.readBytesEx(sis.available()); + } + + public DefineBitsJPEG2Tag(SWF swf, long pos, int length, int characterID, byte[] imageData) throws IOException { + super(swf, ID, "DefineBitsJPEG2", pos, length); + this.characterID = characterID; + this.imageData = imageData; + } + + @Override + public void setImage(byte[] data) { + imageData = data; + setModified(true); + } + + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.write(imageData); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG3Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG3Tag.java index 980dce3fa..ef207be2d 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG3Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG3Tag.java @@ -1,138 +1,137 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.AloneTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import javax.imageio.ImageIO; - -public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI8) - public byte[] imageData; - - @SWFType(BasicType.UI8) - public byte[] bitmapAlphaData; - - public static final int ID = 35; - - @Override - public int getCharacterId() { - return characterID; - } - - @Override - public void setImage(byte[] data) throws IOException { - if (ImageTag.getImageFormat(data).equals("jpg")) { - SerializableImage image = new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))); - byte[] ba = new byte[image.getWidth() * image.getHeight()]; - for (int i = 0; i < ba.length; i++) { - ba[i] = (byte) 255; - } - bitmapAlphaData = ba; - } else { - bitmapAlphaData = new byte[0]; - } - imageData = data; - setModified(true); - } - - @Override - public String getImageFormat() { - String fmt = ImageTag.getImageFormat(imageData); - if (fmt.equals("jpg")) { - fmt = "png"; //transparency - } - return fmt; - } - - @Override - public InputStream getImageData() { - return null; - } - - @Override - public SerializableImage getImage() { - try { - InputStream stream; - if (SWF.hasErrorHeader(imageData)) { - stream = new ByteArrayInputStream(imageData, 4, imageData.length - 4); - } else { - stream = new ByteArrayInputStream(imageData); - } - SerializableImage img = new SerializableImage(ImageIO.read(stream)); - if (bitmapAlphaData.length == 0) { - return img; - } - SerializableImage img2 = new SerializableImage(img.getWidth(), img.getHeight(), SerializableImage.TYPE_INT_ARGB_PRE); - for (int y = 0; y < img.getHeight(); y++) { - for (int x = 0; x < img.getWidth(); x++) { - int val = img.getRGB(x, y); - int a = bitmapAlphaData[x + y * img.getWidth()] & 0xff; - val = (val & 0xffffff) | (a << 24); - img2.setRGB(x, y, colorToInt(multiplyAlpha(intToColor(val)))); - } - } - return img2; - } catch (IOException ex) { - } - return null; - } - - public DefineBitsJPEG3Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBitsJPEG3", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - long alphaDataOffset = sis.readUI32(); - imageData = sis.readBytesEx(alphaDataOffset); - bitmapAlphaData = sis.readBytesZlib(sis.available()); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.writeUI32(imageData.length); - sos.write(imageData); - sos.writeBytesZlib(bitmapAlphaData); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.AloneTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.SerializableImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.imageio.ImageIO; + +public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI8) + public byte[] imageData; + + @SWFType(BasicType.UI8) + public byte[] bitmapAlphaData; + + public static final int ID = 35; + + @Override + public int getCharacterId() { + return characterID; + } + + @Override + public void setImage(byte[] data) throws IOException { + if (ImageTag.getImageFormat(data).equals("jpg")) { + SerializableImage image = new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))); + byte[] ba = new byte[image.getWidth() * image.getHeight()]; + for (int i = 0; i < ba.length; i++) { + ba[i] = (byte) 255; + } + bitmapAlphaData = ba; + } else { + bitmapAlphaData = new byte[0]; + } + imageData = data; + setModified(true); + } + + @Override + public String getImageFormat() { + String fmt = ImageTag.getImageFormat(imageData); + if (fmt.equals("jpg")) { + fmt = "png"; //transparency + } + return fmt; + } + + @Override + public InputStream getImageData() { + return null; + } + + @Override + public SerializableImage getImage() { + try { + InputStream stream; + if (SWF.hasErrorHeader(imageData)) { + stream = new ByteArrayInputStream(imageData, 4, imageData.length - 4); + } else { + stream = new ByteArrayInputStream(imageData); + } + SerializableImage img = new SerializableImage(ImageIO.read(stream)); + if (bitmapAlphaData.length == 0) { + return img; + } + SerializableImage img2 = new SerializableImage(img.getWidth(), img.getHeight(), SerializableImage.TYPE_INT_ARGB_PRE); + for (int y = 0; y < img.getHeight(); y++) { + for (int x = 0; x < img.getWidth(); x++) { + int val = img.getRGB(x, y); + int a = bitmapAlphaData[x + y * img.getWidth()] & 0xff; + val = (val & 0xffffff) | (a << 24); + img2.setRGB(x, y, colorToInt(multiplyAlpha(intToColor(val)))); + } + } + return img2; + } catch (IOException ex) { + } + return null; + } + + public DefineBitsJPEG3Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBitsJPEG3", pos, length); + characterID = sis.readUI16(); + long alphaDataOffset = sis.readUI32(); + imageData = sis.readBytesEx(alphaDataOffset); + bitmapAlphaData = sis.readBytesZlib(sis.available()); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.writeUI32(imageData.length); + sos.write(imageData); + sos.writeBytesZlib(bitmapAlphaData); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG4Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG4Tag.java index d314058cc..2291cd549 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG4Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBitsJPEG4Tag.java @@ -1,151 +1,149 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.AloneTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import javax.imageio.ImageIO; - -/** - * - * - * @author JPEXS - */ -public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI16) - public int deblockParam; - - @SWFType(BasicType.UI8) - public byte[] imageData; - - @SWFType(BasicType.UI8) - public byte[] bitmapAlphaData; - - public static final int ID = 90; - - @Override - public int getCharacterId() { - return characterID; - } - - @Override - public String getImageFormat() { - String fmt = ImageTag.getImageFormat(imageData); - if (fmt.equals("jpg")) { - fmt = "png"; //transparency - } - return fmt; - } - - @Override - public void setImage(byte[] data) { - imageData = data; - if (ImageTag.getImageFormat(data).equals("jpg")) { - SerializableImage image = getImage(); - byte[] ba = new byte[image.getWidth() * image.getHeight()]; - for (int i = 0; i < ba.length; i++) { - ba[i] = (byte) 255; - } - bitmapAlphaData = ba; - } else { - bitmapAlphaData = new byte[0]; - } - setModified(true); - } - - @Override - public InputStream getImageData() { - return null; - } - - @Override - public SerializableImage getImage() { - try { - SerializableImage img = new SerializableImage(ImageIO.read(new ByteArrayInputStream(imageData))); - if (bitmapAlphaData.length == 0) { - return img; - } - SerializableImage img2 = new SerializableImage(img.getWidth(), img.getHeight(), SerializableImage.TYPE_INT_ARGB); - for (int y = 0; y < img.getHeight(); y++) { - for (int x = 0; x < img.getWidth(); x++) { - int val = img.getRGB(x, y); - int a = bitmapAlphaData[x + y * img.getWidth()] & 0xff; - val = (val & 0xffffff) | (a << 24); - img2.setRGB(x, y, colorToInt(multiplyAlpha(intToColor(val)))); - } - } - return img2; - } catch (IOException ex) { - } - return null; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.writeUI32(imageData.length); - sos.writeUI16(deblockParam); - sos.write(imageData); - sos.write(bitmapAlphaData); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineBitsJPEG4Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBitsJPEG4", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - long alphaDataOffset = sis.readUI32(); - deblockParam = sis.readUI16(); - imageData = sis.readBytesEx(alphaDataOffset); - bitmapAlphaData = sis.readBytesEx(sis.available()); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.AloneTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.SerializableImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.imageio.ImageIO; + +/** + * + * + * @author JPEXS + */ +public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI16) + public int deblockParam; + + @SWFType(BasicType.UI8) + public byte[] imageData; + + @SWFType(BasicType.UI8) + public byte[] bitmapAlphaData; + + public static final int ID = 90; + + @Override + public int getCharacterId() { + return characterID; + } + + @Override + public String getImageFormat() { + String fmt = ImageTag.getImageFormat(imageData); + if (fmt.equals("jpg")) { + fmt = "png"; //transparency + } + return fmt; + } + + @Override + public void setImage(byte[] data) { + imageData = data; + if (ImageTag.getImageFormat(data).equals("jpg")) { + SerializableImage image = getImage(); + byte[] ba = new byte[image.getWidth() * image.getHeight()]; + for (int i = 0; i < ba.length; i++) { + ba[i] = (byte) 255; + } + bitmapAlphaData = ba; + } else { + bitmapAlphaData = new byte[0]; + } + setModified(true); + } + + @Override + public InputStream getImageData() { + return null; + } + + @Override + public SerializableImage getImage() { + try { + SerializableImage img = new SerializableImage(ImageIO.read(new ByteArrayInputStream(imageData))); + if (bitmapAlphaData.length == 0) { + return img; + } + SerializableImage img2 = new SerializableImage(img.getWidth(), img.getHeight(), SerializableImage.TYPE_INT_ARGB); + for (int y = 0; y < img.getHeight(); y++) { + for (int x = 0; x < img.getWidth(); x++) { + int val = img.getRGB(x, y); + int a = bitmapAlphaData[x + y * img.getWidth()] & 0xff; + val = (val & 0xffffff) | (a << 24); + img2.setRGB(x, y, colorToInt(multiplyAlpha(intToColor(val)))); + } + } + return img2; + } catch (IOException ex) { + } + return null; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.writeUI32(imageData.length); + sos.writeUI16(deblockParam); + sos.write(imageData); + sos.write(bitmapAlphaData); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineBitsJPEG4Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBitsJPEG4", pos, length); + characterID = sis.readUI16(); + long alphaDataOffset = sis.readUI32(); + deblockParam = sis.readUI16(); + imageData = sis.readBytesEx(alphaDataOffset); + bitmapAlphaData = sis.readBytesEx(sis.available()); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java index 25bac5eae..bb3b30bee 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java @@ -1,220 +1,221 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.AloneTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; -import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA; -import com.jpexs.decompiler.flash.types.ARGB; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Conditional; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; -import java.awt.Color; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.zip.InflaterInputStream; -import javax.imageio.ImageIO; - -public class DefineBitsLossless2Tag extends ImageTag implements AloneTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI8) - public int bitmapFormat; - - @SWFType(BasicType.UI16) - public int bitmapWidth; - - @SWFType(BasicType.UI16) - public int bitmapHeight; - - @SWFType(BasicType.UI8) - @Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED}) - public int bitmapColorTableSize; - - public byte[] zlibBitmapData; //TODO: Parse ALPHACOLORMAPDATA,ALPHABITMAPDATA - - public static final int FORMAT_8BIT_COLORMAPPED = 3; - public static final int FORMAT_32BIT_ARGB = 5; - - public static final int ID = 36; - - @Override - public int getCharacterId() { - return characterID; - } - - @Override - public void setImage(byte[] data) throws IOException { - SerializableImage image = new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))); - ALPHABITMAPDATA bitmapData = new ALPHABITMAPDATA(); - bitmapFormat = DefineBitsLosslessTag.FORMAT_24BIT_RGB; - bitmapWidth = image.getWidth(); - bitmapHeight = image.getHeight(); - bitmapData.bitmapPixelData = new ARGB[bitmapWidth * bitmapHeight]; - int pos = 0; - for (int y = 0; y < bitmapHeight; y++) { - for (int x = 0; x < bitmapWidth; x++) { - int argb = image.getRGB(x, y); - int a = (argb >> 24) & 0xff; - int r = (argb >> 16) & 0xff; - int g = (argb >> 8) & 0xff; - int b = (argb) & 0xff; - - r = r * a / 255; - g = g * a / 255; - b = b * a / 255; - - bitmapData.bitmapPixelData[pos] = new ARGB(); - bitmapData.bitmapPixelData[pos].alpha = a; - bitmapData.bitmapPixelData[pos].red = r; - bitmapData.bitmapPixelData[pos].green = g; - bitmapData.bitmapPixelData[pos].blue = b; - pos++; - } - } - ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion()); - sos.writeALPHABITMAPDATA(bitmapData, bitmapFormat, bitmapWidth, bitmapHeight); - ByteArrayOutputStream zlibOS = new ByteArrayOutputStream(); - SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion()); - sos2.writeBytesZlib(bitmapDataOS.toByteArray()); - zlibBitmapData = zlibOS.toByteArray(); - decompressed = false; - setModified(true); - } - - public DefineBitsLossless2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBitsLossless2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - bitmapFormat = sis.readUI8(); - bitmapWidth = sis.readUI16(); - bitmapHeight = sis.readUI16(); - if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { - bitmapColorTableSize = sis.readUI8(); - } - zlibBitmapData = sis.readBytesEx(sis.available()); - } - private ALPHACOLORMAPDATA colorMapData; - private ALPHABITMAPDATA bitmapData; - private boolean decompressed = false; - - public ALPHACOLORMAPDATA getColorMapData() { - if (!decompressed) { - uncompressData(); - } - return colorMapData; - } - - public ALPHABITMAPDATA getBitmapData() { - if (!decompressed) { - uncompressData(); - } - return bitmapData; - } - - private void uncompressData() { - try { - SWFInputStream sis = new SWFInputStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData)), 10); - if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { - colorMapData = sis.readALPHACOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight); - } - if (bitmapFormat == FORMAT_32BIT_ARGB) { - bitmapData = sis.readALPHABITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight); - } - } catch (IOException ex) { - } - decompressed = true; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.writeUI8(bitmapFormat); - sos.writeUI16(bitmapWidth); - sos.writeUI16(bitmapHeight); - if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { - sos.writeUI8(bitmapColorTableSize); - } - sos.write(zlibBitmapData); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - @Override - public String getImageFormat() { - return "png"; - } - - @Override - public InputStream getImageData() { - return null; - } - - @Override - public SerializableImage getImage() { - SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_ARGB); - ALPHACOLORMAPDATA colorMapData = null; - ALPHABITMAPDATA bitmapData = null; - if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED) { - colorMapData = getColorMapData(); - } - if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB) { - bitmapData = getBitmapData(); - } - int pos32aligned = 0; - int pos = 0; - for (int y = 0; y < bitmapHeight; y++) { - for (int x = 0; x < bitmapWidth; x++) { - Color c = null; - if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) { - c = (multiplyAlpha(colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff].toColor())); - } - if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB)) { - c = (multiplyAlpha(bitmapData.bitmapPixelData[pos].toColor())); - } - bi.setRGB(x, y, c.getRGB()); - pos32aligned++; - pos++; - } - while ((pos32aligned % 4 != 0)) { - pos32aligned++; - } - } - return bi; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.AloneTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; +import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA; +import com.jpexs.decompiler.flash.types.ARGB; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.Helper; +import com.jpexs.helpers.SerializableImage; +import java.awt.Color; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.InflaterInputStream; +import javax.imageio.ImageIO; + +public class DefineBitsLossless2Tag extends ImageTag implements AloneTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI8) + public int bitmapFormat; + + @SWFType(BasicType.UI16) + public int bitmapWidth; + + @SWFType(BasicType.UI16) + public int bitmapHeight; + + @SWFType(BasicType.UI8) + @Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED}) + public int bitmapColorTableSize; + + public byte[] zlibBitmapData; //TODO: Parse ALPHACOLORMAPDATA,ALPHABITMAPDATA + + public static final int FORMAT_8BIT_COLORMAPPED = 3; + public static final int FORMAT_32BIT_ARGB = 5; + + public static final int ID = 36; + + @Override + public int getCharacterId() { + return characterID; + } + + @Override + public void setImage(byte[] data) throws IOException { + SerializableImage image = new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))); + ALPHABITMAPDATA bitmapData = new ALPHABITMAPDATA(); + bitmapFormat = DefineBitsLosslessTag.FORMAT_24BIT_RGB; + bitmapWidth = image.getWidth(); + bitmapHeight = image.getHeight(); + bitmapData.bitmapPixelData = new ARGB[bitmapWidth * bitmapHeight]; + int pos = 0; + for (int y = 0; y < bitmapHeight; y++) { + for (int x = 0; x < bitmapWidth; x++) { + int argb = image.getRGB(x, y); + int a = (argb >> 24) & 0xff; + int r = (argb >> 16) & 0xff; + int g = (argb >> 8) & 0xff; + int b = (argb) & 0xff; + + r = r * a / 255; + g = g * a / 255; + b = b * a / 255; + + bitmapData.bitmapPixelData[pos] = new ARGB(); + bitmapData.bitmapPixelData[pos].alpha = a; + bitmapData.bitmapPixelData[pos].red = r; + bitmapData.bitmapPixelData[pos].green = g; + bitmapData.bitmapPixelData[pos].blue = b; + pos++; + } + } + ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion()); + sos.writeALPHABITMAPDATA(bitmapData, bitmapFormat, bitmapWidth, bitmapHeight); + ByteArrayOutputStream zlibOS = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion()); + sos2.writeBytesZlib(bitmapDataOS.toByteArray()); + zlibBitmapData = zlibOS.toByteArray(); + decompressed = false; + setModified(true); + } + + public DefineBitsLossless2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBitsLossless2", pos, length); + characterID = sis.readUI16(); + bitmapFormat = sis.readUI8(); + bitmapWidth = sis.readUI16(); + bitmapHeight = sis.readUI16(); + if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { + bitmapColorTableSize = sis.readUI8(); + } + zlibBitmapData = sis.readBytesEx(sis.available()); + } + private ALPHACOLORMAPDATA colorMapData; + private ALPHABITMAPDATA bitmapData; + private boolean decompressed = false; + + public ALPHACOLORMAPDATA getColorMapData() { + if (!decompressed) { + uncompressData(); + } + return colorMapData; + } + + public ALPHABITMAPDATA getBitmapData() { + if (!decompressed) { + uncompressData(); + } + return bitmapData; + } + + private void uncompressData() { + try { + SWFInputStream sis = new SWFInputStream(Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData))), SWF.DEFAULT_VERSION); + if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { + colorMapData = sis.readALPHACOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight); + } + if (bitmapFormat == FORMAT_32BIT_ARGB) { + bitmapData = sis.readALPHABITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight); + } + } catch (IOException ex) { + } + decompressed = true; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.writeUI8(bitmapFormat); + sos.writeUI16(bitmapWidth); + sos.writeUI16(bitmapHeight); + if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { + sos.writeUI8(bitmapColorTableSize); + } + sos.write(zlibBitmapData); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + @Override + public String getImageFormat() { + return "png"; + } + + @Override + public InputStream getImageData() { + return null; + } + + @Override + public SerializableImage getImage() { + SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_ARGB); + ALPHACOLORMAPDATA colorMapData = null; + ALPHABITMAPDATA bitmapData = null; + if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED) { + colorMapData = getColorMapData(); + } + if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB) { + bitmapData = getBitmapData(); + } + int pos32aligned = 0; + int pos = 0; + for (int y = 0; y < bitmapHeight; y++) { + for (int x = 0; x < bitmapWidth; x++) { + Color c = null; + if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) { + c = (multiplyAlpha(colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff].toColor())); + } + if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB)) { + c = (multiplyAlpha(bitmapData.bitmapPixelData[pos].toColor())); + } + bi.setRGB(x, y, c.getRGB()); + pos32aligned++; + pos++; + } + while ((pos32aligned % 4 != 0)) { + pos32aligned++; + } + } + return bi; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java b/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java index c376fe950..2fe5d7971 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java @@ -1,225 +1,226 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.AloneTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.types.BITMAPDATA; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.COLORMAPDATA; -import com.jpexs.decompiler.flash.types.PIX24; -import com.jpexs.decompiler.flash.types.RGB; -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.helpers.SerializableImage; -import java.awt.Color; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.zip.InflaterInputStream; -import javax.imageio.ImageIO; - -public class DefineBitsLosslessTag extends ImageTag implements AloneTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI8) - public int bitmapFormat; - - @SWFType(BasicType.UI16) - public int bitmapWidth; - - @SWFType(BasicType.UI16) - public int bitmapHeight; - - @SWFType(BasicType.UI8) - @Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED}) - public int bitmapColorTableSize; - - public byte[] zlibBitmapData; //TODO: Parse COLORMAPDATA,BITMAPDATA - public static final int FORMAT_8BIT_COLORMAPPED = 3; - public static final int FORMAT_15BIT_RGB = 4; - public static final int FORMAT_24BIT_RGB = 5; - - @Internal - private COLORMAPDATA colorMapData; - @Internal - private BITMAPDATA bitmapData; - @Internal - private boolean decompressed = false; - - public static final int ID = 20; - - @Override - public void setImage(byte[] data) throws IOException { - SerializableImage image = new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))); - bitmapFormat = FORMAT_24BIT_RGB; - bitmapWidth = image.getWidth(); - bitmapHeight = image.getHeight(); - bitmapData = new BITMAPDATA(); - bitmapData.bitmapPixelDataPix24 = new PIX24[bitmapWidth * bitmapHeight]; - int pos = 0; - for (int y = 0; y < bitmapHeight; y++) { - for (int x = 0; x < bitmapWidth; x++) { - int argb = image.getRGB(x, y); - //int a = (argb >> 24) & 0xff; - int r = (argb >> 16) & 0xff; - int g = (argb >> 8) & 0xff; - int b = (argb) & 0xff; - bitmapData.bitmapPixelDataPix24[pos] = new PIX24(); - bitmapData.bitmapPixelDataPix24[pos].red = r; - bitmapData.bitmapPixelDataPix24[pos].green = g; - bitmapData.bitmapPixelDataPix24[pos].blue = b; - bitmapData.bitmapPixelDataPix24[pos].reserved = 0xff; //documentation says 0, but image is sometimes broken with 0, so there is 0xff, which works (maybe alpha?) - pos++; - } - } - ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion()); - sos.writeBITMAPDATA(bitmapData, bitmapFormat, bitmapWidth, bitmapHeight); - ByteArrayOutputStream zlibOS = new ByteArrayOutputStream(); - SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion()); - sos2.writeBytesZlib(bitmapDataOS.toByteArray()); - zlibBitmapData = zlibOS.toByteArray(); - decompressed = false; - setModified(true); - } - - @Override - public InputStream getImageData() { - return null; - } - - @Override - public SerializableImage getImage() { - SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_RGB); - COLORMAPDATA colorMapData = null; - BITMAPDATA bitmapData = null; - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) { - colorMapData = getColorMapData(); - } - if ((bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) || (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB)) { - bitmapData = getBitmapData(); - } - int pos32aligned = 0; - int pos = 0; - for (int y = 0; y < bitmapHeight; y++) { - for (int x = 0; x < bitmapWidth; x++) { - Color c = null; - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) { - RGB color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff]; - c = (new Color(color.red, color.green, color.blue)); - } - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { - c = (new Color(bitmapData.bitmapPixelDataPix15[pos].red * 8, bitmapData.bitmapPixelDataPix15[pos].green * 8, bitmapData.bitmapPixelDataPix15[pos].blue * 8)); - } - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { - c = (new Color(bitmapData.bitmapPixelDataPix24[pos].red, bitmapData.bitmapPixelDataPix24[pos].green, bitmapData.bitmapPixelDataPix24[pos].blue)); - } - bi.setRGB(x, y, c.getRGB()); - pos32aligned++; - pos++; - } - while ((pos32aligned % 4 != 0)) { - pos32aligned++; - } - } - return bi; - } - - @Override - public int getCharacterId() { - return characterID; - } - - public COLORMAPDATA getColorMapData() { - if (!decompressed) { - uncompressData(); - } - return colorMapData; - } - - public BITMAPDATA getBitmapData() { - if (!decompressed) { - uncompressData(); - } - return bitmapData; - } - - private void uncompressData() { - try { - SWFInputStream sis = new SWFInputStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData)), 10); - if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { - colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight); - } - if ((bitmapFormat == FORMAT_15BIT_RGB) || (bitmapFormat == FORMAT_24BIT_RGB)) { - bitmapData = sis.readBITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight); - } - } catch (IOException ex) { - } - decompressed = true; - } - - public DefineBitsLosslessTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBitsLossless", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - bitmapFormat = sis.readUI8(); - bitmapWidth = sis.readUI16(); - bitmapHeight = sis.readUI16(); - if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { - bitmapColorTableSize = sis.readUI8(); - } - zlibBitmapData = sis.readBytesEx(sis.available()); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.writeUI8(bitmapFormat); - sos.writeUI16(bitmapWidth); - sos.writeUI16(bitmapHeight); - if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { - sos.writeUI8(bitmapColorTableSize); - } - sos.write(zlibBitmapData); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - @Override - public String getImageFormat() { - return "png"; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.AloneTag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.BITMAPDATA; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.COLORMAPDATA; +import com.jpexs.decompiler.flash.types.PIX24; +import com.jpexs.decompiler.flash.types.RGB; +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.helpers.Helper; +import com.jpexs.helpers.SerializableImage; +import java.awt.Color; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.InflaterInputStream; +import javax.imageio.ImageIO; + +public class DefineBitsLosslessTag extends ImageTag implements AloneTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI8) + public int bitmapFormat; + + @SWFType(BasicType.UI16) + public int bitmapWidth; + + @SWFType(BasicType.UI16) + public int bitmapHeight; + + @SWFType(BasicType.UI8) + @Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED}) + public int bitmapColorTableSize; + + public byte[] zlibBitmapData; //TODO: Parse COLORMAPDATA,BITMAPDATA + public static final int FORMAT_8BIT_COLORMAPPED = 3; + public static final int FORMAT_15BIT_RGB = 4; + public static final int FORMAT_24BIT_RGB = 5; + + @Internal + private COLORMAPDATA colorMapData; + @Internal + private BITMAPDATA bitmapData; + @Internal + private boolean decompressed = false; + + public static final int ID = 20; + + @Override + public void setImage(byte[] data) throws IOException { + SerializableImage image = new SerializableImage(ImageIO.read(new ByteArrayInputStream(data))); + bitmapFormat = FORMAT_24BIT_RGB; + bitmapWidth = image.getWidth(); + bitmapHeight = image.getHeight(); + bitmapData = new BITMAPDATA(); + bitmapData.bitmapPixelDataPix24 = new PIX24[bitmapWidth * bitmapHeight]; + int pos = 0; + for (int y = 0; y < bitmapHeight; y++) { + for (int x = 0; x < bitmapWidth; x++) { + int argb = image.getRGB(x, y); + //int a = (argb >> 24) & 0xff; + int r = (argb >> 16) & 0xff; + int g = (argb >> 8) & 0xff; + int b = (argb) & 0xff; + bitmapData.bitmapPixelDataPix24[pos] = new PIX24(); + bitmapData.bitmapPixelDataPix24[pos].red = r; + bitmapData.bitmapPixelDataPix24[pos].green = g; + bitmapData.bitmapPixelDataPix24[pos].blue = b; + bitmapData.bitmapPixelDataPix24[pos].reserved = 0xff; //documentation says 0, but image is sometimes broken with 0, so there is 0xff, which works (maybe alpha?) + pos++; + } + } + ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion()); + sos.writeBITMAPDATA(bitmapData, bitmapFormat, bitmapWidth, bitmapHeight); + ByteArrayOutputStream zlibOS = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion()); + sos2.writeBytesZlib(bitmapDataOS.toByteArray()); + zlibBitmapData = zlibOS.toByteArray(); + decompressed = false; + setModified(true); + } + + @Override + public InputStream getImageData() { + return null; + } + + @Override + public SerializableImage getImage() { + SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_RGB); + COLORMAPDATA colorMapData = null; + BITMAPDATA bitmapData = null; + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) { + colorMapData = getColorMapData(); + } + if ((bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) || (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB)) { + bitmapData = getBitmapData(); + } + int pos32aligned = 0; + int pos = 0; + for (int y = 0; y < bitmapHeight; y++) { + for (int x = 0; x < bitmapWidth; x++) { + Color c = null; + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) { + RGB color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff]; + c = (new Color(color.red, color.green, color.blue)); + } + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) { + c = (new Color(bitmapData.bitmapPixelDataPix15[pos].red * 8, bitmapData.bitmapPixelDataPix15[pos].green * 8, bitmapData.bitmapPixelDataPix15[pos].blue * 8)); + } + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) { + c = (new Color(bitmapData.bitmapPixelDataPix24[pos].red, bitmapData.bitmapPixelDataPix24[pos].green, bitmapData.bitmapPixelDataPix24[pos].blue)); + } + bi.setRGB(x, y, c.getRGB()); + pos32aligned++; + pos++; + } + while ((pos32aligned % 4 != 0)) { + pos32aligned++; + } + } + return bi; + } + + @Override + public int getCharacterId() { + return characterID; + } + + public COLORMAPDATA getColorMapData() { + if (!decompressed) { + uncompressData(); + } + return colorMapData; + } + + public BITMAPDATA getBitmapData() { + if (!decompressed) { + uncompressData(); + } + return bitmapData; + } + + private void uncompressData() { + try { + SWFInputStream sis = new SWFInputStream(Helper.readStream(new InflaterInputStream(new ByteArrayInputStream(zlibBitmapData))), SWF.DEFAULT_VERSION); + if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { + colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight); + } + if ((bitmapFormat == FORMAT_15BIT_RGB) || (bitmapFormat == FORMAT_24BIT_RGB)) { + bitmapData = sis.readBITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight); + } + } catch (IOException ex) { + } + decompressed = true; + } + + public DefineBitsLosslessTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBitsLossless", pos, length); + characterID = sis.readUI16(); + bitmapFormat = sis.readUI8(); + bitmapWidth = sis.readUI16(); + bitmapHeight = sis.readUI16(); + if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { + bitmapColorTableSize = sis.readUI8(); + } + zlibBitmapData = sis.readBytesEx(sis.available()); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.writeUI8(bitmapFormat); + sos.writeUI16(bitmapWidth); + sos.writeUI16(bitmapHeight); + if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) { + sos.writeUI8(bitmapColorTableSize); + } + sos.write(zlibBitmapData); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + @Override + public String getImageFormat() { + return "png"; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java b/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java index 83dfdc067..513ffb46b 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineBitsTag.java @@ -1,127 +1,126 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.SerializableImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import javax.imageio.ImageIO; - -public class DefineBitsTag extends ImageTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI8) - public byte[] jpegData; - - @Internal - private JPEGTablesTag jtt = null; - public static final int ID = 6; - - @Override - public void setImage(byte[] data) { - throw new UnsupportedOperationException("Set image is not supported for DefineBits"); - } - - @Override - public boolean importSupported() { - // importing a new image will replace the current DefineBitsTag with a new DefineBitsJPEG2Tag - return true; - } - - public DefineBitsTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineBits", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - jpegData = sis.readBytesEx(sis.available()); - } - - private void getJPEGTables() { - if (jtt == null) { - for (Tag t : swf.tags) { - if (t instanceof JPEGTablesTag) { - jtt = (JPEGTablesTag) t; - break; - } - } - } - } - - @Override - public InputStream getImageData() { - return null; - } - - @Override - public SerializableImage getImage() { - getJPEGTables(); - if ((jtt != null)) { - try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - byte[] jttdata = jtt.getData(); - if (jttdata.length != 0) { - baos.write(jttdata, SWF.hasErrorHeader(jttdata) ? 4 : 0, jttdata.length - (SWF.hasErrorHeader(jttdata) ? 6 : 2)); - baos.write(jpegData, SWF.hasErrorHeader(jpegData) ? 6 : 2, jpegData.length - (SWF.hasErrorHeader(jttdata) ? 6 : 2)); - } else { - baos.write(jpegData, 0, jpegData.length); - } - return new SerializableImage(ImageIO.read(new ByteArrayInputStream(baos.toByteArray()))); - } catch (IOException ex) { - return null; - } - } - return null; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.write(jpegData); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - @Override - public int getCharacterId() { - return characterID; - } - - @Override - public String getImageFormat() { - return "jpg"; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.SerializableImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.imageio.ImageIO; + +public class DefineBitsTag extends ImageTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI8) + public byte[] jpegData; + + @Internal + private JPEGTablesTag jtt = null; + public static final int ID = 6; + + @Override + public void setImage(byte[] data) { + throw new UnsupportedOperationException("Set image is not supported for DefineBits"); + } + + @Override + public boolean importSupported() { + // importing a new image will replace the current DefineBitsTag with a new DefineBitsJPEG2Tag + return true; + } + + public DefineBitsTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineBits", pos, length); + characterID = sis.readUI16(); + jpegData = sis.readBytesEx(sis.available()); + } + + private void getJPEGTables() { + if (jtt == null) { + for (Tag t : swf.tags) { + if (t instanceof JPEGTablesTag) { + jtt = (JPEGTablesTag) t; + break; + } + } + } + } + + @Override + public InputStream getImageData() { + return null; + } + + @Override + public SerializableImage getImage() { + getJPEGTables(); + if ((jtt != null)) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + byte[] jttdata = jtt.jpegData; + if (jttdata.length != 0) { + baos.write(jttdata, SWF.hasErrorHeader(jttdata) ? 4 : 0, jttdata.length - (SWF.hasErrorHeader(jttdata) ? 6 : 2)); + baos.write(jpegData, SWF.hasErrorHeader(jpegData) ? 6 : 2, jpegData.length - (SWF.hasErrorHeader(jttdata) ? 6 : 2)); + } else { + baos.write(jpegData, 0, jpegData.length); + } + return new SerializableImage(ImageIO.read(new ByteArrayInputStream(baos.toByteArray()))); + } catch (IOException ex) { + return null; + } + } + return null; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.write(jpegData); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + @Override + public int getCharacterId() { + return characterID; + } + + @Override + public String getImageFormat() { + return "jpg"; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index d3c2ffa4d..ad7304965 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -16,8 +16,7 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -103,9 +102,8 @@ public class DefineButton2Tag extends ButtonTag implements Container { * @param pos * @throws IOException */ - public DefineButton2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineButton2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineButton2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineButton2", pos, length); buttonId = sis.readUI16(); reserved = (int) sis.readUB(7); trackAsMenu = sis.readUB(1) == 1; @@ -123,11 +121,10 @@ public class DefineButton2Tag extends ButtonTag implements Container { */ @Override public byte[] getData() { - ByteArrayInputStream bais = new ByteArrayInputStream(super.data); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; if (Configuration.debugCopy.get()) { + ByteArrayInputStream bais = new ByteArrayInputStream(getOriginalData()); os = new CopyOutputStream(os, bais); } SWFOutputStream sos = new SWFOutputStream(os, getVersion()); @@ -137,39 +134,16 @@ public class DefineButton2Tag extends ButtonTag implements Container { sos.writeUB(1, trackAsMenu ? 1 : 0); ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - OutputStream os2 = baos2; - byte[] origbrdata = null; - if (Configuration.debugCopy.get()) { - SWFInputStream sis = new SWFInputStream(bais, getVersion()); - int len = sis.readUI16(); - if (len != 0) { - origbrdata = sis.readBytesEx(len - 2); - os2 = new CopyOutputStream(os2, new ByteArrayInputStream(origbrdata)); - } - } - try (SWFOutputStream sos2 = new SWFOutputStream(os2, getVersion())) { + try (SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion())) { sos2.writeBUTTONRECORDList(characters, true); } byte[] brdata = baos2.toByteArray(); - if (Configuration.debugCopy.get()) { - if (origbrdata != null) { - if (origbrdata.length != brdata.length) { - /*throw nso*/ - } - } - } - if (Configuration.debugCopy.get()) { - sos = new SWFOutputStream(baos, getVersion()); - } if ((actions == null) || (actions.isEmpty())) { sos.writeUI16(0); } else { sos.writeUI16(2 + brdata.length); } sos.write(brdata); - if (Configuration.debugCopy.get()) { - sos = new SWFOutputStream(new CopyOutputStream(baos, bais), getVersion()); - } sos.writeBUTTONCONDACTIONList(actions); sos.close(); } catch (IOException e) { diff --git a/src/com/jpexs/decompiler/flash/tags/DefineButtonCxformTag.java b/src/com/jpexs/decompiler/flash/tags/DefineButtonCxformTag.java index 4e84d802d..b0ed57631 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineButtonCxformTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineButtonCxformTag.java @@ -1,75 +1,72 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.CXFORM; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineButtonCxformTag extends Tag { - - @SWFType(BasicType.UI16) - public int buttonId; - public CXFORM buttonColorTransform; - public static final int ID = 23; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(buttonId); - sos.writeCXFORM(buttonColorTransform); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineButtonCxformTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineButtonCxform", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - buttonId = sis.readUI16(); - buttonColorTransform = sis.readCXFORM(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.CXFORM; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineButtonCxformTag extends Tag { + + @SWFType(BasicType.UI16) + public int buttonId; + public CXFORM buttonColorTransform; + public static final int ID = 23; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(buttonId); + sos.writeCXFORM(buttonColorTransform); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineButtonCxformTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineButtonCxform", pos, length); + buttonId = sis.readUI16(); + buttonColorTransform = sis.readCXFORM(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java b/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java index e4e576b09..852234181 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java @@ -1,130 +1,127 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineButtonSoundTag extends CharacterIdTag { - - @SWFType(BasicType.UI16) - public int buttonId; - - @SWFType(BasicType.UI16) - public int buttonSoundChar0; - - public SOUNDINFO buttonSoundInfo0; - - @SWFType(BasicType.UI16) - public int buttonSoundChar1; - - public SOUNDINFO buttonSoundInfo1; - - @SWFType(BasicType.UI16) - public int buttonSoundChar2; - - public SOUNDINFO buttonSoundInfo2; - - @SWFType(BasicType.UI16) - public int buttonSoundChar3; - - public SOUNDINFO buttonSoundInfo3; - public static final int ID = 17; - - @Override - public int getCharacterId() { - return buttonId; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(buttonId); - sos.writeUI16(buttonSoundChar0); - if (buttonSoundChar0 != 0) { - sos.writeSOUNDINFO(buttonSoundInfo0); - } - sos.writeUI16(buttonSoundChar1); - if (buttonSoundChar1 != 0) { - sos.writeSOUNDINFO(buttonSoundInfo1); - } - sos.writeUI16(buttonSoundChar2); - if (buttonSoundChar2 != 0) { - sos.writeSOUNDINFO(buttonSoundInfo2); - } - sos.writeUI16(buttonSoundChar3); - if (buttonSoundChar3 != 0) { - sos.writeSOUNDINFO(buttonSoundInfo3); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineButtonSoundTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineButtonSound", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - buttonId = sis.readUI16(); - buttonSoundChar0 = sis.readUI16(); - if (buttonSoundChar0 != 0) { - buttonSoundInfo0 = sis.readSOUNDINFO(); - } - buttonSoundChar1 = sis.readUI16(); - if (buttonSoundChar1 != 0) { - buttonSoundInfo1 = sis.readSOUNDINFO(); - } - buttonSoundChar2 = sis.readUI16(); - if (buttonSoundChar2 != 0) { - buttonSoundInfo2 = sis.readSOUNDINFO(); - } - buttonSoundChar3 = sis.readUI16(); - if (buttonSoundChar3 != 0) { - buttonSoundInfo3 = sis.readSOUNDINFO(); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineButtonSoundTag extends CharacterIdTag { + + @SWFType(BasicType.UI16) + public int buttonId; + + @SWFType(BasicType.UI16) + public int buttonSoundChar0; + + public SOUNDINFO buttonSoundInfo0; + + @SWFType(BasicType.UI16) + public int buttonSoundChar1; + + public SOUNDINFO buttonSoundInfo1; + + @SWFType(BasicType.UI16) + public int buttonSoundChar2; + + public SOUNDINFO buttonSoundInfo2; + + @SWFType(BasicType.UI16) + public int buttonSoundChar3; + + public SOUNDINFO buttonSoundInfo3; + public static final int ID = 17; + + @Override + public int getCharacterId() { + return buttonId; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(buttonId); + sos.writeUI16(buttonSoundChar0); + if (buttonSoundChar0 != 0) { + sos.writeSOUNDINFO(buttonSoundInfo0); + } + sos.writeUI16(buttonSoundChar1); + if (buttonSoundChar1 != 0) { + sos.writeSOUNDINFO(buttonSoundInfo1); + } + sos.writeUI16(buttonSoundChar2); + if (buttonSoundChar2 != 0) { + sos.writeSOUNDINFO(buttonSoundInfo2); + } + sos.writeUI16(buttonSoundChar3); + if (buttonSoundChar3 != 0) { + sos.writeSOUNDINFO(buttonSoundInfo3); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineButtonSoundTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineButtonSound", pos, length); + buttonId = sis.readUI16(); + buttonSoundChar0 = sis.readUI16(); + if (buttonSoundChar0 != 0) { + buttonSoundInfo0 = sis.readSOUNDINFO(); + } + buttonSoundChar1 = sis.readUI16(); + if (buttonSoundChar1 != 0) { + buttonSoundInfo1 = sis.readSOUNDINFO(); + } + buttonSoundChar2 = sis.readUI16(); + if (buttonSoundChar2 != 0) { + buttonSoundInfo2 = sis.readSOUNDINFO(); + } + buttonSoundChar3 = sis.readUI16(); + if (buttonSoundChar3 != 0) { + buttonSoundInfo3 = sis.readSOUNDINFO(); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index d4767cec9..c676e7d7c 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -17,8 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.action.Action; @@ -102,9 +101,8 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { * @param pos * @throws IOException */ - public DefineButtonTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineButton", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineButtonTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineButton", pos, length); buttonId = sis.readUI16(); characters = sis.readBUTTONRECORDList(false); //actions = sis.readActionList(); @@ -122,7 +120,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); } SWFOutputStream sos = new SWFOutputStream(os, getVersion()); try { @@ -171,15 +169,8 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { @Override public List getActions() throws InterruptedException { try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int prevLength = 0; - if (previousTag != null) { - byte[] prevData = previousTag.getData(); - baos.write(prevData); - prevLength = prevData.length; - } - baos.write(actionBytes); - MemoryInputStream rri = new MemoryInputStream(baos.toByteArray()); + int prevLength = (int) (getPos() + hdrSize); + MemoryInputStream rri = new MemoryInputStream(swf.uncompressedData); rri.seek(prevLength); List list = ActionListReader.readActionListTimeout(listeners, getPos() + hdrSize - prevLength, rri, getVersion(), prevLength, -1, toString()/*FIXME?*/); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java b/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java index 8e582f869..6b89958ae 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; @@ -700,9 +700,8 @@ public class DefineEditTextTag extends TextTag { * @param pos * @throws IOException */ - public DefineEditTextTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineEditText", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineEditTextTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineEditText", pos, length); characterID = sis.readUI16(); bounds = sis.readRECT(); hasText = sis.readUB(1) == 1; diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java index a15c0cdcc..4adb7203c 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java @@ -1,445 +1,443 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.FontTag; -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.shaperecords.SHAPERECORD; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.Font; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JPanel; - -/** - * - * - * @author JPEXS - */ -public class DefineFont2Tag extends FontTag { - - @SWFType(BasicType.UI16) - public int fontId; - - public boolean fontFlagsHasLayout; - public boolean fontFlagsShiftJIS; - public boolean fontFlagsSmallText; - public boolean fontFlagsANSI; - public boolean fontFlagsWideOffsets; - public boolean fontFlagsWideCodes; - public boolean fontFlagsItalic; - public boolean fontFlagsBold; - public LANGCODE languageCode; - public String fontName; - @Internal - public int numGlyphs; - public List glyphShapeTable; - - @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") - public List codeTable; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontAscent; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontDescent; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public int fontLeading; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public List fontAdvanceTable; - - @Conditional("fontFlagsHasLayout") - public List fontBoundsTable; - - public KERNINGRECORD[] fontKerningTable; - public static final int ID = 48; - - @Override - public boolean isSmall() { - return fontFlagsSmallText; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - if (fontFlagsHasLayout) { - return fontAdvanceTable.get(glyphIndex); - } else { - return -1; - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, getVersion()); - try { - sos.writeUI16(fontId); - sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeLANGCODE(languageCode); - byte[] fontNameBytes = Utf8Helper.getBytes(fontName); - sos.writeUI8(fontNameBytes.length); - sos.write(fontNameBytes); - sos.writeUI16(numGlyphs); - - List offsetTable = new ArrayList<>(); - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); - 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) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) offset); - } - sos.write(baGlyphShapes); - - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - sos.writeUI16(codeTable.get(i)); - } else { - sos.writeUI8(codeTable.get(i)); - } - } - } - if (fontFlagsHasLayout) { - sos.writeSI16(fontAscent); - sos.writeSI16(fontDescent); - sos.writeSI16(fontLeading); - for (int i = 0; i < numGlyphs; i++) { - sos.writeSI16(fontAdvanceTable.get(i)); - } - for (int i = 0; i < numGlyphs; i++) { - sos.writeRECT(fontBoundsTable.get(i)); - } - sos.writeUI16(fontKerningTable.length); - for (int k = 0; k < fontKerningTable.length; k++) { - sos.writeKERNINGRECORD(fontKerningTable[k], fontFlagsWideCodes); - } - } - - } catch (IOException e) { - } - return baos.toByteArray(); - } - - public DefineFont2Tag(SWF swf) throws IOException { - super(swf, ID, "DefineFont2", null, null, 0); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineFont2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFont2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontId = sis.readUI16(); - fontFlagsHasLayout = sis.readUB(1) == 1; - fontFlagsShiftJIS = sis.readUB(1) == 1; - fontFlagsSmallText = sis.readUB(1) == 1; - fontFlagsANSI = sis.readUB(1) == 1; - fontFlagsWideOffsets = sis.readUB(1) == 1; - fontFlagsWideCodes = sis.readUB(1) == 1; - fontFlagsItalic = sis.readUB(1) == 1; - fontFlagsBold = sis.readUB(1) == 1; - languageCode = sis.readLANGCODE(); - int fontNameLen = sis.readUI8(); - if (swf.version >= 6) { - fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); - } else { - fontName = new String(sis.readBytesEx(fontNameLen)); - } - numGlyphs = sis.readUI16(); - //offsetTable = new long[numGlyphs]; - for (int i = 0; i < numGlyphs; i++) { //offsetTable - if (fontFlagsWideOffsets) { - sis.readUI32(); - } else { - sis.readUI16(); - } - } - if (numGlyphs > 0) { //codeTableOffset - if (fontFlagsWideOffsets) { - sis.readUI32(); - } else { - sis.readUI16(); - } - } - - glyphShapeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - glyphShapeTable.add(sis.readSHAPE(1, false)); - } - - codeTable = new ArrayList<>(); //[numGlyphs]; - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - codeTable.add(sis.readUI16()); - } else { - codeTable.add(sis.readUI8()); - } - } - if (fontFlagsHasLayout) { - fontAscent = sis.readSI16(); - fontDescent = sis.readSI16(); - fontLeading = sis.readSI16(); - fontAdvanceTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontAdvanceTable.add(sis.readSI16()); - } - fontBoundsTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontBoundsTable.add(sis.readRECT()); - } - int kerningCount = sis.readUI16(); - fontKerningTable = new KERNINGRECORD[kerningCount]; - for (int i = 0; i < kerningCount; i++) { - fontKerningTable[i] = sis.readKERNINGRECORD(fontFlagsWideCodes); - } - } - } - - @Override - public int getFontId() { - return fontId; - } - - @Override - public List getGlyphShapeTable() { - return glyphShapeTable; - } - - @Override - public int getCharacterId() { - return fontId; - } - - @Override - public char glyphToChar(int glyphIndex) { - return (char) (int) codeTable.get(glyphIndex); - } - - @Override - public int charToGlyph(char c) { - return codeTable.indexOf((int) c); - } - - @Override - public String getFontName() { - String ret = fontName; - if (ret.contains("" + (char) 0)) { - ret = ret.substring(0, ret.indexOf(0)); - } - return ret; - } - - @Override - public boolean isBold() { - return fontFlagsBold; - } - - @Override - public boolean isItalic() { - return fontFlagsItalic; - } - - @Override - public boolean isSmallEditable() { - return true; - } - - @Override - public boolean isBoldEditable() { - return true; - } - - @Override - public boolean isItalicEditable() { - return true; - } - - @Override - public void setSmall(boolean value) { - fontFlagsSmallText = value; - } - - @Override - public void setBold(boolean value) { - fontFlagsBold = value; - } - - @Override - public void setItalic(boolean value) { - fontFlagsItalic = value; - } - - @Override - public int getDivider() { - return 1; - } - - @Override - public int getAscent() { - if (fontFlagsHasLayout) { - return fontAscent; - } - return -1; - } - - @Override - public int getDescent() { - if (fontFlagsHasLayout) { - return fontDescent; - } - return -1; - } - - @Override - public int getLeading() { - if (fontFlagsHasLayout) { - return fontLeading; - } - return -1; - } - - @Override - public void addCharacter(char character, String fontName) { - int fontStyle = getFontStyle(); - - SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character); - - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = codeTable.size(); - } - - if (!exists) { - shiftGlyphIndices(fontId, pos); - glyphShapeTable.add(pos, shp); - codeTable.add(pos, (int) character); - } else { - glyphShapeTable.set(pos, shp); - } - - if (fontFlagsHasLayout) { - Font fnt = new Font(fontName, fontStyle, 1024); - if (!exists) { - fontBoundsTable.add(pos, shp.getBounds()); - fontAdvanceTable.add(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); - } else { - fontBoundsTable.set(pos, shp.getBounds()); - fontAdvanceTable.set(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); - } - } - if (!exists) { - numGlyphs++; - } - } - - @Override - public String getCharacters(List tags) { - String ret = ""; - for (int i : codeTable) { - ret += (char) i; - } - return ret; - } - - @Override - public boolean hasLayout() { - return fontFlagsHasLayout; - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - char c1 = glyphToChar(glyphIndex); - char c2 = glyphToChar(nextGlyphIndex); - int kerningAdjustment = 0; - for (KERNINGRECORD ker : fontKerningTable) { - if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { - kerningAdjustment = ker.fontKerningAdjustment; - break; - } - } - return kerningAdjustment; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.FontTag; +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.shaperecords.SHAPERECORD; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.Font; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; + +/** + * + * + * @author JPEXS + */ +public class DefineFont2Tag extends FontTag { + + @SWFType(BasicType.UI16) + public int fontId; + + public boolean fontFlagsHasLayout; + public boolean fontFlagsShiftJIS; + public boolean fontFlagsSmallText; + public boolean fontFlagsANSI; + public boolean fontFlagsWideOffsets; + public boolean fontFlagsWideCodes; + public boolean fontFlagsItalic; + public boolean fontFlagsBold; + public LANGCODE languageCode; + public String fontName; + @Internal + public int numGlyphs; + public List glyphShapeTable; + + @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") + public List codeTable; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontAscent; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontDescent; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public int fontLeading; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public List fontAdvanceTable; + + @Conditional("fontFlagsHasLayout") + public List fontBoundsTable; + + public KERNINGRECORD[] fontKerningTable; + public static final int ID = 48; + + @Override + public boolean isSmall() { + return fontFlagsSmallText; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + if (fontFlagsHasLayout) { + return fontAdvanceTable.get(glyphIndex); + } else { + return -1; + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, getVersion()); + try { + sos.writeUI16(fontId); + sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeLANGCODE(languageCode); + byte[] fontNameBytes = Utf8Helper.getBytes(fontName); + sos.writeUI8(fontNameBytes.length); + sos.write(fontNameBytes); + sos.writeUI16(numGlyphs); + + List offsetTable = new ArrayList<>(); + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); + 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) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) offset); + } + sos.write(baGlyphShapes); + + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + sos.writeUI16(codeTable.get(i)); + } else { + sos.writeUI8(codeTable.get(i)); + } + } + } + if (fontFlagsHasLayout) { + sos.writeSI16(fontAscent); + sos.writeSI16(fontDescent); + sos.writeSI16(fontLeading); + for (int i = 0; i < numGlyphs; i++) { + sos.writeSI16(fontAdvanceTable.get(i)); + } + for (int i = 0; i < numGlyphs; i++) { + sos.writeRECT(fontBoundsTable.get(i)); + } + sos.writeUI16(fontKerningTable.length); + for (int k = 0; k < fontKerningTable.length; k++) { + sos.writeKERNINGRECORD(fontKerningTable[k], fontFlagsWideCodes); + } + } + + } catch (IOException e) { + } + return baos.toByteArray(); + } + + public DefineFont2Tag(SWF swf) throws IOException { + super(swf, ID, "DefineFont2", 0, 0); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineFont2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFont2", pos, length); + fontId = sis.readUI16(); + fontFlagsHasLayout = sis.readUB(1) == 1; + fontFlagsShiftJIS = sis.readUB(1) == 1; + fontFlagsSmallText = sis.readUB(1) == 1; + fontFlagsANSI = sis.readUB(1) == 1; + fontFlagsWideOffsets = sis.readUB(1) == 1; + fontFlagsWideCodes = sis.readUB(1) == 1; + fontFlagsItalic = sis.readUB(1) == 1; + fontFlagsBold = sis.readUB(1) == 1; + languageCode = sis.readLANGCODE(); + int fontNameLen = sis.readUI8(); + if (swf.version >= 6) { + fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); + } else { + fontName = new String(sis.readBytesEx(fontNameLen)); + } + numGlyphs = sis.readUI16(); + //offsetTable = new long[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { //offsetTable + if (fontFlagsWideOffsets) { + sis.readUI32(); + } else { + sis.readUI16(); + } + } + if (numGlyphs > 0) { //codeTableOffset + if (fontFlagsWideOffsets) { + sis.readUI32(); + } else { + sis.readUI16(); + } + } + + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + glyphShapeTable.add(sis.readSHAPE(1, false)); + } + + codeTable = new ArrayList<>(); //[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + codeTable.add(sis.readUI16()); + } else { + codeTable.add(sis.readUI8()); + } + } + if (fontFlagsHasLayout) { + fontAscent = sis.readSI16(); + fontDescent = sis.readSI16(); + fontLeading = sis.readSI16(); + fontAdvanceTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontAdvanceTable.add(sis.readSI16()); + } + fontBoundsTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontBoundsTable.add(sis.readRECT()); + } + int kerningCount = sis.readUI16(); + fontKerningTable = new KERNINGRECORD[kerningCount]; + for (int i = 0; i < kerningCount; i++) { + fontKerningTable[i] = sis.readKERNINGRECORD(fontFlagsWideCodes); + } + } + } + + @Override + public int getFontId() { + return fontId; + } + + @Override + public List getGlyphShapeTable() { + return glyphShapeTable; + } + + @Override + public int getCharacterId() { + return fontId; + } + + @Override + public char glyphToChar(int glyphIndex) { + return (char) (int) codeTable.get(glyphIndex); + } + + @Override + public int charToGlyph(char c) { + return codeTable.indexOf((int) c); + } + + @Override + public String getFontName() { + String ret = fontName; + if (ret.contains("" + (char) 0)) { + ret = ret.substring(0, ret.indexOf(0)); + } + return ret; + } + + @Override + public boolean isBold() { + return fontFlagsBold; + } + + @Override + public boolean isItalic() { + return fontFlagsItalic; + } + + @Override + public boolean isSmallEditable() { + return true; + } + + @Override + public boolean isBoldEditable() { + return true; + } + + @Override + public boolean isItalicEditable() { + return true; + } + + @Override + public void setSmall(boolean value) { + fontFlagsSmallText = value; + } + + @Override + public void setBold(boolean value) { + fontFlagsBold = value; + } + + @Override + public void setItalic(boolean value) { + fontFlagsItalic = value; + } + + @Override + public int getDivider() { + return 1; + } + + @Override + public int getAscent() { + if (fontFlagsHasLayout) { + return fontAscent; + } + return -1; + } + + @Override + public int getDescent() { + if (fontFlagsHasLayout) { + return fontDescent; + } + return -1; + } + + @Override + public int getLeading() { + if (fontFlagsHasLayout) { + return fontLeading; + } + return -1; + } + + @Override + public void addCharacter(char character, String fontName) { + int fontStyle = getFontStyle(); + + SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character); + + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = codeTable.size(); + } + + if (!exists) { + shiftGlyphIndices(fontId, pos); + glyphShapeTable.add(pos, shp); + codeTable.add(pos, (int) character); + } else { + glyphShapeTable.set(pos, shp); + } + + if (fontFlagsHasLayout) { + Font fnt = new Font(fontName, fontStyle, 1024); + if (!exists) { + fontBoundsTable.add(pos, shp.getBounds()); + fontAdvanceTable.add(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); + } else { + fontBoundsTable.set(pos, shp.getBounds()); + fontAdvanceTable.set(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); + } + } + if (!exists) { + numGlyphs++; + } + } + + @Override + public String getCharacters(List tags) { + String ret = ""; + for (int i : codeTable) { + ret += (char) i; + } + return ret; + } + + @Override + public boolean hasLayout() { + return fontFlagsHasLayout; + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + char c1 = glyphToChar(glyphIndex); + char c2 = glyphToChar(nextGlyphIndex); + int kerningAdjustment = 0; + for (KERNINGRECORD ker : fontKerningTable) { + if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { + kerningAdjustment = ker.fontKerningAdjustment; + break; + } + } + return kerningAdjustment; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java index f77bc3009..624497d46 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java @@ -1,449 +1,448 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.abc.CopyOutputStream; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.tags.base.FontTag; -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.shaperecords.SHAPERECORD; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.Font; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JPanel; - -public class DefineFont3Tag extends FontTag { - - @SWFType(BasicType.UI16) - public int fontId; - - public boolean fontFlagsHasLayout; - public boolean fontFlagsShiftJIS; - public boolean fontFlagsSmallText; - public boolean fontFlagsANSI; - public boolean fontFlagsWideOffsets; - public boolean fontFlagsWideCodes; - public boolean fontFlagsItalic; - public boolean fontFlagsBold; - public LANGCODE languageCode; - public String fontName; - @Internal - public int numGlyphs; - - public List glyphShapeTable; - - @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") - public List codeTable; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontAscent; - - @SWFType(BasicType.UI16) - @Conditional("fontFlagsHasLayout") - public int fontDescent; - - @SWFType(BasicType.SI16) - @Conditional("fontFlagsHasLayout") - public int fontLeading; - - public List fontAdvanceTable; - public List fontBoundsTable; - public KERNINGRECORD[] fontKerningTable; - public static final int ID = 75; - - @Override - public boolean isSmall() { - return fontFlagsSmallText; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - if (fontFlagsHasLayout && glyphIndex != -1) { - return fontAdvanceTable.get(glyphIndex) / SWF.unitDivisor; - } else { - return -1; - } - } - - @Override - public char glyphToChar(int glyphIndex) { - return (char) (int) codeTable.get(glyphIndex); - } - - @Override - public int charToGlyph(char c) { - return codeTable.indexOf((int) c); - } - - public DefineFont3Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFont3", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontId = sis.readUI16(); - fontFlagsHasLayout = sis.readUB(1) == 1; - fontFlagsShiftJIS = sis.readUB(1) == 1; - fontFlagsSmallText = sis.readUB(1) == 1; - fontFlagsANSI = sis.readUB(1) == 1; - fontFlagsWideOffsets = sis.readUB(1) == 1; - fontFlagsWideCodes = sis.readUB(1) == 1; - fontFlagsItalic = sis.readUB(1) == 1; - fontFlagsBold = sis.readUB(1) == 1; - languageCode = sis.readLANGCODE(); - int fontNameLen = sis.readUI8(); - if (swf.version >= 6) { - fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); - } else { - fontName = new String(sis.readBytesEx(fontNameLen)); - } - numGlyphs = sis.readUI16(); - for (int i = 0; i < numGlyphs; i++) { //offsetTable - if (fontFlagsWideOffsets) { - sis.readUI32(); - } else { - sis.readUI16(); - } - } - if (numGlyphs > 0) { - if (fontFlagsWideOffsets) { - sis.readUI32(); //codeTableOffset - } else { - sis.readUI16(); //codeTableOffset - } - } - glyphShapeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - glyphShapeTable.add(sis.readSHAPE(1, false)); - } - codeTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - codeTable.add(sis.readUI16()); - } else { - codeTable.add(sis.readUI8()); - } - } - if (fontFlagsHasLayout) { - fontAscent = sis.readSI16(); - fontDescent = sis.readSI16(); - fontLeading = sis.readSI16(); - fontAdvanceTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontAdvanceTable.add(sis.readSI16()); - } - fontBoundsTable = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - fontBoundsTable.add(sis.readRECT()); - } - int kerningCount = sis.readUI16(); - fontKerningTable = new KERNINGRECORD[kerningCount]; - for (int i = 0; i < kerningCount; i++) { - fontKerningTable[i] = sis.readKERNINGRECORD(fontFlagsWideCodes); - } - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - if (Configuration.debugCopy.get()) { - sos = new SWFOutputStream(new CopyOutputStream(sos, new ByteArrayInputStream(data)), 10); - } - try { - List offsetTable = new ArrayList<>(); - ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); - SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); - for (int i = 0; i < numGlyphs; i++) { - offsetTable.add(sos3.getPos()); - sos3.writeSHAPE(glyphShapeTable.get(i), 1); - } - byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); - - if (!fontFlagsWideOffsets && numGlyphs > 0) { - // Set wide offsets when necessary - long maxOffset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * 2 + baGlyphShapes.length; - if (maxOffset > 65535) { - fontFlagsWideOffsets = true; - } - } - - sos.writeUI16(fontId); - sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeLANGCODE(languageCode); - byte[] fontNameBytes = Utf8Helper.getBytes(fontName); - sos.writeUI8(fontNameBytes.length); - sos.write(fontNameBytes); - 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 (numGlyphs > 0) { - long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; - if (fontFlagsWideOffsets) { - sos.writeUI32(offset); - } else { - sos.writeUI16((int) offset); - } - sos.write(baGlyphShapes); - - for (int i = 0; i < numGlyphs; i++) { - if (fontFlagsWideCodes) { - sos.writeUI16(codeTable.get(i)); - } else { - sos.writeUI8(codeTable.get(i)); - } - } - } - if (fontFlagsHasLayout) { - sos.writeSI16(fontAscent); - sos.writeSI16(fontDescent); - sos.writeSI16(fontLeading); - for (int i = 0; i < numGlyphs; i++) { - sos.writeSI16(fontAdvanceTable.get(i)); - } - for (int i = 0; i < numGlyphs; i++) { - sos.writeRECT(fontBoundsTable.get(i)); - } - sos.writeUI16(fontKerningTable.length); - for (int k = 0; k < fontKerningTable.length; k++) { - sos.writeKERNINGRECORD(fontKerningTable[k], fontFlagsWideCodes); - } - } - - } catch (IOException e) { - } - return baos.toByteArray(); - } - - @Override - public int getFontId() { - return fontId; - } - - @Override - public List getGlyphShapeTable() { - return glyphShapeTable; - } - - @Override - public int getCharacterId() { - return fontId; - } - - @Override - public String getFontName() { - String ret = fontName; - if (ret.contains("" + (char) 0)) { - ret = ret.substring(0, ret.indexOf(0)); - } - return ret; - } - - @Override - public boolean isBold() { - return fontFlagsBold; - } - - @Override - public boolean isItalic() { - return fontFlagsItalic; - } - - @Override - public boolean isSmallEditable() { - return true; - } - - @Override - public boolean isBoldEditable() { - return true; - } - - @Override - public boolean isItalicEditable() { - return true; - } - - @Override - public void setSmall(boolean value) { - fontFlagsSmallText = value; - } - - @Override - public void setBold(boolean value) { - fontFlagsBold = value; - } - - @Override - public void setItalic(boolean value) { - fontFlagsItalic = value; - } - - @Override - public int getDivider() { - return 20; - } - - @Override - public int getAscent() { - if (fontFlagsHasLayout) { - return fontAscent; - } - return -1; - } - - @Override - public int getDescent() { - if (fontFlagsHasLayout) { - return fontDescent; - } - return -1; - } - - @Override - public int getLeading() { - if (fontFlagsHasLayout) { - return fontLeading; - } - return -1; - } - - @Override - public void addCharacter(char character, String fontName) { - - //Font Align Zones will be removed as adding new character zones is not supported:-( - for (int i = 0; i < swf.tags.size(); i++) { - Tag t = swf.tags.get(i); - if (t instanceof DefineFontAlignZonesTag) { - DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t; - if (fa.fontID == fontId) { - swf.tags.remove(i); - i--; - } - } - } - int fontStyle = getFontStyle(); - SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character); - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = codeTable.size(); - } - - if (!exists) { - shiftGlyphIndices(fontId, pos); - glyphShapeTable.add(pos, shp); - codeTable.add(pos, (int) character); - } else { - glyphShapeTable.set(pos, shp); - } - if (fontFlagsHasLayout) { - - Font fnt = new Font(fontName, fontStyle, 1024); //Not multiplied with divider as it causes problems to create font with height around 20k - if (!exists) { - fontBoundsTable.add(pos, shp.getBounds()); - fontAdvanceTable.add(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); - } else { - fontBoundsTable.set(pos, shp.getBounds()); - fontAdvanceTable.set(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); - } - } - if (!exists) { - numGlyphs++; - } - } - - @Override - public String getCharacters(List tags) { - String ret = ""; - for (int i : codeTable) { - ret += (char) i; - } - return ret; - } - - @Override - public boolean hasLayout() { - return fontFlagsHasLayout; - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - if (glyphIndex == -1 || nextGlyphIndex == -1) { - return 0; - } - char c1 = glyphToChar(glyphIndex); - char c2 = glyphToChar(nextGlyphIndex); - int kerningAdjustment = 0; - for (KERNINGRECORD ker : fontKerningTable) { - if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { - kerningAdjustment = ker.fontKerningAdjustment; - break; - } - } - return kerningAdjustment; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.abc.CopyOutputStream; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.tags.base.FontTag; +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.shaperecords.SHAPERECORD; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.awt.Font; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; + +public class DefineFont3Tag extends FontTag { + + @SWFType(BasicType.UI16) + public int fontId; + + public boolean fontFlagsHasLayout; + public boolean fontFlagsShiftJIS; + public boolean fontFlagsSmallText; + public boolean fontFlagsANSI; + public boolean fontFlagsWideOffsets; + public boolean fontFlagsWideCodes; + public boolean fontFlagsItalic; + public boolean fontFlagsBold; + public LANGCODE languageCode; + public String fontName; + @Internal + public int numGlyphs; + + public List glyphShapeTable; + + @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") + public List codeTable; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontAscent; + + @SWFType(BasicType.UI16) + @Conditional("fontFlagsHasLayout") + public int fontDescent; + + @SWFType(BasicType.SI16) + @Conditional("fontFlagsHasLayout") + public int fontLeading; + + public List fontAdvanceTable; + public List fontBoundsTable; + public KERNINGRECORD[] fontKerningTable; + public static final int ID = 75; + + @Override + public boolean isSmall() { + return fontFlagsSmallText; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + if (fontFlagsHasLayout && glyphIndex != -1) { + return fontAdvanceTable.get(glyphIndex) / SWF.unitDivisor; + } else { + return -1; + } + } + + @Override + public char glyphToChar(int glyphIndex) { + return (char) (int) codeTable.get(glyphIndex); + } + + @Override + public int charToGlyph(char c) { + return codeTable.indexOf((int) c); + } + + public DefineFont3Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFont3", pos, length); + fontId = sis.readUI16(); + fontFlagsHasLayout = sis.readUB(1) == 1; + fontFlagsShiftJIS = sis.readUB(1) == 1; + fontFlagsSmallText = sis.readUB(1) == 1; + fontFlagsANSI = sis.readUB(1) == 1; + fontFlagsWideOffsets = sis.readUB(1) == 1; + fontFlagsWideCodes = sis.readUB(1) == 1; + fontFlagsItalic = sis.readUB(1) == 1; + fontFlagsBold = sis.readUB(1) == 1; + languageCode = sis.readLANGCODE(); + int fontNameLen = sis.readUI8(); + if (swf.version >= 6) { + fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); + } else { + fontName = new String(sis.readBytesEx(fontNameLen)); + } + numGlyphs = sis.readUI16(); + for (int i = 0; i < numGlyphs; i++) { //offsetTable + if (fontFlagsWideOffsets) { + sis.readUI32(); + } else { + sis.readUI16(); + } + } + if (numGlyphs > 0) { + if (fontFlagsWideOffsets) { + sis.readUI32(); //codeTableOffset + } else { + sis.readUI16(); //codeTableOffset + } + } + glyphShapeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + glyphShapeTable.add(sis.readSHAPE(1, false)); + } + codeTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + codeTable.add(sis.readUI16()); + } else { + codeTable.add(sis.readUI8()); + } + } + if (fontFlagsHasLayout) { + fontAscent = sis.readSI16(); + fontDescent = sis.readSI16(); + fontLeading = sis.readSI16(); + fontAdvanceTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontAdvanceTable.add(sis.readSI16()); + } + fontBoundsTable = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + fontBoundsTable.add(sis.readRECT()); + } + int kerningCount = sis.readUI16(); + fontKerningTable = new KERNINGRECORD[kerningCount]; + for (int i = 0; i < kerningCount; i++) { + fontKerningTable[i] = sis.readKERNINGRECORD(fontFlagsWideCodes); + } + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + if (Configuration.debugCopy.get()) { + sos = new SWFOutputStream(new CopyOutputStream(sos, new ByteArrayInputStream(getOriginalData())), getVersion()); + } + try { + List offsetTable = new ArrayList<>(); + ByteArrayOutputStream baosGlyphShapes = new ByteArrayOutputStream(); + SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion()); + for (int i = 0; i < numGlyphs; i++) { + offsetTable.add(sos3.getPos()); + sos3.writeSHAPE(glyphShapeTable.get(i), 1); + } + byte[] baGlyphShapes = baosGlyphShapes.toByteArray(); + + if (!fontFlagsWideOffsets && numGlyphs > 0) { + // Set wide offsets when necessary + long maxOffset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * 2 + baGlyphShapes.length; + if (maxOffset > 65535) { + fontFlagsWideOffsets = true; + } + } + + sos.writeUI16(fontId); + sos.writeUB(1, fontFlagsHasLayout ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsWideOffsets ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeLANGCODE(languageCode); + byte[] fontNameBytes = Utf8Helper.getBytes(fontName); + sos.writeUI8(fontNameBytes.length); + sos.write(fontNameBytes); + 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 (numGlyphs > 0) { + long offset = (glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + baGlyphShapes.length; + if (fontFlagsWideOffsets) { + sos.writeUI32(offset); + } else { + sos.writeUI16((int) offset); + } + sos.write(baGlyphShapes); + + for (int i = 0; i < numGlyphs; i++) { + if (fontFlagsWideCodes) { + sos.writeUI16(codeTable.get(i)); + } else { + sos.writeUI8(codeTable.get(i)); + } + } + } + if (fontFlagsHasLayout) { + sos.writeSI16(fontAscent); + sos.writeSI16(fontDescent); + sos.writeSI16(fontLeading); + for (int i = 0; i < numGlyphs; i++) { + sos.writeSI16(fontAdvanceTable.get(i)); + } + for (int i = 0; i < numGlyphs; i++) { + sos.writeRECT(fontBoundsTable.get(i)); + } + sos.writeUI16(fontKerningTable.length); + for (int k = 0; k < fontKerningTable.length; k++) { + sos.writeKERNINGRECORD(fontKerningTable[k], fontFlagsWideCodes); + } + } + + } catch (IOException e) { + } + return baos.toByteArray(); + } + + @Override + public int getFontId() { + return fontId; + } + + @Override + public List getGlyphShapeTable() { + return glyphShapeTable; + } + + @Override + public int getCharacterId() { + return fontId; + } + + @Override + public String getFontName() { + String ret = fontName; + if (ret.contains("" + (char) 0)) { + ret = ret.substring(0, ret.indexOf(0)); + } + return ret; + } + + @Override + public boolean isBold() { + return fontFlagsBold; + } + + @Override + public boolean isItalic() { + return fontFlagsItalic; + } + + @Override + public boolean isSmallEditable() { + return true; + } + + @Override + public boolean isBoldEditable() { + return true; + } + + @Override + public boolean isItalicEditable() { + return true; + } + + @Override + public void setSmall(boolean value) { + fontFlagsSmallText = value; + } + + @Override + public void setBold(boolean value) { + fontFlagsBold = value; + } + + @Override + public void setItalic(boolean value) { + fontFlagsItalic = value; + } + + @Override + public int getDivider() { + return 20; + } + + @Override + public int getAscent() { + if (fontFlagsHasLayout) { + return fontAscent; + } + return -1; + } + + @Override + public int getDescent() { + if (fontFlagsHasLayout) { + return fontDescent; + } + return -1; + } + + @Override + public int getLeading() { + if (fontFlagsHasLayout) { + return fontLeading; + } + return -1; + } + + @Override + public void addCharacter(char character, String fontName) { + + //Font Align Zones will be removed as adding new character zones is not supported:-( + for (int i = 0; i < swf.tags.size(); i++) { + Tag t = swf.tags.get(i); + if (t instanceof DefineFontAlignZonesTag) { + DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t; + if (fa.fontID == fontId) { + swf.tags.remove(i); + i--; + } + } + } + int fontStyle = getFontStyle(); + SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character); + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = codeTable.size(); + } + + if (!exists) { + shiftGlyphIndices(fontId, pos); + glyphShapeTable.add(pos, shp); + codeTable.add(pos, (int) character); + } else { + glyphShapeTable.set(pos, shp); + } + if (fontFlagsHasLayout) { + + Font fnt = new Font(fontName, fontStyle, 1024); //Not multiplied with divider as it causes problems to create font with height around 20k + if (!exists) { + fontBoundsTable.add(pos, shp.getBounds()); + fontAdvanceTable.add(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); + } else { + fontBoundsTable.set(pos, shp.getBounds()); + fontAdvanceTable.set(pos, (int) getDivider() * Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX())); + } + } + if (!exists) { + numGlyphs++; + } + } + + @Override + public String getCharacters(List tags) { + String ret = ""; + for (int i : codeTable) { + ret += (char) i; + } + return ret; + } + + @Override + public boolean hasLayout() { + return fontFlagsHasLayout; + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + if (glyphIndex == -1 || nextGlyphIndex == -1) { + return 0; + } + char c1 = glyphToChar(glyphIndex); + char c2 = glyphToChar(nextGlyphIndex); + int kerningAdjustment = 0; + for (KERNINGRECORD ker : fontKerningTable) { + if (ker.fontKerningCode1 == c1 && ker.fontKerningCode2 == c2) { + kerningAdjustment = ker.fontKerningAdjustment; + break; + } + } + return kerningAdjustment; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFont4Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineFont4Tag.java index 290e1fd9a..c6f73af30 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFont4Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFont4Tag.java @@ -1,85 +1,82 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class DefineFont4Tag extends CharacterTag { - - @SWFType(BasicType.UI16) - public int fontID; - - @Reserved - @SWFType(value = BasicType.UB, count = 5) - public int reserved; - public boolean fontFlagsHasFontData; - public boolean fontFlagsItalic; - public boolean fontFlagsBold; - public String fontName; - public byte[] fontData; - public static final int ID = 91; - - @Override - public int getCharacterId() { - return fontID; - } - - public DefineFont4Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFont4", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontID = sis.readUI16(); - reserved = (int) sis.readUB(5); - fontFlagsHasFontData = sis.readUB(1) == 1; - fontFlagsItalic = sis.readUB(1) == 1; - fontFlagsBold = sis.readUB(1) == 1; - fontName = sis.readString(); - fontData = sis.readBytesEx(sis.available()); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(fontID); - sos.writeUB(5, reserved); - sos.writeUB(1, fontFlagsHasFontData ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeString(fontName); - sos.write(fontData); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class DefineFont4Tag extends CharacterTag { + + @SWFType(BasicType.UI16) + public int fontID; + + @Reserved + @SWFType(value = BasicType.UB, count = 5) + public int reserved; + public boolean fontFlagsHasFontData; + public boolean fontFlagsItalic; + public boolean fontFlagsBold; + public String fontName; + public byte[] fontData; + public static final int ID = 91; + + @Override + public int getCharacterId() { + return fontID; + } + + public DefineFont4Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFont4", pos, length); + fontID = sis.readUI16(); + reserved = (int) sis.readUB(5); + fontFlagsHasFontData = sis.readUB(1) == 1; + fontFlagsItalic = sis.readUB(1) == 1; + fontFlagsBold = sis.readUB(1) == 1; + fontName = sis.readString(); + fontData = sis.readBytesEx(sis.available()); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(fontID); + sos.writeUB(5, reserved); + sos.writeUB(1, fontFlagsHasFontData ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeString(fontName); + sos.write(fontData); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFontAlignZonesTag.java b/src/com/jpexs/decompiler/flash/tags/DefineFontAlignZonesTag.java index 7f761911b..d2783fdac 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFontAlignZonesTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFontAlignZonesTag.java @@ -1,81 +1,78 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.ZONERECORD; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFArray; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -public class DefineFontAlignZonesTag extends Tag { - - @SWFType(BasicType.UI16) - public int fontID; - @SWFType(value = BasicType.UB, count = 2) - public int CSMTableHint; - @Reserved - @SWFType(value = BasicType.UB, count = 6) - public int reserved; - @SWFArray(value = "zone", countField = "glyphCount") - public List zoneTable; - public static final int ID = 73; - - public DefineFontAlignZonesTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFontAlignZones", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontID = sis.readUI16(); - CSMTableHint = (int) sis.readUB(2); - reserved = (int) sis.readUB(6); - zoneTable = new ArrayList<>(); - while (sis.available() > 0) { - ZONERECORD zr = sis.readZONERECORD(); - zoneTable.add(zr); - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(fontID); - sos.writeUB(2, CSMTableHint); - sos.writeUB(6, reserved); - for (ZONERECORD z : zoneTable) { - sos.writeZONERECORD(z); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.ZONERECORD; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFArray; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class DefineFontAlignZonesTag extends Tag { + + @SWFType(BasicType.UI16) + public int fontID; + @SWFType(value = BasicType.UB, count = 2) + public int CSMTableHint; + @Reserved + @SWFType(value = BasicType.UB, count = 6) + public int reserved; + @SWFArray(value = "zone", countField = "glyphCount") + public List zoneTable; + public static final int ID = 73; + + public DefineFontAlignZonesTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFontAlignZones", pos, length); + fontID = sis.readUI16(); + CSMTableHint = (int) sis.readUB(2); + reserved = (int) sis.readUB(6); + zoneTable = new ArrayList<>(); + while (sis.available() > 0) { + ZONERECORD zr = sis.readZONERECORD(); + zoneTable.add(zr); + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(fontID); + sos.writeUB(2, CSMTableHint); + sos.writeUB(6, reserved); + for (ZONERECORD z : zoneTable) { + sos.writeZONERECORD(z); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java index d0f3c62af..028d831b0 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFontInfo2Tag.java @@ -1,122 +1,119 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author JPEXS - */ -public class DefineFontInfo2Tag extends Tag { - - @SWFType(BasicType.UI16) - public int fontID; - public String fontName; - @Reserved - @SWFType(value = BasicType.UB, count = 2) - public int reserved; - public boolean fontFlagsSmallText; - public boolean fontFlagsShiftJIS; - public boolean fontFlagsANSI; - public boolean fontFlagsItalic; - public boolean fontFlagsBold; - public boolean fontFlagsWideCodes; //always 1 - public LANGCODE languageCode; - @SWFType(BasicType.UI16) - public List codeTable; - public static final int ID = 62; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(fontID); - byte[] fontNameBytes = Utf8Helper.getBytes(fontName); - sos.writeUI8(fontNameBytes.length); - sos.write(fontNameBytes); - sos.writeUB(2, reserved); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - sos.writeLANGCODE(languageCode); - for (int c : codeTable) { - sos.writeUI16(c); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineFontInfo2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFontInfo2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontID = sis.readUI16(); - int fontNameLen = sis.readUI8(); - if (swf.version >= 6) { - fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); - } else { - fontName = new String(sis.readBytesEx(fontNameLen)); - } - reserved = (int) sis.readUB(2); - fontFlagsSmallText = sis.readUB(1) == 1; - fontFlagsShiftJIS = sis.readUB(1) == 1; - fontFlagsANSI = sis.readUB(1) == 1; - fontFlagsItalic = sis.readUB(1) == 1; - fontFlagsBold = sis.readUB(1) == 1; - fontFlagsWideCodes = sis.readUB(1) == 1; //Always 1 - languageCode = sis.readLANGCODE(); - int ctLen = sis.available() / 2; - codeTable = new ArrayList<>(); - for (int i = 0; i < ctLen; i++) { - codeTable.add(sis.readUI16()); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.LANGCODE; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author JPEXS + */ +public class DefineFontInfo2Tag extends Tag { + + @SWFType(BasicType.UI16) + public int fontID; + public String fontName; + @Reserved + @SWFType(value = BasicType.UB, count = 2) + public int reserved; + public boolean fontFlagsSmallText; + public boolean fontFlagsShiftJIS; + public boolean fontFlagsANSI; + public boolean fontFlagsItalic; + public boolean fontFlagsBold; + public boolean fontFlagsWideCodes; //always 1 + public LANGCODE languageCode; + @SWFType(BasicType.UI16) + public List codeTable; + public static final int ID = 62; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(fontID); + byte[] fontNameBytes = Utf8Helper.getBytes(fontName); + sos.writeUI8(fontNameBytes.length); + sos.write(fontNameBytes); + sos.writeUB(2, reserved); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + sos.writeLANGCODE(languageCode); + for (int c : codeTable) { + sos.writeUI16(c); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineFontInfo2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFontInfo2", pos, length); + fontID = sis.readUI16(); + int fontNameLen = sis.readUI8(); + if (swf.version >= 6) { + fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); + } else { + fontName = new String(sis.readBytesEx(fontNameLen)); + } + reserved = (int) sis.readUB(2); + fontFlagsSmallText = sis.readUB(1) == 1; + fontFlagsShiftJIS = sis.readUB(1) == 1; + fontFlagsANSI = sis.readUB(1) == 1; + fontFlagsItalic = sis.readUB(1) == 1; + fontFlagsBold = sis.readUB(1) == 1; + fontFlagsWideCodes = sis.readUB(1) == 1; //Always 1 + languageCode = sis.readLANGCODE(); + int ctLen = sis.available() / 2; + codeTable = new ArrayList<>(); + for (int i = 0; i < ctLen; i++) { + codeTable.add(sis.readUI16()); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java b/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java index b27486644..d35c953c6 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFontInfoTag.java @@ -1,125 +1,122 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author JPEXS - */ -public class DefineFontInfoTag extends Tag { - - @SWFType(BasicType.UI16) - public int fontId; - public String fontName; - @Reserved - @SWFType(value = BasicType.UB, count = 2) - public int reserved; - public boolean fontFlagsSmallText; - public boolean fontFlagsShiftJIS; - public boolean fontFlagsANSI; - public boolean fontFlagsItalic; - public boolean fontFlagsBold; - public boolean fontFlagsWideCodes; - @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") - public List codeTable; - public static final int ID = 13; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(fontId); - byte[] fontNameBytes = Utf8Helper.getBytes(fontName); - sos.writeUI8(fontNameBytes.length); - sos.write(fontNameBytes); - sos.writeUB(2, reserved); - sos.writeUB(1, fontFlagsSmallText ? 1 : 0); - sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); - sos.writeUB(1, fontFlagsANSI ? 1 : 0); - sos.writeUB(1, fontFlagsItalic ? 1 : 0); - sos.writeUB(1, fontFlagsBold ? 1 : 0); - sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); - for (int code : codeTable) { - if (fontFlagsWideCodes) { - sos.writeUI16(code); - } else { - sos.writeUI8(code); - } - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineFontInfoTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFontInfo", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontId = sis.readUI16(); - int fontNameLen = sis.readUI8(); - if (swf.version >= 6) { - fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); - } else { - fontName = new String(sis.readBytesEx(fontNameLen)); - } - reserved = (int) sis.readUB(2); - fontFlagsSmallText = sis.readUB(1) == 1; - fontFlagsShiftJIS = sis.readUB(1) == 1; - fontFlagsANSI = sis.readUB(1) == 1; - fontFlagsItalic = sis.readUB(1) == 1; - fontFlagsBold = sis.readUB(1) == 1; - fontFlagsWideCodes = sis.readUB(1) == 1; - codeTable = new ArrayList<>(); - do { - if (fontFlagsWideCodes) { - codeTable.add(sis.readUI16()); - } else { - codeTable.add(sis.readUI8()); - } - } while (sis.available() > 0); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author JPEXS + */ +public class DefineFontInfoTag extends Tag { + + @SWFType(BasicType.UI16) + public int fontId; + public String fontName; + @Reserved + @SWFType(value = BasicType.UB, count = 2) + public int reserved; + public boolean fontFlagsSmallText; + public boolean fontFlagsShiftJIS; + public boolean fontFlagsANSI; + public boolean fontFlagsItalic; + public boolean fontFlagsBold; + public boolean fontFlagsWideCodes; + @SWFType(value = BasicType.UI8, alternateValue = BasicType.UI16, alternateCondition = "fontFlagsWideCodes") + public List codeTable; + public static final int ID = 13; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(fontId); + byte[] fontNameBytes = Utf8Helper.getBytes(fontName); + sos.writeUI8(fontNameBytes.length); + sos.write(fontNameBytes); + sos.writeUB(2, reserved); + sos.writeUB(1, fontFlagsSmallText ? 1 : 0); + sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0); + sos.writeUB(1, fontFlagsANSI ? 1 : 0); + sos.writeUB(1, fontFlagsItalic ? 1 : 0); + sos.writeUB(1, fontFlagsBold ? 1 : 0); + sos.writeUB(1, fontFlagsWideCodes ? 1 : 0); + for (int code : codeTable) { + if (fontFlagsWideCodes) { + sos.writeUI16(code); + } else { + sos.writeUI8(code); + } + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineFontInfoTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFontInfo", pos, length); + fontId = sis.readUI16(); + int fontNameLen = sis.readUI8(); + if (swf.version >= 6) { + fontName = new String(sis.readBytesEx(fontNameLen), Utf8Helper.charset); + } else { + fontName = new String(sis.readBytesEx(fontNameLen)); + } + reserved = (int) sis.readUB(2); + fontFlagsSmallText = sis.readUB(1) == 1; + fontFlagsShiftJIS = sis.readUB(1) == 1; + fontFlagsANSI = sis.readUB(1) == 1; + fontFlagsItalic = sis.readUB(1) == 1; + fontFlagsBold = sis.readUB(1) == 1; + fontFlagsWideCodes = sis.readUB(1) == 1; + codeTable = new ArrayList<>(); + do { + if (fontFlagsWideCodes) { + codeTable.add(sis.readUI16()); + } else { + codeTable.add(sis.readUI8()); + } + } while (sis.available() > 0); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFontNameTag.java b/src/com/jpexs/decompiler/flash/tags/DefineFontNameTag.java index 15dad8530..7eaf56065 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFontNameTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFontNameTag.java @@ -1,41 +1,38 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -public class DefineFontNameTag extends Tag { - - @SWFType(BasicType.UI16) - public int fontId; - public String fontName; - public String fontCopyright; - public static final int ID = 88; - - public DefineFontNameTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFontName", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontId = sis.readUI16(); - fontName = sis.readString(); - fontCopyright = sis.readString(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.IOException; + +public class DefineFontNameTag extends Tag { + + @SWFType(BasicType.UI16) + public int fontId; + public String fontName; + public String fontCopyright; + public static final int ID = 88; + + public DefineFontNameTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFontName", pos, length); + fontId = sis.readUI16(); + fontName = sis.readString(); + fontCopyright = sis.readString(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java b/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java index 8654112cd..e59496638 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java @@ -1,327 +1,324 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -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.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author JPEXS - */ -public class DefineFontTag extends FontTag { - - @SWFType(BasicType.UI16) - public int fontId; - public List glyphShapeTable; - @Internal - private DefineFontInfoTag fontInfoTag = null; - @Internal - private DefineFontInfo2Tag fontInfo2Tag = null; - public static final int ID = 10; - - @Override - public boolean isSmall() { - return false; - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - return -1; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); - } - - private void ensureFontInfo() { - if (fontInfoTag == null) { - for (Tag t : swf.tags) { - if (t instanceof DefineFontInfoTag) { - if (((DefineFontInfoTag) t).fontId == fontId) { - fontInfoTag = (DefineFontInfoTag) t; - break; - } - } - if (t instanceof DefineFontInfo2Tag) { - if (((DefineFontInfo2Tag) t).fontID == fontId) { - fontInfo2Tag = (DefineFontInfo2Tag) t; - break; - } - } - } - } - } - - @Override - public char glyphToChar(int glyphIndex) { - ensureFontInfo(); - if (fontInfo2Tag != null) { - return (char) (int) fontInfo2Tag.codeTable.get(glyphIndex); - } else if (fontInfoTag != null) { - return (char) (int) fontInfoTag.codeTable.get(glyphIndex); - } else { - return '?'; - } - } - - @Override - public int charToGlyph(char c) { - ensureFontInfo(); - if (fontInfo2Tag != null) { - return fontInfo2Tag.codeTable.indexOf((int) c); - } else if (fontInfoTag != null) { - return fontInfoTag.codeTable.indexOf((int) c); - } - return -1; - - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(fontId); - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - List offsetTable = new ArrayList<>(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion()); - 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()); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineFontTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineFont", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontId = sis.readUI16(); - int firstOffset = sis.readUI16(); - int nGlyphs = firstOffset / 2; - glyphShapeTable = new ArrayList<>(); - - for (int i = 1; i < nGlyphs; i++) { - sis.readUI16(); //offset - } - for (int i = 0; i < nGlyphs; i++) { - glyphShapeTable.add(sis.readSHAPE(1, false)); - } - } - - @Override - public int getFontId() { - return fontId; - } - - @Override - public List getGlyphShapeTable() { - return glyphShapeTable; - } - - @Override - public int getCharacterId() { - return fontId; - } - - @Override - public String getFontName() { - ensureFontInfo(); - if (fontInfo2Tag != null) { - return fontInfo2Tag.fontName; - } - if (fontInfoTag != null) { - return fontInfoTag.fontName; - } - return null; - } - - @Override - public boolean isBold() { - if (fontInfo2Tag != null) { - return fontInfo2Tag.fontFlagsBold; - } - if (fontInfoTag != null) { - return fontInfoTag.fontFlagsBold; - } - return false; - } - - @Override - public boolean isItalic() { - if (fontInfo2Tag != null) { - return fontInfo2Tag.fontFlagsItalic; - } - if (fontInfoTag != null) { - return fontInfoTag.fontFlagsItalic; - } - return false; - } - - @Override - public boolean isSmallEditable() { - return false; - } - - @Override - public boolean isBoldEditable() { - return fontInfo2Tag != null || fontInfoTag != null; - } - - @Override - public boolean isItalicEditable() { - return fontInfo2Tag != null || fontInfoTag != null; - } - - @Override - public void setSmall(boolean value) { - } - - @Override - public void setBold(boolean value) { - if (fontInfo2Tag != null) { - fontInfo2Tag.fontFlagsBold = value; - } - if (fontInfoTag != null) { - fontInfoTag.fontFlagsBold = value; - } - } - - @Override - public void setItalic(boolean value) { - if (fontInfo2Tag != null) { - fontInfo2Tag.fontFlagsItalic = value; - } - if (fontInfoTag != null) { - fontInfoTag.fontFlagsItalic = value; - } - } - - @Override - public int getAscent() { - return -1; - } - - @Override - public int getDescent() { - return -1; - } - - @Override - public int getLeading() { - return -1; - } - - @Override - public int getDivider() { - return 1; - } - - @Override - public void addCharacter(char character, String fontName) { - SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, getFontStyle(), getDivider() * 1024, character); - List codeTable = new ArrayList<>(); - ensureFontInfo(); - if (fontInfoTag != null) { - codeTable = fontInfoTag.codeTable; - } - if (fontInfo2Tag != null) { - codeTable = fontInfo2Tag.codeTable; - } - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < codeTable.size(); i++) { - if (codeTable.get(i) >= code) { - if (codeTable.get(i) == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = codeTable.size(); - } - if (!exists) { - shiftGlyphIndices(fontId, pos); - glyphShapeTable.add(pos, shp); - codeTable.add(pos, (int) character); - } else { - glyphShapeTable.set(pos, shp); - } - - } - - @Override - public String getCharacters(List tags) { - String ret = ""; - ensureFontInfo(); - if (fontInfoTag != null) { - for (int i : fontInfoTag.codeTable) { - ret += (char) i; - } - } - if (fontInfo2Tag != null) { - for (int i : fontInfo2Tag.codeTable) { - ret += (char) i; - } - } - return ret; - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - return 0; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +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.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author JPEXS + */ +public class DefineFontTag extends FontTag { + + @SWFType(BasicType.UI16) + public int fontId; + public List glyphShapeTable; + @Internal + private DefineFontInfoTag fontInfoTag = null; + @Internal + private DefineFontInfo2Tag fontInfo2Tag = null; + public static final int ID = 10; + + @Override + public boolean isSmall() { + return false; + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + return -1; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return glyphShapeTable.get(glyphIndex).getBounds().getWidth(); + } + + private void ensureFontInfo() { + if (fontInfoTag == null) { + for (Tag t : swf.tags) { + if (t instanceof DefineFontInfoTag) { + if (((DefineFontInfoTag) t).fontId == fontId) { + fontInfoTag = (DefineFontInfoTag) t; + break; + } + } + if (t instanceof DefineFontInfo2Tag) { + if (((DefineFontInfo2Tag) t).fontID == fontId) { + fontInfo2Tag = (DefineFontInfo2Tag) t; + break; + } + } + } + } + } + + @Override + public char glyphToChar(int glyphIndex) { + ensureFontInfo(); + if (fontInfo2Tag != null) { + return (char) (int) fontInfo2Tag.codeTable.get(glyphIndex); + } else if (fontInfoTag != null) { + return (char) (int) fontInfoTag.codeTable.get(glyphIndex); + } else { + return '?'; + } + } + + @Override + public int charToGlyph(char c) { + ensureFontInfo(); + if (fontInfo2Tag != null) { + return fontInfo2Tag.codeTable.indexOf((int) c); + } else if (fontInfoTag != null) { + return fontInfoTag.codeTable.indexOf((int) c); + } + return -1; + + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(fontId); + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + List offsetTable = new ArrayList<>(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion()); + 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()); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineFontTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineFont", pos, length); + fontId = sis.readUI16(); + int firstOffset = sis.readUI16(); + int nGlyphs = firstOffset / 2; + glyphShapeTable = new ArrayList<>(); + + for (int i = 1; i < nGlyphs; i++) { + sis.readUI16(); //offset + } + for (int i = 0; i < nGlyphs; i++) { + glyphShapeTable.add(sis.readSHAPE(1, false)); + } + } + + @Override + public int getFontId() { + return fontId; + } + + @Override + public List getGlyphShapeTable() { + return glyphShapeTable; + } + + @Override + public int getCharacterId() { + return fontId; + } + + @Override + public String getFontName() { + ensureFontInfo(); + if (fontInfo2Tag != null) { + return fontInfo2Tag.fontName; + } + if (fontInfoTag != null) { + return fontInfoTag.fontName; + } + return null; + } + + @Override + public boolean isBold() { + if (fontInfo2Tag != null) { + return fontInfo2Tag.fontFlagsBold; + } + if (fontInfoTag != null) { + return fontInfoTag.fontFlagsBold; + } + return false; + } + + @Override + public boolean isItalic() { + if (fontInfo2Tag != null) { + return fontInfo2Tag.fontFlagsItalic; + } + if (fontInfoTag != null) { + return fontInfoTag.fontFlagsItalic; + } + return false; + } + + @Override + public boolean isSmallEditable() { + return false; + } + + @Override + public boolean isBoldEditable() { + return fontInfo2Tag != null || fontInfoTag != null; + } + + @Override + public boolean isItalicEditable() { + return fontInfo2Tag != null || fontInfoTag != null; + } + + @Override + public void setSmall(boolean value) { + } + + @Override + public void setBold(boolean value) { + if (fontInfo2Tag != null) { + fontInfo2Tag.fontFlagsBold = value; + } + if (fontInfoTag != null) { + fontInfoTag.fontFlagsBold = value; + } + } + + @Override + public void setItalic(boolean value) { + if (fontInfo2Tag != null) { + fontInfo2Tag.fontFlagsItalic = value; + } + if (fontInfoTag != null) { + fontInfoTag.fontFlagsItalic = value; + } + } + + @Override + public int getAscent() { + return -1; + } + + @Override + public int getDescent() { + return -1; + } + + @Override + public int getLeading() { + return -1; + } + + @Override + public int getDivider() { + return 1; + } + + @Override + public void addCharacter(char character, String fontName) { + SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, getFontStyle(), getDivider() * 1024, character); + List codeTable = new ArrayList<>(); + ensureFontInfo(); + if (fontInfoTag != null) { + codeTable = fontInfoTag.codeTable; + } + if (fontInfo2Tag != null) { + codeTable = fontInfo2Tag.codeTable; + } + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < codeTable.size(); i++) { + if (codeTable.get(i) >= code) { + if (codeTable.get(i) == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = codeTable.size(); + } + if (!exists) { + shiftGlyphIndices(fontId, pos); + glyphShapeTable.add(pos, shp); + codeTable.add(pos, (int) character); + } else { + glyphShapeTable.set(pos, shp); + } + + } + + @Override + public String getCharacters(List tags) { + String ret = ""; + ensureFontInfo(); + if (fontInfoTag != null) { + for (int i : fontInfoTag.codeTable) { + ret += (char) i; + } + } + if (fontInfo2Tag != null) { + for (int i : fontInfo2Tag.codeTable) { + ret += (char) i; + } + } + return ret; + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + return 0; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java index 666935759..a2d81f6e5 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java @@ -16,8 +16,7 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; @@ -46,7 +45,6 @@ import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.helpers.SerializableImage; import java.awt.Shape; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -155,9 +153,8 @@ public class DefineMorphShape2Tag extends CharacterTag implements MorphShapeTag * @param pos * @throws IOException */ - public DefineMorphShape2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineMorphShape2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineMorphShape2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineMorphShape2", pos, length); characterId = sis.readUI16(); startBounds = sis.readRECT(); endBounds = sis.readRECT(); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java b/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java index edec881b8..938c85fac 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java @@ -16,8 +16,7 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; @@ -45,7 +44,6 @@ import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; import com.jpexs.helpers.SerializableImage; import java.awt.Shape; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -133,9 +131,8 @@ public class DefineMorphShapeTag extends CharacterTag implements MorphShapeTag { * @param pos * @throws IOException */ - public DefineMorphShapeTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineMorphShape", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineMorphShapeTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineMorphShape", pos, length); characterId = sis.readUI16(); startBounds = sis.readRECT(); endBounds = sis.readRECT(); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineScalingGridTag.java b/src/com/jpexs/decompiler/flash/tags/DefineScalingGridTag.java index e475753bc..dc05286ac 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineScalingGridTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineScalingGridTag.java @@ -1,64 +1,61 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * @author JPEXS - */ -public class DefineScalingGridTag extends Tag { - - @SWFType(BasicType.UI16) - public int characterId; - public RECT splitter; - public static final int ID = 78; - - public DefineScalingGridTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineScalingGrid", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterId = sis.readUI16(); - splitter = sis.readRECT(); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterId); - sos.writeRECT(splitter); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author JPEXS + */ +public class DefineScalingGridTag extends Tag { + + @SWFType(BasicType.UI16) + public int characterId; + public RECT splitter; + public static final int ID = 78; + + public DefineScalingGridTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineScalingGrid", pos, length); + characterId = sis.readUI16(); + splitter = sis.readRECT(); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterId); + sos.writeRECT(splitter); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineSceneAndFrameLabelDataTag.java b/src/com/jpexs/decompiler/flash/tags/DefineSceneAndFrameLabelDataTag.java index a0e35f8d2..b5dac57b5 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineSceneAndFrameLabelDataTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineSceneAndFrameLabelDataTag.java @@ -1,107 +1,104 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFArray; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineSceneAndFrameLabelDataTag extends Tag { - - @SWFType(value = BasicType.EncodedU32) - @SWFArray(value = "offset", countField = "sceneCount") - public long[] sceneOffsets; - @SWFArray(value = "name", countField = "sceneCount") - public String[] sceneNames; - - @SWFType(value = BasicType.EncodedU32) - @SWFArray(value = "frameNum", countField = "frameLabelCount") - public long[] frameNums; - - @SWFArray(countField = "frameLabelCount") - public String[] frameNames; - public static final int ID = 86; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - int sceneCount = sceneOffsets.length; - sos.writeEncodedU32(sceneCount); - for (int i = 0; i < sceneCount; i++) { - sos.writeEncodedU32(sceneOffsets[i]); - sos.writeString(sceneNames[i]); - } - int frameLabelCount = frameNums.length; - sos.writeEncodedU32(frameLabelCount); - for (int i = 0; i < frameLabelCount; i++) { - sos.writeEncodedU32(frameNums[i]); - sos.writeString(frameNames[i]); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineSceneAndFrameLabelDataTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineSceneAndFrameLabelData", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - int sceneCount = (int) sis.readEncodedU32(); - sceneOffsets = new long[sceneCount]; - sceneNames = new String[sceneCount]; - for (int i = 0; i < sceneCount; i++) { - sceneOffsets[i] = sis.readEncodedU32(); - sceneNames[i] = sis.readString(); - } - int frameLabelCount = (int) sis.readEncodedU32(); - frameNums = new long[frameLabelCount]; - frameNames = new String[frameLabelCount]; - for (int i = 0; i < frameLabelCount; i++) { - frameNums[i] = sis.readEncodedU32(); - frameNames[i] = sis.readString(); - } - - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFArray; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineSceneAndFrameLabelDataTag extends Tag { + + @SWFType(value = BasicType.EncodedU32) + @SWFArray(value = "offset", countField = "sceneCount") + public long[] sceneOffsets; + @SWFArray(value = "name", countField = "sceneCount") + public String[] sceneNames; + + @SWFType(value = BasicType.EncodedU32) + @SWFArray(value = "frameNum", countField = "frameLabelCount") + public long[] frameNums; + + @SWFArray(countField = "frameLabelCount") + public String[] frameNames; + public static final int ID = 86; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + int sceneCount = sceneOffsets.length; + sos.writeEncodedU32(sceneCount); + for (int i = 0; i < sceneCount; i++) { + sos.writeEncodedU32(sceneOffsets[i]); + sos.writeString(sceneNames[i]); + } + int frameLabelCount = frameNums.length; + sos.writeEncodedU32(frameLabelCount); + for (int i = 0; i < frameLabelCount; i++) { + sos.writeEncodedU32(frameNums[i]); + sos.writeString(frameNames[i]); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineSceneAndFrameLabelDataTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineSceneAndFrameLabelData", pos, length); + int sceneCount = (int) sis.readEncodedU32(); + sceneOffsets = new long[sceneCount]; + sceneNames = new String[sceneCount]; + for (int i = 0; i < sceneCount; i++) { + sceneOffsets[i] = sis.readEncodedU32(); + sceneNames[i] = sis.readString(); + } + int frameLabelCount = (int) sis.readEncodedU32(); + frameNums = new long[frameLabelCount]; + frameNames = new String[frameLabelCount]; + for (int i = 0; i < frameLabelCount; i++) { + frameNums[i] = sis.readEncodedU32(); + frameNames[i] = sis.readString(); + } + + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java index 7f3774b81..e63b4c065 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java @@ -16,14 +16,12 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; @@ -69,9 +67,8 @@ public class DefineShape2Tag extends ShapeTag { return shapeBounds; } - public DefineShape2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineShape2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineShape2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineShape2", pos, length); shapeId = sis.readUI16(); shapeBounds = sis.readRECT(); shapes = sis.readSHAPEWITHSTYLE(2, false); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java index 4db3187a0..903674cef 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java @@ -16,14 +16,12 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; @@ -69,9 +67,8 @@ public class DefineShape3Tag extends ShapeTag { return shapeId; } - public DefineShape3Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineShape3", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineShape3Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineShape3", pos, length); shapeId = sis.readUI16(); shapeBounds = sis.readRECT(); shapes = sis.readSHAPEWITHSTYLE(3, false); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java index f70845209..e12ba6367 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java @@ -16,15 +16,13 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.Reserved; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; @@ -77,9 +75,8 @@ public class DefineShape4Tag extends ShapeTag { return shapeBounds; } - public DefineShape4Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineShape4", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineShape4Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineShape4", pos, length); shapeId = sis.readUI16(); shapeBounds = sis.readRECT(); edgeBounds = sis.readRECT(); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java b/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java index efcb8317c..933b57e52 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java @@ -16,15 +16,13 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Set; @@ -66,9 +64,8 @@ public class DefineShapeTag extends ShapeTag { return shapeBounds; } - public DefineShapeTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineShape", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineShapeTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineShape", pos, length); shapeId = sis.readUI16(); shapeBounds = sis.readRECT(); shapes = sis.readSHAPEWITHSTYLE(1, false); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java b/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java index 25bf78361..7d08fe8be 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineSoundTag.java @@ -1,337 +1,335 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.tags.base.SoundTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.sound.MP3FRAME; -import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA; -import com.jpexs.decompiler.flash.types.sound.SoundFormat; -import com.jpexs.helpers.Helper; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.UnsupportedAudioFileException; - -/** - * - * - * @author JPEXS - */ -public class DefineSoundTag extends CharacterTag implements SoundTag { - - @SWFType(BasicType.UI16) - public int soundId; - - @SWFType(value = BasicType.UB, count = 4) - public int soundFormat; - - @SWFType(value = BasicType.UB, count = 2) - public int soundRate; - - public boolean soundSize; - public boolean soundType; - - @SWFType(BasicType.UI32) - public long soundSampleCount; - - public byte[] soundData; - public static final int ID = 14; - - @Override - public int getCharacterId() { - return soundId; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(soundId); - sos.writeUB(4, soundFormat); - sos.writeUB(2, soundRate); - sos.writeUB(1, soundSize ? 1 : 0); - sos.writeUB(1, soundType ? 1 : 0); - sos.writeUI32(soundSampleCount); - sos.write(soundData); - - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineSoundTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineSound", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - soundId = sis.readUI16(); - soundFormat = (int) sis.readUB(4); - soundRate = (int) sis.readUB(2); - soundSize = sis.readUB(1) == 1; - soundType = sis.readUB(1) == 1; - soundSampleCount = sis.readUI32(); - soundData = sis.readBytesEx(sis.available()); - } - - @Override - public String getExportFormat() { - if (soundFormat == SoundFormat.FORMAT_MP3) { - return "mp3"; - } - if (soundFormat == SoundFormat.FORMAT_ADPCM) { - return "wav"; - } - if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { - return "wav"; - } - if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { - return "wav"; - } - if (soundFormat == SoundFormat.FORMAT_NELLYMOSER || soundFormat == SoundFormat.FORMAT_NELLYMOSER16KHZ || soundFormat == SoundFormat.FORMAT_NELLYMOSER8KHZ) { - return "wav"; - } - return "flv"; - } - - private void loadID3v2(InputStream in) { - int size = -1; - try { - // Read ID3v2 header (10 bytes). - in.mark(10); - size = readID3v2Header(in); - } catch (IOException e) { - } finally { - try { - // Unread ID3v2 header (10 bytes). - in.reset(); - } catch (IOException e) { - } - } - // Load ID3v2 tags. - try { - if (size > 0) { - byte[] rawid3v2 = new byte[size]; - in.read(rawid3v2, 0, rawid3v2.length); - } - } catch (IOException e) { - } - } - - /** - * Parse ID3v2 tag header to find out size of ID3v2 frames. - * - * @param in MP3 InputStream - * @return size of ID3v2 frames + header - * @throws IOException - * @author JavaZOOM - */ - private int readID3v2Header(InputStream in) throws IOException { - byte[] id3header = new byte[4]; - int size = -10; - in.read(id3header, 0, 3); - // Look for ID3v2 - if ((id3header[0] == 'I') && (id3header[1] == 'D') && (id3header[2] == '3')) { - in.read(id3header, 0, 3); - int majorVersion = id3header[0]; - int revision = id3header[1]; - in.read(id3header, 0, 4); - size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]); - } - return (size + 10); - } - - @Override - public boolean setSound(InputStream is, int newSoundFormat) { - int newSoundRate = -1; - boolean newSoundSize = false; - boolean newSoundType = false; - long newSoundSampleCount = -1; - byte newSoundData[]; - switch (newSoundFormat) { - case SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: - try (AudioInputStream audioIs = AudioSystem.getAudioInputStream(new BufferedInputStream(is))) { - AudioFormat fmt = audioIs.getFormat(); - newSoundType = fmt.getChannels() == 2; - newSoundSize = fmt.getSampleSizeInBits() == 16; - newSoundSampleCount = audioIs.getFrameLength(); - newSoundData = Helper.readStream(audioIs); - newSoundRate = (int) Math.round(fmt.getSampleRate()); - switch (newSoundRate) { - case 5512: - newSoundRate = 0; - break; - case 11025: - newSoundRate = 1; - break; - case 22050: - newSoundRate = 2; - break; - case 44100: - newSoundRate = 3; - break; - default: - return false; - } - } catch (UnsupportedAudioFileException | IOException ex) { - return false; - } - break; - case SoundFormat.FORMAT_MP3: - BufferedInputStream bis = new BufferedInputStream(is); - loadID3v2(bis); - byte mp3data[] = Helper.readStream(bis); - - final int ID3_V1_LENTGH = 128; - final int ID3_V1_EXT_LENGTH = 227; - - if (mp3data.length > ID3_V1_LENTGH) { - //ID3v1 - if (mp3data[mp3data.length - ID3_V1_LENTGH] == 'T' && mp3data[mp3data.length - ID3_V1_LENTGH + 1] == 'A' && mp3data[mp3data.length - ID3_V1_LENTGH + 2] == 'G') { - mp3data = Arrays.copyOf(mp3data, mp3data.length - ID3_V1_LENTGH); - if (mp3data.length > ID3_V1_EXT_LENGTH) { - //ID3v1 extended - if (mp3data[mp3data.length - ID3_V1_EXT_LENGTH] == 'T' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 1] == 'A' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 2] == 'G' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 3] == '+') { - mp3data = Arrays.copyOf(mp3data, mp3data.length - ID3_V1_EXT_LENGTH); - } - } - } - } - try { - MP3SOUNDDATA snd = new MP3SOUNDDATA(new ByteArrayInputStream(mp3data), true); - if (!snd.frames.isEmpty()) { - MP3FRAME fr = snd.frames.get(0); - newSoundRate = fr.getSamplingRate(); - switch (newSoundRate) { - case 11025: - newSoundRate = 1; - break; - case 22050: - newSoundRate = 2; - break; - case 44100: - newSoundRate = 3; - break; - default: - return false; - } - newSoundSize = true; - newSoundType = fr.isStereo(); - int len = snd.sampleCount(); - if (fr.isStereo()) { - len = len / 2; - } - newSoundSampleCount = len; - - } - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); - sos.writeSI16(0); //Latency - how to calculate it? - sos.write(mp3data); - newSoundData = baos.toByteArray(); - } catch (IOException ex) { - return false; - } - break; - default: - return false; - } - if (newSoundData != null) { - this.soundSize = newSoundSize; - this.soundRate = newSoundRate; - this.soundSampleCount = newSoundSampleCount; - this.soundData = newSoundData; - this.soundType = newSoundType; - this.soundFormat = newSoundFormat; - setModified(true); - return true; - } - return false; - - } - - @Override - public boolean importSupported() { - return true; - } - - @Override - public int getSoundRate() { - return soundRate; - } - - @Override - public boolean getSoundType() { - return soundType; - } - - @Override - public byte[] getRawSoundData() { - if (soundFormat == SoundFormat.FORMAT_MP3) { - return Arrays.copyOfRange(soundData, 2, soundData.length - 2); - } - return soundData; - } - - @Override - public int getSoundFormatId() { - return soundFormat; - } - - @Override - public long getTotalSoundSampleCount() { - return soundSampleCount; - } - - @Override - public boolean getSoundSize() { - return soundSize; - } - - @Override - public SoundFormat getSoundFormat() { - final int[] rateMap = {5512, 11025, 22050, 44100}; - return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); - } - -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.tags.base.SoundTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.sound.MP3FRAME; +import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import com.jpexs.helpers.Helper; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * + * + * @author JPEXS + */ +public class DefineSoundTag extends CharacterTag implements SoundTag { + + @SWFType(BasicType.UI16) + public int soundId; + + @SWFType(value = BasicType.UB, count = 4) + public int soundFormat; + + @SWFType(value = BasicType.UB, count = 2) + public int soundRate; + + public boolean soundSize; + public boolean soundType; + + @SWFType(BasicType.UI32) + public long soundSampleCount; + + public byte[] soundData; + public static final int ID = 14; + + @Override + public int getCharacterId() { + return soundId; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(soundId); + sos.writeUB(4, soundFormat); + sos.writeUB(2, soundRate); + sos.writeUB(1, soundSize ? 1 : 0); + sos.writeUB(1, soundType ? 1 : 0); + sos.writeUI32(soundSampleCount); + sos.write(soundData); + + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineSoundTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineSound", pos, length); + soundId = sis.readUI16(); + soundFormat = (int) sis.readUB(4); + soundRate = (int) sis.readUB(2); + soundSize = sis.readUB(1) == 1; + soundType = sis.readUB(1) == 1; + soundSampleCount = sis.readUI32(); + soundData = sis.readBytesEx(sis.available()); + } + + @Override + public String getExportFormat() { + if (soundFormat == SoundFormat.FORMAT_MP3) { + return "mp3"; + } + if (soundFormat == SoundFormat.FORMAT_ADPCM) { + return "wav"; + } + if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { + return "wav"; + } + if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { + return "wav"; + } + if (soundFormat == SoundFormat.FORMAT_NELLYMOSER || soundFormat == SoundFormat.FORMAT_NELLYMOSER16KHZ || soundFormat == SoundFormat.FORMAT_NELLYMOSER8KHZ) { + return "wav"; + } + return "flv"; + } + + private void loadID3v2(InputStream in) { + int size = -1; + try { + // Read ID3v2 header (10 bytes). + in.mark(10); + size = readID3v2Header(in); + } catch (IOException e) { + } finally { + try { + // Unread ID3v2 header (10 bytes). + in.reset(); + } catch (IOException e) { + } + } + // Load ID3v2 tags. + try { + if (size > 0) { + byte[] rawid3v2 = new byte[size]; + in.read(rawid3v2, 0, rawid3v2.length); + } + } catch (IOException e) { + } + } + + /** + * Parse ID3v2 tag header to find out size of ID3v2 frames. + * + * @param in MP3 InputStream + * @return size of ID3v2 frames + header + * @throws IOException + * @author JavaZOOM + */ + private int readID3v2Header(InputStream in) throws IOException { + byte[] id3header = new byte[4]; + int size = -10; + in.read(id3header, 0, 3); + // Look for ID3v2 + if ((id3header[0] == 'I') && (id3header[1] == 'D') && (id3header[2] == '3')) { + in.read(id3header, 0, 3); + int majorVersion = id3header[0]; + int revision = id3header[1]; + in.read(id3header, 0, 4); + size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]); + } + return (size + 10); + } + + @Override + public boolean setSound(InputStream is, int newSoundFormat) { + int newSoundRate = -1; + boolean newSoundSize = false; + boolean newSoundType = false; + long newSoundSampleCount = -1; + byte newSoundData[]; + switch (newSoundFormat) { + case SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: + try (AudioInputStream audioIs = AudioSystem.getAudioInputStream(new BufferedInputStream(is))) { + AudioFormat fmt = audioIs.getFormat(); + newSoundType = fmt.getChannels() == 2; + newSoundSize = fmt.getSampleSizeInBits() == 16; + newSoundSampleCount = audioIs.getFrameLength(); + newSoundData = Helper.readStream(audioIs); + newSoundRate = (int) Math.round(fmt.getSampleRate()); + switch (newSoundRate) { + case 5512: + newSoundRate = 0; + break; + case 11025: + newSoundRate = 1; + break; + case 22050: + newSoundRate = 2; + break; + case 44100: + newSoundRate = 3; + break; + default: + return false; + } + } catch (UnsupportedAudioFileException | IOException ex) { + return false; + } + break; + case SoundFormat.FORMAT_MP3: + BufferedInputStream bis = new BufferedInputStream(is); + loadID3v2(bis); + byte mp3data[] = Helper.readStream(bis); + + final int ID3_V1_LENTGH = 128; + final int ID3_V1_EXT_LENGTH = 227; + + if (mp3data.length > ID3_V1_LENTGH) { + //ID3v1 + if (mp3data[mp3data.length - ID3_V1_LENTGH] == 'T' && mp3data[mp3data.length - ID3_V1_LENTGH + 1] == 'A' && mp3data[mp3data.length - ID3_V1_LENTGH + 2] == 'G') { + mp3data = Arrays.copyOf(mp3data, mp3data.length - ID3_V1_LENTGH); + if (mp3data.length > ID3_V1_EXT_LENGTH) { + //ID3v1 extended + if (mp3data[mp3data.length - ID3_V1_EXT_LENGTH] == 'T' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 1] == 'A' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 2] == 'G' && mp3data[mp3data.length - ID3_V1_EXT_LENGTH + 3] == '+') { + mp3data = Arrays.copyOf(mp3data, mp3data.length - ID3_V1_EXT_LENGTH); + } + } + } + } + try { + MP3SOUNDDATA snd = new MP3SOUNDDATA(mp3data, swf.version, true); + if (!snd.frames.isEmpty()) { + MP3FRAME fr = snd.frames.get(0); + newSoundRate = fr.getSamplingRate(); + switch (newSoundRate) { + case 11025: + newSoundRate = 1; + break; + case 22050: + newSoundRate = 2; + break; + case 44100: + newSoundRate = 3; + break; + default: + return false; + } + newSoundSize = true; + newSoundType = fr.isStereo(); + int len = snd.sampleCount(); + if (fr.isStereo()) { + len = len / 2; + } + newSoundSampleCount = len; + + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); + sos.writeSI16(0); //Latency - how to calculate it? + sos.write(mp3data); + newSoundData = baos.toByteArray(); + } catch (IOException ex) { + return false; + } + break; + default: + return false; + } + if (newSoundData != null) { + this.soundSize = newSoundSize; + this.soundRate = newSoundRate; + this.soundSampleCount = newSoundSampleCount; + this.soundData = newSoundData; + this.soundType = newSoundType; + this.soundFormat = newSoundFormat; + setModified(true); + return true; + } + return false; + + } + + @Override + public boolean importSupported() { + return true; + } + + @Override + public int getSoundRate() { + return soundRate; + } + + @Override + public boolean getSoundType() { + return soundType; + } + + @Override + public byte[] getRawSoundData() { + if (soundFormat == SoundFormat.FORMAT_MP3) { + return Arrays.copyOfRange(soundData, 2, soundData.length); + } + return soundData; + } + + @Override + public int getSoundFormatId() { + return soundFormat; + } + + @Override + public long getTotalSoundSampleCount() { + return soundSampleCount; + } + + @Override + public boolean getSoundSize() { + return soundSize; + } + + @Override + public SoundFormat getSoundFormat() { + final int[] rateMap = {5512, 11025, 22050, 44100}; + return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); + } + +} diff --git a/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index b60169c6d..786e17945 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -201,9 +202,8 @@ public class DefineSpriteTag extends CharacterTag implements Container, Drawable * @throws IOException * @throws java.lang.InterruptedException */ - public DefineSpriteTag(SWF swf, byte[] headerData, byte[] data, int level, long pos, boolean parallel, boolean skipUnusualTags) throws IOException, InterruptedException { - super(swf, ID, "DefineSprite", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version, pos); + public DefineSpriteTag(SWFLimitedInputStream sis, int level, long pos, int length, boolean parallel, boolean skipUnusualTags) throws IOException, InterruptedException { + super(sis.swf, ID, "DefineSprite", pos, length); spriteId = sis.readUI16(); frameCount = sis.readUI16(); List subTags = sis.readTagList(swf, this, level + 1, parallel, skipUnusualTags, true, swf.gfx); @@ -225,7 +225,7 @@ public class DefineSpriteTag extends CharacterTag implements Container, Drawable ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); } SWFOutputStream sos = new SWFOutputStream(os, getVersion()); try { diff --git a/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java b/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java index d2c25d060..c0ab3af7c 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; @@ -38,7 +38,6 @@ import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -466,9 +465,8 @@ public class DefineText2Tag extends TextTag { * @param pos * @throws IOException */ - public DefineText2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineText2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineText2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineText2", pos, length); characterID = sis.readUI16(); textBounds = sis.readRECT(); textMatrix = sis.readMatrix(); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java b/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java index f53b47994..6646e8289 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java @@ -18,7 +18,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.AppStrings; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; @@ -39,7 +39,6 @@ import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.Helper; import com.jpexs.helpers.SerializableImage; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -426,7 +425,7 @@ public class DefineTextTag extends TextTag { } public DefineTextTag(SWF swf, int characterID, RECT textBounds, MATRIX textMatrix, List textRecords) { - super(swf, ID, "DefineText", null, null, 0); + super(swf, ID, "DefineText", 0, 0); this.characterID = characterID; this.textBounds = textBounds; this.textMatrix = textMatrix; @@ -477,9 +476,8 @@ public class DefineTextTag extends TextTag { * @param pos * @throws IOException */ - public DefineTextTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineText", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DefineTextTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineText", pos, length); characterID = sis.readUI16(); textBounds = sis.readRECT(); textMatrix = sis.readMatrix(); diff --git a/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java b/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java index 263c24bb3..719d6a9cb 100644 --- a/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java @@ -1,125 +1,123 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineVideoStreamTag extends CharacterTag implements BoundedTag { - - @SWFType(BasicType.UI16) - public int characterID; - - @SWFType(BasicType.UI16) - public int numFrames; - - @SWFType(BasicType.UI16) - public int width; - - @SWFType(BasicType.UI16) - public int height; - - @Reserved - @SWFType(value = BasicType.UB, count = 4) - public int reserved; - - @SWFType(value = BasicType.UB, count = 3) - public int videoFlagsDeblocking; - - public boolean videoFlagsSmoothing; - - @SWFType(BasicType.UI8) - public int codecID; - - public static final int CODEC_SORENSON_H263 = 2; - public static final int CODEC_SCREEN_VIDEO = 3; - public static final int CODEC_VP6 = 4; - public static final int CODEC_VP6_ALPHA = 5; - public static final int ID = 60; - - @Override - public int getCharacterId() { - return characterID; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterID); - sos.writeUI16(numFrames); - sos.writeUI16(width); - sos.writeUI16(height); - sos.writeUB(4, reserved); - sos.writeUB(3, videoFlagsDeblocking); - sos.writeUB(1, videoFlagsSmoothing ? 1 : 0); - sos.writeUI8(codecID); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineVideoStreamTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineVideoStream", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterID = sis.readUI16(); - numFrames = sis.readUI16(); - width = sis.readUI16(); - height = sis.readUI16(); - reserved = (int) sis.readUB(4); - videoFlagsDeblocking = (int) sis.readUB(3); - videoFlagsSmoothing = sis.readUB(1) == 1; - codecID = sis.readUI8(); - } - - @Override - public RECT getRect() { - return new RECT(0, (int) (SWF.unitDivisor * width), 0, (int) (SWF.unitDivisor * height)); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineVideoStreamTag extends CharacterTag implements BoundedTag { + + @SWFType(BasicType.UI16) + public int characterID; + + @SWFType(BasicType.UI16) + public int numFrames; + + @SWFType(BasicType.UI16) + public int width; + + @SWFType(BasicType.UI16) + public int height; + + @Reserved + @SWFType(value = BasicType.UB, count = 4) + public int reserved; + + @SWFType(value = BasicType.UB, count = 3) + public int videoFlagsDeblocking; + + public boolean videoFlagsSmoothing; + + @SWFType(BasicType.UI8) + public int codecID; + + public static final int CODEC_SORENSON_H263 = 2; + public static final int CODEC_SCREEN_VIDEO = 3; + public static final int CODEC_VP6 = 4; + public static final int CODEC_VP6_ALPHA = 5; + public static final int ID = 60; + + @Override + public int getCharacterId() { + return characterID; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterID); + sos.writeUI16(numFrames); + sos.writeUI16(width); + sos.writeUI16(height); + sos.writeUB(4, reserved); + sos.writeUB(3, videoFlagsDeblocking); + sos.writeUB(1, videoFlagsSmoothing ? 1 : 0); + sos.writeUI8(codecID); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineVideoStreamTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineVideoStream", pos, length); + characterID = sis.readUI16(); + numFrames = sis.readUI16(); + width = sis.readUI16(); + height = sis.readUI16(); + reserved = (int) sis.readUB(4); + videoFlagsDeblocking = (int) sis.readUB(3); + videoFlagsSmoothing = sis.readUB(1) == 1; + codecID = sis.readUI8(); + } + + @Override + public RECT getRect() { + return new RECT(0, (int) (SWF.unitDivisor * width), 0, (int) (SWF.unitDivisor * height)); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DoABCDefineTag.java b/src/com/jpexs/decompiler/flash/tags/DoABCDefineTag.java index 96be571c3..8e506a36f 100644 --- a/src/com/jpexs/decompiler/flash/tags/DoABCDefineTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DoABCDefineTag.java @@ -1,119 +1,115 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.CopyOutputStream; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Defines a series of ActionScript 3 bytecodes to be executed - */ -public class DoABCDefineTag extends Tag implements ABCContainerTag { - - @Override - public ABC getABC() { - return abc; - } - /** - * ActionScript 3 bytecodes - */ - @Internal - private final ABC abc; - /** - * A 32-bit flags value, which may contain the following bits set: - * kDoAbcLazyInitializeFlag = 1: Indicates that the ABC block should not be - * executed immediately, but only parsed. A later finddef may cause its - * scripts to execute. - */ - @SWFType(BasicType.UI32) - public long flags; - /** - * The name assigned to the bytecode. - */ - public String name; - public static final int ID = 82; - - @Override - public String getName() { - return "DoABCDefine (" + name + ")"; - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DoABCDefineTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DoABCDefine", headerData, data, pos); - InputStream is = new ByteArrayInputStream(data); - SWFInputStream sis = new SWFInputStream(is, swf.version); - flags = sis.readUI32(); - name = sis.readString(); - abc = new ABC(is, swf, this); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - OutputStream os = bos; - if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); - } - try (SWFOutputStream sos = new SWFOutputStream(os, getVersion())) { - sos.writeUI32(flags); - sos.writeString(name); - abc.saveToStream(sos); - } - return bos.toByteArray(); - } catch (IOException e) { - } - return new byte[0]; - } - - @Override - public int compareTo(ABCContainerTag o) { - if (o instanceof DoABCDefineTag) { - DoABCDefineTag n = (DoABCDefineTag) o; - int lastCmp = name.compareTo(n.name); - return (lastCmp != 0 ? lastCmp - : name.compareTo(n.name)); - } - return 0; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.CopyOutputStream; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Defines a series of ActionScript 3 bytecodes to be executed + */ +public class DoABCDefineTag extends Tag implements ABCContainerTag { + + @Override + public ABC getABC() { + return abc; + } + /** + * ActionScript 3 bytecodes + */ + @Internal + private final ABC abc; + /** + * A 32-bit flags value, which may contain the following bits set: + * kDoAbcLazyInitializeFlag = 1: Indicates that the ABC block should not be + * executed immediately, but only parsed. A later finddef may cause its + * scripts to execute. + */ + @SWFType(BasicType.UI32) + public long flags; + /** + * The name assigned to the bytecode. + */ + public String name; + public static final int ID = 82; + + @Override + public String getName() { + return "DoABCDefine (" + name + ")"; + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DoABCDefineTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DoABCDefine", pos, length); + flags = sis.readUI32(); + name = sis.readString(); + abc = new ABC(sis.getBaseStream(), swf, this); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + OutputStream os = bos; + if (Configuration.debugCopy.get()) { + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); + } + try (SWFOutputStream sos = new SWFOutputStream(os, getVersion())) { + sos.writeUI32(flags); + sos.writeString(name); + abc.saveToStream(sos); + } + return bos.toByteArray(); + } catch (IOException e) { + } + return new byte[0]; + } + + @Override + public int compareTo(ABCContainerTag o) { + if (o instanceof DoABCDefineTag) { + DoABCDefineTag n = (DoABCDefineTag) o; + int lastCmp = name.compareTo(n.name); + return (lastCmp != 0 ? lastCmp + : name.compareTo(n.name)); + } + return 0; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DoABCTag.java b/src/com/jpexs/decompiler/flash/tags/DoABCTag.java index 23cb51815..cadf45609 100644 --- a/src/com/jpexs/decompiler/flash/tags/DoABCTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DoABCTag.java @@ -1,94 +1,92 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.CopyOutputStream; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Defines a series of ActionScript 3 bytecodes to be executed - */ -public class DoABCTag extends Tag implements ABCContainerTag { - - /** - * ActionScript 3 bytecodes - */ - @Internal - private final ABC abc; - public static final int ID = 72; - - @Override - public ABC getABC() { - return abc; - } - - @Override - public String getName() { - return "DoABC"; - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DoABCTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DoABC", headerData, data, pos); - InputStream is = new ByteArrayInputStream(data); - abc = new ABC(is, swf, this); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - OutputStream os = bos; - if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); - } - try (SWFOutputStream sos = new SWFOutputStream(os, getVersion())) { - abc.saveToStream(sos); - } - return bos.toByteArray(); - } catch (IOException e) { - } - return new byte[0]; - } - - @Override - public int compareTo(ABCContainerTag o) { - return 0; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.CopyOutputStream; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Defines a series of ActionScript 3 bytecodes to be executed + */ +public class DoABCTag extends Tag implements ABCContainerTag { + + /** + * ActionScript 3 bytecodes + */ + @Internal + private final ABC abc; + public static final int ID = 72; + + @Override + public ABC getABC() { + return abc; + } + + @Override + public String getName() { + return "DoABC"; + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DoABCTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DoABC", pos, length); + abc = new ABC(sis.getBaseStream(), swf, this); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + OutputStream os = bos; + if (Configuration.debugCopy.get()) { + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); + } + try (SWFOutputStream sos = new SWFOutputStream(os, getVersion())) { + abc.saveToStream(sos); + } + return bos.toByteArray(); + } catch (IOException e) { + } + return new byte[0]; + } + + @Override + public int compareTo(ABCContainerTag o) { + return 0; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/DoActionTag.java b/src/com/jpexs/decompiler/flash/tags/DoActionTag.java index 5b9b19799..f37d9120a 100644 --- a/src/com/jpexs/decompiler/flash/tags/DoActionTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DoActionTag.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; @@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.helpers.Helper; import com.jpexs.helpers.MemoryInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; @@ -54,9 +56,22 @@ public class DoActionTag extends Tag implements ASMSource { * @param data Data bytes * @param pos */ - public DoActionTag(SWF swf, byte[] headerData, byte[] data, long pos) { - super(swf, ID, "DoAction", headerData, data, pos); - actionBytes = data; + public DoActionTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DoAction", pos, length); + actionBytes = sis.readBytesEx(sis.available()); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + */ + public DoActionTag(SWF swf, long pos, int length) { + super(swf, ID, "DoAction", pos, length); + actionBytes = new byte[0]; } /** @@ -108,18 +123,8 @@ public class DoActionTag extends Tag implements ASMSource { @Override public List getActions() throws InterruptedException { try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int prevLength = 0; - if (previousTag != null) { - byte[] prevData = previousTag.getData(); - baos.write(prevData); - prevLength = prevData.length; - byte[] header = getHeader(data); - baos.write(header); - prevLength += header.length; - } - baos.write(actionBytes); - MemoryInputStream rri = new MemoryInputStream(baos.toByteArray()); + int prevLength = (int) getPos(); + MemoryInputStream rri = new MemoryInputStream(swf.uncompressedData); rri.seek(prevLength); List list = ActionListReader.readActionListTimeout(listeners, getPos() - prevLength, rri, getVersion(), prevLength, -1, toString()/*FIXME?*/); return list; diff --git a/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java b/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java index 57d143365..3838159bc 100644 --- a/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java +++ b/src/com/jpexs/decompiler/flash/tags/DoInitActionTag.java @@ -17,8 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionListReader; @@ -31,7 +30,6 @@ import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.Helper; import com.jpexs.helpers.MemoryInputStream; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -63,9 +61,8 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource { * @param pos * @throws IOException */ - public DoInitActionTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DoInitAction", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public DoInitActionTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DoInitAction", pos, length); spriteId = sis.readUI16(); //actions = sis.readActionList(); actionBytes = sis.readBytesEx(sis.available()); @@ -119,21 +116,8 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource { @Override public List getActions() throws InterruptedException { try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int prevLength = 0; - if (previousTag != null) { - byte[] prevData = previousTag.getData(); - baos.write(prevData); - prevLength = prevData.length; - baos.write(0); - baos.write(0); - prevLength += 2; - byte[] header = getHeader(data); - baos.write(header); - prevLength += header.length; - } - baos.write(actionBytes); - MemoryInputStream rri = new MemoryInputStream(baos.toByteArray()); + int prevLength = (int) (getPos() + 2); + MemoryInputStream rri = new MemoryInputStream(swf.uncompressedData); rri.seek(prevLength); List list = ActionListReader.readActionListTimeout(listeners, getPos() + 2 - prevLength, rri, getVersion(), prevLength, -1, toString()/*FIXME?*/); return list; diff --git a/src/com/jpexs/decompiler/flash/tags/EnableDebugger2Tag.java b/src/com/jpexs/decompiler/flash/tags/EnableDebugger2Tag.java index a82e35852..d564c4b5f 100644 --- a/src/com/jpexs/decompiler/flash/tags/EnableDebugger2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/EnableDebugger2Tag.java @@ -1,80 +1,77 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Marks the file is not importable for editing - * - * @author JPEXS - */ -public class EnableDebugger2Tag extends Tag { - - @Reserved - @SWFType(BasicType.UI16) - public int reserved; - /** - * MD5 hash of password - */ - public String passwordHash; - public static final int ID = 64; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(reserved); - sos.writeString(passwordHash); - - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public EnableDebugger2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "EnableDebugger2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - reserved = sis.readUI16(); - passwordHash = sis.readString(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Marks the file is not importable for editing + * + * @author JPEXS + */ +public class EnableDebugger2Tag extends Tag { + + @Reserved + @SWFType(BasicType.UI16) + public int reserved; + /** + * MD5 hash of password + */ + public String passwordHash; + public static final int ID = 64; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(reserved); + sos.writeString(passwordHash); + + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public EnableDebugger2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "EnableDebugger2", pos, length); + reserved = sis.readUI16(); + passwordHash = sis.readString(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/EnableDebuggerTag.java b/src/com/jpexs/decompiler/flash/tags/EnableDebuggerTag.java index f17182cc5..0ed952516 100644 --- a/src/com/jpexs/decompiler/flash/tags/EnableDebuggerTag.java +++ b/src/com/jpexs/decompiler/flash/tags/EnableDebuggerTag.java @@ -1,73 +1,70 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Marks the file is not importable for editing - * - * @author JPEXS - */ -public class EnableDebuggerTag extends Tag { - - /** - * MD5 hash of password - */ - public String passwordHash; - public static final int ID = 58; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - if (passwordHash != null) { - sos.writeString(passwordHash); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public EnableDebuggerTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "EnableDebugger", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - passwordHash = sis.readString(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Marks the file is not importable for editing + * + * @author JPEXS + */ +public class EnableDebuggerTag extends Tag { + + /** + * MD5 hash of password + */ + public String passwordHash; + public static final int ID = 58; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + if (passwordHash != null) { + sos.writeString(passwordHash); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public EnableDebuggerTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "EnableDebugger", pos, length); + passwordHash = sis.readString(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java b/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java index 66b8cf6eb..40700d585 100644 --- a/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java +++ b/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java @@ -1,85 +1,82 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Optional; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Enable flash profiling information - * - * @author JPEXS - */ -public class EnableTelemetryTag extends Tag { - - public static final int ID = 93; - - @SWFType(value = BasicType.UB, count = 16) - @Reserved - public int reserved; - - @Optional - @SWFType(value = BasicType.UI8, count = 32) - public byte[] passwordHash; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUB(16, reserved); - if (passwordHash != null) { - sos.write(passwordHash); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public EnableTelemetryTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - reserved = (int) sis.readUB(16); - if (sis.available() > 0) { - passwordHash = sis.readBytesEx(32); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Optional; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Enable flash profiling information + * + * @author JPEXS + */ +public class EnableTelemetryTag extends Tag { + + public static final int ID = 93; + + @SWFType(value = BasicType.UB, count = 16) + @Reserved + public int reserved; + + @Optional + @SWFType(value = BasicType.UI8, count = 32) + public byte[] passwordHash; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUB(16, reserved); + if (passwordHash != null) { + sos.write(passwordHash); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public EnableTelemetryTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "", pos, length); + reserved = (int) sis.readUB(16); + if (sis.available() > 0) { + passwordHash = sis.readBytesEx(32); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/EndTag.java b/src/com/jpexs/decompiler/flash/tags/EndTag.java index 6490c8e46..2a4e6ac5b 100644 --- a/src/com/jpexs/decompiler/flash/tags/EndTag.java +++ b/src/com/jpexs/decompiler/flash/tags/EndTag.java @@ -1,57 +1,57 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import java.io.IOException; - -/** - * Extends the functionality of the PlaceObject2Tag - * - * @author JPEXS - */ -public class EndTag extends Tag { - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - return new byte[0]; - } - public static final int ID = 0; - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public EndTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "End", headerData, data, pos); - - } - - public EndTag(SWF swf) { - super(swf, ID, "End", new byte[2], new byte[0], 0); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import java.io.IOException; + +/** + * Extends the functionality of the PlaceObject2Tag + * + * @author JPEXS + */ +public class EndTag extends Tag { + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + return new byte[0]; + } + public static final int ID = 0; + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public EndTag(SWF swf, long pos, int length) throws IOException { + super(swf, ID, "End", pos, length); + + } + + public EndTag(SWF swf) { + super(swf, ID, "End", 0, 0); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/ExportAssetsTag.java b/src/com/jpexs/decompiler/flash/tags/ExportAssetsTag.java index 46f5f7704..3bbd1f7c2 100644 --- a/src/com/jpexs/decompiler/flash/tags/ExportAssetsTag.java +++ b/src/com/jpexs/decompiler/flash/tags/ExportAssetsTag.java @@ -1,99 +1,99 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFArray; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * Makes portions of a SWF file available for import by other SWF files - * - * @author JPEXS - */ -public class ExportAssetsTag extends Tag { - - /** - * HashMap with assets - */ - @SWFType(value = BasicType.UI16) - @SWFArray(value = "tag", countField = "count") - public List tags; - - @SWFArray(value = "name", countField = "count") - public List names; - public static final int ID = 56; - - public ExportAssetsTag(SWF swf) { - super(swf, ID, "ExportAssets", new byte[0], new byte[0], 0); - tags = new ArrayList<>(); - names = new ArrayList<>(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public ExportAssetsTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "ExportAssets", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - int count = sis.readUI16(); - tags = new ArrayList<>(); - names = new ArrayList<>(); - for (int i = 0; i < count; i++) { - int characterId = sis.readUI16(); - tags.add(characterId); - String name = sis.readString(); - names.add(name); - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(tags.size()); - for (int i = 0; i < tags.size(); i++) { - sos.writeUI16(tags.get(i)); - sos.writeString(names.get(i)); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFArray; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Makes portions of a SWF file available for import by other SWF files + * + * @author JPEXS + */ +public class ExportAssetsTag extends Tag { + + /** + * HashMap with assets + */ + @SWFType(value = BasicType.UI16) + @SWFArray(value = "tag", countField = "count") + public List tags; + + @SWFArray(value = "name", countField = "count") + public List names; + public static final int ID = 56; + + public ExportAssetsTag(SWF swf) { + super(swf, ID, "ExportAssets", 0, 0); + tags = new ArrayList<>(); + names = new ArrayList<>(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public ExportAssetsTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "ExportAssets", pos, length); + int count = sis.readUI16(); + tags = new ArrayList<>(); + names = new ArrayList<>(); + for (int i = 0; i < count; i++) { + int characterId = sis.readUI16(); + tags.add(characterId); + String name = sis.readString(); + names.add(name); + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(tags.size()); + for (int i = 0; i < tags.size(); i++) { + sos.writeUI16(tags.get(i)); + sos.writeString(names.get(i)); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/FileAttributesTag.java b/src/com/jpexs/decompiler/flash/tags/FileAttributesTag.java index 8543c3155..a03d8a37d 100644 --- a/src/com/jpexs/decompiler/flash/tags/FileAttributesTag.java +++ b/src/com/jpexs/decompiler/flash/tags/FileAttributesTag.java @@ -1,92 +1,92 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class FileAttributesTag extends Tag { - - public boolean useDirectBlit; - public boolean useGPU; - public boolean hasMetadata; - public boolean actionScript3; - public boolean useNetwork; - public boolean noCrossDomainCache; - @Reserved - public boolean reserved1; - @Reserved - public boolean reserved2; - - @SWFType(value = BasicType.UB, count = 24) - @Reserved - public int reserved3; - public static final int ID = 69; - - public FileAttributesTag() { - super(null, ID, "FileAttributes", new byte[0], new byte[0], 0); - } - - public FileAttributesTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "FileAttributes", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - reserved1 = sis.readUB(1) == 1; // reserved - // UB[1] == 0 (reserved) - useDirectBlit = sis.readUB(1) != 0; - useGPU = sis.readUB(1) != 0; - hasMetadata = sis.readUB(1) != 0; - actionScript3 = sis.readUB(1) != 0; - noCrossDomainCache = sis.readUB(1) != 0; - reserved2 = sis.readUB(1) == 1; // reserved - useNetwork = sis.readUB(1) != 0; - // UB[24] == 0 (reserved) - reserved3 = (int) sis.readUB(24); //reserved - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUB(1, reserved1 ? 1 : 0); //reserved - sos.writeUB(1, useDirectBlit ? 1 : 0); - sos.writeUB(1, useGPU ? 1 : 0); - sos.writeUB(1, hasMetadata ? 1 : 0); - sos.writeUB(1, actionScript3 ? 1 : 0); - sos.writeUB(1, noCrossDomainCache ? 1 : 0); - sos.writeUB(1, reserved2 ? 1 : 0); //reserved - sos.writeUB(1, useNetwork ? 1 : 0); - sos.writeUB(24, reserved3); //reserved - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class FileAttributesTag extends Tag { + + public boolean useDirectBlit; + public boolean useGPU; + public boolean hasMetadata; + public boolean actionScript3; + public boolean useNetwork; + public boolean noCrossDomainCache; + @Reserved + public boolean reserved1; + @Reserved + public boolean reserved2; + + @SWFType(value = BasicType.UB, count = 24) + @Reserved + public int reserved3; + public static final int ID = 69; + + public FileAttributesTag(SWF swf) { + super(swf, ID, "FileAttributes", 0, 0); + } + + public FileAttributesTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "FileAttributes", pos, length); + reserved1 = sis.readUB(1) == 1; // reserved + // UB[1] == 0 (reserved) + useDirectBlit = sis.readUB(1) != 0; + useGPU = sis.readUB(1) != 0; + hasMetadata = sis.readUB(1) != 0; + actionScript3 = sis.readUB(1) != 0; + noCrossDomainCache = sis.readUB(1) != 0; + reserved2 = sis.readUB(1) == 1; // reserved + useNetwork = sis.readUB(1) != 0; + // UB[24] == 0 (reserved) + reserved3 = (int) sis.readUB(24); //reserved + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUB(1, reserved1 ? 1 : 0); //reserved + sos.writeUB(1, useDirectBlit ? 1 : 0); + sos.writeUB(1, useGPU ? 1 : 0); + sos.writeUB(1, hasMetadata ? 1 : 0); + sos.writeUB(1, actionScript3 ? 1 : 0); + sos.writeUB(1, noCrossDomainCache ? 1 : 0); + sos.writeUB(1, reserved2 ? 1 : 0); //reserved + sos.writeUB(1, useNetwork ? 1 : 0); + sos.writeUB(24, reserved3); //reserved + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/FrameLabelTag.java b/src/com/jpexs/decompiler/flash/tags/FrameLabelTag.java index df1770463..08eaf8b0d 100644 --- a/src/com/jpexs/decompiler/flash/tags/FrameLabelTag.java +++ b/src/com/jpexs/decompiler/flash/tags/FrameLabelTag.java @@ -1,71 +1,68 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class FrameLabelTag extends Tag { - - public String name; - public boolean namedAnchor = false; - public static final int ID = 43; - - public String getLabelName() { - return name; - } - - public boolean isNamedAnchor() { - return namedAnchor; - } - - public FrameLabelTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "FrameLabel", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - name = sis.readString(); - if (sis.available() > 0) { - if (sis.readUI8() == 1) { - namedAnchor = true; - } - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeString(name); - if (namedAnchor) { - sos.writeUI8(1); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class FrameLabelTag extends Tag { + + public String name; + public boolean namedAnchor = false; + public static final int ID = 43; + + public String getLabelName() { + return name; + } + + public boolean isNamedAnchor() { + return namedAnchor; + } + + public FrameLabelTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "FrameLabel", pos, length); + name = sis.readString(); + if (sis.available() > 0) { + if (sis.readUI8() == 1) { + namedAnchor = true; + } + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeString(name); + if (namedAnchor) { + sos.writeUI8(1); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/ImportAssets2Tag.java b/src/com/jpexs/decompiler/flash/tags/ImportAssets2Tag.java index 6702d4134..a12132c0b 100644 --- a/src/com/jpexs/decompiler/flash/tags/ImportAssets2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/ImportAssets2Tag.java @@ -1,123 +1,120 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.ImportTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFArray; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Imports characters from another file, v2 - * - * @author JPEXS - */ -public class ImportAssets2Tag extends Tag implements ImportTag { - - public String url; - @Reserved - @SWFType(BasicType.UI8) - public int reserved1 = 1; - @Reserved - @SWFType(BasicType.UI8) - public int reserved2 = 0; - /** - * HashMap with assets - */ - @SWFType(value = BasicType.UI16) - @SWFArray(value = "tag", countField = "count") - public List tags; - @SWFArray(value = "name", countField = "count") - public List names; - public static final int ID = 71; - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public ImportAssets2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "ImportAssets2", headerData, data, pos); - tags = new ArrayList<>(); - names = new ArrayList<>(); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - url = sis.readString(); - reserved1 = sis.readUI8();//reserved, must be 1 - reserved2 = sis.readUI8();//reserved, must be 0 - int count = sis.readUI16(); - for (int i = 0; i < count; i++) { - int charId = sis.readUI16(); - String tagName = sis.readString(); - tags.add(charId); - names.add(tagName); - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeString(url); - sos.writeUI8(reserved1); - sos.writeUI8(reserved2); - sos.writeUI16(tags.size()); - for (int i = 0; i < tags.size(); i++) { - sos.writeUI16(tags.get(i)); - sos.writeString(names.get(i)); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - @Override - public Map getAssets() { - Map assets = new HashMap<>(); - for (int i = 0; i < tags.size(); i++) { - assets.put(tags.get(i), names.get(i)); - } - return assets; - } - - @Override - public String getUrl() { - return url; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.ImportTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFArray; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Imports characters from another file, v2 + * + * @author JPEXS + */ +public class ImportAssets2Tag extends Tag implements ImportTag { + + public String url; + @Reserved + @SWFType(BasicType.UI8) + public int reserved1 = 1; + @Reserved + @SWFType(BasicType.UI8) + public int reserved2 = 0; + /** + * HashMap with assets + */ + @SWFType(value = BasicType.UI16) + @SWFArray(value = "tag", countField = "count") + public List tags; + @SWFArray(value = "name", countField = "count") + public List names; + public static final int ID = 71; + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public ImportAssets2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "ImportAssets2", pos, length); + tags = new ArrayList<>(); + names = new ArrayList<>(); + url = sis.readString(); + reserved1 = sis.readUI8();//reserved, must be 1 + reserved2 = sis.readUI8();//reserved, must be 0 + int count = sis.readUI16(); + for (int i = 0; i < count; i++) { + int charId = sis.readUI16(); + String tagName = sis.readString(); + tags.add(charId); + names.add(tagName); + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeString(url); + sos.writeUI8(reserved1); + sos.writeUI8(reserved2); + sos.writeUI16(tags.size()); + for (int i = 0; i < tags.size(); i++) { + sos.writeUI16(tags.get(i)); + sos.writeString(names.get(i)); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + @Override + public Map getAssets() { + Map assets = new HashMap<>(); + for (int i = 0; i < tags.size(); i++) { + assets.put(tags.get(i), names.get(i)); + } + return assets; + } + + @Override + public String getUrl() { + return url; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/ImportAssetsTag.java b/src/com/jpexs/decompiler/flash/tags/ImportAssetsTag.java index 4e8d9d10b..77955b691 100644 --- a/src/com/jpexs/decompiler/flash/tags/ImportAssetsTag.java +++ b/src/com/jpexs/decompiler/flash/tags/ImportAssetsTag.java @@ -1,112 +1,109 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.ImportTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFArray; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Imports characters from another file - * - * @author JPEXS - */ -public class ImportAssetsTag extends Tag implements ImportTag { - - public String url; - /** - * HashMap with assets - */ - @SWFType(value = BasicType.UI16) - @SWFArray(value = "tag", countField = "count") - public List tags; - @SWFArray(value = "name", countField = "count") - public List names; - public static final int ID = 57; - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public ImportAssetsTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "ImportAssets", headerData, data, pos); - tags = new ArrayList<>(); - names = new ArrayList<>(); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - url = sis.readString(); - int count = sis.readUI16(); - for (int i = 0; i < count; i++) { - int charId = sis.readUI16(); - String tagName = sis.readString(); - tags.add(charId); - names.add(tagName); - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeString(url); - sos.writeUI16(tags.size()); - for (int i = 0; i < tags.size(); i++) { - sos.writeUI16(tags.get(i)); - sos.writeString(names.get(i)); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - @Override - public Map getAssets() { - Map assets = new HashMap<>(); - for (int i = 0; i < tags.size(); i++) { - assets.put(tags.get(i), names.get(i)); - } - return assets; - } - - @Override - public String getUrl() { - return url; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.ImportTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFArray; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Imports characters from another file + * + * @author JPEXS + */ +public class ImportAssetsTag extends Tag implements ImportTag { + + public String url; + /** + * HashMap with assets + */ + @SWFType(value = BasicType.UI16) + @SWFArray(value = "tag", countField = "count") + public List tags; + @SWFArray(value = "name", countField = "count") + public List names; + public static final int ID = 57; + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public ImportAssetsTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "ImportAssets", pos, length); + tags = new ArrayList<>(); + names = new ArrayList<>(); + url = sis.readString(); + int count = sis.readUI16(); + for (int i = 0; i < count; i++) { + int charId = sis.readUI16(); + String tagName = sis.readString(); + tags.add(charId); + names.add(tagName); + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeString(url); + sos.writeUI16(tags.size()); + for (int i = 0; i < tags.size(); i++) { + sos.writeUI16(tags.get(i)); + sos.writeString(names.get(i)); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + @Override + public Map getAssets() { + Map assets = new HashMap<>(); + for (int i = 0; i < tags.size(); i++) { + assets.put(tags.get(i), names.get(i)); + } + return assets; + } + + @Override + public String getUrl() { + return url; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/JPEGTablesTag.java b/src/com/jpexs/decompiler/flash/tags/JPEGTablesTag.java index 9d4de8838..577715ebc 100644 --- a/src/com/jpexs/decompiler/flash/tags/JPEGTablesTag.java +++ b/src/com/jpexs/decompiler/flash/tags/JPEGTablesTag.java @@ -1,29 +1,33 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import java.io.IOException; - -public class JPEGTablesTag extends Tag { - - public static final int ID = 8; - - public JPEGTablesTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "JPEGTables", headerData, data, pos); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import java.io.IOException; + +public class JPEGTablesTag extends Tag { + + public static final int ID = 8; + @Internal + public byte[] jpegData; + + public JPEGTablesTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "JPEGTables", pos, length); + jpegData = sis.readBytesEx(sis.available()); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/MetadataTag.java b/src/com/jpexs/decompiler/flash/tags/MetadataTag.java index 40e0ed578..e95f47947 100644 --- a/src/com/jpexs/decompiler/flash/tags/MetadataTag.java +++ b/src/com/jpexs/decompiler/flash/tags/MetadataTag.java @@ -1,59 +1,56 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.annotations.Multiline; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class MetadataTag extends Tag { - - @Multiline - public String xmlMetadata; - public static final int ID = 77; - - public MetadataTag(SWF swf, byte[] headerData, byte[] data, long pos) { - super(swf, ID, "Metadata", headerData, data, pos); - try { - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - xmlMetadata = sis.readString(); - } catch (IOException ex) { - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeString(xmlMetadata); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.annotations.Multiline; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class MetadataTag extends Tag { + + @Multiline + public String xmlMetadata; + public static final int ID = 77; + + public MetadataTag(SWFLimitedInputStream sis, long pos, int length) { + super(sis.swf, ID, "Metadata", pos, length); + try { + xmlMetadata = sis.readString(); + } catch (IOException ex) { + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeString(xmlMetadata); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java b/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java index 114afd880..3c5251159 100644 --- a/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -150,7 +150,7 @@ public class PlaceObject2Tag extends CharacterIdTag implements Container, PlaceO ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); } SWFOutputStream sos = new SWFOutputStream(os, getVersion()); try { @@ -191,7 +191,7 @@ public class PlaceObject2Tag extends CharacterIdTag implements Container, PlaceO } public PlaceObject2Tag(SWF swf, boolean placeFlagHasClipActions, boolean placeFlagHasClipDepth, boolean placeFlagHasName, boolean placeFlagHasRatio, boolean placeFlagHasColorTransform, boolean placeFlagHasMatrix, boolean placeFlagHasCharacter, boolean placeFlagMove, int depth, int characterId, MATRIX matrix, CXFORMWITHALPHA colorTransform, int ratio, String name, int clipDepth, CLIPACTIONS clipActions) { - super(swf, ID, "PlaceObject2", null, null, 0); + super(swf, ID, "PlaceObject2", 0, 0); this.placeFlagHasClipActions = placeFlagHasClipActions; this.placeFlagHasClipDepth = placeFlagHasClipDepth; this.placeFlagHasName = placeFlagHasName; @@ -219,9 +219,8 @@ public class PlaceObject2Tag extends CharacterIdTag implements Container, PlaceO * @param pos * @throws IOException */ - public PlaceObject2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "PlaceObject2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public PlaceObject2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "PlaceObject2", pos, length); placeFlagHasClipActions = sis.readUB(1) == 1; placeFlagHasClipDepth = sis.readUB(1) == 1; placeFlagHasName = sis.readUB(1) == 1; diff --git a/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java b/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java index d587d62f8..52bd37090 100644 --- a/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java @@ -17,8 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.EndOfStreamException; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -226,7 +225,7 @@ public class PlaceObject3Tag extends CharacterIdTag implements Container, PlaceO ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); } SWFOutputStream sos = new SWFOutputStream(os, getVersion()); try { @@ -304,9 +303,8 @@ public class PlaceObject3Tag extends CharacterIdTag implements Container, PlaceO * @param pos * @throws IOException */ - public PlaceObject3Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "PlaceObject3", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public PlaceObject3Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "PlaceObject3", pos, length); placeFlagHasClipActions = sis.readUB(1) == 1; placeFlagHasClipDepth = sis.readUB(1) == 1; placeFlagHasName = sis.readUB(1) == 1; diff --git a/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java b/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java index e1b48bad3..afddc8371 100644 --- a/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java @@ -17,8 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.EndOfStreamException; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -228,7 +227,7 @@ public class PlaceObject4Tag extends CharacterIdTag implements Container, PlaceO ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; if (Configuration.debugCopy.get()) { - os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); + os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData())); } SWFOutputStream sos = new SWFOutputStream(os, getVersion()); try { @@ -305,9 +304,8 @@ public class PlaceObject4Tag extends CharacterIdTag implements Container, PlaceO * @param pos * @throws IOException */ - public PlaceObject4Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "PlaceObject4", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public PlaceObject4Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "PlaceObject4", pos, length); placeFlagHasClipActions = sis.readUB(1) == 1; placeFlagHasClipDepth = sis.readUB(1) == 1; placeFlagHasName = sis.readUB(1) == 1; diff --git a/src/com/jpexs/decompiler/flash/tags/PlaceObjectTag.java b/src/com/jpexs/decompiler/flash/tags/PlaceObjectTag.java index 1132b7512..209a09c10 100644 --- a/src/com/jpexs/decompiler/flash/tags/PlaceObjectTag.java +++ b/src/com/jpexs/decompiler/flash/tags/PlaceObjectTag.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; @@ -30,7 +30,6 @@ import com.jpexs.decompiler.flash.types.RGBA; import com.jpexs.decompiler.flash.types.annotations.Optional; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.filters.FILTER; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -106,9 +105,8 @@ public class PlaceObjectTag extends CharacterIdTag implements PlaceObjectTypeTag * @param pos * @throws IOException */ - public PlaceObjectTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "PlaceObject", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); + public PlaceObjectTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "PlaceObject", pos, length); characterId = sis.readUI16(); depth = sis.readUI16(); matrix = sis.readMatrix(); @@ -118,7 +116,7 @@ public class PlaceObjectTag extends CharacterIdTag implements PlaceObjectTypeTag } public PlaceObjectTag(SWF swf, int characterId, int depth, MATRIX matrix, CXFORM colorTransform) { - super(swf, ID, "PlaceObject", null, null, 0); + super(swf, ID, "PlaceObject", 0, 0); this.characterId = characterId; this.depth = depth; this.matrix = matrix; diff --git a/src/com/jpexs/decompiler/flash/tags/ProductInfoTag.java b/src/com/jpexs/decompiler/flash/tags/ProductInfoTag.java index 73dd29fba..a55f50d7e 100644 --- a/src/com/jpexs/decompiler/flash/tags/ProductInfoTag.java +++ b/src/com/jpexs/decompiler/flash/tags/ProductInfoTag.java @@ -1,97 +1,94 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class ProductInfoTag extends Tag { - - @SWFType(BasicType.UI32) - public long productID; - @SWFType(BasicType.UI32) - public long edition; - @SWFType(BasicType.UI8) - public int majorVersion; - @SWFType(BasicType.UI8) - public int minorVersion; - @SWFType(BasicType.UI32) - public long buildLow; - @SWFType(BasicType.UI32) - public long buildHigh; - @SWFType(BasicType.UI32) - public long compilationDateLow; - @SWFType(BasicType.UI32) - public long compilationDateHigh; - public static final int ID = 41; - - public ProductInfoTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "ProductInfo", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - /* - * 0: Unknown - * 1: Macromedia Flex for J2EE - * 2: Macromedia Flex for .NET - * 3: Adobe Flex - */ - productID = sis.readUI32(); - - /* - * 0: Developer Edition - * 1: Full Commercial Edition - * 2: Non Commercial Edition - * 3: Educational Edition - * 4: Not For Resale (NFR) Edition - * 5: Trial Edition - * 6: None - */ - edition = sis.readUI32(); - majorVersion = sis.readUI8(); - minorVersion = sis.readUI8(); - buildLow = sis.readUI32(); - buildHigh = sis.readUI32(); - compilationDateLow = sis.readUI32(); - compilationDateHigh = sis.readUI32(); - } - - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI32(productID); - sos.writeUI32(edition); - sos.writeUI8(majorVersion); - sos.writeUI8(minorVersion); - sos.writeUI32(buildLow); - sos.writeUI32(buildHigh); - sos.writeUI32(compilationDateLow); - sos.writeUI32(compilationDateHigh); - } catch (IOException e) { - } - return baos.toByteArray(); - } - -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class ProductInfoTag extends Tag { + + @SWFType(BasicType.UI32) + public long productID; + @SWFType(BasicType.UI32) + public long edition; + @SWFType(BasicType.UI8) + public int majorVersion; + @SWFType(BasicType.UI8) + public int minorVersion; + @SWFType(BasicType.UI32) + public long buildLow; + @SWFType(BasicType.UI32) + public long buildHigh; + @SWFType(BasicType.UI32) + public long compilationDateLow; + @SWFType(BasicType.UI32) + public long compilationDateHigh; + public static final int ID = 41; + + public ProductInfoTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "ProductInfo", pos, length); + /* + * 0: Unknown + * 1: Macromedia Flex for J2EE + * 2: Macromedia Flex for .NET + * 3: Adobe Flex + */ + productID = sis.readUI32(); + + /* + * 0: Developer Edition + * 1: Full Commercial Edition + * 2: Non Commercial Edition + * 3: Educational Edition + * 4: Not For Resale (NFR) Edition + * 5: Trial Edition + * 6: None + */ + edition = sis.readUI32(); + majorVersion = sis.readUI8(); + minorVersion = sis.readUI8(); + buildLow = sis.readUI32(); + buildHigh = sis.readUI32(); + compilationDateLow = sis.readUI32(); + compilationDateHigh = sis.readUI32(); + } + + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI32(productID); + sos.writeUI32(edition); + sos.writeUI8(majorVersion); + sos.writeUI8(minorVersion); + sos.writeUI32(buildLow); + sos.writeUI32(buildHigh); + sos.writeUI32(compilationDateLow); + sos.writeUI32(compilationDateHigh); + } catch (IOException e) { + } + return baos.toByteArray(); + } + +} diff --git a/src/com/jpexs/decompiler/flash/tags/ProtectTag.java b/src/com/jpexs/decompiler/flash/tags/ProtectTag.java index 33c1ba75c..80298f94a 100644 --- a/src/com/jpexs/decompiler/flash/tags/ProtectTag.java +++ b/src/com/jpexs/decompiler/flash/tags/ProtectTag.java @@ -1,77 +1,74 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Marks the file is not importable for editing - * - * @author JPEXS - */ -public class ProtectTag extends Tag { - - /** - * MD5 hash of password - */ - public String passwordHash; - public static final int ID = 24; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - if (!"".equals(passwordHash)) { - sos.writeString(passwordHash); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public ProtectTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "Protect", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - if (sis.available() > 0) { - passwordHash = sis.readString(); - } else { - passwordHash = ""; - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Marks the file is not importable for editing + * + * @author JPEXS + */ +public class ProtectTag extends Tag { + + /** + * MD5 hash of password + */ + public String passwordHash; + public static final int ID = 24; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + if (!"".equals(passwordHash)) { + sos.writeString(passwordHash); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public ProtectTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "Protect", pos, length); + if (sis.available() > 0) { + passwordHash = sis.readString(); + } else { + passwordHash = ""; + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/RemoveObject2Tag.java b/src/com/jpexs/decompiler/flash/tags/RemoveObject2Tag.java index c5e7c37db..98a05e995 100644 --- a/src/com/jpexs/decompiler/flash/tags/RemoveObject2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/RemoveObject2Tag.java @@ -1,43 +1,40 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.tags.base.RemoveTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -public class RemoveObject2Tag extends Tag implements RemoveTag { - - @SWFType(BasicType.UI16) - public int depth; - public static final int ID = 28; - - public RemoveObject2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "RemoveObject2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - depth = sis.readUI16(); - } - - @Override - public int getDepth() { - return depth; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.tags.base.RemoveTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.IOException; + +public class RemoveObject2Tag extends Tag implements RemoveTag { + + @SWFType(BasicType.UI16) + public int depth; + public static final int ID = 28; + + public RemoveObject2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "RemoveObject2", pos, length); + depth = sis.readUI16(); + } + + @Override + public int getDepth() { + return depth; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/RemoveObjectTag.java b/src/com/jpexs/decompiler/flash/tags/RemoveObjectTag.java index 024607793..31fa2d79e 100644 --- a/src/com/jpexs/decompiler/flash/tags/RemoveObjectTag.java +++ b/src/com/jpexs/decompiler/flash/tags/RemoveObjectTag.java @@ -1,93 +1,90 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.tags.base.RemoveTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Removes the specified character - * - * @author JPEXS - */ -public class RemoveObjectTag extends CharacterIdTag implements RemoveTag { - - /** - * ID of character to place - */ - @SWFType(BasicType.UI16) - public int characterId; - /** - * Depth of character - */ - @SWFType(BasicType.UI16) - public int depth; - public static final int ID = 5; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterId); - sos.writeUI16(depth); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public RemoveObjectTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "RemoveObject", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterId = sis.readUI16(); - depth = sis.readUI16(); - } - - @Override - public int getDepth() { - return depth; - } - - @Override - public int getCharacterId() { - return characterId; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.tags.base.RemoveTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Removes the specified character + * + * @author JPEXS + */ +public class RemoveObjectTag extends CharacterIdTag implements RemoveTag { + + /** + * ID of character to place + */ + @SWFType(BasicType.UI16) + public int characterId; + /** + * Depth of character + */ + @SWFType(BasicType.UI16) + public int depth; + public static final int ID = 5; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterId); + sos.writeUI16(depth); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public RemoveObjectTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "RemoveObject", pos, length); + characterId = sis.readUI16(); + depth = sis.readUI16(); + } + + @Override + public int getDepth() { + return depth; + } + + @Override + public int getCharacterId() { + return characterId; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/ScriptLimitsTag.java b/src/com/jpexs/decompiler/flash/tags/ScriptLimitsTag.java index 5e9d69c12..285e4f629 100644 --- a/src/com/jpexs/decompiler/flash/tags/ScriptLimitsTag.java +++ b/src/com/jpexs/decompiler/flash/tags/ScriptLimitsTag.java @@ -1,63 +1,60 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class ScriptLimitsTag extends Tag { - - @SWFType(BasicType.UI16) - public int maxRecursionDepth; - - @SWFType(BasicType.UI16) - public int scriptTimeoutSeconds; - - public static final int ID = 65; - - public ScriptLimitsTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "ScriptLimits", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - maxRecursionDepth = sis.readUI16(); - scriptTimeoutSeconds = sis.readUI16(); - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(maxRecursionDepth); - sos.writeUI16(scriptTimeoutSeconds); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class ScriptLimitsTag extends Tag { + + @SWFType(BasicType.UI16) + public int maxRecursionDepth; + + @SWFType(BasicType.UI16) + public int scriptTimeoutSeconds; + + public static final int ID = 65; + + public ScriptLimitsTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "ScriptLimits", pos, length); + maxRecursionDepth = sis.readUI16(); + scriptTimeoutSeconds = sis.readUI16(); + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(maxRecursionDepth); + sos.writeUI16(scriptTimeoutSeconds); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/SetBackgroundColorTag.java b/src/com/jpexs/decompiler/flash/tags/SetBackgroundColorTag.java index 94ac69154..af29acbee 100644 --- a/src/com/jpexs/decompiler/flash/tags/SetBackgroundColorTag.java +++ b/src/com/jpexs/decompiler/flash/tags/SetBackgroundColorTag.java @@ -1,53 +1,51 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.RGB; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -public class SetBackgroundColorTag extends Tag { - - public RGB backgroundColor; - public static final int ID = 9; - - public SetBackgroundColorTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "SetBackgroundColor", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - backgroundColor = sis.readRGB(); - } - - public SetBackgroundColorTag(SWF swf, RGB backgroundColor) { - super(swf, ID, "SetBackgroundColor", null, null, 0); - this.backgroundColor = backgroundColor; - } - - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, getVersion()); - try { - sos.writeRGB(backgroundColor); - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.RGB; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class SetBackgroundColorTag extends Tag { + + public RGB backgroundColor; + public static final int ID = 9; + + public SetBackgroundColorTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "SetBackgroundColor", pos, length); + backgroundColor = sis.readRGB(); + } + + public SetBackgroundColorTag(SWF swf, RGB backgroundColor) { + super(swf, ID, "SetBackgroundColor", 0, 0); + this.backgroundColor = backgroundColor; + } + + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, getVersion()); + try { + sos.writeRGB(backgroundColor); + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/SetTabIndexTag.java b/src/com/jpexs/decompiler/flash/tags/SetTabIndexTag.java index 8dbfec66c..0692f5c27 100644 --- a/src/com/jpexs/decompiler/flash/tags/SetTabIndexTag.java +++ b/src/com/jpexs/decompiler/flash/tags/SetTabIndexTag.java @@ -1,81 +1,78 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Sets the index of an object within the tab order. - * - * @author JPEXS - */ -public class SetTabIndexTag extends Tag { - - /** - * Depth of character - */ - @SWFType(BasicType.UI16) - public int depth; - /** - * Tab order value - */ - @SWFType(BasicType.UI16) - public int tabIndex; - public static final int ID = 66; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(depth); - sos.writeUI16(tabIndex); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public SetTabIndexTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "SetTabIndex", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - depth = sis.readUI16(); - tabIndex = sis.readUI16(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the index of an object within the tab order. + * + * @author JPEXS + */ +public class SetTabIndexTag extends Tag { + + /** + * Depth of character + */ + @SWFType(BasicType.UI16) + public int depth; + /** + * Tab order value + */ + @SWFType(BasicType.UI16) + public int tabIndex; + public static final int ID = 66; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(depth); + sos.writeUI16(tabIndex); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public SetTabIndexTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "SetTabIndex", pos, length); + depth = sis.readUI16(); + tabIndex = sis.readUI16(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/ShowFrameTag.java b/src/com/jpexs/decompiler/flash/tags/ShowFrameTag.java index a765fc0db..d00540668 100644 --- a/src/com/jpexs/decompiler/flash/tags/ShowFrameTag.java +++ b/src/com/jpexs/decompiler/flash/tags/ShowFrameTag.java @@ -55,12 +55,12 @@ public class ShowFrameTag extends Tag { * @param pos * @param data */ - public ShowFrameTag(SWF swf, byte[] headerData, byte[] data, long pos) { - super(swf, ID, "ShowFrame", headerData, data, pos); + public ShowFrameTag(SWF swf, long pos, int length) { + super(swf, ID, "ShowFrame", pos, length); } public ShowFrameTag(SWF swf) { - super(swf, ID, "ShowFrame", null, null, 0); + super(swf, ID, "ShowFrame", 0, 0); } public static boolean isNestedTagType(int tagTypeId) { diff --git a/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java b/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java index 00332fc6f..3736b4f4f 100644 --- a/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java +++ b/src/com/jpexs/decompiler/flash/tags/SoundStreamBlockTag.java @@ -1,44 +1,49 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import java.io.IOException; - -/** - * - * - * @author JPEXS - */ -public class SoundStreamBlockTag extends Tag { - - public static final int ID = 19; - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public SoundStreamBlockTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "SoundStreamBlock", headerData, data, pos); - //all data is streamSoundData - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import java.io.IOException; + +/** + * + * + * @author JPEXS + */ +public class SoundStreamBlockTag extends Tag { + + public static final int ID = 19; + + @Internal + public byte[] streamSoundData; + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public SoundStreamBlockTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "SoundStreamBlock", pos, length); + //all data is streamSoundData + streamSoundData = sis.readBytesEx(sis.available()); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java b/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java index 716114598..bbdfac051 100644 --- a/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/SoundStreamHead2Tag.java @@ -1,230 +1,227 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Conditional; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.sound.SoundFormat; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author JPEXS - */ -public class SoundStreamHead2Tag extends CharacterIdTag implements SoundStreamHeadTypeTag { - - @Reserved - @SWFType(value = BasicType.UB, count = 4) - public int reserved; - - @SWFType(value = BasicType.UB, count = 2) - public int playBackSoundRate; - - public boolean playBackSoundSize; - public boolean playBackSoundType; - - @SWFType(value = BasicType.UB, count = 4) - public int streamSoundCompression; - - @SWFType(value = BasicType.UB, count = 2) - public int streamSoundRate; - - public boolean streamSoundSize; - public boolean streamSoundType; - - @SWFType(BasicType.UI16) - public int streamSoundSampleCount; - - @SWFType(BasicType.SI16) - @Conditional(value = "streamSoundCompression", options = {2}) - public int latencySeek; - - @Internal - private int virtualCharacterId = 0; - public static final int ID = 45; - - @Override - public int getCharacterId() { - return virtualCharacterId; - } - - @Override - public String getExportFormat() { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - return "mp3"; - } - if (streamSoundCompression == SoundFormat.FORMAT_ADPCM) { - return "wav"; - } - if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { - return "wav"; - } - if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { - return "wav"; - } - if (streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER16KHZ || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER8KHZ) { - return "wav"; - } - return "flv"; - } - - @Override - public long getSoundSampleCount() { - return streamSoundSampleCount; - } - - @Override - public void setVirtualCharacterId(int ch) { - virtualCharacterId = ch; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUB(4, reserved); - sos.writeUB(2, playBackSoundRate); - sos.writeUB(1, playBackSoundSize ? 1 : 0); - sos.writeUB(1, playBackSoundType ? 1 : 0); - sos.writeUB(4, streamSoundCompression); - sos.writeUB(2, streamSoundRate); - sos.writeUB(1, streamSoundSize ? 1 : 0); - sos.writeUB(1, streamSoundType ? 1 : 0); - sos.writeUI16(streamSoundSampleCount); - if (streamSoundCompression == 2) { - sos.writeSI16(latencySeek); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public SoundStreamHead2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "SoundStreamHead2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - reserved = (int) sis.readUB(4); - playBackSoundRate = (int) sis.readUB(2); - playBackSoundSize = sis.readUB(1) == 1; - playBackSoundType = sis.readUB(1) == 1; - streamSoundCompression = (int) sis.readUB(4); - streamSoundRate = (int) sis.readUB(2); - streamSoundSize = sis.readUB(1) == 1; - streamSoundType = sis.readUB(1) == 1; - streamSoundSampleCount = sis.readUI16(); - if (streamSoundCompression == 2) { - latencySeek = sis.readSI16(); - } - } - - @Override - public int getSoundFormatId() { - return streamSoundCompression; - } - - @Override - public int getSoundRate() { - return streamSoundRate; - } - - @Override - public boolean getSoundSize() { - return streamSoundSize; - } - - @Override - public boolean getSoundType() { - return streamSoundType; - } - - @Override - public List getBlocks() { - List ret = new ArrayList<>(); - SoundStreamHeadTag.populateSoundStreamBlocks(swf.tags, this, ret); - return ret; - - } - - @Override - public boolean importSupported() { - return false; - } - - @Override - public boolean setSound(InputStream is, int newSoundFormat) { - return false; - } - - @Override - public byte[] getRawSoundData() { - List blocks = getBlocks(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - for (SoundStreamBlockTag block : blocks) { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - baos.write(block.data, 4, block.data.length - 4); - } else { - baos.write(block.data); - } - } - } catch (IOException ex) { - return null; - } - return baos.toByteArray(); - } - - @Override - public long getTotalSoundSampleCount() { - return getBlocks().size() * streamSoundSampleCount; - } - - @Override - public SoundFormat getSoundFormat() { - final int[] rateMap = {5512, 11025, 22050, 44100}; - return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author JPEXS + */ +public class SoundStreamHead2Tag extends CharacterIdTag implements SoundStreamHeadTypeTag { + + @Reserved + @SWFType(value = BasicType.UB, count = 4) + public int reserved; + + @SWFType(value = BasicType.UB, count = 2) + public int playBackSoundRate; + + public boolean playBackSoundSize; + public boolean playBackSoundType; + + @SWFType(value = BasicType.UB, count = 4) + public int streamSoundCompression; + + @SWFType(value = BasicType.UB, count = 2) + public int streamSoundRate; + + public boolean streamSoundSize; + public boolean streamSoundType; + + @SWFType(BasicType.UI16) + public int streamSoundSampleCount; + + @SWFType(BasicType.SI16) + @Conditional(value = "streamSoundCompression", options = {2}) + public int latencySeek; + + @Internal + private int virtualCharacterId = 0; + public static final int ID = 45; + + @Override + public int getCharacterId() { + return virtualCharacterId; + } + + @Override + public String getExportFormat() { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + return "mp3"; + } + if (streamSoundCompression == SoundFormat.FORMAT_ADPCM) { + return "wav"; + } + if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { + return "wav"; + } + if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { + return "wav"; + } + if (streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER16KHZ || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER8KHZ) { + return "wav"; + } + return "flv"; + } + + @Override + public long getSoundSampleCount() { + return streamSoundSampleCount; + } + + @Override + public void setVirtualCharacterId(int ch) { + virtualCharacterId = ch; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUB(4, reserved); + sos.writeUB(2, playBackSoundRate); + sos.writeUB(1, playBackSoundSize ? 1 : 0); + sos.writeUB(1, playBackSoundType ? 1 : 0); + sos.writeUB(4, streamSoundCompression); + sos.writeUB(2, streamSoundRate); + sos.writeUB(1, streamSoundSize ? 1 : 0); + sos.writeUB(1, streamSoundType ? 1 : 0); + sos.writeUI16(streamSoundSampleCount); + if (streamSoundCompression == 2) { + sos.writeSI16(latencySeek); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public SoundStreamHead2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "SoundStreamHead2", pos, length); + reserved = (int) sis.readUB(4); + playBackSoundRate = (int) sis.readUB(2); + playBackSoundSize = sis.readUB(1) == 1; + playBackSoundType = sis.readUB(1) == 1; + streamSoundCompression = (int) sis.readUB(4); + streamSoundRate = (int) sis.readUB(2); + streamSoundSize = sis.readUB(1) == 1; + streamSoundType = sis.readUB(1) == 1; + streamSoundSampleCount = sis.readUI16(); + if (streamSoundCompression == 2) { + latencySeek = sis.readSI16(); + } + } + + @Override + public int getSoundFormatId() { + return streamSoundCompression; + } + + @Override + public int getSoundRate() { + return streamSoundRate; + } + + @Override + public boolean getSoundSize() { + return streamSoundSize; + } + + @Override + public boolean getSoundType() { + return streamSoundType; + } + + @Override + public List getBlocks() { + List ret = new ArrayList<>(); + SoundStreamHeadTag.populateSoundStreamBlocks(swf.tags, this, ret); + return ret; + + } + + @Override + public boolean importSupported() { + return false; + } + + @Override + public boolean setSound(InputStream is, int newSoundFormat) { + return false; + } + + @Override + public byte[] getRawSoundData() { + List blocks = getBlocks(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + for (SoundStreamBlockTag block : blocks) { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + baos.write(block.streamSoundData, 4, block.streamSoundData.length - 4); + } else { + baos.write(block.streamSoundData); + } + } + } catch (IOException ex) { + return null; + } + return baos.toByteArray(); + } + + @Override + public long getTotalSoundSampleCount() { + return getBlocks().size() * streamSoundSampleCount; + } + + @Override + public SoundFormat getSoundFormat() { + final int[] rateMap = {5512, 11025, 22050, 44100}; + return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java b/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java index 8bbbed8e4..2a4020164 100644 --- a/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java +++ b/src/com/jpexs/decompiler/flash/tags/SoundStreamHeadTag.java @@ -1,245 +1,242 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.tags.base.Container; -import com.jpexs.decompiler.flash.tags.base.ContainerItem; -import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.Conditional; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.decompiler.flash.types.annotations.Reserved; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import com.jpexs.decompiler.flash.types.sound.SoundFormat; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author JPEXS - */ -public class SoundStreamHeadTag extends CharacterIdTag implements SoundStreamHeadTypeTag { - - @Reserved - @SWFType(value = BasicType.UB, count = 4) - public int reserved; - @SWFType(value = BasicType.UB, count = 2) - public int playBackSoundRate; - public boolean playBackSoundSize; - public boolean playBackSoundType; - @SWFType(value = BasicType.UB, count = 4) - public int streamSoundCompression; - @SWFType(value = BasicType.UB, count = 2) - public int streamSoundRate; - public boolean streamSoundSize; - public boolean streamSoundType; - @SWFType(value = BasicType.UI16) - public int streamSoundSampleCount; - @Conditional(value = "streamSoundCompression", options = {2}) - public int latencySeek; - @Internal - private int virtualCharacterId = 0; - public static final int ID = 18; - - @Override - public String getExportFormat() { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - return "mp3"; - } - if (streamSoundCompression == SoundFormat.FORMAT_ADPCM) { - return "wav"; - } - if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { - return "wav"; - } - if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { - return "wav"; - } - if (streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER16KHZ || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER8KHZ) { - return "wav"; - } - return "flv"; - } - - @Override - public int getCharacterId() { - return virtualCharacterId; - } - - @Override - public void setVirtualCharacterId(int ch) { - virtualCharacterId = ch; - } - - @Override - public long getSoundSampleCount() { - return streamSoundSampleCount; - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUB(4, reserved); - sos.writeUB(2, playBackSoundRate); - sos.writeUB(1, playBackSoundSize ? 1 : 0); - sos.writeUB(1, playBackSoundType ? 1 : 0); - sos.writeUB(4, streamSoundCompression); - sos.writeUB(2, streamSoundRate); - sos.writeUB(1, streamSoundSize ? 1 : 0); - sos.writeUB(1, streamSoundType ? 1 : 0); - sos.writeUI16(streamSoundSampleCount); - if (streamSoundCompression == 2) { - sos.writeSI16(latencySeek); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public SoundStreamHeadTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "SoundStreamHead", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - reserved = (int) sis.readUB(4); - playBackSoundRate = (int) sis.readUB(2); - playBackSoundSize = sis.readUB(1) == 1; - playBackSoundType = sis.readUB(1) == 1; - streamSoundCompression = (int) sis.readUB(4); - streamSoundRate = (int) sis.readUB(2); - streamSoundSize = sis.readUB(1) == 1; - streamSoundType = sis.readUB(1) == 1; - streamSoundSampleCount = sis.readUI16(); - if (streamSoundCompression == 2) { - latencySeek = sis.readSI16(); - } - } - - @Override - public int getSoundFormatId() { - return streamSoundCompression; - } - - @Override - public int getSoundRate() { - return streamSoundRate; - } - - @Override - public boolean getSoundSize() { - return streamSoundSize; - } - - @Override - public boolean getSoundType() { - return streamSoundType; - } - - public static void populateSoundStreamBlocks(List tags, Tag head, List output) { - boolean found = false; - for (ContainerItem t : tags) { - if (t == head) { - found = true; - continue; - } - if (!found) { - continue; - } - if (t instanceof SoundStreamBlockTag) { - output.add((SoundStreamBlockTag) t); - } - if (t instanceof SoundStreamHeadTypeTag) { - break; - } - if (t instanceof Container) { - populateSoundStreamBlocks(((Container) t).getSubItems(), head, output); - } - } - } - - @Override - public List getBlocks() { - List ret = new ArrayList<>(); - populateSoundStreamBlocks(swf.tags, this, ret); - return ret; - - } - - @Override - public boolean importSupported() { - return false; - } - - @Override - public boolean setSound(InputStream is, int newSoundFormat) { - return false; - } - - @Override - public byte[] getRawSoundData() { - List blocks = getBlocks(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - for (SoundStreamBlockTag block : blocks) { - if (streamSoundCompression == SoundFormat.FORMAT_MP3) { - baos.write(block.data, 4, block.data.length - 4); - } else { - baos.write(block.data); - } - } - } catch (IOException ex) { - return null; - } - return baos.toByteArray(); - } - - @Override - public long getTotalSoundSampleCount() { - return getBlocks().size() * streamSoundSampleCount; - } - - @Override - public SoundFormat getSoundFormat() { - final int[] rateMap = {5512, 11025, 22050, 44100}; - return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.tags.base.Container; +import com.jpexs.decompiler.flash.tags.base.ContainerItem; +import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.flash.types.annotations.Reserved; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import com.jpexs.decompiler.flash.types.sound.SoundFormat; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author JPEXS + */ +public class SoundStreamHeadTag extends CharacterIdTag implements SoundStreamHeadTypeTag { + + @Reserved + @SWFType(value = BasicType.UB, count = 4) + public int reserved; + @SWFType(value = BasicType.UB, count = 2) + public int playBackSoundRate; + public boolean playBackSoundSize; + public boolean playBackSoundType; + @SWFType(value = BasicType.UB, count = 4) + public int streamSoundCompression; + @SWFType(value = BasicType.UB, count = 2) + public int streamSoundRate; + public boolean streamSoundSize; + public boolean streamSoundType; + @SWFType(value = BasicType.UI16) + public int streamSoundSampleCount; + @Conditional(value = "streamSoundCompression", options = {2}) + public int latencySeek; + @Internal + private int virtualCharacterId = 0; + public static final int ID = 18; + + @Override + public String getExportFormat() { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + return "mp3"; + } + if (streamSoundCompression == SoundFormat.FORMAT_ADPCM) { + return "wav"; + } + if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) { + return "wav"; + } + if (streamSoundCompression == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) { + return "wav"; + } + if (streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER16KHZ || streamSoundCompression == SoundFormat.FORMAT_NELLYMOSER8KHZ) { + return "wav"; + } + return "flv"; + } + + @Override + public int getCharacterId() { + return virtualCharacterId; + } + + @Override + public void setVirtualCharacterId(int ch) { + virtualCharacterId = ch; + } + + @Override + public long getSoundSampleCount() { + return streamSoundSampleCount; + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUB(4, reserved); + sos.writeUB(2, playBackSoundRate); + sos.writeUB(1, playBackSoundSize ? 1 : 0); + sos.writeUB(1, playBackSoundType ? 1 : 0); + sos.writeUB(4, streamSoundCompression); + sos.writeUB(2, streamSoundRate); + sos.writeUB(1, streamSoundSize ? 1 : 0); + sos.writeUB(1, streamSoundType ? 1 : 0); + sos.writeUI16(streamSoundSampleCount); + if (streamSoundCompression == 2) { + sos.writeSI16(latencySeek); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public SoundStreamHeadTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "SoundStreamHead", pos, length); + reserved = (int) sis.readUB(4); + playBackSoundRate = (int) sis.readUB(2); + playBackSoundSize = sis.readUB(1) == 1; + playBackSoundType = sis.readUB(1) == 1; + streamSoundCompression = (int) sis.readUB(4); + streamSoundRate = (int) sis.readUB(2); + streamSoundSize = sis.readUB(1) == 1; + streamSoundType = sis.readUB(1) == 1; + streamSoundSampleCount = sis.readUI16(); + if (streamSoundCompression == 2) { + latencySeek = sis.readSI16(); + } + } + + @Override + public int getSoundFormatId() { + return streamSoundCompression; + } + + @Override + public int getSoundRate() { + return streamSoundRate; + } + + @Override + public boolean getSoundSize() { + return streamSoundSize; + } + + @Override + public boolean getSoundType() { + return streamSoundType; + } + + public static void populateSoundStreamBlocks(List tags, Tag head, List output) { + boolean found = false; + for (ContainerItem t : tags) { + if (t == head) { + found = true; + continue; + } + if (!found) { + continue; + } + if (t instanceof SoundStreamBlockTag) { + output.add((SoundStreamBlockTag) t); + } + if (t instanceof SoundStreamHeadTypeTag) { + break; + } + if (t instanceof Container) { + populateSoundStreamBlocks(((Container) t).getSubItems(), head, output); + } + } + } + + @Override + public List getBlocks() { + List ret = new ArrayList<>(); + populateSoundStreamBlocks(swf.tags, this, ret); + return ret; + + } + + @Override + public boolean importSupported() { + return false; + } + + @Override + public boolean setSound(InputStream is, int newSoundFormat) { + return false; + } + + @Override + public byte[] getRawSoundData() { + List blocks = getBlocks(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + for (SoundStreamBlockTag block : blocks) { + if (streamSoundCompression == SoundFormat.FORMAT_MP3) { + baos.write(block.streamSoundData, 4, block.streamSoundData.length - 4); + } else { + baos.write(block.streamSoundData); + } + } + } catch (IOException ex) { + return null; + } + return baos.toByteArray(); + } + + @Override + public long getTotalSoundSampleCount() { + return getBlocks().size() * streamSoundSampleCount; + } + + @Override + public SoundFormat getSoundFormat() { + final int[] rateMap = {5512, 11025, 22050, 44100}; + return new SoundFormat(getSoundFormatId(), rateMap[getSoundRate()], getSoundType()); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/StartSound2Tag.java b/src/com/jpexs/decompiler/flash/tags/StartSound2Tag.java index 8fd97fede..b00e0dd6e 100644 --- a/src/com/jpexs/decompiler/flash/tags/StartSound2Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/StartSound2Tag.java @@ -1,71 +1,68 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class StartSound2Tag extends Tag { - - public String soundClassName; - public SOUNDINFO soundInfo; - public static final int ID = 89; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - /*try { - //sos.write - } catch (IOException e) { - }*/ - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public StartSound2Tag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "StartSound2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - soundClassName = sis.readString(); - soundInfo = sis.readSOUNDINFO(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.SOUNDINFO; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class StartSound2Tag extends Tag { + + public String soundClassName; + public SOUNDINFO soundInfo; + public static final int ID = 89; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + /*try { + //sos.write + } catch (IOException e) { + }*/ + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public StartSound2Tag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "StartSound2", pos, length); + soundClassName = sis.readString(); + soundInfo = sis.readSOUNDINFO(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/StartSoundTag.java b/src/com/jpexs/decompiler/flash/tags/StartSoundTag.java index d9cda4473..e83e0c55f 100644 --- a/src/com/jpexs/decompiler/flash/tags/StartSoundTag.java +++ b/src/com/jpexs/decompiler/flash/tags/StartSoundTag.java @@ -1,75 +1,72 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class StartSoundTag extends Tag { - - @SWFType(BasicType.UI16) - public int soundId; - public SOUNDINFO soundInfo; - public static final int ID = 15; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(soundId); - sos.writeSOUNDINFO(soundInfo); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public StartSoundTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "StartSound", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - soundId = sis.readUI16(); - soundInfo = sis.readSOUNDINFO(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class StartSoundTag extends Tag { + + @SWFType(BasicType.UI16) + public int soundId; + public SOUNDINFO soundInfo; + public static final int ID = 15; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(soundId); + sos.writeSOUNDINFO(soundInfo); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public StartSoundTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "StartSound", pos, length); + soundId = sis.readUI16(); + soundInfo = sis.readSOUNDINFO(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/SymbolClassTag.java b/src/com/jpexs/decompiler/flash/tags/SymbolClassTag.java index f9172d09c..b6c0fe46d 100644 --- a/src/com/jpexs/decompiler/flash/tags/SymbolClassTag.java +++ b/src/com/jpexs/decompiler/flash/tags/SymbolClassTag.java @@ -1,74 +1,71 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFArray; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class SymbolClassTag extends Tag { - - @SWFType(value = BasicType.UI16) - @SWFArray(value = "tag", countField = "numSymbols") - public int[] tags; - @SWFArray(value = "name", countField = "numSymbols") - public String[] names; - public static final int ID = 76; - - public SymbolClassTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "SymbolClass", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - int numSymbols = sis.readUI16(); - tags = new int[numSymbols]; - names = new String[numSymbols]; - for (int ii = 0; ii < numSymbols; ii++) { - int tagID = sis.readUI16(); - String className = sis.readString(); - tags[ii] = tagID; - names[ii] = className; - } - } - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - int numSymbols = tags.length; - sos.writeUI16(numSymbols); - for (int ii = 0; ii < numSymbols; ii++) { - sos.writeUI16(tags[ii]); - sos.writeString(names[ii]); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFArray; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class SymbolClassTag extends Tag { + + @SWFType(value = BasicType.UI16) + @SWFArray(value = "tag", countField = "numSymbols") + public int[] tags; + @SWFArray(value = "name", countField = "numSymbols") + public String[] names; + public static final int ID = 76; + + public SymbolClassTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "SymbolClass", pos, length); + int numSymbols = sis.readUI16(); + tags = new int[numSymbols]; + names = new String[numSymbols]; + for (int ii = 0; ii < numSymbols; ii++) { + int tagID = sis.readUI16(); + String className = sis.readString(); + tags[ii] = tagID; + names[ii] = className; + } + } + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + int numSymbols = tags.length; + sos.writeUI16(numSymbols); + for (int ii = 0; ii < numSymbols; ii++) { + sos.writeUI16(tags[ii]); + sos.writeString(names[ii]); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/Tag.java b/src/com/jpexs/decompiler/flash/tags/Tag.java index a46bc78bb..507fa0a3d 100644 --- a/src/com/jpexs/decompiler/flash/tags/Tag.java +++ b/src/com/jpexs/decompiler/flash/tags/Tag.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.base.ContainerItem; import com.jpexs.decompiler.flash.tags.base.Exportable; @@ -50,25 +51,23 @@ public class Tag implements NeedsCharacters, Exportable, ContainerItem, Serializ * Identifier of tag type */ protected int id; - /** - * Original header data in the tag - */ - protected byte[] headerData; - /** - * Data in the tag - */ - protected byte[] data; /** * If true, then Tag is written to the stream as longer than 0x3f even if it * is not */ @Internal public boolean forceWriteAsLong = false; + /** + * Original position in the SWF file + */ @Internal private final long pos; - protected String tagName; + /** + * Original tag length + */ @Internal - public Tag previousTag; + private final int length; + protected String tagName; @Internal protected transient SWF swf; @Internal @@ -118,25 +117,22 @@ public class Tag implements NeedsCharacters, Exportable, ContainerItem, Serializ /** * Constructor * - * @param swf + * @param swf The SWF * @param id Tag type identifier * @param name Tag name - * @param headerData - * @param data Bytes of data - * @param pos + * @param pos Original position in the SWF file + * @param length Original tag length */ - public Tag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { + public Tag(SWF swf, int id, String name, long pos, int length) { this.id = id; this.tagName = name; - this.headerData = headerData; - this.data = data; this.pos = pos; + this.length = length; this.swf = swf; if (swf == null) { throw new Error("swf parameter cannot be null."); } - if (data == null) { // it is tag build by constructor - this.data = new byte[0]; + if (pos == 0) { // it is tag build by constructor modified = true; } } @@ -287,15 +283,6 @@ public class Tag implements NeedsCharacters, Exportable, ContainerItem, Serializ return requiredTagIds; } - /** - * Gets data bytes - * - * @return Bytes of data - */ - public byte[] getData() { - return data; - } - public int getVersion() { if (swf == null) { return SWF.DEFAULT_VERSION; @@ -303,29 +290,6 @@ public class Tag implements NeedsCharacters, Exportable, ContainerItem, Serializ return swf.version; } - /** - * Gets original read header data - * - * @return Bytes of data - */ - public byte[] getOriginalHeaderData() { - return headerData; - } - - /** - * Gets original read data - * - * @return Bytes of data - */ - public byte[] getOriginalData() { - return data; - } - - public void createOriginalData() { - data = getData(); - headerData = getHeader(data); - } - protected byte[] getHeader(byte[] data) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { @@ -368,15 +332,19 @@ public class Tag implements NeedsCharacters, Exportable, ContainerItem, Serializ * @throws IOException */ public void writeTag(SWFOutputStream sos) throws IOException { + int newLength; if (isModified()) { byte[] newData = getData(); - sos.write(getHeader(newData)); + byte[] newHeaderData = getHeader(newData); + sos.write(newHeaderData); sos.write(newData); - return; + newLength = newData.length + newHeaderData.length; + } else { + sos.write(swf.uncompressedData, (int) pos, length); + newLength = length; } - - sos.write(headerData); - sos.write(data); + + //todo: honfika: update pos and length during save } /** @@ -389,8 +357,33 @@ public class Tag implements NeedsCharacters, Exportable, ContainerItem, Serializ return getName(); } - public final long getOrigDataLength() { - return data.length; + /** + * Gets data bytes + * + * @return Bytes of data + */ + public byte[] getData() { + return getOriginalData(); + } + + public final byte[] getOriginalData() { + // todo honfika: do not copy data + int dataLength = getOriginalDataLength(); + byte[] data = new byte[dataLength]; + System.arraycopy(swf.uncompressedData, (int) (pos + length - dataLength), data, 0, dataLength); + return data; + } + + public final int getOriginalLength() { + return length; + } + + public final int getOriginalDataLength() { + int shortLength = swf.uncompressedData[(int) pos] & 0x003F; + if (shortLength == 0x3f) { + return length - 6; + } + return length - 2; } public boolean hasSubTags() { diff --git a/src/com/jpexs/decompiler/flash/tags/TagStub.java b/src/com/jpexs/decompiler/flash/tags/TagStub.java index 9c96a96a8..819816a3c 100644 --- a/src/com/jpexs/decompiler/flash/tags/TagStub.java +++ b/src/com/jpexs/decompiler/flash/tags/TagStub.java @@ -1,67 +1,60 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class TagStub extends Tag { - - public static final int ID = -1; //TODO: Enter correct ID - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - /*try { - //sos.write - } catch (IOException e) { - }*/ - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public TagStub(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "" /*TODO:Insert name here*/, headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class TagStub extends Tag { + + public static final int ID = -1; //TODO: Enter correct ID + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + return getOriginalData(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public TagStub(SWF swf, long pos, int length) throws IOException { + super(swf, ID, "" /*TODO:Insert name here*/, pos, length); + + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/UnknownTag.java b/src/com/jpexs/decompiler/flash/tags/UnknownTag.java index 853b17c50..397fa5789 100644 --- a/src/com/jpexs/decompiler/flash/tags/UnknownTag.java +++ b/src/com/jpexs/decompiler/flash/tags/UnknownTag.java @@ -24,8 +24,8 @@ import com.jpexs.decompiler.flash.SWF; */ public class UnknownTag extends Tag { - public UnknownTag(SWF swf, int id, byte[] headerData, byte[] data, long pos) { - super(swf, id, "Unknown", headerData, data, pos); + public UnknownTag(SWF swf, int id, long pos, int length) { + super(swf, id, "Unknown", pos, length); } @Override diff --git a/src/com/jpexs/decompiler/flash/tags/VideoFrameTag.java b/src/com/jpexs/decompiler/flash/tags/VideoFrameTag.java index 07495844b..5f820b92a 100644 --- a/src/com/jpexs/decompiler/flash/tags/VideoFrameTag.java +++ b/src/com/jpexs/decompiler/flash/tags/VideoFrameTag.java @@ -1,78 +1,78 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.types.BasicType; -import com.jpexs.decompiler.flash.types.annotations.SWFType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class VideoFrameTag extends Tag { - - @SWFType(BasicType.UI16) - public int streamID; - @SWFType(BasicType.UI16) - public int frameNum; - public byte[] videoData; - public static final int ID = 61; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(streamID); - sos.writeUI16(frameNum); - sos.write(videoData); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public VideoFrameTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "VideoFrame", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - streamID = sis.readUI16(); - frameNum = sis.readUI16(); - videoData = sis.readBytesEx(sis.available()); //TODO: Parse video packets - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.annotations.SWFType; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class VideoFrameTag extends Tag { + + @SWFType(BasicType.UI16) + public int streamID; + @SWFType(BasicType.UI16) + public int frameNum; + public byte[] videoData; + public static final int ID = 61; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(streamID); + sos.writeUI16(frameNum); + sos.write(videoData); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public VideoFrameTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "VideoFrame", pos, length); + streamID = sis.readUI16(); + frameNum = sis.readUI16(); + videoData = sis.readBytesEx(sis.available()); //TODO: Parse video packets + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java b/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java index 068d59389..bd8f9b88f 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java @@ -1,85 +1,85 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; -import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; -import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.timeline.DepthState; -import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.types.BUTTONRECORD; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.helpers.SerializableImage; -import java.awt.Shape; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - -/** - * - * @author JPEXS - */ -public abstract class ButtonTag extends CharacterTag implements DrawableTag, Timelined { - - public static int FRAME_UP = 0; - public static int FRAME_OVER = 1; - public static int FRAME_DOWN = 2; - public static int FRAME_HITTEST = 3; - - public ButtonTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); - } - - public abstract List getRecords(); - - public abstract boolean trackAsMenu(); - - @Override - public Shape getOutline(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { - return getTimeline().getOutline(frame, time, ratio, stateUnderCursor, mouseButton, transformation); - } - - @Override - public void toImage(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - SWF.frameToImage(getTimeline(), frame, time, stateUnderCursor, mouseButton, image, transformation, colorTransform); - } - - @Override - public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException { - SWF.frameToSvg(getTimeline(), 0, 0, null, 0, exporter, colorTransform, level + 1); - } - - public DefineButtonSoundTag getSounds() { - for (Tag t : swf.tags) { - if (t instanceof DefineButtonSoundTag) { - DefineButtonSoundTag st = (DefineButtonSoundTag) t; - if (st.buttonId == getCharacterId()) { - return st; - } - } - } - return null; - } - - @Override - public String toHtmlCanvas(double unitDivisor) { - return getTimeline().toHtmlCanvas(unitDivisor, Arrays.asList(0)); //TODO: handle states? - } - -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; +import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.types.BUTTONRECORD; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.helpers.SerializableImage; +import java.awt.Shape; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author JPEXS + */ +public abstract class ButtonTag extends CharacterTag implements DrawableTag, Timelined { + + public static int FRAME_UP = 0; + public static int FRAME_OVER = 1; + public static int FRAME_DOWN = 2; + public static int FRAME_HITTEST = 3; + + public ButtonTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); + } + + public abstract List getRecords(); + + public abstract boolean trackAsMenu(); + + @Override + public Shape getOutline(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) { + return getTimeline().getOutline(frame, time, ratio, stateUnderCursor, mouseButton, transformation); + } + + @Override + public void toImage(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + SWF.frameToImage(getTimeline(), frame, time, stateUnderCursor, mouseButton, image, transformation, colorTransform); + } + + @Override + public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException { + SWF.frameToSvg(getTimeline(), 0, 0, null, 0, exporter, colorTransform, level + 1); + } + + public DefineButtonSoundTag getSounds() { + for (Tag t : swf.tags) { + if (t instanceof DefineButtonSoundTag) { + DefineButtonSoundTag st = (DefineButtonSoundTag) t; + if (st.buttonId == getCharacterId()) { + return st; + } + } + } + return null; + } + + @Override + public String toHtmlCanvas(double unitDivisor) { + return getTimeline().toHtmlCanvas(unitDivisor, Arrays.asList(0)); //TODO: handle states? + } + +} diff --git a/src/com/jpexs/decompiler/flash/tags/base/CharacterIdTag.java b/src/com/jpexs/decompiler/flash/tags/base/CharacterIdTag.java index 0d4ef9f85..efdc29917 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/CharacterIdTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/CharacterIdTag.java @@ -1,87 +1,87 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.tags.ExportAssetsTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public abstract class CharacterIdTag extends Tag { - - public CharacterIdTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); - } - - public abstract int getCharacterId(); - /** - * List of ExportAssetsTag used for converting to String - */ - @Internal - public List exportAssetsTags = new ArrayList<>(); - protected String className; - protected String exportName; - - public void setExportName(String exportName) { - this.exportName = exportName; - } - - public void setClassName(String className) { - this.className = className; - } - - public String getClassName() { - return className; - } - - @Override - public String getName() { - String nameAppend = ""; - if (exportName != null) { - nameAppend = ": " + exportName; - } - if (className != null) { - nameAppend = ": " + className; - } - if (getCharacterId() != -1) { - return super.getName() + " (" + getCharacterId() + nameAppend + ")"; - } - if (!nameAppend.isEmpty()) { - return super.getName() + " (" + nameAppend + ")"; - } - return super.getName(); - } - - @Override - public String getExportFileName() { - return super.getName() + "_" + getCharacterId() + (((exportName != null) && (!exportName.isEmpty())) ? "_" + exportName : ""); - } - - public String getCharacterExportFileName() { - return getCharacterId() + (((exportName != null) && (!exportName.isEmpty())) ? "_" + exportName : ""); - } - - public String getExportName() { - return exportName; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.tags.ExportAssetsTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public abstract class CharacterIdTag extends Tag { + + public CharacterIdTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); + } + + public abstract int getCharacterId(); + /** + * List of ExportAssetsTag used for converting to String + */ + @Internal + public List exportAssetsTags = new ArrayList<>(); + protected String className; + protected String exportName; + + public void setExportName(String exportName) { + this.exportName = exportName; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } + + @Override + public String getName() { + String nameAppend = ""; + if (exportName != null) { + nameAppend = ": " + exportName; + } + if (className != null) { + nameAppend = ": " + className; + } + if (getCharacterId() != -1) { + return super.getName() + " (" + getCharacterId() + nameAppend + ")"; + } + if (!nameAppend.isEmpty()) { + return super.getName() + " (" + nameAppend + ")"; + } + return super.getName(); + } + + @Override + public String getExportFileName() { + return super.getName() + "_" + getCharacterId() + (((exportName != null) && (!exportName.isEmpty())) ? "_" + exportName : ""); + } + + public String getCharacterExportFileName() { + return getCharacterId() + (((exportName != null) && (!exportName.isEmpty())) ? "_" + exportName : ""); + } + + public String getExportName() { + return exportName; + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java b/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java index 2a47c76da..790668d8b 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java @@ -1,30 +1,31 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; - -/** - * - * @author JPEXS - */ -public abstract class CharacterTag extends CharacterIdTag { - - public CharacterTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; + +/** + * + * @author JPEXS + */ +public abstract class CharacterTag extends CharacterIdTag { + + public CharacterTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index 130a2483c..335e924d1 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -55,8 +55,8 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable protected final int previewSize = 500; - public FontTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); + public FontTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); } public abstract int getFontId(); diff --git a/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java b/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java index 5b6e160b3..f2f71dda8 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/ImageTag.java @@ -1,84 +1,84 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.tags.base; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.helpers.SerializableImage; -import java.awt.Color; -import java.io.IOException; -import java.io.InputStream; - -/** - * - * @author JPEXS - */ -public abstract class ImageTag extends CharacterTag { - - public ImageTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); - } - - public abstract InputStream getImageData(); - - public abstract SerializableImage getImage(); - - public abstract void setImage(byte[] data) throws IOException; - - public abstract String getImageFormat(); - - public boolean importSupported() { - return true; - } - - public static String getImageFormat(byte[] data) { - if (SWF.hasErrorHeader(data)) { - return "jpg"; - } - if (data.length > 2 && ((data[0] & 0xff) == 0xff) && ((data[1] & 0xff) == 0xd8)) { - return "jpg"; - } - if (data.length > 6 && ((data[0] & 0xff) == 0x47) && ((data[1] & 0xff) == 0x49) && ((data[2] & 0xff) == 0x46) && ((data[3] & 0xff) == 0x38) && ((data[4] & 0xff) == 0x39) && ((data[5] & 0xff) == 0x61)) { - return "gif"; - } - - if (data.length > 8 && ((data[0] & 0xff) == 0x89) && ((data[1] & 0xff) == 0x50) && ((data[2] & 0xff) == 0x4e) && ((data[3] & 0xff) == 0x47) && ((data[4] & 0xff) == 0x0d) && ((data[5] & 0xff) == 0x0a) && ((data[6] & 0xff) == 0x1a) && ((data[7] & 0xff) == 0x0a)) { - return "png"; - } - - return "unk"; - } - - protected static int max255(float val) { - if (val > 255) { - return 255; - } - return (int) val; - } - - protected static Color intToColor(int val) { - return new Color(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); - } - - protected static int colorToInt(Color c) { - return (c.getAlpha() << 24) | (c.getBlue() << 16) | (c.getGreen() << 8) | c.getRed(); - } - - protected static Color multiplyAlpha(Color c) { - float multiplier = c.getAlpha() == 0 ? 0 : 255.0f / c.getAlpha(); - return new Color(max255(c.getRed() * multiplier), max255(c.getGreen() * multiplier), max255(c.getBlue() * multiplier), c.getAlpha()); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.helpers.SerializableImage; +import java.awt.Color; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author JPEXS + */ +public abstract class ImageTag extends CharacterTag { + + public ImageTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); + } + + public abstract InputStream getImageData(); + + public abstract SerializableImage getImage(); + + public abstract void setImage(byte[] data) throws IOException; + + public abstract String getImageFormat(); + + public boolean importSupported() { + return true; + } + + public static String getImageFormat(byte[] data) { + if (SWF.hasErrorHeader(data)) { + return "jpg"; + } + if (data.length > 2 && ((data[0] & 0xff) == 0xff) && ((data[1] & 0xff) == 0xd8)) { + return "jpg"; + } + if (data.length > 6 && ((data[0] & 0xff) == 0x47) && ((data[1] & 0xff) == 0x49) && ((data[2] & 0xff) == 0x46) && ((data[3] & 0xff) == 0x38) && ((data[4] & 0xff) == 0x39) && ((data[5] & 0xff) == 0x61)) { + return "gif"; + } + + if (data.length > 8 && ((data[0] & 0xff) == 0x89) && ((data[1] & 0xff) == 0x50) && ((data[2] & 0xff) == 0x4e) && ((data[3] & 0xff) == 0x47) && ((data[4] & 0xff) == 0x0d) && ((data[5] & 0xff) == 0x0a) && ((data[6] & 0xff) == 0x1a) && ((data[7] & 0xff) == 0x0a)) { + return "png"; + } + + return "unk"; + } + + protected static int max255(float val) { + if (val > 255) { + return 255; + } + return (int) val; + } + + protected static Color intToColor(int val) { + return new Color(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff); + } + + protected static int colorToInt(Color c) { + return (c.getAlpha() << 24) | (c.getBlue() << 16) | (c.getGreen() << 8) | c.getRed(); + } + + protected static Color multiplyAlpha(Color c) { + float multiplier = c.getAlpha() == 0 ? 0 : 255.0f / c.getAlpha(); + return new Color(max255(c.getRed() * multiplier), max255(c.getGreen() * multiplier), max255(c.getBlue() * multiplier), c.getAlpha()); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java b/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java index 17ea0f357..4038bb89e 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java @@ -36,8 +36,8 @@ import java.util.Set; */ public abstract class ShapeTag extends CharacterTag implements BoundedTag, DrawableTag { - public ShapeTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); + public ShapeTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); } public abstract SHAPEWITHSTYLE getShapes(); diff --git a/src/com/jpexs/decompiler/flash/tags/base/TextTag.java b/src/com/jpexs/decompiler/flash/tags/base/TextTag.java index d1afbe046..5b84d219c 100644 --- a/src/com/jpexs/decompiler/flash/tags/base/TextTag.java +++ b/src/com/jpexs/decompiler/flash/tags/base/TextTag.java @@ -67,8 +67,8 @@ import org.w3c.dom.Element; */ public abstract class TextTag extends CharacterTag implements BoundedTag, DrawableTag { - public TextTag(SWF swf, int id, String name, byte[] headerData, byte[] data, long pos) { - super(swf, id, name, headerData, data, pos); + public TextTag(SWF swf, int id, String name, long pos, int length) { + super(swf, id, name, pos, length); } public abstract MATRIX getTextMatrix(); diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java index a189c9187..f4b1ae8df 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java @@ -1,393 +1,393 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.DefineFont2Tag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.base.DrawableTag; -import com.jpexs.decompiler.flash.tags.base.FontTag; -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.gfx.FontType; -import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; -import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; -import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType; -import com.jpexs.decompiler.flash.types.gfx.GlyphType; -import com.jpexs.decompiler.flash.types.gfx.KerningPairType; -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -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.Helper; -import java.awt.Font; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.JPanel; - -/** - * - * - * @author JPEXS - */ -public final class DefineCompactedFont extends FontTag implements DrawableTag { - - public static final int ID = 1005; - public int fontId; - public List fonts; - private List shapeCache; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(fontId); - for (FontType ft : fonts) { - ft.write(new GFxOutputStream(sos)); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineCompactedFont(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineCompactedFont", headerData, data, pos); - - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - fontId = sis.readUI16(); - fonts = new ArrayList<>(); - - while (sis.available() > 0) { - fonts.add(new FontType(new GFxInputStream(sis))); - } - rebuildShapeCache(); - } - - public void rebuildShapeCache() { - shapeCache = fonts.get(0).getGlyphShapes(); - } - - @Override - public int getNumFrames() { - return 1; - } - - @Override - public String getFontName() { - String ret = ""; - for (int i = 0; i < fonts.size(); i++) { - if (i > 0) { - ret += ", "; - } - ret += fonts.get(i).fontName; - } - return ret; - } - - @Override - public int getCharacterId() { - return fontId; - } - - @Override - public int getFontId() { - return fontId; - } - - @Override - public List getGlyphShapeTable() { - return shapeCache; - } - - @Override - public void addCharacter(char character, String fontName) { - int fontStyle = getFontStyle(); - FontType font = fonts.get(0); - SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, (int) (SWF.unitDivisor * font.nominalSize), character); - - int code = (int) character; - int pos = -1; - boolean exists = false; - for (int i = 0; i < font.glyphInfo.size(); i++) { - if (font.glyphInfo.get(i).glyphCode >= code) { - if (font.glyphInfo.get(i).glyphCode == code) { - exists = true; - } - pos = i; - break; - } - } - if (pos == -1) { - pos = font.glyphInfo.size(); - } - - if (!exists) { - shiftGlyphIndices(fontId, pos); - } - - Font fnt = new Font(fontName, fontStyle, font.nominalSize); - int advance = (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX()); - if (!exists) { - font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0)); - font.glyphs.add(pos, new GlyphType(shp.shapeRecords)); - shapeCache.add(pos, font.glyphs.get(pos).toSHAPE()); - } else { - font.glyphInfo.set(pos, new GlyphInfoType(code, advance, 0)); - font.glyphs.set(pos, new GlyphType(shp.shapeRecords)); - shapeCache.set(pos, font.glyphs.get(pos).toSHAPE()); - } - SWF.clearImageCache(); - } - - @Override - public char glyphToChar(int glyphIndex) { - return (char) fonts.get(0).glyphInfo.get(glyphIndex).glyphCode; - } - - @Override - public int charToGlyph(char c) { - FontType ft = fonts.get(0); - for (int i = 0; i < ft.glyphInfo.size(); i++) { - if (ft.glyphInfo.get(i).glyphCode == c) { - return i; - } - } - return -1; - } - - @Override - public double getGlyphAdvance(int glyphIndex) { - return fonts.get(0).glyphInfo.get(glyphIndex).advanceX; - } - - @Override - public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { - int char1 = glyphToChar(glyphIndex); - int char2 = glyphToChar(nextGlyphIndex); - for (KerningPairType kp : fonts.get(0).kerning) { - if (kp.char1 == char1 && kp.char2 == char2) { - return kp.advance; - } - } - return 0; - } - - @Override - public int getGlyphWidth(int glyphIndex) { - return getGlyphShapeTable().get(glyphIndex).getBounds().getWidth(); - } - - @Override - public boolean isSmall() { - return false; - } - - @Override - public boolean isBold() { - return (fonts.get(0).flags & FontType.FF_Bold) == FontType.FF_Bold; - } - - @Override - public boolean isItalic() { - return (fonts.get(0).flags & FontType.FF_Italic) == FontType.FF_Italic; - } - - @Override - public boolean isSmallEditable() { - return false; - } - - @Override - public boolean isBoldEditable() { - return true; - } - - @Override - public boolean isItalicEditable() { - return true; - } - - @Override - public void setSmall(boolean value) { - } - - @Override - public void setBold(boolean value) { - for (FontType font : fonts) { - font.flags &= FontType.FF_Bold; - if (!value) { - font.flags ^= FontType.FF_Bold; - } - } - } - - @Override - public void setItalic(boolean value) { - for (FontType font : fonts) { - font.flags &= FontType.FF_Italic; - if (!value) { - font.flags ^= FontType.FF_Italic; - } - } - } - - @Override - public int getDivider() { - return 1; - } - - @Override - public int getAscent() { - return fonts.get(0).ascent; - } - - @Override - public int getDescent() { - return fonts.get(0).descent; - } - - @Override - public int getLeading() { - return fonts.get(0).leading; - } - - @Override - public String getCharacters(List tags) { - FontType ft = fonts.get(0); - String ret = ""; - for (GlyphInfoType gi : ft.glyphInfo) { - ret += (char) gi.glyphCode; - } - return ret; - } - - private int resizemultiplier() { - FontType ft = fonts.get(0); - return (int) Math.round(1024.0 / ft.nominalSize); - } - - private int resize(int val) { - int ret = val * resizemultiplier(); - return ret; - } - - private SHAPE resize(SHAPE shp) { - SHAPE ret = new SHAPE(); - ret.numFillBits = 1; - ret.numLineBits = 0; - List recs = new ArrayList<>(); - for (SHAPERECORD r : shp.shapeRecords) { - SHAPERECORD c = Helper.deepCopy(r); - if (c instanceof StyleChangeRecord) { - StyleChangeRecord scr = (StyleChangeRecord) c; - scr.moveDeltaX = resize(scr.moveDeltaX); - scr.moveDeltaY = resize(scr.moveDeltaY); - scr.calculateBits(); - } - if (c instanceof CurvedEdgeRecord) { - CurvedEdgeRecord cer = (CurvedEdgeRecord) c; - cer.controlDeltaX = resize(cer.controlDeltaX); - cer.controlDeltaY = resize(cer.controlDeltaY); - cer.anchorDeltaX = resize(cer.anchorDeltaX); - cer.anchorDeltaY = resize(cer.anchorDeltaY); - cer.calculateBits(); - } - if (c instanceof StraightEdgeRecord) { - StraightEdgeRecord ser = (StraightEdgeRecord) c; - ser.deltaX = resize(ser.deltaX); - ser.deltaY = resize(ser.deltaY); - ser.calculateBits(); - } - recs.add(c); - } - ret.shapeRecords = recs; - return ret; - } - - public FontTag toClassicFont() { - try { - DefineFont2Tag ret = new DefineFont2Tag(swf); - ret.fontId = fontId; - ret.fontFlagsBold = isBold(); - ret.fontFlagsItalic = isItalic(); - ret.fontFlagsWideOffsets = true; - ret.fontFlagsWideCodes = true; - ret.fontFlagsHasLayout = true; - FontType ft = fonts.get(0); - ret.fontAscent = resize(ft.ascent); - ret.fontDescent = resize(ft.descent); - ret.fontLeading = resize(ft.leading); - ret.fontAdvanceTable = new ArrayList<>(); - ret.fontBoundsTable = new ArrayList<>(); - ret.codeTable = new ArrayList<>(); - ret.glyphShapeTable = new ArrayList<>(); - ret.numGlyphs = ft.glyphInfo.size(); - SHAPE shpA = SHAPERECORD.systemFontCharacterToSHAPE("Times New Roman", 0, getDivider() * 1024, 'A'); - for (GlyphInfoType gi : ft.glyphInfo) { - ret.fontAdvanceTable.add(resize(gi.advanceX)); - ret.codeTable.add(gi.glyphCode); - } - - for (GlyphType gt : ft.glyphs) { - SHAPE shpX = resize(gt.toSHAPE()); - ret.glyphShapeTable.add(shpX); // - ret.fontBoundsTable.add(new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3]))); - } - ret.fontName = ft.fontName; - ret.languageCode = new LANGCODE(1); - ret.fontKerningTable = new KERNINGRECORD[0];/*new KERNINGRECORD[ft.kerning.size()]; - for(int i=0;i. + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.DefineFont2Tag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.tags.base.FontTag; +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.gfx.FontType; +import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; +import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; +import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType; +import com.jpexs.decompiler.flash.types.gfx.GlyphType; +import com.jpexs.decompiler.flash.types.gfx.KerningPairType; +import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; +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.Helper; +import java.awt.Font; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JPanel; + +/** + * + * + * @author JPEXS + */ +public final class DefineCompactedFont extends FontTag implements DrawableTag { + + public static final int ID = 1005; + public int fontId; + public List fonts; + private List shapeCache; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(fontId); + for (FontType ft : fonts) { + ft.write(new GFxOutputStream(sos)); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineCompactedFont(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineCompactedFont", pos, length); + + fontId = sis.readUI16(); + fonts = new ArrayList<>(); + + while (sis.available() > 0) { + fonts.add(new FontType(new GFxInputStream(sis.getBaseStream()))); + } + rebuildShapeCache(); + } + + public void rebuildShapeCache() { + shapeCache = fonts.get(0).getGlyphShapes(); + } + + @Override + public int getNumFrames() { + return 1; + } + + @Override + public String getFontName() { + String ret = ""; + for (int i = 0; i < fonts.size(); i++) { + if (i > 0) { + ret += ", "; + } + ret += fonts.get(i).fontName; + } + return ret; + } + + @Override + public int getCharacterId() { + return fontId; + } + + @Override + public int getFontId() { + return fontId; + } + + @Override + public List getGlyphShapeTable() { + return shapeCache; + } + + @Override + public void addCharacter(char character, String fontName) { + int fontStyle = getFontStyle(); + FontType font = fonts.get(0); + SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, (int) (SWF.unitDivisor * font.nominalSize), character); + + int code = (int) character; + int pos = -1; + boolean exists = false; + for (int i = 0; i < font.glyphInfo.size(); i++) { + if (font.glyphInfo.get(i).glyphCode >= code) { + if (font.glyphInfo.get(i).glyphCode == code) { + exists = true; + } + pos = i; + break; + } + } + if (pos == -1) { + pos = font.glyphInfo.size(); + } + + if (!exists) { + shiftGlyphIndices(fontId, pos); + } + + Font fnt = new Font(fontName, fontStyle, font.nominalSize); + int advance = (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX()); + if (!exists) { + font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0)); + font.glyphs.add(pos, new GlyphType(shp.shapeRecords)); + shapeCache.add(pos, font.glyphs.get(pos).toSHAPE()); + } else { + font.glyphInfo.set(pos, new GlyphInfoType(code, advance, 0)); + font.glyphs.set(pos, new GlyphType(shp.shapeRecords)); + shapeCache.set(pos, font.glyphs.get(pos).toSHAPE()); + } + SWF.clearImageCache(); + } + + @Override + public char glyphToChar(int glyphIndex) { + return (char) fonts.get(0).glyphInfo.get(glyphIndex).glyphCode; + } + + @Override + public int charToGlyph(char c) { + FontType ft = fonts.get(0); + for (int i = 0; i < ft.glyphInfo.size(); i++) { + if (ft.glyphInfo.get(i).glyphCode == c) { + return i; + } + } + return -1; + } + + @Override + public double getGlyphAdvance(int glyphIndex) { + return fonts.get(0).glyphInfo.get(glyphIndex).advanceX; + } + + @Override + public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) { + int char1 = glyphToChar(glyphIndex); + int char2 = glyphToChar(nextGlyphIndex); + for (KerningPairType kp : fonts.get(0).kerning) { + if (kp.char1 == char1 && kp.char2 == char2) { + return kp.advance; + } + } + return 0; + } + + @Override + public int getGlyphWidth(int glyphIndex) { + return getGlyphShapeTable().get(glyphIndex).getBounds().getWidth(); + } + + @Override + public boolean isSmall() { + return false; + } + + @Override + public boolean isBold() { + return (fonts.get(0).flags & FontType.FF_Bold) == FontType.FF_Bold; + } + + @Override + public boolean isItalic() { + return (fonts.get(0).flags & FontType.FF_Italic) == FontType.FF_Italic; + } + + @Override + public boolean isSmallEditable() { + return false; + } + + @Override + public boolean isBoldEditable() { + return true; + } + + @Override + public boolean isItalicEditable() { + return true; + } + + @Override + public void setSmall(boolean value) { + } + + @Override + public void setBold(boolean value) { + for (FontType font : fonts) { + font.flags &= FontType.FF_Bold; + if (!value) { + font.flags ^= FontType.FF_Bold; + } + } + } + + @Override + public void setItalic(boolean value) { + for (FontType font : fonts) { + font.flags &= FontType.FF_Italic; + if (!value) { + font.flags ^= FontType.FF_Italic; + } + } + } + + @Override + public int getDivider() { + return 1; + } + + @Override + public int getAscent() { + return fonts.get(0).ascent; + } + + @Override + public int getDescent() { + return fonts.get(0).descent; + } + + @Override + public int getLeading() { + return fonts.get(0).leading; + } + + @Override + public String getCharacters(List tags) { + FontType ft = fonts.get(0); + String ret = ""; + for (GlyphInfoType gi : ft.glyphInfo) { + ret += (char) gi.glyphCode; + } + return ret; + } + + private int resizemultiplier() { + FontType ft = fonts.get(0); + return (int) Math.round(1024.0 / ft.nominalSize); + } + + private int resize(int val) { + int ret = val * resizemultiplier(); + return ret; + } + + private SHAPE resize(SHAPE shp) { + SHAPE ret = new SHAPE(); + ret.numFillBits = 1; + ret.numLineBits = 0; + List recs = new ArrayList<>(); + for (SHAPERECORD r : shp.shapeRecords) { + SHAPERECORD c = Helper.deepCopy(r); + if (c instanceof StyleChangeRecord) { + StyleChangeRecord scr = (StyleChangeRecord) c; + scr.moveDeltaX = resize(scr.moveDeltaX); + scr.moveDeltaY = resize(scr.moveDeltaY); + scr.calculateBits(); + } + if (c instanceof CurvedEdgeRecord) { + CurvedEdgeRecord cer = (CurvedEdgeRecord) c; + cer.controlDeltaX = resize(cer.controlDeltaX); + cer.controlDeltaY = resize(cer.controlDeltaY); + cer.anchorDeltaX = resize(cer.anchorDeltaX); + cer.anchorDeltaY = resize(cer.anchorDeltaY); + cer.calculateBits(); + } + if (c instanceof StraightEdgeRecord) { + StraightEdgeRecord ser = (StraightEdgeRecord) c; + ser.deltaX = resize(ser.deltaX); + ser.deltaY = resize(ser.deltaY); + ser.calculateBits(); + } + recs.add(c); + } + ret.shapeRecords = recs; + return ret; + } + + public FontTag toClassicFont() { + try { + DefineFont2Tag ret = new DefineFont2Tag(swf); + ret.fontId = fontId; + ret.fontFlagsBold = isBold(); + ret.fontFlagsItalic = isItalic(); + ret.fontFlagsWideOffsets = true; + ret.fontFlagsWideCodes = true; + ret.fontFlagsHasLayout = true; + FontType ft = fonts.get(0); + ret.fontAscent = resize(ft.ascent); + ret.fontDescent = resize(ft.descent); + ret.fontLeading = resize(ft.leading); + ret.fontAdvanceTable = new ArrayList<>(); + ret.fontBoundsTable = new ArrayList<>(); + ret.codeTable = new ArrayList<>(); + ret.glyphShapeTable = new ArrayList<>(); + ret.numGlyphs = ft.glyphInfo.size(); + SHAPE shpA = SHAPERECORD.systemFontCharacterToSHAPE("Times New Roman", 0, getDivider() * 1024, 'A'); + for (GlyphInfoType gi : ft.glyphInfo) { + ret.fontAdvanceTable.add(resize(gi.advanceX)); + ret.codeTable.add(gi.glyphCode); + } + + for (GlyphType gt : ft.glyphs) { + SHAPE shpX = resize(gt.toSHAPE()); + ret.glyphShapeTable.add(shpX); // + ret.fontBoundsTable.add(new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3]))); + } + ret.fontName = ft.fontName; + ret.languageCode = new LANGCODE(1); + ret.fontKerningTable = new KERNINGRECORD[0];/*new KERNINGRECORD[ft.kerning.size()]; + for(int i=0;i. - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineExternalGradient extends Tag { - - public static final int ID = 1003; - public static final int BITMAP_FORMAT_DEFAULT = 0; - public static final int BITMAP_FORMAT_TGA = 1; - public static final int BITMAP_FORMAT_DDS = 2; - public int gradientId; - public int bitmapsFormat; - public int gradientSize; - public String fileName; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(gradientId); - sos.writeUI16(bitmapsFormat); - sos.writeUI16(gradientSize); - byte fileNameBytes[] = fileName.getBytes(); - sos.writeUI8(fileNameBytes.length); - sos.write(fileNameBytes); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineExternalGradient(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineExternalGradient", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - gradientId = sis.readUI16(); - bitmapsFormat = sis.readUI16(); - gradientSize = sis.readUI16(); - int fileNameLen = sis.readUI8(); - fileName = new String(sis.readBytesEx(fileNameLen)); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineExternalGradient extends Tag { + + public static final int ID = 1003; + public static final int BITMAP_FORMAT_DEFAULT = 0; + public static final int BITMAP_FORMAT_TGA = 1; + public static final int BITMAP_FORMAT_DDS = 2; + public int gradientId; + public int bitmapsFormat; + public int gradientSize; + public String fileName; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(gradientId); + sos.writeUI16(bitmapsFormat); + sos.writeUI16(gradientSize); + byte fileNameBytes[] = fileName.getBytes(); + sos.writeUI8(fileNameBytes.length); + sos.write(fileNameBytes); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineExternalGradient(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineExternalGradient", pos, length); + gradientId = sis.readUI16(); + bitmapsFormat = sis.readUI16(); + gradientSize = sis.readUI16(); + int fileNameLen = sis.readUI8(); + fileName = new String(sis.readBytesEx(fileNameLen)); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java index 0fad5ed4f..d68971d4c 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage.java @@ -1,88 +1,85 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineExternalImage extends Tag { - - public static final int ID = 1001; - public int characterId; - public int bitmapFormat; - public int targetWidth; - public int targetHeight; - public String fileName; - public static final int BITMAP_FORMAT_DEFAULT = 0; - public static final int BITMAP_FORMAT_TGA = 1; - public static final int BITMAP_FORMAT_DDS = 2; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterId); - sos.writeUI16(bitmapFormat); - sos.writeUI16(targetWidth); - sos.writeUI16(targetHeight); - byte fileNameBytes[] = fileName.getBytes(); - sos.writeUI8(fileNameBytes.length); - sos.write(fileNameBytes); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineExternalImage(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineExternalImage", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterId = sis.readUI16(); - bitmapFormat = sis.readUI16(); - targetWidth = sis.readUI16(); - targetHeight = sis.readUI16(); - int fileNameLen = sis.readUI8(); - fileName = new String(sis.readBytesEx(fileNameLen)); - - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineExternalImage extends Tag { + + public static final int ID = 1001; + public int characterId; + public int bitmapFormat; + public int targetWidth; + public int targetHeight; + public String fileName; + public static final int BITMAP_FORMAT_DEFAULT = 0; + public static final int BITMAP_FORMAT_TGA = 1; + public static final int BITMAP_FORMAT_DDS = 2; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterId); + sos.writeUI16(bitmapFormat); + sos.writeUI16(targetWidth); + sos.writeUI16(targetHeight); + byte fileNameBytes[] = fileName.getBytes(); + sos.writeUI8(fileNameBytes.length); + sos.write(fileNameBytes); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineExternalImage(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineExternalImage", pos, length); + characterId = sis.readUI16(); + bitmapFormat = sis.readUI16(); + targetWidth = sis.readUI16(); + targetHeight = sis.readUI16(); + int fileNameLen = sis.readUI8(); + fileName = new String(sis.readBytesEx(fileNameLen)); + + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java index ac8394903..2f461e114 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalImage2.java @@ -1,100 +1,97 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineExternalImage2 extends Tag { - - public static final int ID = 1009; - public long characterId; - public int bitmapFormat; - public int targetWidth; - public int targetHeight; - public String exportName; - public String fileName; - public byte[] extraData; //? - public static final int BITMAP_FORMAT_DEFAULT = 0; - public static final int BITMAP_FORMAT_TGA = 1; - public static final int BITMAP_FORMAT_DDS = 2; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI32(characterId); - sos.writeUI16(bitmapFormat); - sos.writeUI16(targetWidth); - sos.writeUI16(targetHeight); - byte exportNameBytes[] = exportName.getBytes(); - sos.writeUI8(exportNameBytes.length); - sos.write(exportNameBytes); - byte fileNameBytes[] = fileName.getBytes(); - sos.writeUI8(fileNameBytes.length); - sos.write(fileNameBytes); - if (extraData != null) { - sos.write(extraData); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineExternalImage2(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineExternalImage2", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterId = sis.readUI32(); - bitmapFormat = sis.readUI16(); - targetWidth = sis.readUI16(); - targetHeight = sis.readUI16(); - int exportNameLen = sis.readUI8(); - exportName = new String(sis.readBytesEx(exportNameLen)); - int fileNameLen = sis.readUI8(); - fileName = new String(sis.readBytesEx(fileNameLen)); - if (sis.available() > 0) { //there is usually one zero byte, bod knows why - extraData = sis.readBytesEx(sis.available()); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineExternalImage2 extends Tag { + + public static final int ID = 1009; + public long characterId; + public int bitmapFormat; + public int targetWidth; + public int targetHeight; + public String exportName; + public String fileName; + public byte[] extraData; //? + public static final int BITMAP_FORMAT_DEFAULT = 0; + public static final int BITMAP_FORMAT_TGA = 1; + public static final int BITMAP_FORMAT_DDS = 2; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI32(characterId); + sos.writeUI16(bitmapFormat); + sos.writeUI16(targetWidth); + sos.writeUI16(targetHeight); + byte exportNameBytes[] = exportName.getBytes(); + sos.writeUI8(exportNameBytes.length); + sos.write(exportNameBytes); + byte fileNameBytes[] = fileName.getBytes(); + sos.writeUI8(fileNameBytes.length); + sos.write(fileNameBytes); + if (extraData != null) { + sos.write(extraData); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineExternalImage2(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineExternalImage2", pos, length); + characterId = sis.readUI32(); + bitmapFormat = sis.readUI16(); + targetWidth = sis.readUI16(); + targetHeight = sis.readUI16(); + int exportNameLen = sis.readUI8(); + exportName = new String(sis.readBytesEx(exportNameLen)); + int fileNameLen = sis.readUI8(); + fileName = new String(sis.readBytesEx(fileNameLen)); + if (sis.available() > 0) { //there is usually one zero byte, bod knows why + extraData = sis.readBytesEx(sis.available()); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java index dbc62d346..887c6f1ae 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalSound.java @@ -1,101 +1,98 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineExternalSound extends Tag { - - public static final int ID = 1006; - public int characterId; - public int soundFormat; - public int bits; - public int channels; - public long sampleRate; - public long sampleCount; - public long seekSample; - public String exportName; - public String fileName; - public static final int SOUND_FORMAT_WAV = 0; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterId); - sos.writeUI16(soundFormat); - sos.writeUI16(bits); - sos.writeUI16(channels); - sos.writeUI32(sampleRate); - sos.writeUI32(sampleCount); - sos.writeUI32(seekSample); - byte[] exportNameBytes = exportName.getBytes(); - sos.writeUI8(exportNameBytes.length); - sos.write(exportNameBytes); - byte[] fileNameBytes = fileName.getBytes(); - sos.writeUI8(fileNameBytes.length); - sos.write(fileNameBytes); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineExternalSound(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineExternalSound", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterId = sis.readUI16(); - soundFormat = sis.readUI16(); - bits = sis.readUI16(); - channels = sis.readUI16(); - sampleRate = sis.readUI32(); - sampleCount = sis.readUI32(); - seekSample = sis.readUI32(); - int exportNameLen = sis.readUI8(); - exportName = new String(sis.readBytesEx(exportNameLen)); - int fileNameLen = sis.readUI8(); - fileName = new String(sis.readBytesEx(fileNameLen)); - - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineExternalSound extends Tag { + + public static final int ID = 1006; + public int characterId; + public int soundFormat; + public int bits; + public int channels; + public long sampleRate; + public long sampleCount; + public long seekSample; + public String exportName; + public String fileName; + public static final int SOUND_FORMAT_WAV = 0; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterId); + sos.writeUI16(soundFormat); + sos.writeUI16(bits); + sos.writeUI16(channels); + sos.writeUI32(sampleRate); + sos.writeUI32(sampleCount); + sos.writeUI32(seekSample); + byte[] exportNameBytes = exportName.getBytes(); + sos.writeUI8(exportNameBytes.length); + sos.write(exportNameBytes); + byte[] fileNameBytes = fileName.getBytes(); + sos.writeUI8(fileNameBytes.length); + sos.write(fileNameBytes); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineExternalSound(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineExternalSound", pos, length); + characterId = sis.readUI16(); + soundFormat = sis.readUI16(); + bits = sis.readUI16(); + channels = sis.readUI16(); + sampleRate = sis.readUI32(); + sampleCount = sis.readUI32(); + seekSample = sis.readUI32(); + int exportNameLen = sis.readUI8(); + exportName = new String(sis.readBytesEx(exportNameLen)); + int fileNameLen = sis.readUI8(); + fileName = new String(sis.readBytesEx(fileNameLen)); + + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java index 029172be3..8041250f7 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineExternalStreamSound.java @@ -1,98 +1,95 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineExternalStreamSound extends Tag { - - public static final int ID = 1007; - public int soundFormat; - public int bits; - public int channels; - public long sampleRate; - public long sampleCount; - public long seekSample; - public long startFrame; - public long lastFrame; - public String fileName; - public static final int SOUND_FORMAT_WAV = 0; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(soundFormat); - sos.writeUI16(bits); - sos.writeUI16(channels); - sos.writeUI32(sampleRate); - sos.writeUI32(sampleCount); - sos.writeUI32(seekSample); - sos.writeUI32(startFrame); - sos.writeUI32(lastFrame); - byte[] fileNameBytes = fileName.getBytes(); - sos.writeUI8(fileNameBytes.length); - sos.write(fileNameBytes); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineExternalStreamSound(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineExternalStreamSound", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - soundFormat = sis.readUI16(); - bits = sis.readUI16(); - channels = sis.readUI16(); - sampleRate = sis.readUI32(); - sampleCount = sis.readUI32(); - seekSample = sis.readUI32(); - startFrame = sis.readUI32(); - lastFrame = sis.readUI32(); - int fileNameLen = sis.readUI8(); - fileName = new String(sis.readBytesEx(fileNameLen)); - - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineExternalStreamSound extends Tag { + + public static final int ID = 1007; + public int soundFormat; + public int bits; + public int channels; + public long sampleRate; + public long sampleCount; + public long seekSample; + public long startFrame; + public long lastFrame; + public String fileName; + public static final int SOUND_FORMAT_WAV = 0; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(soundFormat); + sos.writeUI16(bits); + sos.writeUI16(channels); + sos.writeUI32(sampleRate); + sos.writeUI32(sampleCount); + sos.writeUI32(seekSample); + sos.writeUI32(startFrame); + sos.writeUI32(lastFrame); + byte[] fileNameBytes = fileName.getBytes(); + sos.writeUI8(fileNameBytes.length); + sos.write(fileNameBytes); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineExternalStreamSound(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineExternalStreamSound", pos, length); + soundFormat = sis.readUI16(); + bits = sis.readUI16(); + channels = sis.readUI16(); + sampleRate = sis.readUI32(); + sampleCount = sis.readUI32(); + seekSample = sis.readUI32(); + startFrame = sis.readUI32(); + lastFrame = sis.readUI32(); + int fileNameLen = sis.readUI8(); + fileName = new String(sis.readBytesEx(fileNameLen)); + + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java index 720504801..b9576f325 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineGradientMap.java @@ -1,76 +1,73 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineGradientMap extends Tag { - - public static final int ID = 1004; - public int indices[]; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(indices.length); - for (int i = 0; i < indices.length; i++) { - sos.writeUI16(indices[i]); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineGradientMap(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineGradientMap", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - int numGradients = sis.readUI16(); - indices = new int[numGradients]; - for (int i = 0; i < numGradients; i++) { - indices[i] = sis.readUI16(); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineGradientMap extends Tag { + + public static final int ID = 1004; + public int indices[]; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(indices.length); + for (int i = 0; i < indices.length; i++) { + sos.writeUI16(indices[i]); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineGradientMap(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineGradientMap", pos, length); + int numGradients = sis.readUI16(); + indices = new int[numGradients]; + for (int i = 0; i < numGradients; i++) { + indices[i] = sis.readUI16(); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java b/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java index 4c23b0254..e7cf00b7f 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/DefineSubImage.java @@ -1,84 +1,81 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class DefineSubImage extends Tag { - - public static final int ID = 1008; - public int characterId; - public int imageCharacterId; - public int x1; - public int y1; - public int x2; - public int y2; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI16(characterId); - sos.writeUI16(imageCharacterId); - sos.writeUI16(x1); - sos.writeUI16(y1); - sos.writeUI16(x2); - sos.writeUI16(y2); - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public DefineSubImage(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "DefineSubImage", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - characterId = sis.readUI16(); - imageCharacterId = sis.readUI16(); - x1 = sis.readUI16(); - y1 = sis.readUI16(); - x2 = sis.readUI16(); - y2 = sis.readUI16(); - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class DefineSubImage extends Tag { + + public static final int ID = 1008; + public int characterId; + public int imageCharacterId; + public int x1; + public int y1; + public int x2; + public int y2; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI16(characterId); + sos.writeUI16(imageCharacterId); + sos.writeUI16(x1); + sos.writeUI16(y1); + sos.writeUI16(x2); + sos.writeUI16(y2); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public DefineSubImage(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "DefineSubImage", pos, length); + characterId = sis.readUI16(); + imageCharacterId = sis.readUI16(); + x1 = sis.readUI16(); + y1 = sis.readUI16(); + x2 = sis.readUI16(); + y2 = sis.readUI16(); + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfoTag.java b/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfoTag.java index 516ba3b88..8831fab39 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfoTag.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/ExporterInfoTag.java @@ -1,114 +1,111 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * - * - * @author JPEXS - */ -public class ExporterInfoTag extends Tag { - - public static final int ID = 1000; - //Version (1.10 will be encoded as 0x10A) - public int version; - //Version 1.10 (0x10A) and above - flags - public long flags; - public int bitmapFormat; - public byte[] prefix; - public String swfName; - public List codeOffsets; - public static final int BITMAP_FORMAT_TGA = 1; - public static final int BITMAP_FORMAT_DDS = 2; - 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; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, version); - try { - sos.writeUI16(this.version); - if (this.version >= 0x10a) { - sos.writeUI32(flags); - } - sos.writeUI16(bitmapFormat); - sos.writeUI8(prefix.length); - sos.write(prefix); - byte swfNameBytes[] = swfName.getBytes(); - sos.writeUI8(swfNameBytes.length); - sos.write(swfNameBytes); - if (codeOffsets != null) { - sos.writeUI16(codeOffsets.size()); - for (long l : codeOffsets) { - sos.writeUI32(l); - } - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public ExporterInfoTag(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "ExporterInfo", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version); - this.version = sis.readUI16(); - if (this.version >= 0x10a) { - flags = sis.readUI32(); - } - bitmapFormat = sis.readUI16(); - int prefixLen = sis.readUI8(); - prefix = sis.readBytesEx(prefixLen); - int swfNameLen = sis.readUI8(); - swfName = new String(sis.readBytesEx(swfNameLen)); - if (sis.available() > 0) // (version >= 0x401) //? - { - codeOffsets = new ArrayList<>(); - int numCodeOffsets = sis.readUI16(); - for (int i = 0; i < numCodeOffsets; i++) { - codeOffsets.add(sis.readUI32()); - } - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * + * + * @author JPEXS + */ +public class ExporterInfoTag extends Tag { + + public static final int ID = 1000; + //Version (1.10 will be encoded as 0x10A) + public int version; + //Version 1.10 (0x10A) and above - flags + public long flags; + public int bitmapFormat; + public byte[] prefix; + public String swfName; + public List codeOffsets; + public static final int BITMAP_FORMAT_TGA = 1; + public static final int BITMAP_FORMAT_DDS = 2; + 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; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, version); + try { + sos.writeUI16(this.version); + if (this.version >= 0x10a) { + sos.writeUI32(flags); + } + sos.writeUI16(bitmapFormat); + sos.writeUI8(prefix.length); + sos.write(prefix); + byte swfNameBytes[] = swfName.getBytes(); + sos.writeUI8(swfNameBytes.length); + sos.write(swfNameBytes); + if (codeOffsets != null) { + sos.writeUI16(codeOffsets.size()); + for (long l : codeOffsets) { + sos.writeUI32(l); + } + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public ExporterInfoTag(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "ExporterInfo", pos, length); + this.version = sis.readUI16(); + if (this.version >= 0x10a) { + flags = sis.readUI32(); + } + bitmapFormat = sis.readUI16(); + int prefixLen = sis.readUI8(); + prefix = sis.readBytesEx(prefixLen); + int swfNameLen = sis.readUI8(); + swfName = new String(sis.readBytesEx(swfNameLen)); + if (sis.available() > 0) // (version >= 0x401) //? + { + codeOffsets = new ArrayList<>(); + int numCodeOffsets = sis.readUI16(); + for (int i = 0; i < numCodeOffsets; i++) { + codeOffsets.add(sis.readUI32()); + } + } + } +} diff --git a/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java b/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java index 31499cde7..f7b634686 100644 --- a/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java +++ b/src/com/jpexs/decompiler/flash/tags/gfx/FontTextureInfo.java @@ -1,117 +1,114 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -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.Tag; -import com.jpexs.decompiler.flash.types.gfx.FONTINFO; -import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; -import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; -import com.jpexs.decompiler.flash.types.gfx.TEXGLYPH; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * - * @author JPEXS - */ -public class FontTextureInfo extends Tag { - - public static final int ID = 1002; - public long textureID; - public int textureFormat; - public String fileName; - public int textureWidth; - public int textureHeight; - public int padPixels; - public int nominalGlyphSz; - public TEXGLYPH texGlyphs[]; - public FONTINFO fonts[]; - public static final int TEXTURE_FORMAT_DEFAULT = 0; - public static final int TEXTURE_FORMAT_TGA = 1; - public static final int TEXTURE_FORMAT_DDS = 2; - - /** - * Gets data bytes - * - * @return Bytes of data - */ - @Override - public byte[] getData() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream os = baos; - SWFOutputStream sos = new SWFOutputStream(os, getVersion()); - try { - sos.writeUI32(textureID); - sos.writeUI16(textureFormat); - byte fileNameBytes[] = fileName.getBytes(); - sos.writeUI8(fileNameBytes.length); - sos.write(fileNameBytes); - sos.writeUI16(textureWidth); - sos.writeUI16(textureHeight); - sos.writeUI8(padPixels); - sos.writeUI16(nominalGlyphSz); - sos.writeUI16(texGlyphs.length); - for (int i = 0; i < texGlyphs.length; i++) { - texGlyphs[i].write(new GFxOutputStream(sos)); - } - sos.writeUI16(fonts.length); - for (int i = 0; i < fonts.length; i++) { - fonts[i].write(new GFxOutputStream(sos)); - } - } catch (IOException e) { - } - return baos.toByteArray(); - } - - /** - * Constructor - * - * @param swf - * @param headerData - * @param data Data bytes - * @param pos - * @throws IOException - */ - public FontTextureInfo(SWF swf, byte[] headerData, byte[] data, long pos) throws IOException { - super(swf, ID, "FontTextureInfo", headerData, data, pos); - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version); - textureID = sis.readUI32(); - textureFormat = sis.readUI16(); - int fileNameLen = sis.readUI8(); - fileName = new String(sis.readBytesEx(fileNameLen)); - textureWidth = sis.readUI16(); - textureHeight = sis.readUI16(); - padPixels = sis.readUI8(); - nominalGlyphSz = sis.readUI16(); - int numTexGlyphs = sis.readUI16(); - texGlyphs = new TEXGLYPH[numTexGlyphs]; - for (int i = 0; i < numTexGlyphs; i++) { - texGlyphs[i] = new TEXGLYPH(new GFxInputStream(sis)); - } - int numFonts = sis.readUI16(); - fonts = new FONTINFO[numFonts]; - for (int i = 0; i < numFonts; i++) { - fonts[i] = new FONTINFO(new GFxInputStream(sis)); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.tags.gfx; + +import com.jpexs.decompiler.flash.SWFLimitedInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.gfx.FONTINFO; +import com.jpexs.decompiler.flash.types.gfx.GFxInputStream; +import com.jpexs.decompiler.flash.types.gfx.GFxOutputStream; +import com.jpexs.decompiler.flash.types.gfx.TEXGLYPH; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * + * @author JPEXS + */ +public class FontTextureInfo extends Tag { + + public static final int ID = 1002; + public long textureID; + public int textureFormat; + public String fileName; + public int textureWidth; + public int textureHeight; + public int padPixels; + public int nominalGlyphSz; + public TEXGLYPH texGlyphs[]; + public FONTINFO fonts[]; + public static final int TEXTURE_FORMAT_DEFAULT = 0; + public static final int TEXTURE_FORMAT_TGA = 1; + public static final int TEXTURE_FORMAT_DDS = 2; + + /** + * Gets data bytes + * + * @return Bytes of data + */ + @Override + public byte[] getData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, getVersion()); + try { + sos.writeUI32(textureID); + sos.writeUI16(textureFormat); + byte fileNameBytes[] = fileName.getBytes(); + sos.writeUI8(fileNameBytes.length); + sos.write(fileNameBytes); + sos.writeUI16(textureWidth); + sos.writeUI16(textureHeight); + sos.writeUI8(padPixels); + sos.writeUI16(nominalGlyphSz); + sos.writeUI16(texGlyphs.length); + for (int i = 0; i < texGlyphs.length; i++) { + texGlyphs[i].write(new GFxOutputStream(sos)); + } + sos.writeUI16(fonts.length); + for (int i = 0; i < fonts.length; i++) { + fonts[i].write(new GFxOutputStream(sos)); + } + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param headerData + * @param data Data bytes + * @param pos + * @throws IOException + */ + public FontTextureInfo(SWFLimitedInputStream sis, long pos, int length) throws IOException { + super(sis.swf, ID, "FontTextureInfo", pos, length); + textureID = sis.readUI32(); + textureFormat = sis.readUI16(); + int fileNameLen = sis.readUI8(); + fileName = new String(sis.readBytesEx(fileNameLen)); + textureWidth = sis.readUI16(); + textureHeight = sis.readUI16(); + padPixels = sis.readUI8(); + nominalGlyphSz = sis.readUI16(); + int numTexGlyphs = sis.readUI16(); + texGlyphs = new TEXGLYPH[numTexGlyphs]; + for (int i = 0; i < numTexGlyphs; i++) { + texGlyphs[i] = new TEXGLYPH(new GFxInputStream(sis.getBaseStream())); + } + int numFonts = sis.readUI16(); + fonts = new FONTINFO[numFonts]; + for (int i = 0; i < numFonts; i++) { + fonts[i] = new FONTINFO(new GFxInputStream(sis.getBaseStream())); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java b/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java index 4569fe18f..c1d039f5f 100644 --- a/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java +++ b/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java @@ -61,10 +61,9 @@ public class BUTTONCONDACTION implements ASMSource, Exportable, ContainerItem, S return pos; } - public BUTTONCONDACTION(SWF swf, InputStream is, long containerOffset, Tag tag) throws IOException { + public BUTTONCONDACTION(SWF swf, SWFInputStream sis, long containerOffset, Tag tag) throws IOException { this.swf = swf; this.tag = tag; - SWFInputStream sis = new SWFInputStream(is, swf.version); pos = containerOffset; int condActionSize = sis.readUI16(); isLast = condActionSize <= 0; diff --git a/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java b/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java index 39d96070b..bf9765847 100644 --- a/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java +++ b/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java @@ -107,10 +107,9 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem, S hdrPos = 0; } - public CLIPACTIONRECORD(SWF swf, InputStream is, long pos, Tag tag) throws IOException { + public CLIPACTIONRECORD(SWF swf, SWFInputStream sis, long pos, Tag tag) throws IOException { this.swf = swf; this.tag = tag; - SWFInputStream sis = new SWFInputStream(is, swf.version); eventFlags = sis.readCLIPEVENTFLAGS(); if (eventFlags.isClear()) { return; @@ -123,7 +122,6 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem, S hdrPos = sis.getPos(); actionBytes = sis.readBytesEx(actionRecordSize); this.pos = pos; - } @Override diff --git a/src/com/jpexs/decompiler/flash/types/gfx/FontType.java b/src/com/jpexs/decompiler/flash/types/gfx/FontType.java index b6c9d9b4c..c26f6c69b 100644 --- a/src/com/jpexs/decompiler/flash/types/gfx/FontType.java +++ b/src/com/jpexs/decompiler/flash/types/gfx/FontType.java @@ -1,115 +1,114 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.gfx; - -import com.jpexs.decompiler.flash.types.SHAPE; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class FontType implements Serializable { - - public static final int FF_Italic = 0x0001; - public static final int FF_Bold = 0x0002; - public String fontName; - public int flags; - public int nominalSize; - public int ascent; - public int descent; - public int leading; - public List glyphs; - public List glyphInfo; - public List kerning; - - public FontType(GFxInputStream sis) throws IOException { - sis = new GFxInputStream(sis); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int val; - while ((val = sis.readUI8()) > 0) { - baos.write(val); - } - fontName = new String(baos.toByteArray()); - flags = sis.readUI16(); - nominalSize = sis.readUI16(); - ascent = sis.readSI16(); - descent = sis.readSI16(); - leading = sis.readSI16(); - long numGlyphs = sis.readUI32(); - long glyphBytesLen = sis.readUI32(); - byte glyphBytes[] = new byte[(int) glyphBytesLen]; - sis.read(glyphBytes); - glyphInfo = new ArrayList<>(); - for (int i = 0; i < numGlyphs; i++) { - glyphInfo.add(new GlyphInfoType(sis)); - } - - long kerningTableSize = sis.readUI30(); - kerning = new ArrayList<>(); - for (int i = 0; i < kerningTableSize; i++) { - kerning.add(new KerningPairType(sis)); - } - - glyphs = new ArrayList<>(); - for (int i = 0; i < glyphInfo.size(); i++) { - sis.setPos(glyphInfo.get(i).globalOffset); - glyphs.add(new GlyphType(sis)); - } - } - - public List getGlyphShapes() { - List ret = new ArrayList<>(); - for (GlyphType g : glyphs) { - ret.add(g.toSHAPE()); - } - return ret; - } - - public void write(GFxOutputStream sos) throws IOException { - sos = new GFxOutputStream(sos); - sos.write(fontName.getBytes()); - sos.writeUI8(0); - sos.writeUI16(flags); - sos.writeUI16(nominalSize); - sos.writeUI16(ascent); - sos.writeUI16(descent); - sos.writeUI16(leading); - sos.writeUI32(glyphInfo.size()); //numGlyphs - long headerLen = sos.getPos() + 4; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GFxOutputStream sos2 = new GFxOutputStream(baos); - for (int i = 0; i < glyphs.size(); i++) { - glyphInfo.get(i).globalOffset = headerLen + sos2.getPos(); - glyphs.get(i).write(sos2); - } - byte[] glyphBytes = baos.toByteArray(); - sos.writeUI32(glyphBytes.length); - sos.write(glyphBytes); - for (int i = 0; i < glyphInfo.size(); i++) { - glyphInfo.get(i).write(sos); - } - sos.writeUI30(kerning.size()); - for (KerningPairType kp : kerning) { - kp.write(sos); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.gfx; + +import com.jpexs.decompiler.flash.types.SHAPE; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class FontType implements Serializable { + + public static final int FF_Italic = 0x0001; + public static final int FF_Bold = 0x0002; + public String fontName; + public int flags; + public int nominalSize; + public int ascent; + public int descent; + public int leading; + public List glyphs; + public List glyphInfo; + public List kerning; + + public FontType(GFxInputStream sis) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int val; + while ((val = sis.readUI8()) > 0) { + baos.write(val); + } + fontName = new String(baos.toByteArray()); + flags = sis.readUI16(); + nominalSize = sis.readUI16(); + ascent = sis.readSI16(); + descent = sis.readSI16(); + leading = sis.readSI16(); + long numGlyphs = sis.readUI32(); + long glyphBytesLen = sis.readUI32(); + byte glyphBytes[] = new byte[(int) glyphBytesLen]; + sis.read(glyphBytes); + glyphInfo = new ArrayList<>(); + for (int i = 0; i < numGlyphs; i++) { + glyphInfo.add(new GlyphInfoType(sis)); + } + + long kerningTableSize = sis.readUI30(); + kerning = new ArrayList<>(); + for (int i = 0; i < kerningTableSize; i++) { + kerning.add(new KerningPairType(sis)); + } + + glyphs = new ArrayList<>(); + for (int i = 0; i < glyphInfo.size(); i++) { + sis.setPos(glyphInfo.get(i).globalOffset); + glyphs.add(new GlyphType(sis)); + } + } + + public List getGlyphShapes() { + List ret = new ArrayList<>(); + for (GlyphType g : glyphs) { + ret.add(g.toSHAPE()); + } + return ret; + } + + public void write(GFxOutputStream sos) throws IOException { + sos = new GFxOutputStream(sos); + sos.write(fontName.getBytes()); + sos.writeUI8(0); + sos.writeUI16(flags); + sos.writeUI16(nominalSize); + sos.writeUI16(ascent); + sos.writeUI16(descent); + sos.writeUI16(leading); + sos.writeUI32(glyphInfo.size()); //numGlyphs + long headerLen = sos.getPos() + 4; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GFxOutputStream sos2 = new GFxOutputStream(baos); + for (int i = 0; i < glyphs.size(); i++) { + glyphInfo.get(i).globalOffset = headerLen + sos2.getPos(); + glyphs.get(i).write(sos2); + } + byte[] glyphBytes = baos.toByteArray(); + sos.writeUI32(glyphBytes.length); + sos.write(glyphBytes); + for (int i = 0; i < glyphInfo.size(); i++) { + glyphInfo.get(i).write(sos); + } + sos.writeUI30(kerning.size()); + for (KerningPairType kp : kerning) { + kp.write(sos); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/types/gfx/GFxInputStream.java b/src/com/jpexs/decompiler/flash/types/gfx/GFxInputStream.java index 68a1d8302..001168436 100644 --- a/src/com/jpexs/decompiler/flash/types/gfx/GFxInputStream.java +++ b/src/com/jpexs/decompiler/flash/types/gfx/GFxInputStream.java @@ -1,163 +1,165 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.gfx; - -import com.jpexs.helpers.ReReadableInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * - * @author JPEXS - */ -public class GFxInputStream extends InputStream { - - private final ReReadableInputStream is; - private static final int MaxUInt7 = (1 << 7) - 1; - - public GFxInputStream(InputStream is) { - this.is = new ReReadableInputStream(is); - } - - @Override - public int available() throws IOException { - return is.available(); - } - - public void setPos(long pos) throws IOException { - is.seek(pos); - } - - public long getPos() { - return is.getPos(); - } - - @Override - public int read() throws IOException { - return is.read(); - } - - public int readUI8() throws IOException { - return read(); - } - - public int readUI16() throws IOException { - return read() + (read() << 8); - } - - /** - * Reads one SI16 (Signed 16bit integer) value from the stream - * - * @return SI16 value - * @throws IOException - */ - public int readSI16() throws IOException { - int uval = read() + (read() << 8); - if (uval >= 0x8000) { - return -(((~uval) & 0xffff) + 1); - } else { - return uval; - } - } - - public long readUI32() throws IOException { - return (read() + (read() << 8) + (read() << 16) + (read() << 24)) & 0xffffffff; - } - - public long readUI30() throws IOException { - long v; - int tb = readUI8(); - long t = tb; - switch (tb & 3) { - case 0: - v = t >> 2; - return v; - - case 1: - t >>= 2; - v = t | (readUI8() << 6); - return v; - case 2: - t >>= 2; - t |= (readUI8() << 6); - v = t | (readUI8() << 14); - return v; - } - t >>= 2; - t |= (readUI8() << 6); - t |= (readUI8() << 14); - v = t | (readUI8() << 22); - return v; - } - - public float readFLOAT() throws IOException { - int val = (int) readUI32(); - float ret = Float.intBitsToFloat(val); - return ret; - } - - public int readSI8() throws IOException { - int uval = read(); - if (uval >= 0x80) { - return -(((~uval) & 0xff) + 1); - } else { - return uval; - } - } - - public int readSI15() throws IOException { - int t = readSI8(); - int v; - if ((t & 1) == 0) { - v = t >> 1; - return v; - } - t = ((t >> 1) & MaxUInt7); - v = (t | (readSI8() << 7)); - return v; - } - - public int readUI15() throws IOException { - int t = readUI8(); - int v; - if ((t & 1) == 0) { - v = t >> 1; - return v; - } - t = (t >> 1); - v = (t | (readUI8() << 7)); - return v; - } - - /** - * Reads bytes from the stream - * - * @param count Number of bytes to read - * @return Array of read bytes - * @throws IOException - */ - public byte[] readBytes(long count) throws IOException { - if (count <= 0) { - return new byte[0]; - } - byte[] ret = new byte[(int) count]; - for (int i = 0; i < count; i++) { - ret[i] = (byte) read(); - } - return ret; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.gfx; + +import com.jpexs.helpers.ReReadableInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author JPEXS + */ +public class GFxInputStream { + + private final ReReadableInputStream is; + private static final int MaxUInt7 = (1 << 7) - 1; + + public GFxInputStream(InputStream is) { + this.is = new ReReadableInputStream(is); + } + + public int available() throws IOException { + return is.available(); + } + + public void setPos(long pos) throws IOException { + is.seek(pos); + } + + public long getPos() { + return is.getPos(); + } + + public int read() throws IOException { + return is.read(); + } + + public int readUI8() throws IOException { + return read(); + } + + public int readUI16() throws IOException { + return read() + (read() << 8); + } + + /** + * Reads one SI16 (Signed 16bit integer) value from the stream + * + * @return SI16 value + * @throws IOException + */ + public int readSI16() throws IOException { + int uval = read() + (read() << 8); + if (uval >= 0x8000) { + return -(((~uval) & 0xffff) + 1); + } else { + return uval; + } + } + + public long readUI32() throws IOException { + return (read() + (read() << 8) + (read() << 16) + (read() << 24)) & 0xffffffff; + } + + public long readUI30() throws IOException { + long v; + int tb = readUI8(); + long t = tb; + switch (tb & 3) { + case 0: + v = t >> 2; + return v; + + case 1: + t >>= 2; + v = t | (readUI8() << 6); + return v; + case 2: + t >>= 2; + t |= (readUI8() << 6); + v = t | (readUI8() << 14); + return v; + } + t >>= 2; + t |= (readUI8() << 6); + t |= (readUI8() << 14); + v = t | (readUI8() << 22); + return v; + } + + public float readFLOAT() throws IOException { + int val = (int) readUI32(); + float ret = Float.intBitsToFloat(val); + return ret; + } + + public int readSI8() throws IOException { + int uval = read(); + if (uval >= 0x80) { + return -(((~uval) & 0xff) + 1); + } else { + return uval; + } + } + + public int readSI15() throws IOException { + int t = readSI8(); + int v; + if ((t & 1) == 0) { + v = t >> 1; + return v; + } + t = ((t >> 1) & MaxUInt7); + v = (t | (readSI8() << 7)); + return v; + } + + public int readUI15() throws IOException { + int t = readUI8(); + int v; + if ((t & 1) == 0) { + v = t >> 1; + return v; + } + t = (t >> 1); + v = (t | (readUI8() << 7)); + return v; + } + + /** + * Reads bytes from the stream + * + * @param count Number of bytes to read + * @return Array of read bytes + * @throws IOException + */ + public byte[] readBytes(long count) throws IOException { + if (count <= 0) { + return new byte[0]; + } + byte[] ret = new byte[(int) count]; + for (int i = 0; i < count; i++) { + ret[i] = (byte) read(); + } + return ret; + } + + void read(byte[] bytes) throws IOException { + is.read(bytes); + } +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/AdpcmDecoder.java b/src/com/jpexs/decompiler/flash/types/sound/AdpcmDecoder.java index 6bc71a4c5..c2d23039e 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/AdpcmDecoder.java +++ b/src/com/jpexs/decompiler/flash/types/sound/AdpcmDecoder.java @@ -1,281 +1,281 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import com.jpexs.decompiler.flash.EndOfStreamException; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.SWFOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * - * @author JPEXS - */ -public class AdpcmDecoder extends SoundDecoder { - - private static final int[] indexAdjustTable2bit = { - -1, 2, - -1, 2}; - private static final int[] indexAdjustTable3bit = { - -1, -1, 2, 4, - -1, -1, 2, 4}; - private static final int[] indexAdjustTable4bit = { - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8}; - private static final int[] indexAdjustTable5bit = { - -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16, - -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16}; - private static final int[] stepSizeTable = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, - 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, - 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, - 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, - 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, - 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, - 27086, 29794, 32767 - }; - - public AdpcmDecoder(SoundFormat soundFormat) { - super(soundFormat); - } - - private static class AdpcmState { - - public int index; - public int sample; - }; - - private static int decode2bit(int deltaCode, AdpcmState state) { - assert (deltaCode == (deltaCode & 3)); - - int step = stepSizeTable[state.index]; - - int difference = step >> 1; - if ((deltaCode & 1) == 1) { - difference += step; - } - if ((deltaCode & 2) == 2) { - difference = -difference; - } - - state.sample += difference; - if (state.sample > 32767) { - state.sample = 32767; - } else if (state.sample < -32768) { - state.sample = -32768; - } - - state.index += indexAdjustTable2bit[deltaCode]; - if (state.index < 0) { - state.index = 0; - } else if (state.index > 88) { - state.index = 88; - } - - return state.sample; - } - - private static int decode3bit(int deltaCode, AdpcmState state) { - assert (deltaCode == (deltaCode & 7)); - - int step = stepSizeTable[state.index]; - - int difference = step >> 2; - if ((deltaCode & 1) == 1) { - difference += step >> 1; - } - if ((deltaCode & 2) == 2) { - difference += step; - } - if ((deltaCode & 4) == 4) { - difference = -difference; - } - - state.sample += difference; - if (state.sample > 32767) { - state.sample = 32767; - } else if (state.sample < -32768) { - state.sample = -32768; - } - - state.index += indexAdjustTable3bit[deltaCode]; - if (state.index < 0) { - state.index = 0; - } else if (state.index > 88) { - state.index = 88; - } - - return state.sample; - } - - private static int decode4bit(int deltaCode, AdpcmState state) { - assert (deltaCode == (deltaCode & 15)); - - int step = stepSizeTable[state.index]; - - int difference = step >> 3; - if ((deltaCode & 1) == 1) { - difference += step >> 2; - } - if ((deltaCode & 2) == 2) { - difference += step >> 1; - } - if ((deltaCode & 4) == 4) { - difference += step; - } - if ((deltaCode & 8) == 8) { - difference = -difference; - } - - state.sample += difference; - if (state.sample > 32767) { - state.sample = 32767; - } else if (state.sample < -32768) { - state.sample = -32768; - } - - state.index += indexAdjustTable4bit[deltaCode]; - if (state.index < 0) { - state.index = 0; - } else if (state.index > 88) { - state.index = 88; - } - - return state.sample; - } - - private static int decode5bit(int deltaCode, AdpcmState state) { - assert (deltaCode >= 0); - assert (deltaCode <= 31 /* 2#11111 */); - - int step = stepSizeTable[state.index]; - - int difference = step >> 4; - if ((deltaCode & 1) == 1) { - difference += step >> 3; - } - if ((deltaCode & 2) == 2) { - difference += step >> 2; - } - if ((deltaCode & 4) == 4) { - difference += step >> 1; - } - if ((deltaCode & 8) == 8) { - difference += step; - } - if ((deltaCode & 16) == 16) { - difference = -difference; - } - - state.sample += difference; - if (state.sample > 32767) { - state.sample = 32767; - } else if (state.sample < -32768) { - state.sample = -32768; - } - - state.index += indexAdjustTable5bit[deltaCode]; - if (state.index < 0) { - state.index = 0; - } else if (state.index > 88) { - state.index = 88; - } - - return state.sample; - } - - @Override - public void decode(InputStream is, OutputStream os) throws IOException { - int adpcm_code_size; - SWFInputStream sis = new SWFInputStream(is, SWF.DEFAULT_VERSION); - SWFOutputStream sos = new SWFOutputStream(os, SWF.DEFAULT_VERSION); - adpcm_code_size = (int) sis.readUB(2); - int bits_per_code = adpcm_code_size + 2; - try { - do { - if (soundFormat.stereo) { - int initialSampleLeft = (int) sis.readSB(16); - int initialIndexLeft = (int) sis.readUB(6); - int initialSampleRight = (int) sis.readSB(16); - int initialIndexRight = (int) sis.readUB(6); - AdpcmState stateLeft = new AdpcmState(); - stateLeft.index = initialIndexLeft; - stateLeft.sample = initialSampleLeft; - AdpcmState stateRight = new AdpcmState(); - stateRight.index = initialIndexRight; - stateRight.sample = initialSampleRight; - for (int i = 1; (i <= 4095) && (sis.availableBits() >= bits_per_code * 2); i++) { - int codeLeft = (int) sis.readUB(bits_per_code); - int codeRight = (int) sis.readUB(bits_per_code); - int valLeft = 0; - int valRight = 0; - switch (bits_per_code) { - case 2: - valLeft = decode2bit(codeLeft, stateLeft); - valRight = decode2bit(codeRight, stateRight); - break; - case 3: - valLeft = decode3bit(codeLeft, stateLeft); - valRight = decode3bit(codeRight, stateRight); - break; - case 4: - valLeft = decode4bit(codeLeft, stateLeft); - valRight = decode4bit(codeRight, stateRight); - break; - case 5: - valLeft = decode5bit(codeLeft, stateLeft); - valRight = decode5bit(codeRight, stateRight); - break; - } - sos.writeSI16(valLeft); - sos.writeSI16(valRight); - } - } else { - int initialSample = (int) sis.readSB(16); - int initialIndex = (int) sis.readUB(6); - AdpcmState state = new AdpcmState(); - state.index = initialIndex; - state.sample = initialSample; - for (int i = 1; (i <= 4095) && (sis.availableBits() >= bits_per_code); i++) { - int code = (int) sis.readUB(bits_per_code); - int val = 0; - switch (bits_per_code) { - case 2: - val = decode2bit(code, state); - break; - case 3: - val = decode3bit(code, state); - break; - case 4: - val = decode4bit(code, state); - break; - case 5: - val = decode5bit(code, state); - break; - } - sos.writeSI16(val); - } - } - } while (sis.available() > 0); - } catch (EndOfStreamException eos) { - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import com.jpexs.decompiler.flash.EndOfStreamException; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * + * @author JPEXS + */ +public class AdpcmDecoder extends SoundDecoder { + + private static final int[] indexAdjustTable2bit = { + -1, 2, + -1, 2}; + private static final int[] indexAdjustTable3bit = { + -1, -1, 2, 4, + -1, -1, 2, 4}; + private static final int[] indexAdjustTable4bit = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8}; + private static final int[] indexAdjustTable5bit = { + -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16, + -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16}; + private static final int[] stepSizeTable = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, + 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, + 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, + 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, + 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, + 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, + 27086, 29794, 32767 + }; + + public AdpcmDecoder(SoundFormat soundFormat) { + super(soundFormat); + } + + private static class AdpcmState { + + public int index; + public int sample; + }; + + private static int decode2bit(int deltaCode, AdpcmState state) { + assert (deltaCode == (deltaCode & 3)); + + int step = stepSizeTable[state.index]; + + int difference = step >> 1; + if ((deltaCode & 1) == 1) { + difference += step; + } + if ((deltaCode & 2) == 2) { + difference = -difference; + } + + state.sample += difference; + if (state.sample > 32767) { + state.sample = 32767; + } else if (state.sample < -32768) { + state.sample = -32768; + } + + state.index += indexAdjustTable2bit[deltaCode]; + if (state.index < 0) { + state.index = 0; + } else if (state.index > 88) { + state.index = 88; + } + + return state.sample; + } + + private static int decode3bit(int deltaCode, AdpcmState state) { + assert (deltaCode == (deltaCode & 7)); + + int step = stepSizeTable[state.index]; + + int difference = step >> 2; + if ((deltaCode & 1) == 1) { + difference += step >> 1; + } + if ((deltaCode & 2) == 2) { + difference += step; + } + if ((deltaCode & 4) == 4) { + difference = -difference; + } + + state.sample += difference; + if (state.sample > 32767) { + state.sample = 32767; + } else if (state.sample < -32768) { + state.sample = -32768; + } + + state.index += indexAdjustTable3bit[deltaCode]; + if (state.index < 0) { + state.index = 0; + } else if (state.index > 88) { + state.index = 88; + } + + return state.sample; + } + + private static int decode4bit(int deltaCode, AdpcmState state) { + assert (deltaCode == (deltaCode & 15)); + + int step = stepSizeTable[state.index]; + + int difference = step >> 3; + if ((deltaCode & 1) == 1) { + difference += step >> 2; + } + if ((deltaCode & 2) == 2) { + difference += step >> 1; + } + if ((deltaCode & 4) == 4) { + difference += step; + } + if ((deltaCode & 8) == 8) { + difference = -difference; + } + + state.sample += difference; + if (state.sample > 32767) { + state.sample = 32767; + } else if (state.sample < -32768) { + state.sample = -32768; + } + + state.index += indexAdjustTable4bit[deltaCode]; + if (state.index < 0) { + state.index = 0; + } else if (state.index > 88) { + state.index = 88; + } + + return state.sample; + } + + private static int decode5bit(int deltaCode, AdpcmState state) { + assert (deltaCode >= 0); + assert (deltaCode <= 31 /* 2#11111 */); + + int step = stepSizeTable[state.index]; + + int difference = step >> 4; + if ((deltaCode & 1) == 1) { + difference += step >> 3; + } + if ((deltaCode & 2) == 2) { + difference += step >> 2; + } + if ((deltaCode & 4) == 4) { + difference += step >> 1; + } + if ((deltaCode & 8) == 8) { + difference += step; + } + if ((deltaCode & 16) == 16) { + difference = -difference; + } + + state.sample += difference; + if (state.sample > 32767) { + state.sample = 32767; + } else if (state.sample < -32768) { + state.sample = -32768; + } + + state.index += indexAdjustTable5bit[deltaCode]; + if (state.index < 0) { + state.index = 0; + } else if (state.index > 88) { + state.index = 88; + } + + return state.sample; + } + + @Override + public void decode(byte[] data, OutputStream os) throws IOException { + int adpcm_code_size; + SWFInputStream sis = new SWFInputStream(data, SWF.DEFAULT_VERSION); + SWFOutputStream sos = new SWFOutputStream(os, SWF.DEFAULT_VERSION); + adpcm_code_size = (int) sis.readUB(2); + int bits_per_code = adpcm_code_size + 2; + try { + do { + if (soundFormat.stereo) { + int initialSampleLeft = (int) sis.readSB(16); + int initialIndexLeft = (int) sis.readUB(6); + int initialSampleRight = (int) sis.readSB(16); + int initialIndexRight = (int) sis.readUB(6); + AdpcmState stateLeft = new AdpcmState(); + stateLeft.index = initialIndexLeft; + stateLeft.sample = initialSampleLeft; + AdpcmState stateRight = new AdpcmState(); + stateRight.index = initialIndexRight; + stateRight.sample = initialSampleRight; + for (int i = 1; (i <= 4095) && (sis.availableBits() >= bits_per_code * 2); i++) { + int codeLeft = (int) sis.readUB(bits_per_code); + int codeRight = (int) sis.readUB(bits_per_code); + int valLeft = 0; + int valRight = 0; + switch (bits_per_code) { + case 2: + valLeft = decode2bit(codeLeft, stateLeft); + valRight = decode2bit(codeRight, stateRight); + break; + case 3: + valLeft = decode3bit(codeLeft, stateLeft); + valRight = decode3bit(codeRight, stateRight); + break; + case 4: + valLeft = decode4bit(codeLeft, stateLeft); + valRight = decode4bit(codeRight, stateRight); + break; + case 5: + valLeft = decode5bit(codeLeft, stateLeft); + valRight = decode5bit(codeRight, stateRight); + break; + } + sos.writeSI16(valLeft); + sos.writeSI16(valRight); + } + } else { + int initialSample = (int) sis.readSB(16); + int initialIndex = (int) sis.readUB(6); + AdpcmState state = new AdpcmState(); + state.index = initialIndex; + state.sample = initialSample; + for (int i = 1; (i <= 4095) && (sis.availableBits() >= bits_per_code); i++) { + int code = (int) sis.readUB(bits_per_code); + int val = 0; + switch (bits_per_code) { + case 2: + val = decode2bit(code, state); + break; + case 3: + val = decode3bit(code, state); + break; + case 4: + val = decode4bit(code, state); + break; + case 5: + val = decode5bit(code, state); + break; + } + sos.writeSI16(val); + } + } + } while (sis.available() > 0); + } catch (EndOfStreamException eos) { + } + } +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/MP3Decoder.java b/src/com/jpexs/decompiler/flash/types/sound/MP3Decoder.java index 11b587995..2bdaa955d 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/MP3Decoder.java +++ b/src/com/jpexs/decompiler/flash/types/sound/MP3Decoder.java @@ -1,110 +1,111 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import javazoom.jl.decoder.Bitstream; -import javazoom.jl.decoder.BitstreamException; -import javazoom.jl.decoder.Decoder; -import javazoom.jl.decoder.DecoderException; -import javazoom.jl.decoder.Header; -import javazoom.jl.decoder.SampleBuffer; - -/** - * - * @author JPEXS - */ -public class MP3Decoder extends SoundDecoder { - - public MP3Decoder(SoundFormat soundFormat) { - super(soundFormat); - } - - @Override - public void decode(InputStream is, OutputStream os) throws IOException { - Decoder decoder = new Decoder(); - Bitstream bitstream = new Bitstream(is); - SampleBuffer buf; - while ((buf = readFrame(decoder, bitstream)) != null) { - short audio[] = buf.getBuffer(); - byte d[] = new byte[buf.getBufferLength() * 2]; - for (int i = 0; i < buf.getBufferLength(); i++) { - int s = audio[i]; - d[i * 2] = (byte) (s & 0xff); - d[i * 2 + 1] = (byte) ((s >> 8) & 0xff); - } - os.write(d); - } - } - - private SampleBuffer readFrame(Decoder decoder, Bitstream bitstream) { - try { - Header h = bitstream.readFrame(); - if (h == null) { - return null; - } - soundFormat.samplingRate = getSamplingRate(h); - soundFormat.stereo = h.mode() != Header.SINGLE_CHANNEL; - try { - SampleBuffer ret = (SampleBuffer) decoder.decodeFrame(h, bitstream); - bitstream.closeFrame(); - return ret; - } catch (DecoderException ex) { - return null; - } - } catch (BitstreamException ex) { - return null; - } - - } - - private static int getSamplingRate(Header h) { - switch (h.sample_frequency()) { - case Header.THIRTYTWO: - if (h.version() == Header.MPEG1) { - return 32000; - } else if (h.version() == Header.MPEG2_LSF) { - return 16000; - } else // SZD - { - return 8000; - } - case Header.FOURTYFOUR_POINT_ONE: - if (h.version() == Header.MPEG1) { - return 44100; - } else if (h.version() == Header.MPEG2_LSF) { - return 22050; - } else // SZD - { - return 11025; - } - case Header.FOURTYEIGHT: - if (h.version() == Header.MPEG1) { - return 48000; - } else if (h.version() == Header.MPEG2_LSF) { - return 24000; - } else // SZD - { - return 12000; - } - default: - return 0; - } - } -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javazoom.jl.decoder.Bitstream; +import javazoom.jl.decoder.BitstreamException; +import javazoom.jl.decoder.Decoder; +import javazoom.jl.decoder.DecoderException; +import javazoom.jl.decoder.Header; +import javazoom.jl.decoder.SampleBuffer; + +/** + * + * @author JPEXS + */ +public class MP3Decoder extends SoundDecoder { + + public MP3Decoder(SoundFormat soundFormat) { + super(soundFormat); + } + + @Override + public void decode(byte[] data, OutputStream os) throws IOException { + Decoder decoder = new Decoder(); + Bitstream bitstream = new Bitstream(new ByteArrayInputStream(data)); + SampleBuffer buf; + while ((buf = readFrame(decoder, bitstream)) != null) { + short audio[] = buf.getBuffer(); + byte d[] = new byte[buf.getBufferLength() * 2]; + for (int i = 0; i < buf.getBufferLength(); i++) { + int s = audio[i]; + d[i * 2] = (byte) (s & 0xff); + d[i * 2 + 1] = (byte) ((s >> 8) & 0xff); + } + os.write(d); + } + } + + private SampleBuffer readFrame(Decoder decoder, Bitstream bitstream) { + try { + Header h = bitstream.readFrame(); + if (h == null) { + return null; + } + soundFormat.samplingRate = getSamplingRate(h); + soundFormat.stereo = h.mode() != Header.SINGLE_CHANNEL; + try { + SampleBuffer ret = (SampleBuffer) decoder.decodeFrame(h, bitstream); + bitstream.closeFrame(); + return ret; + } catch (DecoderException ex) { + return null; + } + } catch (BitstreamException ex) { + return null; + } + + } + + private static int getSamplingRate(Header h) { + switch (h.sample_frequency()) { + case Header.THIRTYTWO: + if (h.version() == Header.MPEG1) { + return 32000; + } else if (h.version() == Header.MPEG2_LSF) { + return 16000; + } else // SZD + { + return 8000; + } + case Header.FOURTYFOUR_POINT_ONE: + if (h.version() == Header.MPEG1) { + return 44100; + } else if (h.version() == Header.MPEG2_LSF) { + return 22050; + } else // SZD + { + return 11025; + } + case Header.FOURTYEIGHT: + if (h.version() == Header.MPEG1) { + return 48000; + } else if (h.version() == Header.MPEG2_LSF) { + return 24000; + } else // SZD + { + return 12000; + } + default: + return 0; + } + } +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/MP3SOUNDDATA.java b/src/com/jpexs/decompiler/flash/types/sound/MP3SOUNDDATA.java index eb082db8f..998fb888a 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/MP3SOUNDDATA.java +++ b/src/com/jpexs/decompiler/flash/types/sound/MP3SOUNDDATA.java @@ -1,58 +1,59 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import javazoom.jl.decoder.Bitstream; -import javazoom.jl.decoder.Decoder; - -/** - * - * @author JPEXS - */ -public class MP3SOUNDDATA { - - public int seekSamples; - public List frames; - - public MP3SOUNDDATA(InputStream is, boolean raw) throws IOException { - SWFInputStream sis = new SWFInputStream(is, SWF.DEFAULT_VERSION); - if (!raw) { - seekSamples = sis.readSI16(); - } - frames = new ArrayList<>(); - MP3FRAME f; - Decoder decoder = new Decoder(); - Bitstream bitstream = new Bitstream(is); - while ((f = MP3FRAME.readFrame(bitstream, decoder)) != null) { - frames.add(f); - } - } - - public int sampleCount() { - int r = 0; - for (MP3FRAME f : frames) { - r += f.getSamples().getBufferLength(); - } - return r; - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javazoom.jl.decoder.Bitstream; +import javazoom.jl.decoder.Decoder; + +/** + * + * @author JPEXS + */ +public class MP3SOUNDDATA { + + public int seekSamples; + public List frames; + + public MP3SOUNDDATA(byte[] data, int version, boolean raw) throws IOException { + SWFInputStream sis = new SWFInputStream(data, version); + if (!raw) { + seekSamples = sis.readSI16(); + } + frames = new ArrayList<>(); + MP3FRAME f; + Decoder decoder = new Decoder(); + Bitstream bitstream = new Bitstream(new ByteArrayInputStream(data, 2, data.length - 2)); + while ((f = MP3FRAME.readFrame(bitstream, decoder)) != null) { + frames.add(f); + } + } + + public int sampleCount() { + int r = 0; + for (MP3FRAME f : frames) { + r += f.getSamples().getBufferLength(); + } + return r; + } +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/NellyMoserDecoder.java b/src/com/jpexs/decompiler/flash/types/sound/NellyMoserDecoder.java index caca9a2e7..2c4216dcf 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/NellyMoserDecoder.java +++ b/src/com/jpexs/decompiler/flash/types/sound/NellyMoserDecoder.java @@ -1,64 +1,66 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import lt.dkd.nellymoser.CodecImpl; - -/** - * - * @author JPEXS - */ -public class NellyMoserDecoder extends SoundDecoder { - - public static final int NELLY_BLOCK_LEN = 64; - public static final int NELLY_BUF_LEN = 128; - public static final int NELLY_SAMPLES = 2 * NELLY_BUF_LEN; - - public NellyMoserDecoder(SoundFormat soundFormat) { - super(soundFormat); - } - - @Override - public void decode(InputStream is, OutputStream os) throws IOException { - soundFormat.stereo = false; - float audioD[] = new float[NELLY_SAMPLES]; - - final float[] state = new float[64]; - - SWFInputStream sis = new SWFInputStream(is, SWF.DEFAULT_VERSION); - while (sis.available() > 0) { - byte[] block = sis.readBytes(NELLY_BLOCK_LEN); - CodecImpl.decode(state, block, audioD); - short audio[] = new short[NELLY_SAMPLES]; - for (int i = 0; i < audioD.length; i++) { - audio[i] = (short) (audioD[i]); - } - byte d[] = new byte[audio.length * 2]; - for (int i = 0; i < audio.length; i++) { - int s = audio[i]; - d[i * 2] = (byte) (s & 0xff); - d[i * 2 + 1] = (byte) ((s >> 8) & 0xff); - } - os.write(d); - } - } -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import lt.dkd.nellymoser.CodecImpl; + +/** + * + * @author JPEXS + */ +public class NellyMoserDecoder extends SoundDecoder { + + public static final int NELLY_BLOCK_LEN = 64; + public static final int NELLY_BUF_LEN = 128; + public static final int NELLY_SAMPLES = 2 * NELLY_BUF_LEN; + + public NellyMoserDecoder(SoundFormat soundFormat) { + super(soundFormat); + } + + @Override + public void decode(byte[] data, OutputStream os) throws IOException { + soundFormat.stereo = false; + float audioD[] = new float[NELLY_SAMPLES]; + + final float[] state = new float[64]; + + byte[] block = new byte[NELLY_BLOCK_LEN]; + int blockCount = data.length / NELLY_BLOCK_LEN; + for (int j = 0; j < blockCount; j++) { + System.arraycopy(data, j * NELLY_BLOCK_LEN, block, 0, NELLY_BLOCK_LEN); + CodecImpl.decode(state, block, audioD); + short audio[] = new short[NELLY_SAMPLES]; + for (int i = 0; i < audioD.length; i++) { + audio[i] = (short) (audioD[i]); + } + byte d[] = new byte[audio.length * 2]; + for (int i = 0; i < audio.length; i++) { + int s = audio[i]; + d[i * 2] = (byte) (s & 0xff); + d[i * 2 + 1] = (byte) ((s >> 8) & 0xff); + } + os.write(d); + } + } +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/NoDecoder.java b/src/com/jpexs/decompiler/flash/types/sound/NoDecoder.java index bac18b2e4..ecda60986 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/NoDecoder.java +++ b/src/com/jpexs/decompiler/flash/types/sound/NoDecoder.java @@ -1,43 +1,39 @@ -/* - * Copyright (C) 2014 * @author JPEXS - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * - * @author JPEXS - */ -public class NoDecoder extends SoundDecoder { - - public NoDecoder(SoundFormat soundFormat) { - super(soundFormat); - } - - @Override - public void decode(InputStream is, OutputStream os) throws IOException { - byte buf[] = new byte[1024]; - int cnt; - while ((cnt = is.read(buf)) > 0) { - os.write(buf, 0, cnt); - } - } - -} +/* + * Copyright (C) 2014 * @author JPEXS + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * + * @author JPEXS + */ +public class NoDecoder extends SoundDecoder { + + public NoDecoder(SoundFormat soundFormat) { + super(soundFormat); + } + + @Override + public void decode(byte[] data, OutputStream os) throws IOException { + os.write(data); + } + +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/SoundDecoder.java b/src/com/jpexs/decompiler/flash/types/sound/SoundDecoder.java index a6332ff8d..16d81e990 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/SoundDecoder.java +++ b/src/com/jpexs/decompiler/flash/types/sound/SoundDecoder.java @@ -1,44 +1,44 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * - * @author JPEXS - */ -public abstract class SoundDecoder { - - public SoundFormat soundFormat; - - public SoundDecoder(SoundFormat soundFormat) { - this.soundFormat = soundFormat; - } - - public byte[] decode(byte[] data) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - decode(new ByteArrayInputStream(data), baos); - return baos.toByteArray(); - } - - public abstract void decode(InputStream is, OutputStream os) throws IOException; -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * + * @author JPEXS + */ +public abstract class SoundDecoder { + + public SoundFormat soundFormat; + + public SoundDecoder(SoundFormat soundFormat) { + this.soundFormat = soundFormat; + } + + public byte[] decode(byte[] data) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + decode(data, baos); + return baos.toByteArray(); + } + + public abstract void decode(byte[] data, OutputStream os) throws IOException; +} diff --git a/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java b/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java index e7210160b..36ab7f30e 100644 --- a/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java +++ b/src/com/jpexs/decompiler/flash/types/sound/SoundFormat.java @@ -1,214 +1,210 @@ -/* - * Copyright (C) 2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash.types.sound; - -import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.DataLine; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.SourceDataLine; - -/** - * - * @author JPEXS - */ -public class SoundFormat { - - public int formatId; - public int samplingRate; - public boolean stereo; - - //int[] rateMap = {5512, 11025, 22050, 44100}; - public static final int FORMAT_UNCOMPRESSED_NATIVE_ENDIAN = 0; - public static final int FORMAT_ADPCM = 1; - public static final int FORMAT_MP3 = 2; - public static final int FORMAT_UNCOMPRESSED_LITTLE_ENDIAN = 3; - public static final int FORMAT_NELLYMOSER16KHZ = 4; - public static final int FORMAT_NELLYMOSER8KHZ = 5; - public static final int FORMAT_NELLYMOSER = 6; - public static final int FORMAT_SPEEX = 11; - - public static final int EXPORT_WAV = 0; - public static final int EXPORT_MP3 = 1; - public static final int EXPORT_FLV = 2; - - public SoundFormat() { - - } - - public int getNativeExportFormat() { - switch (formatId) { - case FORMAT_UNCOMPRESSED_NATIVE_ENDIAN: - case FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: - case FORMAT_ADPCM: - return EXPORT_WAV; - case FORMAT_MP3: - return EXPORT_MP3; - case FORMAT_NELLYMOSER16KHZ: - case FORMAT_NELLYMOSER8KHZ: - case FORMAT_NELLYMOSER: - case FORMAT_SPEEX: - return EXPORT_FLV; - default: - return EXPORT_FLV; - } - } - - public SoundFormat(int formatId, int samplingRate, boolean stereo) { - this.formatId = formatId; - this.samplingRate = samplingRate; - this.stereo = stereo; - ensureFormat(); - } - - public byte[] decode(byte data[]) { - try { - return getDecoder().decode(data); - } catch (IOException ex) { - return null; - } - } - - public boolean decode(InputStream is, OutputStream os) { - try { - getDecoder().decode(is, os); - return true; - } catch (IOException ex) { - return false; - } - } - - public boolean play(byte data[]) { - return play(new ByteArrayInputStream(data)); - } - - public boolean play(InputStream is) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - if (!decode(is, baos)) { - return false; - } - - AudioFormat audioFormat = new AudioFormat(samplingRate, 16, stereo ? 2 : 1, true, false); - DataLine.Info info = new DataLine.Info(SourceDataLine.class, - audioFormat); - try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) { - line.open(audioFormat); - byte data[] = baos.toByteArray(); - line.write(data, 0, data.length); - line.drain(); - line.stop(); - return true; - } catch (LineUnavailableException ex) { - return false; - } - } - - private void ensureFormat() { - switch (formatId) { - case FORMAT_NELLYMOSER16KHZ: - samplingRate = 16000; - break; - case FORMAT_NELLYMOSER8KHZ: - samplingRate = 8000; - break; - case FORMAT_NELLYMOSER: - samplingRate = 22050; - break; - } - } - - public SoundDecoder getDecoder() { - ensureFormat(); - switch (formatId) { - case FORMAT_UNCOMPRESSED_NATIVE_ENDIAN: - case FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: - return new NoDecoder(this); - case FORMAT_ADPCM: - return new AdpcmDecoder(this); - case FORMAT_MP3: - return new MP3Decoder(this); - case FORMAT_NELLYMOSER16KHZ: - return new NellyMoserDecoder(this); - case FORMAT_NELLYMOSER8KHZ: - return new NellyMoserDecoder(this); - case FORMAT_NELLYMOSER: - return new NellyMoserDecoder(this); - case FORMAT_SPEEX: - return null; //I haven't seen any Speex audio in the wild - default: - return null; - } - } - - private static void writeLE(OutputStream os, long val, int size) throws IOException { - for (int i = 0; i < size; i++) { - os.write((int) (val & 0xff)); - val >>= 8; - } - } - - public boolean createWav(InputStream is, OutputStream os) { - ensureFormat(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - decode(is, baos); - try { - createWavFromPcmData(os, samplingRate, true, stereo, baos.toByteArray()); - return true; - } catch (IOException ex) { - return false; - } - } - - public static void createWavFromPcmData(OutputStream fos, int soundRateHz, boolean sample16bit, boolean stereo, byte[] data) throws IOException { - ByteArrayOutputStream subChunk1Data = new ByteArrayOutputStream(); - int audioFormat = 1; //PCM - writeLE(subChunk1Data, audioFormat, 2); - int numChannels = stereo ? 2 : 1; - writeLE(subChunk1Data, numChannels, 2); - - int sampleRate = soundRateHz;//rateMap[soundRate]; - writeLE(subChunk1Data, sampleRate, 4); - int bitsPerSample = sample16bit ? 16 : 8; - int byteRate = sampleRate * numChannels * bitsPerSample / 8; - writeLE(subChunk1Data, byteRate, 4); - int blockAlign = numChannels * bitsPerSample / 8; - writeLE(subChunk1Data, blockAlign, 2); - writeLE(subChunk1Data, bitsPerSample, 2); - - ByteArrayOutputStream chunks = new ByteArrayOutputStream(); - chunks.write(Utf8Helper.getBytes("fmt ")); - byte[] subChunk1DataBytes = subChunk1Data.toByteArray(); - writeLE(chunks, subChunk1DataBytes.length, 4); - chunks.write(subChunk1DataBytes); - - chunks.write(Utf8Helper.getBytes("data")); - writeLE(chunks, data.length, 4); - chunks.write(data); - - fos.write(Utf8Helper.getBytes("RIFF")); - byte[] chunkBytes = chunks.toByteArray(); - writeLE(fos, 4 + chunkBytes.length, 4); - fos.write(Utf8Helper.getBytes("WAVE")); - fos.write(chunkBytes); - } -} +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.types.sound; + +import com.jpexs.helpers.utf8.Utf8Helper; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; + +/** + * + * @author JPEXS + */ +public class SoundFormat { + + public int formatId; + public int samplingRate; + public boolean stereo; + + //int[] rateMap = {5512, 11025, 22050, 44100}; + public static final int FORMAT_UNCOMPRESSED_NATIVE_ENDIAN = 0; + public static final int FORMAT_ADPCM = 1; + public static final int FORMAT_MP3 = 2; + public static final int FORMAT_UNCOMPRESSED_LITTLE_ENDIAN = 3; + public static final int FORMAT_NELLYMOSER16KHZ = 4; + public static final int FORMAT_NELLYMOSER8KHZ = 5; + public static final int FORMAT_NELLYMOSER = 6; + public static final int FORMAT_SPEEX = 11; + + public static final int EXPORT_WAV = 0; + public static final int EXPORT_MP3 = 1; + public static final int EXPORT_FLV = 2; + + public SoundFormat() { + + } + + public int getNativeExportFormat() { + switch (formatId) { + case FORMAT_UNCOMPRESSED_NATIVE_ENDIAN: + case FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: + case FORMAT_ADPCM: + return EXPORT_WAV; + case FORMAT_MP3: + return EXPORT_MP3; + case FORMAT_NELLYMOSER16KHZ: + case FORMAT_NELLYMOSER8KHZ: + case FORMAT_NELLYMOSER: + case FORMAT_SPEEX: + return EXPORT_FLV; + default: + return EXPORT_FLV; + } + } + + public SoundFormat(int formatId, int samplingRate, boolean stereo) { + this.formatId = formatId; + this.samplingRate = samplingRate; + this.stereo = stereo; + ensureFormat(); + } + + public byte[] decode(byte data[]) { + try { + return getDecoder().decode(data); + } catch (IOException ex) { + return null; + } + } + + public boolean decode(byte[] data, OutputStream os) { + try { + getDecoder().decode(data, os); + return true; + } catch (IOException ex) { + return false; + } + } + + public boolean play(byte[] data) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if (!decode(data, baos)) { + return false; + } + + AudioFormat audioFormat = new AudioFormat(samplingRate, 16, stereo ? 2 : 1, true, false); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, + audioFormat); + try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) { + line.open(audioFormat); + byte[] outData = baos.toByteArray(); + line.write(outData, 0, outData.length); + line.drain(); + line.stop(); + return true; + } catch (LineUnavailableException ex) { + return false; + } + } + + private void ensureFormat() { + switch (formatId) { + case FORMAT_NELLYMOSER16KHZ: + samplingRate = 16000; + break; + case FORMAT_NELLYMOSER8KHZ: + samplingRate = 8000; + break; + case FORMAT_NELLYMOSER: + samplingRate = 22050; + break; + } + } + + public SoundDecoder getDecoder() { + ensureFormat(); + switch (formatId) { + case FORMAT_UNCOMPRESSED_NATIVE_ENDIAN: + case FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: + return new NoDecoder(this); + case FORMAT_ADPCM: + return new AdpcmDecoder(this); + case FORMAT_MP3: + return new MP3Decoder(this); + case FORMAT_NELLYMOSER16KHZ: + return new NellyMoserDecoder(this); + case FORMAT_NELLYMOSER8KHZ: + return new NellyMoserDecoder(this); + case FORMAT_NELLYMOSER: + return new NellyMoserDecoder(this); + case FORMAT_SPEEX: + return null; //I haven't seen any Speex audio in the wild + default: + return null; + } + } + + private static void writeLE(OutputStream os, long val, int size) throws IOException { + for (int i = 0; i < size; i++) { + os.write((int) (val & 0xff)); + val >>= 8; + } + } + + public boolean createWav(byte[] data, OutputStream os) { + ensureFormat(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + decode(data, baos); + try { + createWavFromPcmData(os, samplingRate, true, stereo, baos.toByteArray()); + return true; + } catch (IOException ex) { + return false; + } + } + + public static void createWavFromPcmData(OutputStream fos, int soundRateHz, boolean sample16bit, boolean stereo, byte[] data) throws IOException { + ByteArrayOutputStream subChunk1Data = new ByteArrayOutputStream(); + int audioFormat = 1; //PCM + writeLE(subChunk1Data, audioFormat, 2); + int numChannels = stereo ? 2 : 1; + writeLE(subChunk1Data, numChannels, 2); + + int sampleRate = soundRateHz;//rateMap[soundRate]; + writeLE(subChunk1Data, sampleRate, 4); + int bitsPerSample = sample16bit ? 16 : 8; + int byteRate = sampleRate * numChannels * bitsPerSample / 8; + writeLE(subChunk1Data, byteRate, 4); + int blockAlign = numChannels * bitsPerSample / 8; + writeLE(subChunk1Data, blockAlign, 2); + writeLE(subChunk1Data, bitsPerSample, 2); + + ByteArrayOutputStream chunks = new ByteArrayOutputStream(); + chunks.write(Utf8Helper.getBytes("fmt ")); + byte[] subChunk1DataBytes = subChunk1Data.toByteArray(); + writeLE(chunks, subChunk1DataBytes.length, 4); + chunks.write(subChunk1DataBytes); + + chunks.write(Utf8Helper.getBytes("data")); + writeLE(chunks, data.length, 4); + chunks.write(data); + + fos.write(Utf8Helper.getBytes("RIFF")); + byte[] chunkBytes = chunks.toByteArray(); + writeLE(fos, 4 + chunkBytes.length, 4); + fos.write(Utf8Helper.getBytes("WAVE")); + fos.write(chunkBytes); + } +} diff --git a/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 0e1943a90..d692a5f35 100644 --- a/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.RetryTask; import com.jpexs.decompiler.flash.RunnableIOEx; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFCompression; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -1393,7 +1394,7 @@ public class XFLConverter { for (Tag t : tags) { if (found && (t instanceof SoundStreamBlockTag)) { SoundStreamBlockTag bl = (SoundStreamBlockTag) t; - soundData = bl.getData(); + soundData = bl.streamSoundData; break; } if (t == symbol) { @@ -1437,7 +1438,7 @@ public class XFLConverter { bits = 18; } if (soundFormat == SoundFormat.FORMAT_ADPCM) { - SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(soundData), swf.version); + SWFInputStream sis = new SWFInputStream(soundData, swf.version); exportFormat = "wav"; try { int adpcmCodeSize = (int) sis.readUB(2); @@ -1453,7 +1454,7 @@ public class XFLConverter { } format += 4; //quality best try { - MP3SOUNDDATA s = new MP3SOUNDDATA(new ByteArrayInputStream(soundData), false); + MP3SOUNDDATA s = new MP3SOUNDDATA(soundData, swf.version, false); //sis.readSI16(); //MP3FRAME frame = new MP3FRAME(sis); MP3FRAME frame = s.frames.get(0); @@ -2845,8 +2846,8 @@ public class XFLConverter { + " CONFIG::FLASH_AUTHORING="true";\n" + " 0\n" + " \n" - + " " + (swf.compressed ? "1" : "0") + "\n" - + " " + (swf.lzma ? "1" : "0") + "\n" + + " " + (swf.compression == SWFCompression.NONE ? "0" : "1") + "\n" + + " " + (swf.compression == SWFCompression.LZMA ? "1" : "0") + "\n" + " 1\n" + " 0\n" + " 0\n" diff --git a/src/com/jpexs/helpers/Helper.java b/src/com/jpexs/helpers/Helper.java index e3d850615..b97abc224 100644 --- a/src/com/jpexs/helpers/Helper.java +++ b/src/com/jpexs/helpers/Helper.java @@ -38,6 +38,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.OutputStream; import java.lang.reflect.Field; import java.text.MessageFormat; import java.util.ArrayList; @@ -449,18 +450,29 @@ public class Helper { } ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copyStream(is, baos, Long.MAX_VALUE); + return baos.toByteArray(); + } + + public static void copyStream(InputStream is, OutputStream os, long maxLength) { try { - byte[] buf = new byte[4096]; + final int bufSize = 4096; + byte[] buf = new byte[bufSize]; int cnt = 0; while ((cnt = is.read(buf)) > 0) { - baos.write(buf, 0, cnt); + os.write(buf, 0, cnt); + maxLength -= cnt; + + // last chunk is smaller + if (maxLength < bufSize) { + buf = new byte[(int) maxLength]; + } } } catch (IOException ex) { Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); } - return baos.toByteArray(); } - + public static void writeFile(String file, byte[] ... data) { try (FileOutputStream fos = new FileOutputStream(file)) { diff --git a/src/com/jpexs/helpers/NulStream.java b/src/com/jpexs/helpers/NulStream.java new file mode 100644 index 000000000..c6d2091a7 --- /dev/null +++ b/src/com/jpexs/helpers/NulStream.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.helpers; + +import java.io.OutputStream; + +/** + * + * @author JPEXS + */ +public class NulStream extends OutputStream { + + @Override + public void write(int i) { + } + +} diff --git a/test/com/jpexs/decompiler/flash/SWFStreamTest.java b/test/com/jpexs/decompiler/flash/SWFStreamTest.java index 543f086d6..0db33a5e3 100644 --- a/test/com/jpexs/decompiler/flash/SWFStreamTest.java +++ b/test/com/jpexs/decompiler/flash/SWFStreamTest.java @@ -1,185 +1,176 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.gui.Main; -import com.jpexs.decompiler.flash.types.RECT; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -/** - * - * @author JPEXS - */ -public class SWFStreamTest { - - @BeforeClass - public void init(){ - Main.initLogging(false); - } - - @Test - public void testNeededBits() { - assertEquals(SWFOutputStream.getNeededBitsU(3), 2); - assertEquals(SWFOutputStream.getNeededBitsU(255), 8); - assertEquals(SWFOutputStream.getNeededBitsS(3), 3); - assertEquals(SWFOutputStream.getNeededBitsS(255), 9); - assertEquals(SWFOutputStream.getNeededBitsS(-2), 3); - assertEquals(SWFOutputStream.getNeededBitsS(-597), 11); - assertEquals(SWFOutputStream.getNeededBitsF(15.5f), 21); - assertEquals(SWFOutputStream.getNeededBitsF(0.1f), 17); - assertEquals(SWFOutputStream.getNeededBitsF(-2.8891602f), 19); - } - - @Test - public void testFB() throws IOException { - double f = 5.25; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) { - sos.writeFB(20, f); - } - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - try (SWFInputStream sis = new SWFInputStream(bais, 10)) { - assertTrue(Double.compare(f, sis.readFB(20)) == 0); - } - } - - @Test - public void testUB() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) { - sos.writeUB(5, 1); - sos.writeUB(6, 2); - sos.writeUB(7, 3); - sos.writeUB(8, 4); - sos.writeUB(9, 5); - } - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - try (SWFInputStream sis = new SWFInputStream(bais, 10)) { - assertEquals(1, sis.readUB(5)); - assertEquals(2, sis.readUB(6)); - assertEquals(3, sis.readUB(7)); - assertEquals(4, sis.readUB(8)); - assertEquals(5, sis.readUB(9)); - } - } - - @Test - public void testSB() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) { - sos.writeSB(5, -1); - sos.writeSB(6, 2); - sos.writeSB(7, -3); - sos.writeSB(8, 4); - sos.writeSB(9, -5); - } - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - try (SWFInputStream sis = new SWFInputStream(bais, 10)) { - assertEquals(-1, sis.readSB(5)); - assertEquals(2, sis.readSB(6)); - assertEquals(-3, sis.readSB(7)); - assertEquals(4, sis.readSB(8)); - assertEquals(-5, sis.readSB(9)); - } - } - - @Test - public void testFLOATAndDouble() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, 10); - float f = 5.25f; - sos.writeFLOAT(f); - sos.close(); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - SWFInputStream sis = new SWFInputStream(bais, 10); - assertEquals(f, sis.readFLOAT()); - sis.close(); - - baos = new ByteArrayOutputStream(); - sos = new SWFOutputStream(baos, 10); - f = 5.25f; - sos.writeFLOAT16(f); - sos.close(); - bais = new ByteArrayInputStream(baos.toByteArray()); - sis = new SWFInputStream(bais, 10); - assertEquals(f, sis.readFLOAT16()); - sis.close(); - - baos = new ByteArrayOutputStream(); - sos = new SWFOutputStream(baos, 10); - double d = 5.25; - sos.writeDOUBLE(d); - sos.close(); - bais = new ByteArrayInputStream(baos.toByteArray()); - sis = new SWFInputStream(bais, 10); - assertEquals(d, sis.readDOUBLE()); - sis.close(); - } - - @Test - public void testFIXEDandFIXED8() throws IOException { - //example from specification - ByteArrayInputStream bais = new ByteArrayInputStream(new byte[]{(byte) 0x00, (byte) 0x80, (byte) 0x07, (byte) 0x00}); - SWFInputStream sis = new SWFInputStream(bais, 10); - assertTrue(Double.compare(7.5, sis.readFIXED()) == 0); - sis.close(); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - SWFOutputStream sos = new SWFOutputStream(baos, 10); - double dd = 5.25; - sos.writeFIXED(dd); - sos.close(); - bais = new ByteArrayInputStream(baos.toByteArray()); - sis = new SWFInputStream(bais, 10); - assertTrue(Double.compare(dd, sis.readFIXED()) == 0); - sis.close(); - - baos = new ByteArrayOutputStream(); - sos = new SWFOutputStream(baos, 10); - float ff = 5.25f; - sos.writeFIXED8(ff); - sos.close(); - bais = new ByteArrayInputStream(baos.toByteArray()); - sis = new SWFInputStream(bais, 10); - assertEquals(ff, sis.readFIXED8()); - sis.close(); - } - - @Test - public void testRECT() throws IOException { - RECT rect; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) { - rect = new RECT(-0x80000000, 0x7FFFFFFF, -0x80000000, 0x7FFFFFFF); - sos.writeRECT(rect); - } - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - try (SWFInputStream sis = new SWFInputStream(bais, 10)) { - RECT readRECT = sis.readRECT(); - assertEquals(readRECT.Xmin, -0x3FFFFFFF); - assertEquals(readRECT.Xmax, 0x3FFFFFFF); - assertEquals(readRECT.Ymin, -0x3FFFFFFF); - assertEquals(readRECT.Ymax, 0x3FFFFFFF); - } - } -} +/* + * Copyright (C) 2010-2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.gui.Main; +import com.jpexs.decompiler.flash.types.RECT; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class SWFStreamTest { + + @BeforeClass + public void init(){ + Main.initLogging(false); + } + + @Test + public void testNeededBits() { + assertEquals(SWFOutputStream.getNeededBitsU(3), 2); + assertEquals(SWFOutputStream.getNeededBitsU(255), 8); + assertEquals(SWFOutputStream.getNeededBitsS(3), 3); + assertEquals(SWFOutputStream.getNeededBitsS(255), 9); + assertEquals(SWFOutputStream.getNeededBitsS(-2), 3); + assertEquals(SWFOutputStream.getNeededBitsS(-597), 11); + assertEquals(SWFOutputStream.getNeededBitsF(15.5f), 21); + assertEquals(SWFOutputStream.getNeededBitsF(0.1f), 17); + assertEquals(SWFOutputStream.getNeededBitsF(-2.8891602f), 19); + } + + @Test + public void testFB() throws IOException { + double f = 5.25; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION)) { + sos.writeFB(20, f); + } + try (SWFInputStream sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION)) { + assertTrue(Double.compare(f, sis.readFB(20)) == 0); + } + } + + @Test + public void testUB() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION)) { + sos.writeUB(5, 1); + sos.writeUB(6, 2); + sos.writeUB(7, 3); + sos.writeUB(8, 4); + sos.writeUB(9, 5); + } + try (SWFInputStream sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION)) { + assertEquals(1, sis.readUB(5)); + assertEquals(2, sis.readUB(6)); + assertEquals(3, sis.readUB(7)); + assertEquals(4, sis.readUB(8)); + assertEquals(5, sis.readUB(9)); + } + } + + @Test + public void testSB() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION)) { + sos.writeSB(5, -1); + sos.writeSB(6, 2); + sos.writeSB(7, -3); + sos.writeSB(8, 4); + sos.writeSB(9, -5); + } + try (SWFInputStream sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION)) { + assertEquals(-1, sis.readSB(5)); + assertEquals(2, sis.readSB(6)); + assertEquals(-3, sis.readSB(7)); + assertEquals(4, sis.readSB(8)); + assertEquals(-5, sis.readSB(9)); + } + } + + @Test + public void testFLOATAndDouble() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); + float f = 5.25f; + sos.writeFLOAT(f); + sos.close(); + SWFInputStream sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION); + assertEquals(f, sis.readFLOAT()); + sis.close(); + + baos = new ByteArrayOutputStream(); + sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); + f = 5.25f; + sos.writeFLOAT16(f); + sos.close(); + sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION); + assertEquals(f, sis.readFLOAT16()); + sis.close(); + + baos = new ByteArrayOutputStream(); + sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); + double d = 5.25; + sos.writeDOUBLE(d); + sos.close(); + sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION); + assertEquals(d, sis.readDOUBLE()); + sis.close(); + } + + @Test + public void testFIXEDandFIXED8() throws IOException { + //example from specification + byte[] data = new byte[]{(byte) 0x00, (byte) 0x80, (byte) 0x07, (byte) 0x00}; + SWFInputStream sis = new SWFInputStream(data, SWF.DEFAULT_VERSION); + assertTrue(Double.compare(7.5, sis.readFIXED()) == 0); + sis.close(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); + double dd = 5.25; + sos.writeFIXED(dd); + sos.close(); + sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION); + assertTrue(Double.compare(dd, sis.readFIXED()) == 0); + sis.close(); + + baos = new ByteArrayOutputStream(); + sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION); + float ff = 5.25f; + sos.writeFIXED8(ff); + sos.close(); + sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION); + assertEquals(ff, sis.readFIXED8()); + sis.close(); + } + + @Test + public void testRECT() throws IOException { + RECT rect; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (SWFOutputStream sos = new SWFOutputStream(baos, SWF.DEFAULT_VERSION)) { + rect = new RECT(-0x80000000, 0x7FFFFFFF, -0x80000000, 0x7FFFFFFF); + sos.writeRECT(rect); + } + try (SWFInputStream sis = new SWFInputStream(baos.toByteArray(), SWF.DEFAULT_VERSION)) { + RECT readRECT = sis.readRECT(); + assertEquals(readRECT.Xmin, -0x3FFFFFFF); + assertEquals(readRECT.Xmax, 0x3FFFFFFF); + assertEquals(readRECT.Ymin, -0x3FFFFFFF); + assertEquals(readRECT.Ymax, 0x3FFFFFFF); + } + } +}