tag names moved to constants

This commit is contained in:
honfika@gmail.com
2015-05-14 21:46:26 +02:00
parent 74c4d44796
commit 3de39c93bb
86 changed files with 13357 additions and 13196 deletions

View File

@@ -2564,7 +2564,7 @@ public class SWFInputStream implements AutoCloseable {
FILLSTYLEARRAY ret = new FILLSTYLEARRAY();
newDumpLevel(name, "FILLSTYLEARRAY");
int fillStyleCount = readUI8("fillStyleCount");
if (((shapeNum == 2) || (shapeNum == 3) || (shapeNum == 4/*?*/)) && (fillStyleCount == 0xff)) {
if (shapeNum > 1 && fillStyleCount == 0xff) {
fillStyleCount = readUI16("fillStyleCount");
}
ret.fillStyles = new FILLSTYLE[fillStyleCount];
@@ -2645,7 +2645,7 @@ public class SWFInputStream implements AutoCloseable {
if (lineStyleCount == 0xff) {
lineStyleCount = readUI16("lineStyleCount");
}
if ((shapeNum == 1 || shapeNum == 2 || shapeNum == 3)) {
if (shapeNum <= 3) {
ret.lineStyles = new LINESTYLE[lineStyleCount];
for (int i = 0; i < lineStyleCount; i++) {
ret.lineStyles[i] = readLINESTYLE(shapeNum, "lineStyle");

View File

@@ -1186,7 +1186,7 @@ public class SWFOutputStream extends OutputStream {
*/
public void writeFILLSTYLEARRAY(FILLSTYLEARRAY value, int shapeNum) throws IOException {
int fillStyleCount = value.fillStyles.length;
if (shapeNum == 2 || shapeNum == 3) {
if (shapeNum > 1) {
if (fillStyleCount >= 0xff) {
writeUI8(0xff);
writeUI16(fillStyleCount);
@@ -1303,7 +1303,7 @@ public class SWFOutputStream extends OutputStream {
*/
public void writeLINESTYLEARRAY(LINESTYLEARRAY value, int shapeNum) throws IOException {
int lineStyleCount;
if (shapeNum == 1 || shapeNum == 2 || shapeNum == 3) {
if (shapeNum <= 3) {
lineStyleCount = value.lineStyles.length;
if (lineStyleCount >= 0xff) {
writeUI8(0xff);

View File

@@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.TagInfo;
import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA;
import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA;
import com.jpexs.decompiler.flash.types.ARGB;
@@ -240,9 +241,9 @@ public class SwfXmlImporter {
private Object createObject(String type, SWF swf, Tag tag) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (swfTags == null) {
Map<String, Class> tags = new HashMap<>();
Map<Integer, Class> knownTags = Tag.getKnownClasses();
Map<Integer, TagInfo> knownTags = Tag.getKnownClasses();
for (Integer key : knownTags.keySet()) {
Class cls = knownTags.get(key);
Class cls = knownTags.get(key).cls;
if (!ReflectionTools.canInstantiate(cls)) {
System.err.println("Can't instantiate: " + cls.getName());
}

View File

@@ -1,127 +1,129 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class CSMTextSettingsTag extends Tag implements CharacterIdTag {
@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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public CSMTextSettingsTag(SWF swf) {
super(swf, ID, "CSMTextSettings", null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public CSMTextSettingsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "CSMTextSettings", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
textID = sis.readUI16("textID");
useFlashType = (int) sis.readUB(2, "useFlashType");
gridFit = (int) sis.readUB(3, "gridFit");
reserved = (int) sis.readUB(3, "reserved");
thickness = sis.readFLOAT("thickness"); //F32 = FLOAT
sharpness = sis.readFLOAT("sharpness"); //F32 = FLOAT
reserved2 = sis.readUI8("reserved2"); //reserved
}
@Override
public int getCharacterId() {
return textID;
}
@Override
public void setCharacterId(int characterId) {
this.textID = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class CSMTextSettingsTag extends Tag implements CharacterIdTag {
@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;
public static final String NAME = "CSMTextSettings";
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public CSMTextSettingsTag(SWF swf) {
super(swf, ID, NAME, null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public CSMTextSettingsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
textID = sis.readUI16("textID");
useFlashType = (int) sis.readUB(2, "useFlashType");
gridFit = (int) sis.readUB(3, "gridFit");
reserved = (int) sis.readUB(3, "reserved");
thickness = sis.readFLOAT("thickness"); //F32 = FLOAT
sharpness = sis.readFLOAT("sharpness"); //F32 = FLOAT
reserved2 = sis.readUI8("reserved2"); //reserved
}
@Override
public int getCharacterId() {
return textID;
}
@Override
public void setCharacterId(int characterId) {
this.textID = characterId;
}
}

View File

@@ -37,6 +37,8 @@ public class DebugIDTag extends Tag {
public static final int ID = 63;
public static final String NAME = "DebugID";
/**
* Gets data bytes
*
@@ -61,7 +63,7 @@ public class DebugIDTag extends Tag {
* @param swf
*/
public DebugIDTag(SWF swf) {
super(swf, ID, "DebugID", null);
super(swf, ID, NAME, null);
debugId = new byte[16];
}
@@ -73,7 +75,7 @@ public class DebugIDTag extends Tag {
* @throws IOException
*/
public DebugIDTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DebugID", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,151 +1,153 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.configuration.Configuration;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.types.BasicType;
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.helpers.ByteArrayRange;
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 java.util.Arrays;
/**
*
* @author JPEXS
*/
public class DefineBinaryDataTag extends CharacterTag {
@SWFType(BasicType.UI16)
public int tag;
public ByteArrayRange binaryData;
@Reserved
@SWFType(BasicType.UI32)
public long reserved;
public static final int ID = 87;
@Internal
public SWF innerSwf;
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineBinaryDataTag(SWF swf) {
super(swf, ID, "DefineBinaryData", null);
tag = swf.getNextCharacterId();
binaryData = ByteArrayRange.EMPTY;
}
public DefineBinaryDataTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBinaryData", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
tag = sis.readUI16("tag");
reserved = sis.readUI32("reserved");
binaryData = sis.readByteRangeEx(sis.available(), "binaryData");
if (Configuration.autoLoadEmbeddedSwfs.get()) {
try {
InputStream is = new ByteArrayInputStream(binaryData.getArray(), binaryData.getPos(), binaryData.getLength());
SWF bswf = new SWF(is, null, "(SWF Data)", Configuration.parallelSpeedUp.get());
innerSwf = bswf;
bswf.binaryData = this;
} catch (IOException | InterruptedException ex) {
// ignore
}
}
}
@Override
public int getCharacterId() {
return tag;
}
@Override
public void setCharacterId(int characterId) {
this.tag = characterId;
}
public boolean isSwfData() {
try {
if (binaryData.getLength() > 8) {
String signature = new String(binaryData.getRangeData(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)) {
return true;
}
}
} catch (Exception ex) {
}
return false;
}
@Override
public boolean isModified() {
if (super.isModified()) {
return true;
}
if (innerSwf != null) {
return innerSwf.isModified();
}
return false;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.configuration.Configuration;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.types.BasicType;
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.helpers.ByteArrayRange;
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 java.util.Arrays;
/**
*
* @author JPEXS
*/
public class DefineBinaryDataTag extends CharacterTag {
@SWFType(BasicType.UI16)
public int tag;
public ByteArrayRange binaryData;
@Reserved
@SWFType(BasicType.UI32)
public long reserved;
public static final int ID = 87;
public static final String NAME = "DefineBinaryData";
@Internal
public SWF innerSwf;
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineBinaryDataTag(SWF swf) {
super(swf, ID, NAME, null);
tag = swf.getNextCharacterId();
binaryData = ByteArrayRange.EMPTY;
}
public DefineBinaryDataTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
tag = sis.readUI16("tag");
reserved = sis.readUI32("reserved");
binaryData = sis.readByteRangeEx(sis.available(), "binaryData");
if (Configuration.autoLoadEmbeddedSwfs.get()) {
try {
InputStream is = new ByteArrayInputStream(binaryData.getArray(), binaryData.getPos(), binaryData.getLength());
SWF bswf = new SWF(is, null, "(SWF Data)", Configuration.parallelSpeedUp.get());
innerSwf = bswf;
bswf.binaryData = this;
} catch (IOException | InterruptedException ex) {
// ignore
}
}
}
@Override
public int getCharacterId() {
return tag;
}
@Override
public void setCharacterId(int characterId) {
this.tag = characterId;
}
public boolean isSwfData() {
try {
if (binaryData.getLength() > 8) {
String signature = new String(binaryData.getRangeData(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)) {
return true;
}
}
} catch (Exception ex) {
}
return false;
}
@Override
public boolean isModified() {
if (super.isModified()) {
return true;
}
if (innerSwf != null) {
return innerSwf.isModified();
}
return false;
}
}

View File

@@ -1,142 +1,144 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag {
@SWFType(BasicType.UI16)
public int characterID;
@SWFType(BasicType.UI8)
public ByteArrayRange imageData;
public static final int ID = 21;
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = characterId;
}
@Override
public String getImageFormat() {
return ImageTag.getImageFormat(imageData);
}
@Override
public InputStream getImageData() {
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
try {
BufferedImage image = ImageHelper.read(getImageData());
if (image == null) {
Logger.getLogger(DefineBitsJPEG2Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage ret = new SerializableImage(image);
cachedImage = ret;
return ret;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG2Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
return null;
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsJPEG2Tag(SWF swf) {
super(swf, ID, "DefineBitsJPEG2", null);
characterID = swf.getNextCharacterId();
imageData = ByteArrayRange.EMPTY;
}
public DefineBitsJPEG2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBitsJPEG2", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
imageData = sis.readByteRangeEx(sis.available(), "imageData");
}
public DefineBitsJPEG2Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
super(swf, ID, "DefineBitsJPEG2", data);
this.characterID = characterID;
this.imageData = new ByteArrayRange(imageData);
}
@Override
public void setImage(byte[] data) {
imageData = new ByteArrayRange(data);
clearCache();
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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineBitsJPEG2Tag extends ImageTag implements AloneTag {
@SWFType(BasicType.UI16)
public int characterID;
@SWFType(BasicType.UI8)
public ByteArrayRange imageData;
public static final int ID = 21;
public static final String NAME = "DefineBitsJPEG2";
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = characterId;
}
@Override
public String getImageFormat() {
return ImageTag.getImageFormat(imageData);
}
@Override
public InputStream getImageData() {
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
try {
BufferedImage image = ImageHelper.read(getImageData());
if (image == null) {
Logger.getLogger(DefineBitsJPEG2Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage ret = new SerializableImage(image);
cachedImage = ret;
return ret;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG2Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
return null;
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsJPEG2Tag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
imageData = ByteArrayRange.EMPTY;
}
public DefineBitsJPEG2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
imageData = sis.readByteRangeEx(sis.available(), "imageData");
}
public DefineBitsJPEG2Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
super(swf, ID, NAME, data);
this.characterID = characterID;
this.imageData = new ByteArrayRange(imageData);
}
@Override
public void setImage(byte[] data) {
imageData = new ByteArrayRange(data);
clearCache();
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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
}

View File

@@ -1,175 +1,177 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
@SWFType(BasicType.UI16)
public int characterID;
@SWFType(BasicType.UI8)
public ByteArrayRange imageData;
@SWFType(BasicType.UI8)
public byte[] bitmapAlphaData;
public static final int ID = 35;
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = characterId;
}
@Override
public void setImage(byte[] data) throws IOException {
if (ImageTag.getImageFormat(data).equals("jpg")) {
SerializableImage image = new SerializableImage(ImageHelper.read(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 = new ByteArrayRange(data);
clearCache();
setModified(true);
}
@Override
public String getImageFormat() {
String fmt = ImageTag.getImageFormat(imageData);
if (fmt.equals("jpg")) {
fmt = "png"; //transparency
}
return fmt;
}
@Override
public InputStream getImageData() {
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
try {
BufferedImage image = ImageHelper.read(getImageData());
if (image == null) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage img = new SerializableImage(image);
if (bitmapAlphaData.length == 0) {
cachedImage = img;
return img;
}
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
int a = bitmapAlphaData[i] & 0xff;
pixels[i] = multiplyAlpha((pixels[i] & 0xffffff) | (a << 24));
}
cachedImage = img;
return img;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
return null;
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsJPEG3Tag(SWF swf) {
super(swf, ID, "DefineBitsJPEG3", null);
characterID = swf.getNextCharacterId();
imageData = ByteArrayRange.EMPTY;
bitmapAlphaData = new byte[0];
}
public DefineBitsJPEG3Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBitsJPEG3", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
long alphaDataOffset = sis.readUI32("alphaDataOffset");
imageData = sis.readByteRangeEx(alphaDataOffset, "imageData");
bitmapAlphaData = sis.readBytesZlib(sis.available(), "bitmapAlphaData");
}
/**
* 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.getLength());
sos.write(imageData);
sos.writeBytesZlib(bitmapAlphaData);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
@SWFType(BasicType.UI16)
public int characterID;
@SWFType(BasicType.UI8)
public ByteArrayRange imageData;
@SWFType(BasicType.UI8)
public byte[] bitmapAlphaData;
public static final int ID = 35;
public static final String NAME = "DefineBitsJPEG3";
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = characterId;
}
@Override
public void setImage(byte[] data) throws IOException {
if (ImageTag.getImageFormat(data).equals("jpg")) {
SerializableImage image = new SerializableImage(ImageHelper.read(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 = new ByteArrayRange(data);
clearCache();
setModified(true);
}
@Override
public String getImageFormat() {
String fmt = ImageTag.getImageFormat(imageData);
if (fmt.equals("jpg")) {
fmt = "png"; //transparency
}
return fmt;
}
@Override
public InputStream getImageData() {
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
try {
BufferedImage image = ImageHelper.read(getImageData());
if (image == null) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage img = new SerializableImage(image);
if (bitmapAlphaData.length == 0) {
cachedImage = img;
return img;
}
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
int a = bitmapAlphaData[i] & 0xff;
pixels[i] = multiplyAlpha((pixels[i] & 0xffffff) | (a << 24));
}
cachedImage = img;
return img;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
return null;
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsJPEG3Tag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
imageData = ByteArrayRange.EMPTY;
bitmapAlphaData = new byte[0];
}
public DefineBitsJPEG3Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
long alphaDataOffset = sis.readUI32("alphaDataOffset");
imageData = sis.readByteRangeEx(alphaDataOffset, "imageData");
bitmapAlphaData = sis.readBytesZlib(sis.available(), "bitmapAlphaData");
}
/**
* 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.getLength());
sos.write(imageData);
sos.writeBytesZlib(bitmapAlphaData);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
}

View File

@@ -1,186 +1,188 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @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 ByteArrayRange imageData;
@SWFType(BasicType.UI8)
public ByteArrayRange bitmapAlphaData;
public static final int ID = 90;
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = 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 = new ByteArrayRange(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 = new ByteArrayRange(ba);
} else {
bitmapAlphaData = ByteArrayRange.EMPTY;
}
clearCache();
setModified(true);
}
@Override
public InputStream getImageData() {
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
try {
BufferedImage image = ImageHelper.read(getImageData());
if (image == null) {
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage img = new SerializableImage(image);
if (bitmapAlphaData.getLength() == 0) {
cachedImage = img;
return img;
}
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
int a = bitmapAlphaData.get(i) & 0xff;
pixels[i] = multiplyAlpha((pixels[i] & 0xffffff) | (a << 24));
}
cachedImage = img;
return img;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to get image", 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.getLength());
sos.writeUI16(deblockParam);
sos.write(imageData);
sos.write(bitmapAlphaData);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsJPEG4Tag(SWF swf) {
super(swf, ID, "DefineBitsJPEG4", null);
characterID = swf.getNextCharacterId();
imageData = ByteArrayRange.EMPTY;
bitmapAlphaData = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineBitsJPEG4Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBitsJPEG4", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
long alphaDataOffset = sis.readUI32("alphaDataOffset");
deblockParam = sis.readUI16("deblockParam");
imageData = sis.readByteRangeEx(alphaDataOffset, "imageData");
bitmapAlphaData = sis.readByteRangeEx(sis.available(), "bitmapAlphaData");
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @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 ByteArrayRange imageData;
@SWFType(BasicType.UI8)
public ByteArrayRange bitmapAlphaData;
public static final int ID = 90;
public static final String NAME = "DefineBitsJPEG4";
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = 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 = new ByteArrayRange(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 = new ByteArrayRange(ba);
} else {
bitmapAlphaData = ByteArrayRange.EMPTY;
}
clearCache();
setModified(true);
}
@Override
public InputStream getImageData() {
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
try {
BufferedImage image = ImageHelper.read(getImageData());
if (image == null) {
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage img = new SerializableImage(image);
if (bitmapAlphaData.getLength() == 0) {
cachedImage = img;
return img;
}
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
int a = bitmapAlphaData.get(i) & 0xff;
pixels[i] = multiplyAlpha((pixels[i] & 0xffffff) | (a << 24));
}
cachedImage = img;
return img;
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to get image", 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.getLength());
sos.writeUI16(deblockParam);
sos.write(imageData);
sos.write(bitmapAlphaData);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsJPEG4Tag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
imageData = ByteArrayRange.EMPTY;
bitmapAlphaData = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineBitsJPEG4Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
long alphaDataOffset = sis.readUI32("alphaDataOffset");
deblockParam = sis.readUI16("deblockParam");
imageData = sis.readByteRangeEx(alphaDataOffset, "imageData");
bitmapAlphaData = sis.readByteRangeEx(sis.available(), "bitmapAlphaData");
}
}

View File

@@ -81,6 +81,8 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
public static final int ID = 36;
public static final String NAME = "DefineBitsLossless2";
@Override
public int getCharacterId() {
return characterID;
@@ -152,7 +154,7 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
* @param swf
*/
public DefineBitsLossless2Tag(SWF swf) {
super(swf, ID, "DefineBitsLossless2", null);
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
bitmapFormat = DefineBitsLossless2Tag.FORMAT_32BIT_ARGB;
bitmapWidth = 1;
@@ -161,7 +163,7 @@ public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
}
public DefineBitsLossless2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBitsLossless2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -83,6 +83,8 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
public static final int ID = 20;
public static final String NAME = "DefineBitsLossless";
private byte[] createEmptyImage() {
try {
BITMAPDATA bitmapData = new BITMAPDATA();
@@ -230,7 +232,7 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
* @param swf
*/
public DefineBitsLosslessTag(SWF swf) {
super(swf, ID, "DefineBitsLossless", null);
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
bitmapFormat = DefineBitsLosslessTag.FORMAT_24BIT_RGB;
bitmapWidth = 1;
@@ -239,7 +241,7 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
}
public DefineBitsLosslessTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBitsLossless", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,158 +1,160 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineBitsTag extends ImageTag implements TagChangedListener {
@SWFType(BasicType.UI16)
public int characterID;
@SWFType(BasicType.UI8)
public ByteArrayRange jpegData;
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;
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsTag(SWF swf) {
super(swf, ID, "DefineBits", null);
characterID = swf.getNextCharacterId();
jpegData = ByteArrayRange.EMPTY;
}
public DefineBitsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineBits", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
jpegData = sis.readByteRangeEx(sis.available(), "jpegData");
}
@Override
public InputStream getImageData() {
return null;
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
if (swf.getJtt() != null) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] jttdata = swf.getJtt().jpegData;
if (jttdata.length != 0) {
int jttErrorLength = hasErrorHeader(jttdata) ? 4 : 0;
baos.write(jttdata, jttErrorLength, jttdata.length - jttErrorLength - 2);
}
int errorLength = hasErrorHeader(jpegData) ? 4 : 0;
baos.write(jpegData.getArray(), jpegData.getPos() + errorLength, jpegData.getLength() - errorLength);
BufferedImage image = ImageHelper.read(baos.toByteArray());
if (image == null) {
Logger.getLogger(DefineBitsTag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage ret = new SerializableImage(image);
cachedImage = ret;
return ret;
} catch (IOException ex) {
Logger.getLogger(DefineBitsTag.class.getName()).log(Level.SEVERE, "Failed to get image", 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.write(jpegData);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = characterId;
}
@Override
public String getImageFormat() {
return "jpg";
}
@Override
public void handleEvent(Tag tag) {
clearCache();
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.ImageHelper;
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.ByteArrayRange;
import com.jpexs.helpers.SerializableImage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineBitsTag extends ImageTag implements TagChangedListener {
@SWFType(BasicType.UI16)
public int characterID;
@SWFType(BasicType.UI8)
public ByteArrayRange jpegData;
public static final int ID = 6;
public static final String NAME = "DefineBits";
@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;
}
/**
* Constructor
*
* @param swf
*/
public DefineBitsTag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
jpegData = ByteArrayRange.EMPTY;
}
public DefineBitsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
jpegData = sis.readByteRangeEx(sis.available(), "jpegData");
}
@Override
public InputStream getImageData() {
return null;
}
@Override
public SerializableImage getImage() {
if (cachedImage != null) {
return cachedImage;
}
if (swf.getJtt() != null) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] jttdata = swf.getJtt().jpegData;
if (jttdata.length != 0) {
int jttErrorLength = hasErrorHeader(jttdata) ? 4 : 0;
baos.write(jttdata, jttErrorLength, jttdata.length - jttErrorLength - 2);
}
int errorLength = hasErrorHeader(jpegData) ? 4 : 0;
baos.write(jpegData.getArray(), jpegData.getPos() + errorLength, jpegData.getLength() - errorLength);
BufferedImage image = ImageHelper.read(baos.toByteArray());
if (image == null) {
Logger.getLogger(DefineBitsTag.class.getName()).log(Level.SEVERE, "Failed to load image");
return null;
}
SerializableImage ret = new SerializableImage(image);
cachedImage = ret;
return ret;
} catch (IOException ex) {
Logger.getLogger(DefineBitsTag.class.getName()).log(Level.SEVERE, "Failed to get image", 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.write(jpegData);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = characterId;
}
@Override
public String getImageFormat() {
return "jpg";
}
@Override
public void handleEvent(Tag tag) {
clearCache();
}
}

View File

@@ -1,358 +1,360 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ASMSourceContainer;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.types.BUTTONCONDACTION;
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
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.Set;
/**
* Extends the capabilities of DefineButton by allowing any state transition to
* trigger actions
*
* @author JPEXS
*/
public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
/**
* ID for this character
*/
@SWFType(BasicType.UI16)
public int buttonId;
@Reserved
@SWFType(value = BasicType.UB, count = 7)
public int reserved;
/**
* Track as menu button
*/
public boolean trackAsMenu;
/**
* Characters that make up the button
*/
public List<BUTTONRECORD> characters;
/**
* Actions to execute at particular button events
*/
public List<BUTTONCONDACTION> actions = new ArrayList<>();
public static final int ID = 34;
private Timeline timeline;
private boolean isSingleFrameInitialized;
private boolean isSingleFrame;
private static final Cache<DefineButton2Tag, RECT> rectCache = Cache.getInstance(true, true, "rect_button2");
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = characterId;
}
@Override
public List<BUTTONRECORD> getRecords() {
return characters;
}
/**
* Constructor
*
* @param swf
*/
public DefineButton2Tag(SWF swf) {
super(swf, ID, "DefineButton2", null);
buttonId = swf.getNextCharacterId();
characters = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButton2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineButton2", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
reserved = (int) sis.readUB(7, "reserved");
trackAsMenu = sis.readUB(1, "trackAsMenu") == 1;
int actionOffset = sis.readUI16("actionOffset");
characters = sis.readBUTTONRECORDList(true, "characters");
if (actionOffset > 0) {
actions = sis.readBUTTONCONDACTIONList(swf, this, "actions");
}
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
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());
try {
sos.writeUI16(buttonId);
sos.writeUB(7, reserved);
sos.writeUB(1, trackAsMenu ? 1 : 0);
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
try (SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion())) {
sos2.writeBUTTONRECORDList(characters, true);
}
byte[] brdata = baos2.toByteArray();
if ((actions == null) || (actions.isEmpty())) {
sos.writeUI16(0);
} else {
sos.writeUI16(2 + brdata.length);
}
sos.write(brdata);
sos.writeBUTTONCONDACTIONList(actions);
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Returns all sub-items
*
* @return List of sub-items
*/
@Override
public List<BUTTONCONDACTION> getSubItems() {
return actions;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (BUTTONRECORD r : characters) {
needed.add(r.characterId);
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
BUTTONRECORD character = characters.get(i);
if (character.characterId == oldCharacterId) {
character.characterId = newCharacterId;
modified = true;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
if (characters.get(i).characterId == characterId) {
characters.remove(i);
modified = true;
i--;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
if (rectCache.contains(this)) {
return rectCache.get(this);
}
RECT rect = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
for (BUTTONRECORD r : characters) {
CharacterTag ch = swf.getCharacter(r.characterId);
if (ch instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) ch;
if (!added.contains(bt)) {
added.add(bt);
RECT r2 = bt.getRect(added);
added.remove(bt);
MATRIX mat = r.placeMatrix;
if (mat != null) {
r2 = mat.apply(r2);
}
rect.Xmin = Math.min(r2.Xmin, rect.Xmin);
rect.Ymin = Math.min(r2.Ymin, rect.Ymin);
rect.Xmax = Math.max(r2.Xmax, rect.Xmax);
rect.Ymax = Math.max(r2.Ymax, rect.Ymax);
}
}
}
rectCache.put(this, rect);
return rect;
}
public static void clearCache() {
rectCache.clear();
}
@Override
public boolean trackAsMenu() {
return trackAsMenu;
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
if (!isSingleFrameInitialized) {
initialiteIsSingleFrame();
}
return isSingleFrame;
}
private synchronized void initialiteIsSingleFrame() {
if (!isSingleFrameInitialized) {
isSingleFrame = getTimeline().isSingleFrame();
isSingleFrameInitialized = true;
}
}
@Override
public Timeline getTimeline() {
if (timeline != null) {
return timeline;
}
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
return timeline;
}
@Override
public void resetTimeline() {
if (timeline != null) {
timeline.reset(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
}
}
private void initTimeline(Timeline timeline) {
int maxDepth = 0;
Frame frameUp = new Frame(timeline, 0);
Frame frameDown = new Frame(timeline, 0);
Frame frameOver = new Frame(timeline, 0);
Frame frameHit = new Frame(timeline, 0);
for (BUTTONRECORD r : this.characters) {
DepthState layer = new DepthState(swf, null);
layer.colorTransForm = r.colorTransform;
layer.blendMode = r.blendMode;
layer.filters = r.filterList;
layer.matrix = r.placeMatrix;
layer.characterId = r.characterId;
if (r.placeDepth > maxDepth) {
maxDepth = r.placeDepth;
}
if (r.buttonStateUp) {
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false));
}
if (r.buttonStateDown) {
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false));
}
if (r.buttonStateOver) {
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false));
}
if (r.buttonStateHitTest) {
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false));
}
}
timeline.addFrame(frameUp);
if (frameOver.layers.isEmpty()) {
frameOver = frameUp;
}
timeline.addFrame(frameOver);
if (frameDown.layers.isEmpty()) {
frameDown = frameOver;
}
timeline.addFrame(frameDown);
if (frameHit.layers.isEmpty()) {
frameHit = frameUp;
}
timeline.addFrame(frameHit);
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ASMSourceContainer;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.types.BUTTONCONDACTION;
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
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.Set;
/**
* Extends the capabilities of DefineButton by allowing any state transition to
* trigger actions
*
* @author JPEXS
*/
public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
/**
* ID for this character
*/
@SWFType(BasicType.UI16)
public int buttonId;
@Reserved
@SWFType(value = BasicType.UB, count = 7)
public int reserved;
/**
* Track as menu button
*/
public boolean trackAsMenu;
/**
* Characters that make up the button
*/
public List<BUTTONRECORD> characters;
/**
* Actions to execute at particular button events
*/
public List<BUTTONCONDACTION> actions = new ArrayList<>();
public static final int ID = 34;
public static final String NAME = "DefineButton2";
private Timeline timeline;
private boolean isSingleFrameInitialized;
private boolean isSingleFrame;
private static final Cache<DefineButton2Tag, RECT> rectCache = Cache.getInstance(true, true, "rect_button2");
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = characterId;
}
@Override
public List<BUTTONRECORD> getRecords() {
return characters;
}
/**
* Constructor
*
* @param swf
*/
public DefineButton2Tag(SWF swf) {
super(swf, ID, NAME, null);
buttonId = swf.getNextCharacterId();
characters = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButton2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
reserved = (int) sis.readUB(7, "reserved");
trackAsMenu = sis.readUB(1, "trackAsMenu") == 1;
int actionOffset = sis.readUI16("actionOffset");
characters = sis.readBUTTONRECORDList(true, "characters");
if (actionOffset > 0) {
actions = sis.readBUTTONCONDACTIONList(swf, this, "actions");
}
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
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());
try {
sos.writeUI16(buttonId);
sos.writeUB(7, reserved);
sos.writeUB(1, trackAsMenu ? 1 : 0);
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
try (SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion())) {
sos2.writeBUTTONRECORDList(characters, true);
}
byte[] brdata = baos2.toByteArray();
if ((actions == null) || (actions.isEmpty())) {
sos.writeUI16(0);
} else {
sos.writeUI16(2 + brdata.length);
}
sos.write(brdata);
sos.writeBUTTONCONDACTIONList(actions);
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Returns all sub-items
*
* @return List of sub-items
*/
@Override
public List<BUTTONCONDACTION> getSubItems() {
return actions;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (BUTTONRECORD r : characters) {
needed.add(r.characterId);
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
BUTTONRECORD character = characters.get(i);
if (character.characterId == oldCharacterId) {
character.characterId = newCharacterId;
modified = true;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
if (characters.get(i).characterId == characterId) {
characters.remove(i);
modified = true;
i--;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
if (rectCache.contains(this)) {
return rectCache.get(this);
}
RECT rect = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
for (BUTTONRECORD r : characters) {
CharacterTag ch = swf.getCharacter(r.characterId);
if (ch instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) ch;
if (!added.contains(bt)) {
added.add(bt);
RECT r2 = bt.getRect(added);
added.remove(bt);
MATRIX mat = r.placeMatrix;
if (mat != null) {
r2 = mat.apply(r2);
}
rect.Xmin = Math.min(r2.Xmin, rect.Xmin);
rect.Ymin = Math.min(r2.Ymin, rect.Ymin);
rect.Xmax = Math.max(r2.Xmax, rect.Xmax);
rect.Ymax = Math.max(r2.Ymax, rect.Ymax);
}
}
}
rectCache.put(this, rect);
return rect;
}
public static void clearCache() {
rectCache.clear();
}
@Override
public boolean trackAsMenu() {
return trackAsMenu;
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
if (!isSingleFrameInitialized) {
initialiteIsSingleFrame();
}
return isSingleFrame;
}
private synchronized void initialiteIsSingleFrame() {
if (!isSingleFrameInitialized) {
isSingleFrame = getTimeline().isSingleFrame();
isSingleFrameInitialized = true;
}
}
@Override
public Timeline getTimeline() {
if (timeline != null) {
return timeline;
}
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
return timeline;
}
@Override
public void resetTimeline() {
if (timeline != null) {
timeline.reset(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
}
}
private void initTimeline(Timeline timeline) {
int maxDepth = 0;
Frame frameUp = new Frame(timeline, 0);
Frame frameDown = new Frame(timeline, 0);
Frame frameOver = new Frame(timeline, 0);
Frame frameHit = new Frame(timeline, 0);
for (BUTTONRECORD r : this.characters) {
DepthState layer = new DepthState(swf, null);
layer.colorTransForm = r.colorTransform;
layer.blendMode = r.blendMode;
layer.filters = r.filterList;
layer.matrix = r.placeMatrix;
layer.characterId = r.characterId;
if (r.placeDepth > maxDepth) {
maxDepth = r.placeDepth;
}
if (r.buttonStateUp) {
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false));
}
if (r.buttonStateDown) {
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false));
}
if (r.buttonStateOver) {
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false));
}
if (r.buttonStateHitTest) {
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false));
}
}
timeline.addFrame(frameUp);
if (frameOver.layers.isEmpty()) {
frameOver = frameUp;
}
timeline.addFrame(frameOver);
if (frameDown.layers.isEmpty()) {
frameDown = frameOver;
}
timeline.addFrame(frameDown);
if (frameHit.layers.isEmpty()) {
frameHit = frameUp;
}
timeline.addFrame(frameHit);
}
}

View File

@@ -1,100 +1,102 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.CXFORM;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineButtonCxformTag extends Tag implements CharacterIdTag {
@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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineButtonCxformTag(SWF swf) {
super(swf, ID, "DefineButtonCxform", null);
buttonColorTransform = new CXFORM();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButtonCxformTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineButtonCxform", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
buttonColorTransform = sis.readCXFORM("buttonColorTransform");
}
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.CXFORM;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineButtonCxformTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int buttonId;
public CXFORM buttonColorTransform;
public static final int ID = 23;
public static final String NAME = "DefineButtonCxform";
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineButtonCxformTag(SWF swf) {
super(swf, ID, NAME, null);
buttonColorTransform = new CXFORM();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButtonCxformTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
buttonColorTransform = sis.readCXFORM("buttonColorTransform");
}
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = characterId;
}
}

View File

@@ -1,147 +1,149 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineButtonSoundTag extends Tag implements 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;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = 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(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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineButtonSoundTag(SWF swf) {
super(swf, ID, "DefineButtonSound", null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButtonSoundTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineButtonSound", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
buttonSoundChar0 = sis.readUI16("buttonSoundChar0");
if (buttonSoundChar0 != 0) {
buttonSoundInfo0 = sis.readSOUNDINFO("buttonSoundInfo0");
}
buttonSoundChar1 = sis.readUI16("buttonSoundChar1");
if (buttonSoundChar1 != 0) {
buttonSoundInfo1 = sis.readSOUNDINFO("buttonSoundInfo1");
}
buttonSoundChar2 = sis.readUI16("buttonSoundChar2");
if (buttonSoundChar2 != 0) {
buttonSoundInfo2 = sis.readSOUNDINFO("buttonSoundInfo2");
}
buttonSoundChar3 = sis.readUI16("buttonSoundChar3");
if (buttonSoundChar3 != 0) {
buttonSoundInfo3 = sis.readSOUNDINFO("buttonSoundInfo3");
}
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineButtonSoundTag extends Tag implements 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;
public static final String NAME = "DefineButtonSound";
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = 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(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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineButtonSoundTag(SWF swf) {
super(swf, ID, NAME, null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButtonSoundTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
buttonSoundChar0 = sis.readUI16("buttonSoundChar0");
if (buttonSoundChar0 != 0) {
buttonSoundInfo0 = sis.readSOUNDINFO("buttonSoundInfo0");
}
buttonSoundChar1 = sis.readUI16("buttonSoundChar1");
if (buttonSoundChar1 != 0) {
buttonSoundInfo1 = sis.readSOUNDINFO("buttonSoundInfo1");
}
buttonSoundChar2 = sis.readUI16("buttonSoundChar2");
if (buttonSoundChar2 != 0) {
buttonSoundInfo2 = sis.readSOUNDINFO("buttonSoundInfo2");
}
buttonSoundChar3 = sis.readUI16("buttonSoundChar3");
if (buttonSoundChar3 != 0) {
buttonSoundInfo3 = sis.readSOUNDINFO("buttonSoundInfo3");
}
}
}

View File

@@ -1,449 +1,451 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.SWFOutputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
import com.jpexs.helpers.Helper;
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.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Defines a button character
*
* @author JPEXS
*/
public class DefineButtonTag extends ButtonTag implements ASMSource {
/**
* ID for this character
*/
@SWFType(BasicType.UI16)
public int buttonId;
/**
* Characters that make up the button
*/
public List<BUTTONRECORD> characters;
/**
* Actions to perform
*/
//public List<Action> actions;
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 7;
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = characterId;
}
private Timeline timeline;
private boolean isSingleFrameInitialized;
private boolean isSingleFrame;
private static final Cache<DefineButtonTag, RECT> rectCache = Cache.getInstance(true, true, "rect_button");
@Override
public List<BUTTONRECORD> getRecords() {
return characters;
}
/**
* Constructor
*
* @param swf
*/
public DefineButtonTag(SWF swf) {
super(swf, ID, "DefineButton", null);
buttonId = swf.getNextCharacterId();
characters = new ArrayList<>();
actionBytes = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButtonTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineButton", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
characters = sis.readBUTTONRECORDList(false, "characters");
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
if (Configuration.debugCopy.get()) {
os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData()));
}
SWFOutputStream sos = new SWFOutputStream(os, getVersion());
try {
sos.writeUI16(buttonId);
sos.writeBUTTONRECORDList(characters, false);
sos.write(getActionBytes());
//sos.write(Action.actionsToBytes(actions, true, version));
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Converts actions to ASM source
*
* @param exportMode PCode or hex?
* @param writer
* @param actions
* @return ASM source
* @throws java.lang.InterruptedException
*/
@Override
public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException {
if (actions == null) {
actions = getActions();
}
return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer);
}
/**
* Whether or not this object contains ASM source
*
* @return True when contains
*/
@Override
public boolean containsSource() {
return true;
}
/**
* Returns actions associated with this object
*
* @return List of actions
* @throws java.lang.InterruptedException
*/
@Override
public ActionList getActions() throws InterruptedException {
try {
int prevLength = actionBytes.getPos();
SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray());
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (Exception ex) {
Logger.getLogger(DefineButtonTag.class.getName()).log(Level.SEVERE, null, ex);
return new ActionList();
}
}
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
}
@Override
public byte[] getActionBytes() {
return actionBytes.getRangeData();
}
@Override
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setModified() {
setModified(true);
}
@Override
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) {
return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData());
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (BUTTONRECORD r : characters) {
needed.add(r.characterId);
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
BUTTONRECORD character = characters.get(i);
if (character.characterId == oldCharacterId) {
character.characterId = newCharacterId;
modified = true;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
if (characters.get(i).characterId == characterId) {
characters.remove(i);
modified = true;
i--;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
if (rectCache.contains(this)) {
return rectCache.get(this);
}
RECT rect = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
for (BUTTONRECORD r : characters) {
CharacterTag ch = swf.getCharacter(r.characterId);
if (ch instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) ch;
if (!added.contains(bt)) {
added.add(bt);
RECT r2 = bt.getRect(added);
added.remove(bt);
MATRIX mat = r.placeMatrix;
if (mat != null) {
r2 = mat.apply(r2);
}
rect.Xmin = Math.min(r2.Xmin, rect.Xmin);
rect.Ymin = Math.min(r2.Ymin, rect.Ymin);
rect.Xmax = Math.max(r2.Xmax, rect.Xmax);
rect.Ymax = Math.max(r2.Ymax, rect.Ymax);
}
}
}
rectCache.put(this, rect);
return rect;
}
public static void clearCache() {
rectCache.clear();
}
List<DisassemblyListener> listeners = new ArrayList<>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
@Override
public boolean trackAsMenu() {
return false;
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
if (!isSingleFrameInitialized) {
initialiteIsSingleFrame();
}
return isSingleFrame;
}
private synchronized void initialiteIsSingleFrame() {
if (!isSingleFrameInitialized) {
isSingleFrame = getTimeline().isSingleFrame();
isSingleFrameInitialized = true;
}
}
@Override
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
return writer;
}
@Override
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
return writer;
}
@Override
public int getPrefixLineCount() {
return 0;
}
@Override
public String removePrefixAndSuffix(String source) {
return source;
}
@Override
public Timeline getTimeline() {
if (timeline != null) {
return timeline;
}
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
return timeline;
}
@Override
public void resetTimeline() {
if (timeline != null) {
timeline.reset(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
}
}
private void initTimeline(Timeline timeline) {
ColorTransform clrTrans = null;
for (Tag t : swf.tags) {
if (t instanceof DefineButtonCxformTag) {
DefineButtonCxformTag cx = (DefineButtonCxformTag) t;
clrTrans = cx.buttonColorTransform;
}
}
int maxDepth = 0;
Frame frameUp = new Frame(timeline, 0);
Frame frameDown = new Frame(timeline, 0);
Frame frameOver = new Frame(timeline, 0);
Frame frameHit = new Frame(timeline, 0);
for (BUTTONRECORD r : this.characters) {
DepthState layer = new DepthState(swf, null);
layer.colorTransForm = clrTrans;
layer.blendMode = r.blendMode;
layer.filters = r.filterList;
layer.matrix = r.placeMatrix;
layer.characterId = r.characterId;
if (r.placeDepth > maxDepth) {
maxDepth = r.placeDepth;
}
if (r.buttonStateUp) {
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false));
}
if (r.buttonStateDown) {
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false));
}
if (r.buttonStateOver) {
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false));
}
if (r.buttonStateHitTest) {
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false));
}
}
timeline.addFrame(frameUp);
if (frameOver.layers.isEmpty()) {
frameOver = frameUp;
}
timeline.addFrame(frameOver);
if (frameDown.layers.isEmpty()) {
frameDown = frameOver;
}
timeline.addFrame(frameDown);
if (frameHit.layers.isEmpty()) {
frameHit = frameUp;
}
timeline.addFrame(frameHit);
}
@Override
public Tag getSourceTag() {
return this;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.SWFOutputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
import com.jpexs.helpers.Helper;
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.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Defines a button character
*
* @author JPEXS
*/
public class DefineButtonTag extends ButtonTag implements ASMSource {
/**
* ID for this character
*/
@SWFType(BasicType.UI16)
public int buttonId;
/**
* Characters that make up the button
*/
public List<BUTTONRECORD> characters;
/**
* Actions to perform
*/
//public List<Action> actions;
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 7;
public static final String NAME = "DefineButton";
@Override
public int getCharacterId() {
return buttonId;
}
@Override
public void setCharacterId(int characterId) {
this.buttonId = characterId;
}
private Timeline timeline;
private boolean isSingleFrameInitialized;
private boolean isSingleFrame;
private static final Cache<DefineButtonTag, RECT> rectCache = Cache.getInstance(true, true, "rect_button");
@Override
public List<BUTTONRECORD> getRecords() {
return characters;
}
/**
* Constructor
*
* @param swf
*/
public DefineButtonTag(SWF swf) {
super(swf, ID, NAME, null);
buttonId = swf.getNextCharacterId();
characters = new ArrayList<>();
actionBytes = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineButtonTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");
characters = sis.readBUTTONRECORDList(false, "characters");
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
if (Configuration.debugCopy.get()) {
os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData()));
}
SWFOutputStream sos = new SWFOutputStream(os, getVersion());
try {
sos.writeUI16(buttonId);
sos.writeBUTTONRECORDList(characters, false);
sos.write(getActionBytes());
//sos.write(Action.actionsToBytes(actions, true, version));
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Converts actions to ASM source
*
* @param exportMode PCode or hex?
* @param writer
* @param actions
* @return ASM source
* @throws java.lang.InterruptedException
*/
@Override
public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException {
if (actions == null) {
actions = getActions();
}
return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer);
}
/**
* Whether or not this object contains ASM source
*
* @return True when contains
*/
@Override
public boolean containsSource() {
return true;
}
/**
* Returns actions associated with this object
*
* @return List of actions
* @throws java.lang.InterruptedException
*/
@Override
public ActionList getActions() throws InterruptedException {
try {
int prevLength = actionBytes.getPos();
SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray());
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (Exception ex) {
Logger.getLogger(DefineButtonTag.class.getName()).log(Level.SEVERE, null, ex);
return new ActionList();
}
}
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
}
@Override
public byte[] getActionBytes() {
return actionBytes.getRangeData();
}
@Override
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setModified() {
setModified(true);
}
@Override
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) {
return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData());
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (BUTTONRECORD r : characters) {
needed.add(r.characterId);
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
BUTTONRECORD character = characters.get(i);
if (character.characterId == oldCharacterId) {
character.characterId = newCharacterId;
modified = true;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = false;
for (int i = 0; i < characters.size(); i++) {
if (characters.get(i).characterId == characterId) {
characters.remove(i);
modified = true;
i--;
}
}
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
if (rectCache.contains(this)) {
return rectCache.get(this);
}
RECT rect = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
for (BUTTONRECORD r : characters) {
CharacterTag ch = swf.getCharacter(r.characterId);
if (ch instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) ch;
if (!added.contains(bt)) {
added.add(bt);
RECT r2 = bt.getRect(added);
added.remove(bt);
MATRIX mat = r.placeMatrix;
if (mat != null) {
r2 = mat.apply(r2);
}
rect.Xmin = Math.min(r2.Xmin, rect.Xmin);
rect.Ymin = Math.min(r2.Ymin, rect.Ymin);
rect.Xmax = Math.max(r2.Xmax, rect.Xmax);
rect.Ymax = Math.max(r2.Ymax, rect.Ymax);
}
}
}
rectCache.put(this, rect);
return rect;
}
public static void clearCache() {
rectCache.clear();
}
List<DisassemblyListener> listeners = new ArrayList<>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
@Override
public boolean trackAsMenu() {
return false;
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
if (!isSingleFrameInitialized) {
initialiteIsSingleFrame();
}
return isSingleFrame;
}
private synchronized void initialiteIsSingleFrame() {
if (!isSingleFrameInitialized) {
isSingleFrame = getTimeline().isSingleFrame();
isSingleFrameInitialized = true;
}
}
@Override
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
return writer;
}
@Override
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
return writer;
}
@Override
public int getPrefixLineCount() {
return 0;
}
@Override
public String removePrefixAndSuffix(String source) {
return source;
}
@Override
public Timeline getTimeline() {
if (timeline != null) {
return timeline;
}
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
return timeline;
}
@Override
public void resetTimeline() {
if (timeline != null) {
timeline.reset(swf, this, new ArrayList<Tag>(), buttonId, getRect());
initTimeline(timeline);
}
}
private void initTimeline(Timeline timeline) {
ColorTransform clrTrans = null;
for (Tag t : swf.tags) {
if (t instanceof DefineButtonCxformTag) {
DefineButtonCxformTag cx = (DefineButtonCxformTag) t;
clrTrans = cx.buttonColorTransform;
}
}
int maxDepth = 0;
Frame frameUp = new Frame(timeline, 0);
Frame frameDown = new Frame(timeline, 0);
Frame frameOver = new Frame(timeline, 0);
Frame frameHit = new Frame(timeline, 0);
for (BUTTONRECORD r : this.characters) {
DepthState layer = new DepthState(swf, null);
layer.colorTransForm = clrTrans;
layer.blendMode = r.blendMode;
layer.filters = r.filterList;
layer.matrix = r.placeMatrix;
layer.characterId = r.characterId;
if (r.placeDepth > maxDepth) {
maxDepth = r.placeDepth;
}
if (r.buttonStateUp) {
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false));
}
if (r.buttonStateDown) {
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false));
}
if (r.buttonStateOver) {
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false));
}
if (r.buttonStateHitTest) {
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false));
}
}
timeline.addFrame(frameUp);
if (frameOver.layers.isEmpty()) {
frameOver = frameUp;
}
timeline.addFrame(frameOver);
if (frameDown.layers.isEmpty()) {
frameDown = frameOver;
}
timeline.addFrame(frameDown);
if (frameHit.layers.isEmpty()) {
frameHit = frameUp;
}
timeline.addFrame(frameHit);
}
@Override
public Tag getSourceTag() {
return this;
}
}

View File

@@ -1,117 +1,119 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
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;
}
@Override
public void setCharacterId(int characterId) {
this.fontID = characterId;
}
/**
* Constructor
*
* @param swf
*/
public DefineFont4Tag(SWF swf) {
super(swf, ID, "DefineFont4", null);
fontID = swf.getNextCharacterId();
fontName = "New font";
fontData = new byte[0];
}
public DefineFont4Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineFont4", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
reserved = (int) sis.readUB(5, "reserved");
fontFlagsHasFontData = sis.readUB(1, "fontFlagsHasFontData") == 1;
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
fontName = sis.readString("fontName");
fontData = sis.readBytesEx(sis.available(), "fontData");
}
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
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;
public static final String NAME = "DefineFont4";
@Override
public int getCharacterId() {
return fontID;
}
@Override
public void setCharacterId(int characterId) {
this.fontID = characterId;
}
/**
* Constructor
*
* @param swf
*/
public DefineFont4Tag(SWF swf) {
super(swf, ID, NAME, null);
fontID = swf.getNextCharacterId();
fontName = "New font";
fontData = new byte[0];
}
public DefineFont4Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
reserved = (int) sis.readUB(5, "reserved");
fontFlagsHasFontData = sis.readUB(1, "fontFlagsHasFontData") == 1;
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
fontName = sis.readString("fontName");
fontData = sis.readBytesEx(sis.available(), "fontData");
}
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
}

View File

@@ -1,115 +1,117 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class DefineFontAlignZonesTag extends Tag implements CharacterIdTag {
@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<ZONERECORD> zoneTable;
public static final int ID = 73;
/**
* Constructor
*
* @param swf
*/
public DefineFontAlignZonesTag(SWF swf) {
super(swf, ID, "DefineFontAlignZones", null);
zoneTable = new ArrayList<>();
}
public DefineFontAlignZonesTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineFontAlignZones", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
CSMTableHint = (int) sis.readUB(2, "CSMTableHint");
reserved = (int) sis.readUB(6, "reserved");
zoneTable = new ArrayList<>();
while (sis.available() > 0) {
ZONERECORD zr = sis.readZONERECORD("record");
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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return fontID;
}
@Override
public void setCharacterId(int characterId) {
this.fontID = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class DefineFontAlignZonesTag extends Tag implements CharacterIdTag {
@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<ZONERECORD> zoneTable;
public static final int ID = 73;
public static final String NAME = "DefineFontAlignZones";
/**
* Constructor
*
* @param swf
*/
public DefineFontAlignZonesTag(SWF swf) {
super(swf, ID, NAME, null);
zoneTable = new ArrayList<>();
}
public DefineFontAlignZonesTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
CSMTableHint = (int) sis.readUB(2, "CSMTableHint");
reserved = (int) sis.readUB(6, "reserved");
zoneTable = new ArrayList<>();
while (sis.available() > 0) {
ZONERECORD zr = sis.readZONERECORD("record");
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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return fontID;
}
@Override
public void setCharacterId(int characterId) {
this.fontID = characterId;
}
}

View File

@@ -1,158 +1,160 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.LANGCODE;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
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 implements CharacterIdTag {
@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<Integer> 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineFontInfo2Tag(SWF swf) {
super(swf, ID, "DefineFontInfo2", null);
fontName = "New Font Info Name";
languageCode = new LANGCODE();
codeTable = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineFontInfo2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineFontInfo2", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
}
reserved = (int) sis.readUB(2, "reserved");
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1;
fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1;
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; //Always 1
languageCode = sis.readLANGCODE("languageCode");
int ctLen = sis.available() / 2;
codeTable = new ArrayList<>();
for (int i = 0; i < ctLen; i++) {
codeTable.add(sis.readUI16("code"));
}
}
@Override
public int getCharacterId() {
return fontID;
}
@Override
public void setCharacterId(int characterId) {
this.fontID = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.LANGCODE;
import com.jpexs.decompiler.flash.types.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
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 implements CharacterIdTag {
@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<Integer> codeTable;
public static final int ID = 62;
public static final String NAME = "DefineFontInfo2";
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineFontInfo2Tag(SWF swf) {
super(swf, ID, NAME, null);
fontName = "New Font Info Name";
languageCode = new LANGCODE();
codeTable = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineFontInfo2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
}
reserved = (int) sis.readUB(2, "reserved");
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1;
fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1;
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1; //Always 1
languageCode = sis.readLANGCODE("languageCode");
int ctLen = sis.available() / 2;
codeTable = new ArrayList<>();
for (int i = 0; i < ctLen; i++) {
codeTable.add(sis.readUI16("code"));
}
}
@Override
public int getCharacterId() {
return fontID;
}
@Override
public void setCharacterId(int characterId) {
this.fontID = characterId;
}
}

View File

@@ -1,159 +1,161 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
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 implements CharacterIdTag {
@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<Integer> 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineFontInfoTag(SWF swf) {
super(swf, ID, "DefineFontInfo", null);
fontName = "New Font Info Name";
codeTable = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineFontInfoTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineFontInfo", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
}
reserved = (int) sis.readUB(2, "reserved");
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1;
fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1;
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1;
codeTable = new ArrayList<>();
while (sis.available() > 0) {
if (fontFlagsWideCodes) {
codeTable.add(sis.readUI16("code"));
} else {
codeTable.add(sis.readUI8("code"));
}
}
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.Reserved;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
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 implements CharacterIdTag {
@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<Integer> codeTable;
public static final int ID = 13;
public static final String NAME = "DefineFontInfo";
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineFontInfoTag(SWF swf) {
super(swf, ID, NAME, null);
fontName = "New Font Info Name";
codeTable = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineFontInfoTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
}
reserved = (int) sis.readUB(2, "reserved");
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1;
fontFlagsANSI = sis.readUB(1, "fontFlagsANSI") == 1;
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
fontFlagsWideCodes = sis.readUB(1, "fontFlagsWideCodes") == 1;
codeTable = new ArrayList<>();
while (sis.available() > 0) {
if (fontFlagsWideCodes) {
codeTable.add(sis.readUI16("code"));
} else {
codeTable.add(sis.readUI8("code"));
}
}
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
}

View File

@@ -1,97 +1,99 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineFontNameTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int fontId;
public String fontName;
public String fontCopyright;
public static final int ID = 88;
/**
* Constructor
*
* @param swf
*/
public DefineFontNameTag(SWF swf) {
super(swf, ID, "DefineFontName", null);
fontName = "New Font Name";
fontCopyright = "Copyright text";
}
public DefineFontNameTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineFontName", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
fontName = sis.readString("fontName");
fontCopyright = sis.readString("fontCopyright");
}
/**
* 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.writeString(fontName);
sos.writeString(fontCopyright);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineFontNameTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int fontId;
public String fontName;
public String fontCopyright;
public static final int ID = 88;
public static final String NAME = "DefineFontName";
/**
* Constructor
*
* @param swf
*/
public DefineFontNameTag(SWF swf) {
super(swf, ID, NAME, null);
fontName = "New Font Name";
fontCopyright = "Copyright text";
}
public DefineFontNameTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
fontName = sis.readString("fontName");
fontCopyright = sis.readString("fontCopyright");
}
/**
* 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.writeString(fontName);
sos.writeString(fontCopyright);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
}

View File

@@ -1,368 +1,370 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.awt.Font;
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<SHAPE> 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<Integer> 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineFontTag(SWF swf) {
super(swf, ID, "DefineFont", null);
fontId = swf.getNextCharacterId();
glyphShapeTable = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineFontTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineFont", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
glyphShapeTable = new ArrayList<>();
if (sis.available() > 0) {
long pos = sis.getPos();
int firstOffset = sis.readUI16("firstOffset");
int nGlyphs = firstOffset / 2;
long[] offsetTable = new long[nGlyphs];
offsetTable[0] = firstOffset;
for (int i = 1; i < nGlyphs; i++) {
offsetTable[i] = sis.readUI16("offset");
}
for (int i = 0; i < nGlyphs; i++) {
sis.seek(pos + offsetTable[i]);
glyphShapeTable.add(sis.readSHAPE(1, false, "shape"));
}
}
}
@Override
public int getFontId() {
return fontId;
}
@Override
public List<SHAPE> getGlyphShapeTable() {
return glyphShapeTable;
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
@Override
public String getFontNameIntag() {
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 double getDivider() {
return 1;
}
@Override
public void addCharacter(char character, Font font) {
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character);
List<Integer> 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);
}
setModified(true);
}
@Override
public void setAdvanceValues(Font font) {
throw new UnsupportedOperationException("Setting the advance values for DefineFontTag is not supported.");
}
@Override
public String getCharacters(List<Tag> tags) {
StringBuilder ret = new StringBuilder();
ensureFontInfo();
if (fontInfoTag != null) {
for (int i : fontInfoTag.codeTable) {
ret.append((char) i);
}
}
if (fontInfo2Tag != null) {
for (int i : fontInfo2Tag.codeTable) {
ret.append((char) i);
}
}
return ret.toString();
}
@Override
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
return 0;
}
@Override
public int getCharKerningAdjustment(char c1, char c2) {
return 0;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.awt.Font;
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<SHAPE> glyphShapeTable;
@Internal
private DefineFontInfoTag fontInfoTag = null;
@Internal
private DefineFontInfo2Tag fontInfo2Tag = null;
public static final int ID = 10;
public static final String NAME = "DefineFont";
@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<Integer> 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineFontTag(SWF swf) {
super(swf, ID, NAME, null);
fontId = swf.getNextCharacterId();
glyphShapeTable = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineFontTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
glyphShapeTable = new ArrayList<>();
if (sis.available() > 0) {
long pos = sis.getPos();
int firstOffset = sis.readUI16("firstOffset");
int nGlyphs = firstOffset / 2;
long[] offsetTable = new long[nGlyphs];
offsetTable[0] = firstOffset;
for (int i = 1; i < nGlyphs; i++) {
offsetTable[i] = sis.readUI16("offset");
}
for (int i = 0; i < nGlyphs; i++) {
sis.seek(pos + offsetTable[i]);
glyphShapeTable.add(sis.readSHAPE(1, false, "shape"));
}
}
}
@Override
public int getFontId() {
return fontId;
}
@Override
public List<SHAPE> getGlyphShapeTable() {
return glyphShapeTable;
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
@Override
public String getFontNameIntag() {
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 double getDivider() {
return 1;
}
@Override
public void addCharacter(char character, Font font) {
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character);
List<Integer> 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);
}
setModified(true);
}
@Override
public void setAdvanceValues(Font font) {
throw new UnsupportedOperationException("Setting the advance values for DefineFontTag is not supported.");
}
@Override
public String getCharacters(List<Tag> tags) {
StringBuilder ret = new StringBuilder();
ensureFontInfo();
if (fontInfoTag != null) {
for (int i : fontInfoTag.codeTable) {
ret.append((char) i);
}
}
if (fontInfo2Tag != null) {
for (int i : fontInfo2Tag.codeTable) {
ret.append((char) i);
}
}
return ret.toString();
}
@Override
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
return 0;
}
@Override
public int getCharKerningAdjustment(char c1, char c2) {
return 0;
}
}

View File

@@ -54,6 +54,8 @@ public class DefineMorphShape2Tag extends MorphShapeTag {
public static final int ID = 84;
public static final String NAME = "DefineMorphShape2";
/**
* Gets data bytes
*
@@ -94,7 +96,7 @@ public class DefineMorphShape2Tag extends MorphShapeTag {
* @param swf
*/
public DefineMorphShape2Tag(SWF swf) {
super(swf, ID, "DefineMorphShape2", null);
super(swf, ID, NAME, null);
characterId = swf.getNextCharacterId();
startBounds = new RECT();
endBounds = new RECT();
@@ -116,7 +118,7 @@ public class DefineMorphShape2Tag extends MorphShapeTag {
* @throws IOException
*/
public DefineMorphShape2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineMorphShape2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -39,6 +39,8 @@ public class DefineMorphShapeTag extends MorphShapeTag {
public static final int ID = 46;
public static final String NAME = "DefineMorphShape";
/**
* Gets data bytes
*
@@ -74,7 +76,7 @@ public class DefineMorphShapeTag extends MorphShapeTag {
* @param swf
*/
public DefineMorphShapeTag(SWF swf) {
super(swf, ID, "DefineMorphShape", null);
super(swf, ID, NAME, null);
characterId = swf.getNextCharacterId();
startBounds = new RECT();
endBounds = new RECT();
@@ -94,7 +96,7 @@ public class DefineMorphShapeTag extends MorphShapeTag {
* @throws IOException
*/
public DefineMorphShapeTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineMorphShape", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,93 +1,95 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.RECT;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineScalingGridTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int characterId;
public RECT splitter;
public static final int ID = 78;
/**
* Constructor
*
* @param swf
*/
public DefineScalingGridTag(SWF swf) {
super(swf, ID, "DefineScalingGrid", null);
splitter = new RECT();
}
public DefineScalingGridTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineScalingGrid", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterId = sis.readUI16("characterId");
splitter = sis.readRECT("splitter");
}
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return characterId;
}
@Override
public void setCharacterId(int characterId) {
this.characterId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.RECT;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author JPEXS
*/
public class DefineScalingGridTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int characterId;
public RECT splitter;
public static final int ID = 78;
public static final String NAME = "DefineScalingGrid";
/**
* Constructor
*
* @param swf
*/
public DefineScalingGridTag(SWF swf) {
super(swf, ID, NAME, null);
splitter = new RECT();
}
public DefineScalingGridTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterId = sis.readUI16("characterId");
splitter = sis.readRECT("splitter");
}
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getCharacterId() {
return characterId;
}
@Override
public void setCharacterId(int characterId) {
this.characterId = characterId;
}
}

View File

@@ -49,6 +49,8 @@ public class DefineSceneAndFrameLabelDataTag extends Tag {
public static final int ID = 86;
public static final String NAME = "DefineSceneAndFrameLabelData";
/**
* Gets data bytes
*
@@ -84,7 +86,7 @@ public class DefineSceneAndFrameLabelDataTag extends Tag {
* @param swf
*/
public DefineSceneAndFrameLabelDataTag(SWF swf) {
super(swf, ID, "DefineSceneAndFrameLabelData", null);
super(swf, ID, NAME, null);
sceneOffsets = new long[0];
sceneNames = new String[0];
frameNums = new long[0];
@@ -99,7 +101,7 @@ public class DefineSceneAndFrameLabelDataTag extends Tag {
* @throws IOException
*/
public DefineSceneAndFrameLabelDataTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineSceneAndFrameLabelData", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,158 +1,160 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ShapeTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShape2Tag extends ShapeTag {
public static final int ID = 22;
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 2;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShape2Tag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShape2Tag(SWF swf) {
super(swf, ID, "DefineShape2", null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(2);
}
public DefineShape2Tag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, "DefineShape2", data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), sis.available());
}
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, getVersion());
try {
sos.writeUI16(shapeId);
sos.writeRECT(shapeBounds);
sos.writeSHAPEWITHSTYLE(getShapes(), getShapeNum());
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ShapeTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShape2Tag extends ShapeTag {
public static final int ID = 22;
public static final String NAME = "DefineShape2";
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 2;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShape2Tag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShape2Tag(SWF swf) {
super(swf, ID, NAME, null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(2);
}
public DefineShape2Tag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), sis.available());
}
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, getVersion());
try {
sos.writeUI16(shapeId);
sos.writeRECT(shapeBounds);
sos.writeSHAPEWITHSTYLE(getShapes(), getShapeNum());
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}

View File

@@ -1,160 +1,162 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ShapeTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShape3Tag extends ShapeTag {
public static final int ID = 32;
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 3;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(3, false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShape3Tag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShape3Tag(SWF swf) {
super(swf, ID, "DefineShape3", null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(3);
}
public DefineShape3Tag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, "DefineShape3", data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(3, false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), 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(shapeId);
sos.writeRECT(shapeBounds);
sos.writeSHAPEWITHSTYLE(getShapes(), 3);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ShapeTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShape3Tag extends ShapeTag {
public static final int ID = 32;
public static final String NAME = "DefineShape3";
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 3;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(3, false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShape3Tag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShape3Tag(SWF swf) {
super(swf, ID, NAME, null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(3);
}
public DefineShape3Tag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(3, false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), 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(shapeId);
sos.writeRECT(shapeBounds);
sos.writeSHAPEWITHSTYLE(getShapes(), 3);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}

View File

@@ -1,186 +1,188 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShape4Tag extends ShapeTag {
public RECT edgeBounds;
@Reserved
@SWFType(value = BasicType.UB, count = 5)
public int reserved;
public boolean usesFillWindingRule;
public boolean usesNonScalingStrokes;
public boolean usesScalingStrokes;
public static final int ID = 83;
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 4;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(4, false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShape4Tag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShape4Tag(SWF swf) {
super(swf, ID, "DefineShape4", null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
edgeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(4);
}
public DefineShape4Tag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, "DefineShape4", data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
edgeBounds = sis.readRECT("edgeBounds");
reserved = (int) sis.readUB(5, "reserved");
usesFillWindingRule = sis.readUB(1, "usesFillWindingRule") == 1;
usesNonScalingStrokes = sis.readUB(1, "usesNonScalingStrokes") == 1;
usesScalingStrokes = sis.readUB(1, "usesScalingStrokes") == 1;
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(4, false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), 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(shapeId);
sos.writeRECT(shapeBounds);
sos.writeRECT(edgeBounds);
sos.writeUB(5, reserved);
sos.writeUB(1, usesFillWindingRule ? 1 : 0);
sos.writeUB(1, usesNonScalingStrokes ? 1 : 0);
sos.writeUB(1, usesScalingStrokes ? 1 : 0);
sos.writeSHAPEWITHSTYLE(getShapes(), 4);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShape4Tag extends ShapeTag {
public RECT edgeBounds;
@Reserved
@SWFType(value = BasicType.UB, count = 5)
public int reserved;
public boolean usesFillWindingRule;
public boolean usesNonScalingStrokes;
public boolean usesScalingStrokes;
public static final int ID = 83;
public static final String NAME = "DefineShape4";
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 4;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(4, false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShape4Tag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShape4Tag(SWF swf) {
super(swf, ID, NAME, null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
edgeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(4);
}
public DefineShape4Tag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
edgeBounds = sis.readRECT("edgeBounds");
reserved = (int) sis.readUB(5, "reserved");
usesFillWindingRule = sis.readUB(1, "usesFillWindingRule") == 1;
usesNonScalingStrokes = sis.readUB(1, "usesNonScalingStrokes") == 1;
usesScalingStrokes = sis.readUB(1, "usesScalingStrokes") == 1;
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(4, false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), 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(shapeId);
sos.writeRECT(shapeBounds);
sos.writeRECT(edgeBounds);
sos.writeUB(5, reserved);
sos.writeUB(1, usesFillWindingRule ? 1 : 0);
sos.writeUB(1, usesNonScalingStrokes ? 1 : 0);
sos.writeUB(1, usesScalingStrokes ? 1 : 0);
sos.writeSHAPEWITHSTYLE(getShapes(), 4);
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}

View File

@@ -1,158 +1,160 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ShapeTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShapeTag extends ShapeTag {
public static final int ID = 2;
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 1;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShapeTag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShapeTag(SWF swf) {
super(swf, ID, "DefineShape", null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(1);
}
public DefineShapeTag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, "DefineShape", data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), sis.available());
}
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, getVersion());
try {
sos.writeUI16(shapeId);
sos.writeRECT(shapeBounds);
sos.writeSHAPEWITHSTYLE(getShapes(), getShapeNum());
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ShapeTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class DefineShapeTag extends ShapeTag {
public static final int ID = 2;
public static final String NAME = "DefineShape";
private ByteArrayRange shapeData;
@Override
public int getShapeNum() {
return 1;
}
@Override
public SHAPEWITHSTYLE getShapes() {
if (shapes == null && shapeData != null) {
try {
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
sis.seek(shapeData.getPos());
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
shapeData = null; // not needed anymore, give it to GC
} catch (IOException ex) {
Logger.getLogger(DefineShapeTag.class.getName()).log(Level.SEVERE, null, ex);
}
}
return shapes;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
getShapes().getNeededCharacters(needed);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getShapes().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getShapes().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return shapeBounds;
}
/**
* Constructor
*
* @param swf
*/
public DefineShapeTag(SWF swf) {
super(swf, ID, NAME, null);
shapeId = swf.getNextCharacterId();
shapeBounds = new RECT();
shapes = SHAPEWITHSTYLE.createEmpty(1);
}
public DefineShapeTag(SWFInputStream sis, ByteArrayRange data, boolean lazy) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, lazy);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
shapeId = sis.readUI16("shapeId");
shapeBounds = sis.readRECT("shapeBounds");
if (!lazy) {
shapes = sis.readSHAPEWITHSTYLE(getShapeNum(), false, "shapes");
} else {
shapeData = new ByteArrayRange(data.getArray(), (int) sis.getPos(), sis.available());
}
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, getVersion());
try {
sos.writeUI16(shapeId);
sos.writeRECT(shapeBounds);
sos.writeSHAPEWITHSTYLE(getShapes(), getShapeNum());
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
@Override
public int getNumFrames() {
return 1;
}
@Override
public boolean isSingleFrame() {
return true;
}
@Override
public int getCharacterId() {
return shapeId;
}
@Override
public void setCharacterId(int characterId) {
this.shapeId = characterId;
}
}

View File

@@ -1,362 +1,364 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ByteArrayRange;
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.ArrayList;
import java.util.Arrays;
import java.util.List;
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 ByteArrayRange soundData;
public static final int ID = 14;
@Override
public int getCharacterId() {
return soundId;
}
@Override
public void setCharacterId(int characterId) {
this.soundId = 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(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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineSoundTag(SWF swf) {
super(swf, ID, "DefineSound", null);
soundId = swf.getNextCharacterId();
soundData = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineSoundTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineSound", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
soundId = sis.readUI16("soundId");
soundFormat = (int) sis.readUB(4, "soundFormat");
soundRate = (int) sis.readUB(2, "soundRate");
soundSize = sis.readUB(1, "soundSize") == 1;
soundType = sis.readUB(1, "soundType") == 1;
soundSampleCount = sis.readUI32("soundSampleCount");
soundData = sis.readByteRangeEx(sis.available(), "soundData");
}
@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 SWFInputStream(swf, 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 = new ByteArrayRange(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 List<byte[]> getRawSoundData() {
List<byte[]> ret = new ArrayList<>();
if (soundFormat == SoundFormat.FORMAT_MP3) {
ret.add(soundData.getRangeData(2, soundData.getLength() - 2));
return ret;
}
ret.add(soundData.getRangeData());
return ret;
}
@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-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ByteArrayRange;
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.ArrayList;
import java.util.Arrays;
import java.util.List;
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 ByteArrayRange soundData;
public static final int ID = 14;
public static final String NAME = "DefineSound";
@Override
public int getCharacterId() {
return soundId;
}
@Override
public void setCharacterId(int characterId) {
this.soundId = 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(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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineSoundTag(SWF swf) {
super(swf, ID, NAME, null);
soundId = swf.getNextCharacterId();
soundData = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineSoundTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
soundId = sis.readUI16("soundId");
soundFormat = (int) sis.readUB(4, "soundFormat");
soundRate = (int) sis.readUB(2, "soundRate");
soundSize = sis.readUB(1, "soundSize") == 1;
soundType = sis.readUB(1, "soundType") == 1;
soundSampleCount = sis.readUI32("soundSampleCount");
soundData = sis.readByteRangeEx(sis.available(), "soundData");
}
@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 SWFInputStream(swf, 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 = new ByteArrayRange(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 List<byte[]> getRawSoundData() {
List<byte[]> ret = new ArrayList<>();
if (soundFormat == SoundFormat.FORMAT_MP3) {
ret.add(soundData.getRangeData(2, soundData.getLength() - 2));
return ret;
}
ret.add(soundData.getRangeData());
return ret;
}
@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());
}
}

View File

@@ -1,394 +1,396 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.RenderContext;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
import com.jpexs.helpers.SerializableImage;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
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.HashSet;
import java.util.List;
import java.util.Set;
/**
* Defines a sprite character
*
* @author JPEXS
*/
public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timelined {
/**
* Character ID of sprite
*/
@SWFType(BasicType.UI16)
public int spriteId;
/**
* Number of frames in sprite
*/
@SWFType(BasicType.UI16)
public int frameCount;
/**
* A series of tags
*/
public List<Tag> subTags;
public boolean hasEndTag;
public static final int ID = 39;
private Timeline timeline;
private boolean isSingleFrameInitialized;
private boolean isSingleFrame;
private static final Cache<DefineSpriteTag, RECT> rectCache = Cache.getInstance(true, true, "rect_sprite");
@Override
public Timeline getTimeline() {
if (timeline == null) {
timeline = new Timeline(swf, this, subTags, spriteId, getRect());
}
return timeline;
}
@Override
public void resetTimeline() {
if (timeline != null) {
timeline.reset(swf, this, subTags, spriteId, getRect());
}
}
@Override
public int getCharacterId() {
return spriteId;
}
@Override
public void setCharacterId(int characterId) {
this.spriteId = characterId;
}
private RECT getCharacterBounds(Set<Integer> characters, Set<BoundedTag> added) {
RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
boolean foundSomething = false;
for (int c : characters) {
Tag t = swf.getCharacter(c);
RECT r = null;
if (t instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) t;
if (!added.contains(bt)) {
added.add(bt);
r = bt.getRect(added);
added.remove(bt);
}
}
if (r != null) {
foundSomething = true;
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
ret.Ymax = Math.max(r.Ymax, ret.Ymax);
}
}
if (!foundSomething) {
return new RECT();
}
return ret;
}
@Override
public RECT getRect() {
return getRect(new HashSet<>());
}
@Override
public RECT getRect(Set<BoundedTag> added) {
if (rectCache.contains(this)) {
return rectCache.get(this);
}
RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
HashMap<Integer, Integer> depthMap = new HashMap<>();
boolean foundSomething = false;
for (Tag t : subTags) {
MATRIX m = null;
int characterId = -1;
if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag pot = (PlaceObjectTypeTag) t;
m = pot.getMatrix();
int charId = pot.getCharacterId();
if (charId > -1) {
depthMap.put(pot.getDepth(), charId);
characterId = charId;
} else {
Integer chi = depthMap.get(pot.getDepth());
if (chi != null) {
characterId = chi;
}
}
}
if (characterId == -1) {
continue;
}
Set<Integer> need = new HashSet<>();
need.add(characterId);
RECT r = getCharacterBounds(need, added);
if (m != null) {
AffineTransform trans = SWF.matrixToTransform(m);
java.awt.Point topleft = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmin, r.Ymin), topleft);
java.awt.Point topright = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmax, r.Ymin), topright);
java.awt.Point bottomright = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmax, r.Ymax), bottomright);
java.awt.Point bottomleft = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmin, r.Ymax), bottomleft);
r.Xmin = (int) Math.min(Math.min(Math.min(topleft.x, topright.x), bottomleft.x), bottomright.x);
r.Ymin = (int) Math.min(Math.min(Math.min(topleft.y, topright.y), bottomleft.y), bottomright.y);
r.Xmax = (int) Math.max(Math.max(Math.max(topleft.x, topright.x), bottomleft.x), bottomright.x);
r.Ymax = (int) Math.max(Math.max(Math.max(topleft.y, topright.y), bottomleft.y), bottomright.y);
}
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
ret.Ymax = Math.max(r.Ymax, ret.Ymax);
foundSomething = true;
}
if (!foundSomething) {
ret = new RECT();
}
rectCache.put(this, ret);
return ret;
}
/**
* Constructor
*
* @param swf
*/
public DefineSpriteTag(SWF swf) {
super(swf, ID, "DefineSprite", null);
spriteId = swf.getNextCharacterId();
subTags = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @param level
* @param parallel
* @param skipUnusualTags
* @throws IOException
* @throws java.lang.InterruptedException
*/
public DefineSpriteTag(SWFInputStream sis, int level, ByteArrayRange data, boolean parallel, boolean skipUnusualTags) throws IOException, InterruptedException {
super(sis.getSwf(), ID, "DefineSprite", data);
readData(sis, data, level, parallel, skipUnusualTags, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException, InterruptedException {
spriteId = sis.readUI16("spriteId");
frameCount = sis.readUI16("frameCount");
List<Tag> subTags = sis.readTagList(this, level + 1, parallel, skipUnusualTags, true, lazy);
if (subTags.size() > 0 && subTags.get(subTags.size() - 1).getId() == EndTag.ID) {
hasEndTag = true;
subTags.remove(subTags.size() - 1);
}
this.subTags = subTags;
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
if (Configuration.debugCopy.get()) {
os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData()));
}
SWFOutputStream sos = new SWFOutputStream(os, getVersion());
try {
sos.writeUI16(spriteId);
sos.writeUI16(frameCount);
sos.writeTags(subTags);
if (hasEndTag) {
sos.writeUI16(0);
}
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
public List<Tag> getSubTags() {
return subTags;
}
@Override
public void setModified(boolean value) {
if (!value) {
for (Tag subTag : subTags) {
subTag.setModified(false);
}
}
super.setModified(value);
}
@Override
public void createOriginalData() {
super.createOriginalData();
for (Tag subTag : subTags) {
subTag.createOriginalData();
}
}
public static void clearCache() {
rectCache.clear();
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (Tag t : subTags) {
if (t instanceof CharacterIdTag) {
needed.add(((CharacterIdTag) t).getCharacterId());
}
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getTimeline().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getTimeline().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public int getUsedParameters() {
return PARAMETER_FRAME | PARAMETER_TIME | PARAMETER_RATIO; // inner tags can contain morphshapes, too
}
@Override
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation) {
return getTimeline().getOutline(frame, time, ratio, renderContext, transformation);
}
@Override
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
SWF.frameToImage(getTimeline(), frame, time, renderContext, image, transformation, colorTransform);
}
@Override
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
SWF.frameToSvg(getTimeline(), 0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
}
@Override
public String toHtmlCanvas(double unitDivisor) {
return getTimeline().toHtmlCanvas(unitDivisor, null);
}
@Override
public int getNumFrames() {
// flashplayer ignores the count stored in frameCount
return getTimeline().getFrameCount(); // frameCount
}
@Override
public boolean isSingleFrame() {
if (!isSingleFrameInitialized) {
initialiteIsSingleFrame();
}
return isSingleFrame;
}
private synchronized void initialiteIsSingleFrame() {
if (!isSingleFrameInitialized) {
if (getTimeline().getRealFrameCount() > 1) {
isSingleFrameInitialized = true;
return;
}
isSingleFrame = getTimeline().isSingleFrame();
isSingleFrameInitialized = true;
}
}
@Override
public boolean isModified() {
if (super.isModified()) {
return true;
}
for (Tag t : subTags) {
if (t.isModified()) {
return true;
}
}
return false;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.RenderContext;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Cache;
import com.jpexs.helpers.SerializableImage;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
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.HashSet;
import java.util.List;
import java.util.Set;
/**
* Defines a sprite character
*
* @author JPEXS
*/
public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timelined {
/**
* Character ID of sprite
*/
@SWFType(BasicType.UI16)
public int spriteId;
/**
* Number of frames in sprite
*/
@SWFType(BasicType.UI16)
public int frameCount;
/**
* A series of tags
*/
public List<Tag> subTags;
public boolean hasEndTag;
public static final int ID = 39;
public static final String NAME = "DefineSprite";
private Timeline timeline;
private boolean isSingleFrameInitialized;
private boolean isSingleFrame;
private static final Cache<DefineSpriteTag, RECT> rectCache = Cache.getInstance(true, true, "rect_sprite");
@Override
public Timeline getTimeline() {
if (timeline == null) {
timeline = new Timeline(swf, this, subTags, spriteId, getRect());
}
return timeline;
}
@Override
public void resetTimeline() {
if (timeline != null) {
timeline.reset(swf, this, subTags, spriteId, getRect());
}
}
@Override
public int getCharacterId() {
return spriteId;
}
@Override
public void setCharacterId(int characterId) {
this.spriteId = characterId;
}
private RECT getCharacterBounds(Set<Integer> characters, Set<BoundedTag> added) {
RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
boolean foundSomething = false;
for (int c : characters) {
Tag t = swf.getCharacter(c);
RECT r = null;
if (t instanceof BoundedTag) {
BoundedTag bt = (BoundedTag) t;
if (!added.contains(bt)) {
added.add(bt);
r = bt.getRect(added);
added.remove(bt);
}
}
if (r != null) {
foundSomething = true;
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
ret.Ymax = Math.max(r.Ymax, ret.Ymax);
}
}
if (!foundSomething) {
return new RECT();
}
return ret;
}
@Override
public RECT getRect() {
return getRect(new HashSet<>());
}
@Override
public RECT getRect(Set<BoundedTag> added) {
if (rectCache.contains(this)) {
return rectCache.get(this);
}
RECT ret = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
HashMap<Integer, Integer> depthMap = new HashMap<>();
boolean foundSomething = false;
for (Tag t : subTags) {
MATRIX m = null;
int characterId = -1;
if (t instanceof PlaceObjectTypeTag) {
PlaceObjectTypeTag pot = (PlaceObjectTypeTag) t;
m = pot.getMatrix();
int charId = pot.getCharacterId();
if (charId > -1) {
depthMap.put(pot.getDepth(), charId);
characterId = charId;
} else {
Integer chi = depthMap.get(pot.getDepth());
if (chi != null) {
characterId = chi;
}
}
}
if (characterId == -1) {
continue;
}
Set<Integer> need = new HashSet<>();
need.add(characterId);
RECT r = getCharacterBounds(need, added);
if (m != null) {
AffineTransform trans = SWF.matrixToTransform(m);
java.awt.Point topleft = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmin, r.Ymin), topleft);
java.awt.Point topright = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmax, r.Ymin), topright);
java.awt.Point bottomright = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmax, r.Ymax), bottomright);
java.awt.Point bottomleft = new java.awt.Point();
trans.transform(new java.awt.Point(r.Xmin, r.Ymax), bottomleft);
r.Xmin = (int) Math.min(Math.min(Math.min(topleft.x, topright.x), bottomleft.x), bottomright.x);
r.Ymin = (int) Math.min(Math.min(Math.min(topleft.y, topright.y), bottomleft.y), bottomright.y);
r.Xmax = (int) Math.max(Math.max(Math.max(topleft.x, topright.x), bottomleft.x), bottomright.x);
r.Ymax = (int) Math.max(Math.max(Math.max(topleft.y, topright.y), bottomleft.y), bottomright.y);
}
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
ret.Ymax = Math.max(r.Ymax, ret.Ymax);
foundSomething = true;
}
if (!foundSomething) {
ret = new RECT();
}
rectCache.put(this, ret);
return ret;
}
/**
* Constructor
*
* @param swf
*/
public DefineSpriteTag(SWF swf) {
super(swf, ID, NAME, null);
spriteId = swf.getNextCharacterId();
subTags = new ArrayList<>();
}
/**
* Constructor
*
* @param sis
* @param data
* @param level
* @param parallel
* @param skipUnusualTags
* @throws IOException
* @throws java.lang.InterruptedException
*/
public DefineSpriteTag(SWFInputStream sis, int level, ByteArrayRange data, boolean parallel, boolean skipUnusualTags) throws IOException, InterruptedException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, level, parallel, skipUnusualTags, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException, InterruptedException {
spriteId = sis.readUI16("spriteId");
frameCount = sis.readUI16("frameCount");
List<Tag> subTags = sis.readTagList(this, level + 1, parallel, skipUnusualTags, true, lazy);
if (subTags.size() > 0 && subTags.get(subTags.size() - 1).getId() == EndTag.ID) {
hasEndTag = true;
subTags.remove(subTags.size() - 1);
}
this.subTags = subTags;
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
if (Configuration.debugCopy.get()) {
os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData()));
}
SWFOutputStream sos = new SWFOutputStream(os, getVersion());
try {
sos.writeUI16(spriteId);
sos.writeUI16(frameCount);
sos.writeTags(subTags);
if (hasEndTag) {
sos.writeUI16(0);
}
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
public List<Tag> getSubTags() {
return subTags;
}
@Override
public void setModified(boolean value) {
if (!value) {
for (Tag subTag : subTags) {
subTag.setModified(false);
}
}
super.setModified(value);
}
@Override
public void createOriginalData() {
super.createOriginalData();
for (Tag subTag : subTags) {
subTag.createOriginalData();
}
}
public static void clearCache() {
rectCache.clear();
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (Tag t : subTags) {
if (t instanceof CharacterIdTag) {
needed.add(((CharacterIdTag) t).getCharacterId());
}
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
boolean modified = getTimeline().replaceCharacter(oldCharacterId, newCharacterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public boolean removeCharacter(int characterId) {
boolean modified = getTimeline().removeCharacter(characterId);
if (modified) {
setModified(true);
}
return modified;
}
@Override
public int getUsedParameters() {
return PARAMETER_FRAME | PARAMETER_TIME | PARAMETER_RATIO; // inner tags can contain morphshapes, too
}
@Override
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation) {
return getTimeline().getOutline(frame, time, ratio, renderContext, transformation);
}
@Override
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
SWF.frameToImage(getTimeline(), frame, time, renderContext, image, transformation, colorTransform);
}
@Override
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
SWF.frameToSvg(getTimeline(), 0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
}
@Override
public String toHtmlCanvas(double unitDivisor) {
return getTimeline().toHtmlCanvas(unitDivisor, null);
}
@Override
public int getNumFrames() {
// flashplayer ignores the count stored in frameCount
return getTimeline().getFrameCount(); // frameCount
}
@Override
public boolean isSingleFrame() {
if (!isSingleFrameInitialized) {
initialiteIsSingleFrame();
}
return isSingleFrame;
}
private synchronized void initialiteIsSingleFrame() {
if (!isSingleFrameInitialized) {
if (getTimeline().getRealFrameCount() > 1) {
isSingleFrameInitialized = true;
return;
}
isSingleFrame = getTimeline().isSingleFrame();
isSingleFrameInitialized = true;
}
}
@Override
public boolean isModified() {
if (super.isModified()) {
return true;
}
for (Tag t : subTags) {
if (t.isModified()) {
return true;
}
}
return false;
}
}

View File

@@ -1,67 +1,69 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.StaticTextTag;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.helpers.ByteArrayRange;
import java.io.IOException;
import java.util.ArrayList;
/**
*
* @author JPEXS
*/
public class DefineText2Tag extends StaticTextTag {
public static final int ID = 33;
/**
* Constructor
*
* @param swf
*/
public DefineText2Tag(SWF swf) {
super(swf, ID, "DefineText2", null);
characterID = swf.getNextCharacterId();
textBounds = new RECT();
textMatrix = new MATRIX();
textRecords = new ArrayList<>();
glyphBits = 0;
advanceBits = 0;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineText2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineText2", data);
readData(sis, data, 0, false, false, false);
}
@Override
public int getTextNum() {
return 2;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.StaticTextTag;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.helpers.ByteArrayRange;
import java.io.IOException;
import java.util.ArrayList;
/**
*
* @author JPEXS
*/
public class DefineText2Tag extends StaticTextTag {
public static final int ID = 33;
public static final String NAME = "DefineText2";
/**
* Constructor
*
* @param swf
*/
public DefineText2Tag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
textBounds = new RECT();
textMatrix = new MATRIX();
textRecords = new ArrayList<>();
glyphBits = 0;
advanceBits = 0;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineText2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public int getTextNum() {
return 2;
}
}

View File

@@ -1,79 +1,81 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.StaticTextTag;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import com.jpexs.helpers.ByteArrayRange;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class DefineTextTag extends StaticTextTag {
public static final int ID = 11;
/**
* Constructor
*
* @param swf
*/
public DefineTextTag(SWF swf) {
super(swf, ID, "DefineText", null);
characterID = swf.getNextCharacterId();
textBounds = new RECT();
textMatrix = new MATRIX();
textRecords = new ArrayList<>();
glyphBits = 0;
advanceBits = 0;
}
public DefineTextTag(SWF swf, int characterID, RECT textBounds, MATRIX textMatrix, List<TEXTRECORD> textRecords) {
super(swf, ID, "DefineText", null);
this.characterID = characterID;
this.textBounds = textBounds;
this.textMatrix = textMatrix;
this.textRecords = textRecords;
this.glyphBits = 0;
this.advanceBits = 0;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineTextTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineText", data);
readData(sis, data, 0, false, false, false);
}
@Override
public int getTextNum() {
return 1;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.StaticTextTag;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import com.jpexs.helpers.ByteArrayRange;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class DefineTextTag extends StaticTextTag {
public static final int ID = 11;
public static final String NAME = "DefineText";
/**
* Constructor
*
* @param swf
*/
public DefineTextTag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
textBounds = new RECT();
textMatrix = new MATRIX();
textRecords = new ArrayList<>();
glyphBits = 0;
advanceBits = 0;
}
public DefineTextTag(SWF swf, int characterID, RECT textBounds, MATRIX textMatrix, List<TEXTRECORD> textRecords) {
super(swf, ID, NAME, null);
this.characterID = characterID;
this.textBounds = textBounds;
this.textMatrix = textMatrix;
this.textRecords = textRecords;
this.glyphBits = 0;
this.advanceBits = 0;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineTextTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public int getTextNum() {
return 1;
}
}

View File

@@ -1,152 +1,154 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
/**
*
* @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;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineVideoStreamTag(SWF swf) {
super(swf, ID, "DefineVideoStream", null);
characterID = swf.getNextCharacterId();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineVideoStreamTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineVideoStream", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
numFrames = sis.readUI16("numFrames");
width = sis.readUI16("width");
height = sis.readUI16("height");
reserved = (int) sis.readUB(4, "reserved");
videoFlagsDeblocking = (int) sis.readUB(3, "videoFlagsDeblocking");
videoFlagsSmoothing = sis.readUB(1, "videoFlagsSmoothing") == 1;
codecID = sis.readUI8("codecID");
}
@Override
public RECT getRect() {
return getRect(null); // parameter not used
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return new RECT(0, (int) (SWF.unitDivisor * width), 0, (int) (SWF.unitDivisor * height));
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
/**
*
* @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;
public static final String NAME = "DefineVideoStream";
@Override
public int getCharacterId() {
return characterID;
}
@Override
public void setCharacterId(int characterId) {
this.characterID = 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineVideoStreamTag(SWF swf) {
super(swf, ID, NAME, null);
characterID = swf.getNextCharacterId();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineVideoStreamTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterID = sis.readUI16("characterID");
numFrames = sis.readUI16("numFrames");
width = sis.readUI16("width");
height = sis.readUI16("height");
reserved = (int) sis.readUB(4, "reserved");
videoFlagsDeblocking = (int) sis.readUB(3, "videoFlagsDeblocking");
videoFlagsSmoothing = sis.readUB(1, "videoFlagsSmoothing") == 1;
codecID = sis.readUI8("codecID");
}
@Override
public RECT getRect() {
return getRect(null); // parameter not used
}
@Override
public RECT getRect(Set<BoundedTag> added) {
return new RECT(0, (int) (SWF.unitDivisor * width), 0, (int) (SWF.unitDivisor * height));
}
}

View File

@@ -1,156 +1,158 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ABCInputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFField;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
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
*
* @author JPEXS
*/
public class DoABCDefineTag extends Tag implements ABCContainerTag {
/**
* ActionScript 3 bytecodes
*/
@HideInRawEdit
@SWFField
private 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 ABC getABC() {
return abc;
}
@Override
public String getName() {
return "DoABCDefine (" + name + ")";
}
/**
* Constructor
*
* @param swf
*/
public DoABCDefineTag(SWF swf) {
super(swf, ID, "DoABCDefine", null);
name = "New DoABC";
abc = new ABC(this);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DoABCDefineTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DoABCDefine", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
flags = sis.readUI32("flags");
name = sis.readString("name");
ABCInputStream ais = new ABCInputStream(sis.getBaseStream());
// put it to the dumpview:
sis.readByteRangeEx(sis.available(), "abcBytes");
abc = new ABC(ais, 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) {
throw new Error("This should never happen.", e);
}
}
@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;
}
@Override
public void setModified(boolean value) {
super.setModified(value);
if (value == false && !isModified()) {
ABC abc = getABC();
for (ScriptInfo si : abc.script_info) {
si.setModified(false);
}
}
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ABCInputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFField;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
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
*
* @author JPEXS
*/
public class DoABCDefineTag extends Tag implements ABCContainerTag {
/**
* ActionScript 3 bytecodes
*/
@HideInRawEdit
@SWFField
private 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;
public static final String NAME = "DoABCDefine";
@Override
public ABC getABC() {
return abc;
}
@Override
public String getName() {
return super.getName() + " (" + name + ")";
}
/**
* Constructor
*
* @param swf
*/
public DoABCDefineTag(SWF swf) {
super(swf, ID, NAME, null);
name = "New DoABC";
abc = new ABC(this);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DoABCDefineTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
flags = sis.readUI32("flags");
name = sis.readString("name");
ABCInputStream ais = new ABCInputStream(sis.getBaseStream());
// put it to the dumpview:
sis.readByteRangeEx(sis.available(), "abcBytes");
abc = new ABC(ais, 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) {
throw new Error("This should never happen.", e);
}
}
@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;
}
@Override
public void setModified(boolean value) {
super.setModified(value);
if (value == false && !isModified()) {
ABC abc = getABC();
for (ScriptInfo si : abc.script_info) {
si.setModified(false);
}
}
}
}

View File

@@ -1,128 +1,125 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ABCInputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFField;
import com.jpexs.helpers.ByteArrayRange;
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
*
* @author JPEXS
*/
public class DoABCTag extends Tag implements ABCContainerTag {
/**
* ActionScript 3 bytecodes
*/
@HideInRawEdit
@SWFField
private ABC abc;
public static final int ID = 72;
@Override
public ABC getABC() {
return abc;
}
@Override
public String getName() {
return "DoABC";
}
/**
* Constructor
*
* @param swf
*/
public DoABCTag(SWF swf) {
super(swf, ID, "DoABC", null);
abc = new ABC(this);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DoABCTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DoABC", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
ABCInputStream ais = new ABCInputStream(sis.getBaseStream());
// put it to the dumpview:
sis.readByteRangeEx(sis.available(), "abcBytes");
abc = new ABC(ais, 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) {
throw new Error("This should never happen.", e);
}
}
@Override
public int compareTo(ABCContainerTag o) {
return 0;
}
@Override
public void setModified(boolean value) {
super.setModified(value);
if (value == false && !isModified()) {
ABC abc = getABC();
for (ScriptInfo si : abc.script_info) {
si.setModified(false);
}
}
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ABCInputStream;
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFField;
import com.jpexs.helpers.ByteArrayRange;
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
*
* @author JPEXS
*/
public class DoABCTag extends Tag implements ABCContainerTag {
/**
* ActionScript 3 bytecodes
*/
@HideInRawEdit
@SWFField
private ABC abc;
public static final int ID = 72;
public static final String NAME = "DoABC";
@Override
public ABC getABC() {
return abc;
}
/**
* Constructor
*
* @param swf
*/
public DoABCTag(SWF swf) {
super(swf, ID, NAME, null);
abc = new ABC(this);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DoABCTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
ABCInputStream ais = new ABCInputStream(sis.getBaseStream());
// put it to the dumpview:
sis.readByteRangeEx(sis.available(), "abcBytes");
abc = new ABC(ais, 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) {
throw new Error("This should never happen.", e);
}
}
@Override
public int compareTo(ABCContainerTag o) {
return 0;
}
@Override
public void setModified(boolean value) {
super.setModified(value);
if (value == false && !isModified()) {
ABC abc = getABC();
for (ScriptInfo si : abc.script_info) {
si.setModified(false);
}
}
}
}

View File

@@ -1,210 +1,212 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Instructs Flash Player to perform a list of actions when the current frame is
* complete.
*
* @author JPEXS
*/
public class DoActionTag extends Tag implements ASMSource {
/**
* List of actions to perform
*/
//public List<Action> actions = new ArrayList<Action>();
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 12;
/**
* Constructor
*
* @param swf
*/
public DoActionTag(SWF swf) {
super(swf, ID, "DoAction", null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws java.io.IOException
*/
public DoActionTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DoAction", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");
}
/**
* Constructor
*
* @param swf
* @param data
*/
public DoActionTag(SWF swf, ByteArrayRange data) {
super(swf, ID, "DoAction", data);
actionBytes = ByteArrayRange.EMPTY;
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
return getActionBytes();
}
/**
* Converts actions to ASM source
*
* @param exportMode PCode or hex?
* @param writer
* @param actions
* @return ASM source
* @throws java.lang.InterruptedException
*/
@Override
public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException {
if (actions == null) {
actions = getActions();
}
return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer);
}
/**
* Whether or not this object contains ASM source
*
* @return True when contains
*/
@Override
public boolean containsSource() {
return true;
}
@Override
public ActionList getActions() throws InterruptedException {
try {
int prevLength = actionBytes.getPos();
SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray());
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (Exception ex) {
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ActionList();
}
}
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
}
@Override
public byte[] getActionBytes() {
return actionBytes.getRangeData();
}
@Override
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setModified() {
setModified(true);
}
@Override
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) {
return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData());
}
List<DisassemblyListener> listeners = new ArrayList<>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
@Override
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
return writer;
}
@Override
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
return writer;
}
@Override
public int getPrefixLineCount() {
return 0;
}
@Override
public String removePrefixAndSuffix(String source) {
return source;
}
@Override
public Tag getSourceTag() {
return this;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Instructs Flash Player to perform a list of actions when the current frame is
* complete.
*
* @author JPEXS
*/
public class DoActionTag extends Tag implements ASMSource {
/**
* List of actions to perform
*/
//public List<Action> actions = new ArrayList<Action>();
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 12;
public static final String NAME = "DoAction";
/**
* Constructor
*
* @param swf
*/
public DoActionTag(SWF swf) {
super(swf, ID, NAME, null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws java.io.IOException
*/
public DoActionTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");
}
/**
* Constructor
*
* @param swf
* @param data
*/
public DoActionTag(SWF swf, ByteArrayRange data) {
super(swf, ID, NAME, data);
actionBytes = ByteArrayRange.EMPTY;
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
return getActionBytes();
}
/**
* Converts actions to ASM source
*
* @param exportMode PCode or hex?
* @param writer
* @param actions
* @return ASM source
* @throws java.lang.InterruptedException
*/
@Override
public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException {
if (actions == null) {
actions = getActions();
}
return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer);
}
/**
* Whether or not this object contains ASM source
*
* @return True when contains
*/
@Override
public boolean containsSource() {
return true;
}
@Override
public ActionList getActions() throws InterruptedException {
try {
int prevLength = actionBytes.getPos();
SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray());
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (Exception ex) {
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ActionList();
}
}
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
}
@Override
public byte[] getActionBytes() {
return actionBytes.getRangeData();
}
@Override
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setModified() {
setModified(true);
}
@Override
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) {
return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData());
}
List<DisassemblyListener> listeners = new ArrayList<>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
@Override
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
return writer;
}
@Override
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
return writer;
}
@Override
public int getPrefixLineCount() {
return 0;
}
@Override
public String removePrefixAndSuffix(String source) {
return source;
}
@Override
public Tag getSourceTag() {
return this;
}
}

View File

@@ -1,258 +1,260 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
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;
/**
*
* @author JPEXS
*/
public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
/**
* Identifier of Sprite
*/
@SWFType(BasicType.UI16)
public int spriteId = 0;
/**
* List of actions to perform
*/
//public List<Action> actions = new ArrayList<Action>();
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 59;
/**
* Constructor
*
* @param swf
*/
public DoInitActionTag(SWF swf) {
super(swf, ID, "DoInitAction", null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DoInitActionTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DoInitAction", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
spriteId = sis.readUI16("spriteId");
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, getVersion());
try {
sos.writeUI16(spriteId);
sos.write(getActionBytes());
//sos.write(Action.actionsToBytes(actions, true, version));
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Whether or not this object contains ASM source
*
* @return True when contains
*/
@Override
public boolean containsSource() {
return true;
}
/**
* Converts actions to ASM source
*
* @param exportMode PCode or hex?
* @param writer
* @param actions
* @return ASM source
* @throws java.lang.InterruptedException
*/
@Override
public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException {
if (actions == null) {
actions = getActions();
}
return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer);
}
@Override
public ActionList getActions() throws InterruptedException {
try {
int prevLength = actionBytes.getPos();
SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray());
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (Exception ex) {
Logger.getLogger(DoInitActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ActionList();
}
}
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
}
@Override
public byte[] getActionBytes() {
return actionBytes.getRangeData();
}
@Override
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setModified() {
setModified(true);
}
@Override
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) {
return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData());
}
@Override
public int getCharacterId() {
return spriteId;
}
@Override
public void setCharacterId(int characterId) {
this.spriteId = characterId;
}
List<DisassemblyListener> listeners = new ArrayList<>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
@Override
public String getExportFileName() {
String expName = swf.getExportName(spriteId);
if ((expName == null) || expName.isEmpty()) {
return super.getExportFileName();
}
String[] pathParts;
if (expName.contains(".")) {
pathParts = expName.split("\\.");
} else {
pathParts = new String[]{expName};
}
return pathParts[pathParts.length - 1];
}
@Override
public String getName() {
String expName = swf == null ? "" : swf.getExportName(spriteId);
if ((expName == null) || expName.isEmpty()) {
return super.getName();
}
String[] pathParts;
if (expName.contains(".")) {
pathParts = expName.split("\\.");
} else {
pathParts = new String[]{expName};
}
return pathParts[pathParts.length - 1];
}
@Override
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
return writer;
}
@Override
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
return writer;
}
@Override
public int getPrefixLineCount() {
return 0;
}
@Override
public String removePrefixAndSuffix(String source) {
return source;
}
@Override
public Tag getSourceTag() {
return this;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionListReader;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
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;
/**
*
* @author JPEXS
*/
public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
/**
* Identifier of Sprite
*/
@SWFType(BasicType.UI16)
public int spriteId = 0;
/**
* List of actions to perform
*/
//public List<Action> actions = new ArrayList<Action>();
@HideInRawEdit
public ByteArrayRange actionBytes;
public static final int ID = 59;
public static final String NAME = "DoInitAction";
/**
* Constructor
*
* @param swf
*/
public DoInitActionTag(SWF swf) {
super(swf, ID, NAME, null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DoInitActionTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
spriteId = sis.readUI16("spriteId");
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, getVersion());
try {
sos.writeUI16(spriteId);
sos.write(getActionBytes());
//sos.write(Action.actionsToBytes(actions, true, version));
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Whether or not this object contains ASM source
*
* @return True when contains
*/
@Override
public boolean containsSource() {
return true;
}
/**
* Converts actions to ASM source
*
* @param exportMode PCode or hex?
* @param writer
* @param actions
* @return ASM source
* @throws java.lang.InterruptedException
*/
@Override
public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException {
if (actions == null) {
actions = getActions();
}
return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer);
}
@Override
public ActionList getActions() throws InterruptedException {
try {
int prevLength = actionBytes.getPos();
SWFInputStream rri = new SWFInputStream(swf, actionBytes.getArray());
if (prevLength != 0) {
rri.seek(prevLength);
}
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.getLength(), toString()/*FIXME?*/);
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (Exception ex) {
Logger.getLogger(DoInitActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ActionList();
}
}
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
}
@Override
public byte[] getActionBytes() {
return actionBytes.getRangeData();
}
@Override
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setModified() {
setModified(true);
}
@Override
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) {
return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData());
}
@Override
public int getCharacterId() {
return spriteId;
}
@Override
public void setCharacterId(int characterId) {
this.spriteId = characterId;
}
List<DisassemblyListener> listeners = new ArrayList<>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
@Override
public String getExportFileName() {
String expName = swf.getExportName(spriteId);
if ((expName == null) || expName.isEmpty()) {
return super.getExportFileName();
}
String[] pathParts;
if (expName.contains(".")) {
pathParts = expName.split("\\.");
} else {
pathParts = new String[]{expName};
}
return pathParts[pathParts.length - 1];
}
@Override
public String getName() {
String expName = swf == null ? "" : swf.getExportName(spriteId);
if ((expName == null) || expName.isEmpty()) {
return super.getName();
}
String[] pathParts;
if (expName.contains(".")) {
pathParts = expName.split("\\.");
} else {
pathParts = new String[]{expName};
}
return pathParts[pathParts.length - 1];
}
@Override
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
return writer;
}
@Override
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
return writer;
}
@Override
public int getPrefixLineCount() {
return 0;
}
@Override
public String removePrefixAndSuffix(String source) {
return source;
}
@Override
public Tag getSourceTag() {
return this;
}
}

View File

@@ -45,6 +45,8 @@ public class EnableDebugger2Tag extends Tag {
public static final int ID = 64;
public static final String NAME = "EnableDebugger2";
/**
* Gets data bytes
*
@@ -71,7 +73,7 @@ public class EnableDebugger2Tag extends Tag {
* @param swf
*/
public EnableDebugger2Tag(SWF swf) {
super(swf, ID, "EnableDebugger2", null);
super(swf, ID, NAME, null);
passwordHash = "PasswordHash";
}
@@ -83,7 +85,7 @@ public class EnableDebugger2Tag extends Tag {
* @throws IOException
*/
public EnableDebugger2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "EnableDebugger2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -38,6 +38,8 @@ public class EnableDebuggerTag extends Tag {
public static final int ID = 58;
public static final String NAME = "EnableDebugger";
/**
* Gets data bytes
*
@@ -64,7 +66,7 @@ public class EnableDebuggerTag extends Tag {
* @param swf
*/
public EnableDebuggerTag(SWF swf) {
super(swf, ID, "EnableDebugger", null);
super(swf, ID, NAME, null);
passwordHash = "PasswordHash";
}
@@ -76,7 +78,7 @@ public class EnableDebuggerTag extends Tag {
* @throws IOException
*/
public EnableDebuggerTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "EnableDebugger", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -37,6 +37,8 @@ public class EnableTelemetryTag extends Tag {
public static final int ID = 93;
public static final String NAME = "EnableTelemetry";
@SWFType(value = BasicType.UB, count = 16)
@Reserved
public int reserved;
@@ -72,7 +74,7 @@ public class EnableTelemetryTag extends Tag {
* @param swf
*/
public EnableTelemetryTag(SWF swf) {
super(swf, ID, "EnableTelemetry", null);
super(swf, ID, NAME, null);
passwordHash = new byte[32];
}
@@ -84,7 +86,7 @@ public class EnableTelemetryTag extends Tag {
* @throws IOException
*/
public EnableTelemetryTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -40,13 +40,15 @@ public class EndTag extends Tag {
public static final int ID = 0;
public static final String NAME = "End";
/**
* Constructor
*
* @param swf
*/
public EndTag(SWF swf) {
super(swf, ID, "End", null);
super(swf, ID, NAME, null);
}
/**
@@ -57,7 +59,7 @@ public class EndTag extends Tag {
* @throws IOException
*/
public EndTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "End", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -49,13 +49,15 @@ public class ExportAssetsTag extends SymbolClassTypeTag {
public static final int ID = 56;
public static final String NAME = "ExportAssets";
/**
* Constructor
*
* @param swf
*/
public ExportAssetsTag(SWF swf) {
super(swf, ID, "ExportAssets", null);
super(swf, ID, NAME, null);
tags = new ArrayList<>();
names = new ArrayList<>();
}
@@ -68,7 +70,7 @@ public class ExportAssetsTag extends SymbolClassTypeTag {
* @throws IOException
*/
public ExportAssetsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "ExportAssets", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -53,17 +53,19 @@ public class FileAttributesTag extends Tag {
public static final int ID = 69;
public static final String NAME = "FileAttributes";
/**
* Constructor
*
* @param swf
*/
public FileAttributesTag(SWF swf) {
super(swf, ID, "FileAttributes", null);
super(swf, ID, NAME, null);
}
public FileAttributesTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "FileAttributes", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -32,6 +32,8 @@ public class FrameLabelTag extends Tag {
public static final int ID = 43;
public static final String NAME = "FrameLabel";
public String getLabelName() {
return name;
}
@@ -46,12 +48,12 @@ public class FrameLabelTag extends Tag {
* @param swf
*/
public FrameLabelTag(SWF swf) {
super(swf, ID, "FrameLabel", null);
super(swf, ID, NAME, null);
name = "New frame label";
}
public FrameLabelTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "FrameLabel", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -62,13 +62,15 @@ public class ImportAssets2Tag extends Tag implements ImportTag {
public static final int ID = 71;
public static final String NAME = "ImportAssets2";
/**
* Constructor
*
* @param swf
*/
public ImportAssets2Tag(SWF swf) {
super(swf, ID, "ImportAssets2", null);
super(swf, ID, NAME, null);
url = "";
tags = new ArrayList<>();
}
@@ -81,7 +83,7 @@ public class ImportAssets2Tag extends Tag implements ImportTag {
* @throws IOException
*/
public ImportAssets2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "ImportAssets2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -53,13 +53,15 @@ public class ImportAssetsTag extends Tag implements ImportTag {
public static final int ID = 57;
public static final String NAME = "ImportAssets";
/**
* Constructor
*
* @param swf
*/
public ImportAssetsTag(SWF swf) {
super(swf, ID, "ImportAssets", null);
super(swf, ID, NAME, null);
url = "";
tags = new ArrayList<>();
}
@@ -72,7 +74,7 @@ public class ImportAssetsTag extends Tag implements ImportTag {
* @throws IOException
*/
public ImportAssetsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "ImportAssets", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -29,6 +29,8 @@ public class JPEGTablesTag extends Tag {
public static final int ID = 8;
public static final String NAME = "JPEGTables";
@HideInRawEdit
public byte[] jpegData;
@@ -38,12 +40,12 @@ public class JPEGTablesTag extends Tag {
* @param swf
*/
public JPEGTablesTag(SWF swf) {
super(swf, ID, "JPEGTables", null);
super(swf, ID, NAME, null);
jpegData = new byte[0];
}
public JPEGTablesTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "JPEGTables", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -32,18 +32,20 @@ public class MetadataTag extends Tag {
public static final int ID = 77;
public static final String NAME = "Metadata";
/**
* Constructor
*
* @param swf
*/
public MetadataTag(SWF swf) {
super(swf, ID, "Metadata", null);
super(swf, ID, NAME, null);
xmlMetadata = "";
}
public MetadataTag(SWFInputStream sis, ByteArrayRange data) {
super(sis.getSwf(), ID, "Metadata", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,440 +1,442 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ASMSourceContainer;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD;
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.filters.FILTER;
import com.jpexs.helpers.ByteArrayRange;
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.Set;
/**
* Extends the functionality of the PlaceObject2Tag
*
* @author JPEXS
*/
public class PlaceObject2Tag extends PlaceObjectTypeTag implements ASMSourceContainer {
/**
* @since SWF 5 Has clip actions (sprite characters only)
*/
public boolean placeFlagHasClipActions;
/**
* Has clip depth
*/
public boolean placeFlagHasClipDepth;
/**
* Has name
*/
public boolean placeFlagHasName;
/**
* Has ratio
*/
public boolean placeFlagHasRatio;
/**
* Has color transform
*/
public boolean placeFlagHasColorTransform;
/**
* Has matrix
*/
public boolean placeFlagHasMatrix;
/**
* Places a character
*/
public boolean placeFlagHasCharacter;
/**
* Defines a character to be moved
*/
public boolean placeFlagMove;
/**
* Depth of character
*/
@SWFType(BasicType.UI16)
public int depth;
/**
* If PlaceFlagHasCharacter, ID of character to place
*/
@SWFType(BasicType.UI16)
@Conditional("placeFlagHasCharacter")
public int characterId;
/**
* If PlaceFlagHasMatrix, Transform matrix data
*/
@Conditional("placeFlagHasMatrix")
public MATRIX matrix;
/**
* If PlaceFlagHasColorTransform, Color transform data
*/
@Conditional("placeFlagHasColorTransform")
public CXFORMWITHALPHA colorTransform;
/**
* If PlaceFlagHasRatio, ratio
*/
@SWFType(BasicType.UI16)
@Conditional("placeFlagHasRatio")
public int ratio;
/**
* If PlaceFlagHasName, Name of character
*/
@Conditional("placeFlagHasName")
public String name;
/**
* If PlaceFlagHasClipDepth, Clip depth
*/
@Conditional("placeFlagHasClipDepth")
public int clipDepth;
/**
* @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data
*/
@Conditional("placeFlagHasClipActions")
@HideInRawEdit //TODO: make editable
public CLIPACTIONS clipActions;
public static final int ID = 26;
@Override
public int getClipDepth() {
if (placeFlagHasClipDepth) {
return clipDepth;
}
return -1;
}
@Override
public List<FILTER> getFilters() {
return null;
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
if (Configuration.debugCopy.get()) {
os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData()));
}
SWFOutputStream sos = new SWFOutputStream(os, getVersion());
try {
sos.writeUB(1, placeFlagHasClipActions ? 1 : 0);
sos.writeUB(1, placeFlagHasClipDepth ? 1 : 0);
sos.writeUB(1, placeFlagHasName ? 1 : 0);
sos.writeUB(1, placeFlagHasRatio ? 1 : 0);
sos.writeUB(1, placeFlagHasColorTransform ? 1 : 0);
sos.writeUB(1, placeFlagHasMatrix ? 1 : 0);
sos.writeUB(1, placeFlagHasCharacter ? 1 : 0);
sos.writeUB(1, placeFlagMove ? 1 : 0);
sos.writeUI16(depth);
if (placeFlagHasCharacter) {
sos.writeUI16(characterId);
}
if (placeFlagHasMatrix) {
sos.writeMatrix(matrix);
}
if (placeFlagHasColorTransform) {
sos.writeCXFORMWITHALPHA(colorTransform);
}
if (placeFlagHasRatio) {
sos.writeUI16(ratio);
}
if (placeFlagHasName) {
sos.writeString(name);
}
if (placeFlagHasClipDepth) {
sos.writeUI16(clipDepth);
}
if (placeFlagHasClipActions) {
sos.writeCLIPACTIONS(clipActions);
}
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public PlaceObject2Tag(SWF swf) {
super(swf, ID, "PlaceObject2", null);
}
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);
this.placeFlagHasClipActions = placeFlagHasClipActions;
this.placeFlagHasClipDepth = placeFlagHasClipDepth;
this.placeFlagHasName = placeFlagHasName;
this.placeFlagHasRatio = placeFlagHasRatio;
this.placeFlagHasColorTransform = placeFlagHasColorTransform;
this.placeFlagHasMatrix = placeFlagHasMatrix;
this.placeFlagHasCharacter = placeFlagHasCharacter;
this.placeFlagMove = placeFlagMove;
this.depth = depth;
this.characterId = characterId;
this.matrix = matrix;
this.colorTransform = colorTransform;
this.ratio = ratio;
this.name = name;
this.clipDepth = clipDepth;
this.clipActions = clipActions;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public PlaceObject2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "PlaceObject2", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
placeFlagHasClipActions = sis.readUB(1, "placeFlagHasClipActions") == 1;
placeFlagHasClipDepth = sis.readUB(1, "placeFlagHasClipDepth") == 1;
placeFlagHasName = sis.readUB(1, "placeFlagHasName") == 1;
placeFlagHasRatio = sis.readUB(1, "placeFlagHasRatio") == 1;
placeFlagHasColorTransform = sis.readUB(1, "placeFlagHasColorTransform") == 1;
placeFlagHasMatrix = sis.readUB(1, "placeFlagHasMatrix") == 1;
placeFlagHasCharacter = sis.readUB(1, "placeFlagHasCharacter") == 1;
placeFlagMove = sis.readUB(1, "placeFlagMove") == 1;
depth = sis.readUI16("depth");
if (placeFlagHasCharacter) {
characterId = sis.readUI16("characterId");
}
if (placeFlagHasMatrix) {
matrix = sis.readMatrix("matrix");
}
if (placeFlagHasColorTransform) {
colorTransform = sis.readCXFORMWITHALPHA("colorTransform");
}
if (placeFlagHasRatio) {
ratio = sis.readUI16("ratio");
}
if (placeFlagHasName) {
name = sis.readString("name");
}
if (placeFlagHasClipDepth) {
clipDepth = sis.readUI16("clipDepth");
}
if (placeFlagHasClipActions) {
clipActions = sis.readCLIPACTIONS(swf, this, "clipActions");
}
}
/**
* Returns all sub-items
*
* @return List of sub-items
*/
@Override
public List<CLIPACTIONRECORD> getSubItems() {
if (placeFlagHasClipActions) {
return clipActions.clipActionRecords;
}
return new ArrayList<>();
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
if (placeFlagHasCharacter) {
needed.add(characterId);
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
return false;
}
@Override
public boolean removeCharacter(int characterId) {
// the place object tag will be removed
return false;
}
@Override
public int getCharacterId() {
if (placeFlagHasCharacter) {
return characterId;
} else {
return -1;
}
}
@Override
public void setCharacterId(int characterId) {
placeFlagHasCharacter = true;
this.characterId = characterId;
}
@Override
public int getDepth() {
return depth;
}
@Override
public MATRIX getMatrix() {
if (placeFlagHasMatrix) {
return matrix;
} else {
return null;
}
}
@Override
public String getInstanceName() {
if (placeFlagHasName) {
return name;
}
return null;
}
@Override
public ColorTransform getColorTransform() {
if (placeFlagHasColorTransform) {
return colorTransform;
} else {
return null;
}
}
@Override
public int getBlendMode() {
return 0;
}
@Override
public boolean cacheAsBitmap() {
return false;
}
@Override
public String getClassName() {
return null;
}
@Override
public boolean isVisible() {
return true;
}
@Override
public RGBA getBackgroundColor() {
return null;
}
@Override
public boolean flagMove() {
return placeFlagMove;
}
@Override
public int getRatio() {
if (!placeFlagHasRatio) {
return -1;
}
return ratio;
}
@Override
public void setInstanceName(String name) {
placeFlagHasName = true;
this.name = name;
}
@Override
public void setClassName(String className) {
//not supported
}
@Override
public String getName() {
if (placeFlagHasName) {
return super.getName() + " (" + name + ")";
} else {
return super.getName();
}
}
@Override
public CLIPACTIONS getClipActions() {
if (placeFlagHasClipActions) {
return clipActions;
} else {
return null;
}
}
@Override
public void writeTagWithMatrix(SWFOutputStream sos, MATRIX m) throws IOException {
MATRIX old = matrix;
matrix = m;
boolean mod = isModified();
setModified(true);
super.writeTag(sos);
setModified(mod);
matrix = old;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.ASMSourceContainer;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD;
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.filters.FILTER;
import com.jpexs.helpers.ByteArrayRange;
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.Set;
/**
* Extends the functionality of the PlaceObject2Tag
*
* @author JPEXS
*/
public class PlaceObject2Tag extends PlaceObjectTypeTag implements ASMSourceContainer {
/**
* @since SWF 5 Has clip actions (sprite characters only)
*/
public boolean placeFlagHasClipActions;
/**
* Has clip depth
*/
public boolean placeFlagHasClipDepth;
/**
* Has name
*/
public boolean placeFlagHasName;
/**
* Has ratio
*/
public boolean placeFlagHasRatio;
/**
* Has color transform
*/
public boolean placeFlagHasColorTransform;
/**
* Has matrix
*/
public boolean placeFlagHasMatrix;
/**
* Places a character
*/
public boolean placeFlagHasCharacter;
/**
* Defines a character to be moved
*/
public boolean placeFlagMove;
/**
* Depth of character
*/
@SWFType(BasicType.UI16)
public int depth;
/**
* If PlaceFlagHasCharacter, ID of character to place
*/
@SWFType(BasicType.UI16)
@Conditional("placeFlagHasCharacter")
public int characterId;
/**
* If PlaceFlagHasMatrix, Transform matrix data
*/
@Conditional("placeFlagHasMatrix")
public MATRIX matrix;
/**
* If PlaceFlagHasColorTransform, Color transform data
*/
@Conditional("placeFlagHasColorTransform")
public CXFORMWITHALPHA colorTransform;
/**
* If PlaceFlagHasRatio, ratio
*/
@SWFType(BasicType.UI16)
@Conditional("placeFlagHasRatio")
public int ratio;
/**
* If PlaceFlagHasName, Name of character
*/
@Conditional("placeFlagHasName")
public String name;
/**
* If PlaceFlagHasClipDepth, Clip depth
*/
@Conditional("placeFlagHasClipDepth")
public int clipDepth;
/**
* @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data
*/
@Conditional("placeFlagHasClipActions")
@HideInRawEdit //TODO: make editable
public CLIPACTIONS clipActions;
public static final int ID = 26;
public static final String NAME = "PlaceObject2";
@Override
public int getClipDepth() {
if (placeFlagHasClipDepth) {
return clipDepth;
}
return -1;
}
@Override
public List<FILTER> getFilters() {
return null;
}
/**
* Gets data bytes
*
* @return Bytes of data
*/
@Override
public byte[] getData() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
if (Configuration.debugCopy.get()) {
os = new CopyOutputStream(os, new ByteArrayInputStream(getOriginalData()));
}
SWFOutputStream sos = new SWFOutputStream(os, getVersion());
try {
sos.writeUB(1, placeFlagHasClipActions ? 1 : 0);
sos.writeUB(1, placeFlagHasClipDepth ? 1 : 0);
sos.writeUB(1, placeFlagHasName ? 1 : 0);
sos.writeUB(1, placeFlagHasRatio ? 1 : 0);
sos.writeUB(1, placeFlagHasColorTransform ? 1 : 0);
sos.writeUB(1, placeFlagHasMatrix ? 1 : 0);
sos.writeUB(1, placeFlagHasCharacter ? 1 : 0);
sos.writeUB(1, placeFlagMove ? 1 : 0);
sos.writeUI16(depth);
if (placeFlagHasCharacter) {
sos.writeUI16(characterId);
}
if (placeFlagHasMatrix) {
sos.writeMatrix(matrix);
}
if (placeFlagHasColorTransform) {
sos.writeCXFORMWITHALPHA(colorTransform);
}
if (placeFlagHasRatio) {
sos.writeUI16(ratio);
}
if (placeFlagHasName) {
sos.writeString(name);
}
if (placeFlagHasClipDepth) {
sos.writeUI16(clipDepth);
}
if (placeFlagHasClipActions) {
sos.writeCLIPACTIONS(clipActions);
}
sos.close();
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public PlaceObject2Tag(SWF swf) {
super(swf, ID, NAME, null);
}
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, NAME, null);
this.placeFlagHasClipActions = placeFlagHasClipActions;
this.placeFlagHasClipDepth = placeFlagHasClipDepth;
this.placeFlagHasName = placeFlagHasName;
this.placeFlagHasRatio = placeFlagHasRatio;
this.placeFlagHasColorTransform = placeFlagHasColorTransform;
this.placeFlagHasMatrix = placeFlagHasMatrix;
this.placeFlagHasCharacter = placeFlagHasCharacter;
this.placeFlagMove = placeFlagMove;
this.depth = depth;
this.characterId = characterId;
this.matrix = matrix;
this.colorTransform = colorTransform;
this.ratio = ratio;
this.name = name;
this.clipDepth = clipDepth;
this.clipActions = clipActions;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public PlaceObject2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
placeFlagHasClipActions = sis.readUB(1, "placeFlagHasClipActions") == 1;
placeFlagHasClipDepth = sis.readUB(1, "placeFlagHasClipDepth") == 1;
placeFlagHasName = sis.readUB(1, "placeFlagHasName") == 1;
placeFlagHasRatio = sis.readUB(1, "placeFlagHasRatio") == 1;
placeFlagHasColorTransform = sis.readUB(1, "placeFlagHasColorTransform") == 1;
placeFlagHasMatrix = sis.readUB(1, "placeFlagHasMatrix") == 1;
placeFlagHasCharacter = sis.readUB(1, "placeFlagHasCharacter") == 1;
placeFlagMove = sis.readUB(1, "placeFlagMove") == 1;
depth = sis.readUI16("depth");
if (placeFlagHasCharacter) {
characterId = sis.readUI16("characterId");
}
if (placeFlagHasMatrix) {
matrix = sis.readMatrix("matrix");
}
if (placeFlagHasColorTransform) {
colorTransform = sis.readCXFORMWITHALPHA("colorTransform");
}
if (placeFlagHasRatio) {
ratio = sis.readUI16("ratio");
}
if (placeFlagHasName) {
name = sis.readString("name");
}
if (placeFlagHasClipDepth) {
clipDepth = sis.readUI16("clipDepth");
}
if (placeFlagHasClipActions) {
clipActions = sis.readCLIPACTIONS(swf, this, "clipActions");
}
}
/**
* Returns all sub-items
*
* @return List of sub-items
*/
@Override
public List<CLIPACTIONRECORD> getSubItems() {
if (placeFlagHasClipActions) {
return clipActions.clipActionRecords;
}
return new ArrayList<>();
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
if (placeFlagHasCharacter) {
needed.add(characterId);
}
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
return false;
}
@Override
public boolean removeCharacter(int characterId) {
// the place object tag will be removed
return false;
}
@Override
public int getCharacterId() {
if (placeFlagHasCharacter) {
return characterId;
} else {
return -1;
}
}
@Override
public void setCharacterId(int characterId) {
placeFlagHasCharacter = true;
this.characterId = characterId;
}
@Override
public int getDepth() {
return depth;
}
@Override
public MATRIX getMatrix() {
if (placeFlagHasMatrix) {
return matrix;
} else {
return null;
}
}
@Override
public String getInstanceName() {
if (placeFlagHasName) {
return name;
}
return null;
}
@Override
public ColorTransform getColorTransform() {
if (placeFlagHasColorTransform) {
return colorTransform;
} else {
return null;
}
}
@Override
public int getBlendMode() {
return 0;
}
@Override
public boolean cacheAsBitmap() {
return false;
}
@Override
public String getClassName() {
return null;
}
@Override
public boolean isVisible() {
return true;
}
@Override
public RGBA getBackgroundColor() {
return null;
}
@Override
public boolean flagMove() {
return placeFlagMove;
}
@Override
public int getRatio() {
if (!placeFlagHasRatio) {
return -1;
}
return ratio;
}
@Override
public void setInstanceName(String name) {
placeFlagHasName = true;
this.name = name;
}
@Override
public void setClassName(String className) {
//not supported
}
@Override
public String getName() {
if (placeFlagHasName) {
return super.getName() + " (" + name + ")";
} else {
return super.getName();
}
}
@Override
public CLIPACTIONS getClipActions() {
if (placeFlagHasClipActions) {
return clipActions;
} else {
return null;
}
}
@Override
public void writeTagWithMatrix(SWFOutputStream sos, MATRIX m) throws IOException {
MATRIX old = matrix;
matrix = m;
boolean mod = isModified();
setModified(true);
super.writeTag(sos);
setModified(mod);
matrix = old;
}
}

View File

@@ -1,250 +1,252 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
import com.jpexs.decompiler.flash.types.CXFORM;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Set;
/**
* Adds character to the display list
*
* @author JPEXS
*/
public class PlaceObjectTag extends PlaceObjectTypeTag {
/**
* ID of character to place
*/
@SWFType(BasicType.UI16)
public int characterId;
/**
* Depth of character
*/
@SWFType(BasicType.UI16)
public int depth;
/**
* Transform matrix data
*/
public MATRIX matrix;
/**
* Color transform data
*/
@Optional
public CXFORM colorTransform;
public static final int ID = 4;
@Override
public List<FILTER> getFilters() {
return null;
}
@Override
public int getClipDepth() {
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(characterId);
sos.writeUI16(depth);
sos.writeMatrix(matrix);
if (colorTransform != null) {
sos.writeCXFORM(colorTransform);
}
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public PlaceObjectTag(SWF swf) {
super(swf, ID, "PlaceObject", null);
matrix = new MATRIX();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public PlaceObjectTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "PlaceObject", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterId = sis.readUI16("characterId");
depth = sis.readUI16("depth");
matrix = sis.readMatrix("matrix");
if (sis.available() > 0) {
colorTransform = sis.readCXFORM("colorTransform");
}
}
public PlaceObjectTag(SWF swf, int characterId, int depth, MATRIX matrix, CXFORM colorTransform) {
super(swf, ID, "PlaceObject", null);
this.characterId = characterId;
this.depth = depth;
this.matrix = matrix;
this.colorTransform = colorTransform;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
needed.add(characterId);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
return false;
}
@Override
public boolean removeCharacter(int characterId) {
// the place object tag will be removed
return false;
}
@Override
public int getCharacterId() {
return characterId;
}
@Override
public void setCharacterId(int characterId) {
this.characterId = characterId;
}
@Override
public int getDepth() {
return depth;
}
@Override
public MATRIX getMatrix() {
return matrix;
}
@Override
public String getInstanceName() {
return null;
}
@Override
public ColorTransform getColorTransform() {
return colorTransform;
}
@Override
public int getBlendMode() {
return 0;
}
@Override
public boolean cacheAsBitmap() {
return false;
}
@Override
public String getClassName() {
return null;
}
@Override
public boolean isVisible() {
return true;
}
@Override
public RGBA getBackgroundColor() {
return null;
}
@Override
public boolean flagMove() {
return false;
}
@Override
public int getRatio() {
return -1;
}
@Override
public void setInstanceName(String name) {
//not supported
}
@Override
public void setClassName(String className) {
//not supported
}
@Override
public CLIPACTIONS getClipActions() {
return null;
}
@Override
public void writeTagWithMatrix(SWFOutputStream sos, MATRIX m) throws IOException {
MATRIX old = matrix;
matrix = m;
boolean mod = isModified();
setModified(true);
super.writeTag(sos);
setModified(mod);
matrix = old;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
import com.jpexs.decompiler.flash.types.CXFORM;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.MATRIX;
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Set;
/**
* Adds character to the display list
*
* @author JPEXS
*/
public class PlaceObjectTag extends PlaceObjectTypeTag {
/**
* ID of character to place
*/
@SWFType(BasicType.UI16)
public int characterId;
/**
* Depth of character
*/
@SWFType(BasicType.UI16)
public int depth;
/**
* Transform matrix data
*/
public MATRIX matrix;
/**
* Color transform data
*/
@Optional
public CXFORM colorTransform;
public static final int ID = 4;
public static final String NAME = "PlaceObject";
@Override
public List<FILTER> getFilters() {
return null;
}
@Override
public int getClipDepth() {
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(characterId);
sos.writeUI16(depth);
sos.writeMatrix(matrix);
if (colorTransform != null) {
sos.writeCXFORM(colorTransform);
}
} catch (IOException e) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public PlaceObjectTag(SWF swf) {
super(swf, ID, NAME, null);
matrix = new MATRIX();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public PlaceObjectTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterId = sis.readUI16("characterId");
depth = sis.readUI16("depth");
matrix = sis.readMatrix("matrix");
if (sis.available() > 0) {
colorTransform = sis.readCXFORM("colorTransform");
}
}
public PlaceObjectTag(SWF swf, int characterId, int depth, MATRIX matrix, CXFORM colorTransform) {
super(swf, ID, NAME, null);
this.characterId = characterId;
this.depth = depth;
this.matrix = matrix;
this.colorTransform = colorTransform;
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
needed.add(characterId);
}
@Override
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
return false;
}
@Override
public boolean removeCharacter(int characterId) {
// the place object tag will be removed
return false;
}
@Override
public int getCharacterId() {
return characterId;
}
@Override
public void setCharacterId(int characterId) {
this.characterId = characterId;
}
@Override
public int getDepth() {
return depth;
}
@Override
public MATRIX getMatrix() {
return matrix;
}
@Override
public String getInstanceName() {
return null;
}
@Override
public ColorTransform getColorTransform() {
return colorTransform;
}
@Override
public int getBlendMode() {
return 0;
}
@Override
public boolean cacheAsBitmap() {
return false;
}
@Override
public String getClassName() {
return null;
}
@Override
public boolean isVisible() {
return true;
}
@Override
public RGBA getBackgroundColor() {
return null;
}
@Override
public boolean flagMove() {
return false;
}
@Override
public int getRatio() {
return -1;
}
@Override
public void setInstanceName(String name) {
//not supported
}
@Override
public void setClassName(String className) {
//not supported
}
@Override
public CLIPACTIONS getClipActions() {
return null;
}
@Override
public void writeTagWithMatrix(SWFOutputStream sos, MATRIX m) throws IOException {
MATRIX old = matrix;
matrix = m;
boolean mod = isModified();
setModified(true);
super.writeTag(sos);
setModified(mod);
matrix = old;
}
}

View File

@@ -54,17 +54,19 @@ public class ProductInfoTag extends Tag {
public static final int ID = 41;
public static final String NAME = "ProductInfo";
/**
* Constructor
*
* @param swf
*/
public ProductInfoTag(SWF swf) {
super(swf, ID, "ProductInfo", null);
super(swf, ID, NAME, null);
}
public ProductInfoTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "ProductInfo", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -38,6 +38,8 @@ public class ProtectTag extends Tag {
public static final int ID = 24;
public static final String NAME = "Protect";
/**
* Gets data bytes
*
@@ -64,7 +66,7 @@ public class ProtectTag extends Tag {
* @param swf
*/
public ProtectTag(SWF swf) {
super(swf, ID, "Protect", null);
super(swf, ID, NAME, null);
passwordHash = "";
}
@@ -76,7 +78,7 @@ public class ProtectTag extends Tag {
* @throws IOException
*/
public ProtectTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "Protect", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -34,17 +34,19 @@ public class RemoveObject2Tag extends RemoveTag {
public static final int ID = 28;
public static final String NAME = "RemoveObject2";
/**
* Constructor
*
* @param swf
*/
public RemoveObject2Tag(SWF swf) {
super(swf, ID, "RemoveObject2", null);
super(swf, ID, NAME, null);
}
public RemoveObject2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "RemoveObject2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,113 +1,115 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Removes the specified character
*
* @author JPEXS
*/
public class RemoveObjectTag extends RemoveTag implements CharacterIdTag {
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public RemoveObjectTag(SWF swf) {
super(swf, ID, "RemoveObject", null);
characterId = swf.getNextCharacterId();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public RemoveObjectTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "RemoveObject", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterId = sis.readUI16("characterId");
depth = sis.readUI16("depth");
}
@Override
public int getDepth() {
return depth;
}
@Override
public int getCharacterId() {
return characterId;
}
@Override
public void setCharacterId(int characterId) {
this.characterId = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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 com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Removes the specified character
*
* @author JPEXS
*/
public class RemoveObjectTag extends RemoveTag implements CharacterIdTag {
/**
* 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;
public static final String NAME = "RemoveObject";
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public RemoveObjectTag(SWF swf) {
super(swf, ID, NAME, null);
characterId = swf.getNextCharacterId();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public RemoveObjectTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
characterId = sis.readUI16("characterId");
depth = sis.readUI16("depth");
}
@Override
public int getDepth() {
return depth;
}
@Override
public int getCharacterId() {
return characterId;
}
@Override
public void setCharacterId(int characterId) {
this.characterId = characterId;
}
}

View File

@@ -36,17 +36,19 @@ public class ScriptLimitsTag extends Tag {
public static final int ID = 65;
public static final String NAME = "ScriptLimits";
/**
* Constructor
*
* @param swf
*/
public ScriptLimitsTag(SWF swf) {
super(swf, ID, "ScriptLimits", null);
super(swf, ID, NAME, null);
}
public ScriptLimitsTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "ScriptLimits", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -30,23 +30,25 @@ public class SetBackgroundColorTag extends Tag {
public static final int ID = 9;
public static final String NAME = "SetBackgroundColor";
/**
* Constructor
*
* @param swf
*/
public SetBackgroundColorTag(SWF swf) {
super(swf, ID, "SetBackgroundColor", null);
super(swf, ID, NAME, null);
backgroundColor = new RGB();
}
public SetBackgroundColorTag(SWF swf, RGB backgroundColor) {
super(swf, ID, "SetBackgroundColor", null);
super(swf, ID, NAME, null);
this.backgroundColor = backgroundColor;
}
public SetBackgroundColorTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "SetBackgroundColor", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -47,6 +47,8 @@ public class SetTabIndexTag extends Tag {
public static final int ID = 66;
public static final String NAME = "SetTabIndex";
/**
* Gets data bytes
*
@@ -72,7 +74,7 @@ public class SetTabIndexTag extends Tag {
* @param swf
*/
public SetTabIndexTag(SWF swf) {
super(swf, ID, "SetTabIndex", null);
super(swf, ID, NAME, null);
}
/**
@@ -83,7 +85,7 @@ public class SetTabIndexTag extends Tag {
* @throws IOException
*/
public SetTabIndexTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "SetTabIndex", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -31,6 +31,8 @@ public class ShowFrameTag extends Tag {
public static final int ID = 1;
public static final String NAME = "ShowFrame";
private static List<Integer> nestedTagTypeIds = new ArrayList<Integer>() {
{
add(PlaceObjectTag.ID);
@@ -55,7 +57,7 @@ public class ShowFrameTag extends Tag {
* @param swf
*/
public ShowFrameTag(SWF swf) {
super(swf, ID, "ShowFrame", null);
super(swf, ID, NAME, null);
}
/**
@@ -65,7 +67,7 @@ public class ShowFrameTag extends Tag {
* @param data
*/
public ShowFrameTag(SWFInputStream sis, ByteArrayRange data) {
super(sis.getSwf(), ID, "ShowFrame", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -34,6 +34,8 @@ public class SoundStreamBlockTag extends Tag {
public static final int ID = 19;
public static final String NAME = "SoundStreamBlock";
@HideInRawEdit
public ByteArrayRange streamSoundData;
@@ -43,7 +45,7 @@ public class SoundStreamBlockTag extends Tag {
* @param swf
*/
public SoundStreamBlockTag(SWF swf) {
super(swf, ID, "SoundStreamBlock", null);
super(swf, ID, NAME, null);
streamSoundData = ByteArrayRange.EMPTY;
}
@@ -55,7 +57,7 @@ public class SoundStreamBlockTag extends Tag {
* @throws IOException
*/
public SoundStreamBlockTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "SoundStreamBlock", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -1,251 +1,253 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
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 Tag 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 void setCharacterId(int characterId) {
virtualCharacterId = characterId;
}
@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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public SoundStreamHead2Tag(SWF swf) {
super(swf, ID, "SoundStreamHead2", null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public SoundStreamHead2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "SoundStreamHead2", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
reserved = (int) sis.readUB(4, "reserved");
playBackSoundRate = (int) sis.readUB(2, "playBackSoundRate");
playBackSoundSize = sis.readUB(1, "playBackSoundSize") == 1;
playBackSoundType = sis.readUB(1, "playBackSoundType") == 1;
streamSoundCompression = (int) sis.readUB(4, "streamSoundCompression");
streamSoundRate = (int) sis.readUB(2, "streamSoundRate");
streamSoundSize = sis.readUB(1, "streamSoundSize") == 1;
streamSoundType = sis.readUB(1, "streamSoundType") == 1;
streamSoundSampleCount = sis.readUI16("streamSoundSampleCount");
if (streamSoundCompression == 2) {
latencySeek = sis.readSI16("latencySeek");
}
}
@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<SoundStreamBlockTag> getBlocks() {
List<SoundStreamBlockTag> ret = new ArrayList<>();
SoundStreamHeadTag.populateSoundStreamBlocks(0, swf.tags, this, ret);
return ret;
}
@Override
public boolean importSupported() {
return false;
}
@Override
public boolean setSound(InputStream is, int newSoundFormat) {
return false;
}
@Override
public List<byte[]> getRawSoundData() {
List<byte[]> ret = new ArrayList<>();
List<SoundStreamBlockTag> blocks = getBlocks();
for (SoundStreamBlockTag block : blocks) {
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
ret.add(block.streamSoundData.getRangeData(4, block.streamSoundData.getLength() - 4));
} else {
ret.add(block.streamSoundData.getRangeData());
}
}
return ret;
}
@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());
}
@Override
public String getCharacterExportFileName() {
String exportName = swf.getExportName(getCharacterId());
return getCharacterId() + (exportName != null ? "_" + exportName : "");
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
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 Tag 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;
public static final String NAME = "SoundStreamHead2";
@Override
public int getCharacterId() {
return virtualCharacterId;
}
@Override
public void setCharacterId(int characterId) {
virtualCharacterId = characterId;
}
@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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public SoundStreamHead2Tag(SWF swf) {
super(swf, ID, NAME, null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public SoundStreamHead2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
reserved = (int) sis.readUB(4, "reserved");
playBackSoundRate = (int) sis.readUB(2, "playBackSoundRate");
playBackSoundSize = sis.readUB(1, "playBackSoundSize") == 1;
playBackSoundType = sis.readUB(1, "playBackSoundType") == 1;
streamSoundCompression = (int) sis.readUB(4, "streamSoundCompression");
streamSoundRate = (int) sis.readUB(2, "streamSoundRate");
streamSoundSize = sis.readUB(1, "streamSoundSize") == 1;
streamSoundType = sis.readUB(1, "streamSoundType") == 1;
streamSoundSampleCount = sis.readUI16("streamSoundSampleCount");
if (streamSoundCompression == 2) {
latencySeek = sis.readSI16("latencySeek");
}
}
@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<SoundStreamBlockTag> getBlocks() {
List<SoundStreamBlockTag> ret = new ArrayList<>();
SoundStreamHeadTag.populateSoundStreamBlocks(0, swf.tags, this, ret);
return ret;
}
@Override
public boolean importSupported() {
return false;
}
@Override
public boolean setSound(InputStream is, int newSoundFormat) {
return false;
}
@Override
public List<byte[]> getRawSoundData() {
List<byte[]> ret = new ArrayList<>();
List<SoundStreamBlockTag> blocks = getBlocks();
for (SoundStreamBlockTag block : blocks) {
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
ret.add(block.streamSoundData.getRangeData(4, block.streamSoundData.getLength() - 4));
} else {
ret.add(block.streamSoundData.getRangeData());
}
}
return ret;
}
@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());
}
@Override
public String getCharacterExportFileName() {
String exportName = swf.getExportName(getCharacterId());
return getCharacterId() + (exportName != null ? "_" + exportName : "");
}
}

View File

@@ -1,274 +1,276 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
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 Tag 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 setCharacterId(int characterId) {
virtualCharacterId = characterId;
}
@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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public SoundStreamHeadTag(SWF swf) {
super(swf, ID, "SoundStreamHead", null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public SoundStreamHeadTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "SoundStreamHead", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
reserved = (int) sis.readUB(4, "reserved");
playBackSoundRate = (int) sis.readUB(2, "playBackSoundRate");
playBackSoundSize = sis.readUB(1, "playBackSoundSize") == 1;
playBackSoundType = sis.readUB(1, "playBackSoundType") == 1;
streamSoundCompression = (int) sis.readUB(4, "streamSoundCompression");
streamSoundRate = (int) sis.readUB(2, "streamSoundRate");
streamSoundSize = sis.readUB(1, "streamSoundSize") == 1;
streamSoundType = sis.readUB(1, "streamSoundType") == 1;
streamSoundSampleCount = sis.readUI16("streamSoundSampleCount");
if (streamSoundCompression == 2) {
latencySeek = sis.readSI16("latencySeek");
}
}
@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(int containerId, List<Tag> tags, SoundStreamHeadTypeTag head, List<SoundStreamBlockTag> output) {
boolean found = false;
for (Tag t : tags) {
if (t == head) {
found = true;
head.setVirtualCharacterId(containerId);
continue;
}
if (t instanceof DefineSpriteTag) {
DefineSpriteTag sprite = (DefineSpriteTag) t;
populateSoundStreamBlocks(sprite.getCharacterId(), sprite.getSubTags(), head, output);
}
if (!found) {
continue;
}
if (t instanceof SoundStreamBlockTag) {
output.add((SoundStreamBlockTag) t);
}
if (t instanceof SoundStreamHeadTypeTag) {
break;
}
}
}
@Override
public List<SoundStreamBlockTag> getBlocks() {
List<SoundStreamBlockTag> ret = new ArrayList<>();
populateSoundStreamBlocks(0, swf.tags, this, ret);
return ret;
}
@Override
public boolean importSupported() {
return false;
}
@Override
public boolean setSound(InputStream is, int newSoundFormat) {
return false;
}
@Override
public List<byte[]> getRawSoundData() {
List<byte[]> ret = new ArrayList<>();
List<SoundStreamBlockTag> blocks = getBlocks();
for (SoundStreamBlockTag block : blocks) {
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
ret.add(block.streamSoundData.getRangeData(4, block.streamSoundData.getLength() - 4));
} else {
ret.add(block.streamSoundData.getRangeData());
}
}
return ret;
}
@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());
}
@Override
public String getCharacterExportFileName() {
String exportName = swf.getExportName(getCharacterId());
return getCharacterId() + (exportName != null ? "_" + exportName : "");
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.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 com.jpexs.helpers.ByteArrayRange;
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 Tag 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;
public static final String NAME = "SoundStreamHead";
@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 setCharacterId(int characterId) {
virtualCharacterId = characterId;
}
@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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public SoundStreamHeadTag(SWF swf) {
super(swf, ID, NAME, null);
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public SoundStreamHeadTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
reserved = (int) sis.readUB(4, "reserved");
playBackSoundRate = (int) sis.readUB(2, "playBackSoundRate");
playBackSoundSize = sis.readUB(1, "playBackSoundSize") == 1;
playBackSoundType = sis.readUB(1, "playBackSoundType") == 1;
streamSoundCompression = (int) sis.readUB(4, "streamSoundCompression");
streamSoundRate = (int) sis.readUB(2, "streamSoundRate");
streamSoundSize = sis.readUB(1, "streamSoundSize") == 1;
streamSoundType = sis.readUB(1, "streamSoundType") == 1;
streamSoundSampleCount = sis.readUI16("streamSoundSampleCount");
if (streamSoundCompression == 2) {
latencySeek = sis.readSI16("latencySeek");
}
}
@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(int containerId, List<Tag> tags, SoundStreamHeadTypeTag head, List<SoundStreamBlockTag> output) {
boolean found = false;
for (Tag t : tags) {
if (t == head) {
found = true;
head.setVirtualCharacterId(containerId);
continue;
}
if (t instanceof DefineSpriteTag) {
DefineSpriteTag sprite = (DefineSpriteTag) t;
populateSoundStreamBlocks(sprite.getCharacterId(), sprite.getSubTags(), head, output);
}
if (!found) {
continue;
}
if (t instanceof SoundStreamBlockTag) {
output.add((SoundStreamBlockTag) t);
}
if (t instanceof SoundStreamHeadTypeTag) {
break;
}
}
}
@Override
public List<SoundStreamBlockTag> getBlocks() {
List<SoundStreamBlockTag> ret = new ArrayList<>();
populateSoundStreamBlocks(0, swf.tags, this, ret);
return ret;
}
@Override
public boolean importSupported() {
return false;
}
@Override
public boolean setSound(InputStream is, int newSoundFormat) {
return false;
}
@Override
public List<byte[]> getRawSoundData() {
List<byte[]> ret = new ArrayList<>();
List<SoundStreamBlockTag> blocks = getBlocks();
for (SoundStreamBlockTag block : blocks) {
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
ret.add(block.streamSoundData.getRangeData(4, block.streamSoundData.getLength() - 4));
} else {
ret.add(block.streamSoundData.getRangeData());
}
}
return ret;
}
@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());
}
@Override
public String getCharacterExportFileName() {
String exportName = swf.getExportName(getCharacterId());
return getCharacterId() + (exportName != null ? "_" + exportName : "");
}
}

View File

@@ -26,7 +26,6 @@ import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
@@ -38,6 +37,8 @@ public class StartSound2Tag extends Tag {
public static final int ID = 89;
public static final String NAME = "StartSound2";
/**
* Gets data bytes
*
@@ -63,7 +64,7 @@ public class StartSound2Tag extends Tag {
* @param swf
*/
public StartSound2Tag(SWF swf) {
super(swf, ID, "StartSound2", null);
super(swf, ID, NAME, null);
soundClassName = "NewSoundClass";
soundInfo = new SOUNDINFO();
}
@@ -76,7 +77,7 @@ public class StartSound2Tag extends Tag {
* @throws IOException
*/
public StartSound2Tag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "StartSound2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -41,6 +41,8 @@ public class StartSoundTag extends Tag {
public static final int ID = 15;
public static final String NAME = "StartSound";
/**
* Gets data bytes
*
@@ -66,7 +68,7 @@ public class StartSoundTag extends Tag {
* @param swf
*/
public StartSoundTag(SWF swf) {
super(swf, ID, "StartSound", null);
super(swf, ID, NAME, null);
soundInfo = new SOUNDINFO();
}
@@ -78,7 +80,7 @@ public class StartSoundTag extends Tag {
* @throws IOException
*/
public StartSoundTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "StartSound", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -41,19 +41,21 @@ public class SymbolClassTag extends SymbolClassTypeTag {
public static final int ID = 76;
public static final String NAME = "SymbolClass";
/**
* Constructor
*
* @param swf
*/
public SymbolClassTag(SWF swf) {
super(swf, ID, "SymbolClass", null);
super(swf, ID, NAME, null);
tags = new ArrayList<>();
names = new ArrayList<>();
}
public SymbolClassTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "SymbolClass", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags;
/**
*
* @author JPEXS
*/
public class TagInfo {
public int id;
public Class cls;
public String name;
public TagInfo(int id, Class cls, String name) {
this.id = id;
this.cls = cls;
this.name = name;
}
}

View File

@@ -1,105 +1,107 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class VideoFrameTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int streamID;
@SWFType(BasicType.UI16)
public int frameNum;
public ByteArrayRange 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public VideoFrameTag(SWF swf) {
super(swf, ID, "VideoFrame", null);
videoData = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public VideoFrameTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "VideoFrame", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
streamID = sis.readUI16("streamID");
frameNum = sis.readUI16("frameNum");
videoData = sis.readByteRangeEx(sis.available(), "videoData"); //TODO: Parse video packets
}
@Override
public int getCharacterId() {
return streamID;
}
@Override
public void setCharacterId(int characterId) {
this.streamID = characterId;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.annotations.SWFType;
import com.jpexs.helpers.ByteArrayRange;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class VideoFrameTag extends Tag implements CharacterIdTag {
@SWFType(BasicType.UI16)
public int streamID;
@SWFType(BasicType.UI16)
public int frameNum;
public ByteArrayRange videoData;
public static final int ID = 61;
public static final String NAME = "VideoFrame";
/**
* 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public VideoFrameTag(SWF swf) {
super(swf, ID, NAME, null);
videoData = ByteArrayRange.EMPTY;
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public VideoFrameTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
streamID = sis.readUI16("streamID");
frameNum = sis.readUI16("frameNum");
videoData = sis.readByteRangeEx(sis.available(), "videoData"); //TODO: Parse video packets
}
@Override
public int getCharacterId() {
return streamID;
}
@Override
public void setCharacterId(int characterId) {
this.streamID = characterId;
}
}

View File

@@ -1,430 +1,432 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.FontHelper;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.Tag;
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.ByteArrayRange;
import com.jpexs.helpers.MemoryInputStream;
import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author JPEXS
*/
public final class DefineCompactedFont extends FontTag {
public static final int ID = 1005;
public int fontId;
public List<FontType> fonts;
private List<SHAPE> 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineCompactedFont(SWF swf) {
super(swf, ID, "DefineCompactedFont", null);
fontId = swf.getNextCharacterId();
fonts = new ArrayList<>();
FontType ft = new FontType();
fonts.add(ft);
rebuildShapeCache();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineCompactedFont(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineCompactedFont", data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
fonts = new ArrayList<>();
MemoryInputStream mis = sis.getBaseStream();
while (mis.available() > 0) {
GFxInputStream gis = new GFxInputStream(mis);
gis.dumpInfo = sis.dumpInfo;
gis.newDumpLevel("fontType", "FontType");
fonts.add(new FontType(gis));
gis.endDumpLevel();
}
rebuildShapeCache();
}
public void rebuildShapeCache() {
shapeCache = fonts.get(0).getGlyphShapes();
}
@Override
public String getFontNameIntag() {
StringBuilder ret = new StringBuilder();
for (int i = 0; i < fonts.size(); i++) {
if (i > 0) {
ret.append(", ");
}
ret.append(fonts.get(i).fontName);
}
return ret.toString();
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
@Override
public int getFontId() {
return fontId;
}
@Override
public List<SHAPE> getGlyphShapeTable() {
return shapeCache;
}
@Override
public void addCharacter(char character, Font cfont) {
int fontStyle = getFontStyle();
FontType font = fonts.get(0);
double d = 1;
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(cfont, (int) (font.nominalSize * d), 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 = cfont.deriveFont(fontStyle, Math.round(font.nominalSize * d));
int advance = (int) Math.round(FontHelper.getFontAdvance(fnt, character));
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());
}
setModified(true);
getSwf().clearImageCache();
}
@Override
public void setAdvanceValues(Font font) {
throw new UnsupportedOperationException("Setting the advance values for DefineCompactedFont is not supported.");
}
@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 resize(fonts.get(0).glyphInfo.get(glyphIndex).advanceX);
}
@Override
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
char c1 = glyphToChar(glyphIndex);
char c2 = glyphToChar(nextGlyphIndex);
return getCharKerningAdjustment(c1, c2);
}
@Override
public int getCharKerningAdjustment(char c1, char c2) {
for (KerningPairType kp : fonts.get(0).kerning) {
if (kp.char1 == c1 && kp.char2 == c2) {
return resize(kp.advance);
}
}
return 0;
}
@Override
public int getGlyphWidth(int glyphIndex) {
return resize(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 double 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<Tag> tags) {
FontType ft = fonts.get(0);
StringBuilder ret = new StringBuilder(ft.glyphInfo.size());
for (GlyphInfoType gi : ft.glyphInfo) {
ret.append((char) gi.glyphCode);
}
return ret.toString();
}
@Override
public RECT getGlyphBounds(int glyphIndex) {
GlyphType gt = fonts.get(0).glyphs.get(glyphIndex);
return new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3]));
}
public SHAPE resizeShape(SHAPE shp) {
SHAPE ret = new SHAPE();
ret.numFillBits = 1;
ret.numLineBits = 0;
List<SHAPERECORD> recs = new ArrayList<>();
for (SHAPERECORD r : shp.shapeRecords) {
SHAPERECORD c = r.clone();
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;
}
protected int resize(double val) {
FontType ft = fonts.get(0);
return (int) Math.round(val * 1024.0 / ft.nominalSize);
}
@Override
public FontTag toClassicFont() {
DefineFont2Tag ret = new DefineFont2Tag(swf);
ret.fontId = getFontId();
ret.fontFlagsBold = isBold();
ret.fontFlagsItalic = isItalic();
ret.fontFlagsWideOffsets = true;
ret.fontFlagsWideCodes = true;
ret.fontFlagsHasLayout = true;
ret.fontAscent = (getAscent());
ret.fontDescent = (getDescent());
ret.fontLeading = (getLeading());
ret.fontAdvanceTable = new ArrayList<>();
ret.fontBoundsTable = new ArrayList<>();
ret.codeTable = new ArrayList<>();
ret.glyphShapeTable = new ArrayList<>();
List<SHAPE> shp = getGlyphShapeTable();
for (int g = 0; g < shp.size(); g++) {
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
ret.codeTable.add((int) glyphToChar(g));
SHAPE shpX = resizeShape(shp.get(g));
ret.glyphShapeTable.add(shpX);
ret.fontBoundsTable.add(getGlyphBounds(g));
}
ret.fontName = getFontNameIntag();
ret.languageCode = new LANGCODE(1);
ret.fontKerningTable = new ArrayList<>();
FontType ft = fonts.get(0);
for (int i = 0; i < ft.kerning.size(); i++) {
KERNINGRECORD kr = new KERNINGRECORD();
kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance);
kr.fontKerningCode1 = ft.kerning.get(i).char1;
kr.fontKerningCode2 = ft.kerning.get(i).char2;
ret.fontKerningTable.add(kr);
}
return ret;
}
@Override
public boolean hasLayout() {
return true;
}
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
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.helpers.FontHelper;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.Tag;
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.ByteArrayRange;
import com.jpexs.helpers.MemoryInputStream;
import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author JPEXS
*/
public final class DefineCompactedFont extends FontTag {
public static final int ID = 1005;
public static final String NAME = "DefineCompactedFont";
public int fontId;
public List<FontType> fonts;
private List<SHAPE> 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) {
throw new Error("This should never happen.", e);
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
*/
public DefineCompactedFont(SWF swf) {
super(swf, ID, NAME, null);
fontId = swf.getNextCharacterId();
fonts = new ArrayList<>();
FontType ft = new FontType();
fonts.add(ft);
rebuildShapeCache();
}
/**
* Constructor
*
* @param sis
* @param data
* @throws IOException
*/
public DefineCompactedFont(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
fonts = new ArrayList<>();
MemoryInputStream mis = sis.getBaseStream();
while (mis.available() > 0) {
GFxInputStream gis = new GFxInputStream(mis);
gis.dumpInfo = sis.dumpInfo;
gis.newDumpLevel("fontType", "FontType");
fonts.add(new FontType(gis));
gis.endDumpLevel();
}
rebuildShapeCache();
}
public void rebuildShapeCache() {
shapeCache = fonts.get(0).getGlyphShapes();
}
@Override
public String getFontNameIntag() {
StringBuilder ret = new StringBuilder();
for (int i = 0; i < fonts.size(); i++) {
if (i > 0) {
ret.append(", ");
}
ret.append(fonts.get(i).fontName);
}
return ret.toString();
}
@Override
public int getCharacterId() {
return fontId;
}
@Override
public void setCharacterId(int characterId) {
this.fontId = characterId;
}
@Override
public int getFontId() {
return fontId;
}
@Override
public List<SHAPE> getGlyphShapeTable() {
return shapeCache;
}
@Override
public void addCharacter(char character, Font cfont) {
int fontStyle = getFontStyle();
FontType font = fonts.get(0);
double d = 1;
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(cfont, (int) (font.nominalSize * d), 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 = cfont.deriveFont(fontStyle, Math.round(font.nominalSize * d));
int advance = (int) Math.round(FontHelper.getFontAdvance(fnt, character));
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());
}
setModified(true);
getSwf().clearImageCache();
}
@Override
public void setAdvanceValues(Font font) {
throw new UnsupportedOperationException("Setting the advance values for DefineCompactedFont is not supported.");
}
@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 resize(fonts.get(0).glyphInfo.get(glyphIndex).advanceX);
}
@Override
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
char c1 = glyphToChar(glyphIndex);
char c2 = glyphToChar(nextGlyphIndex);
return getCharKerningAdjustment(c1, c2);
}
@Override
public int getCharKerningAdjustment(char c1, char c2) {
for (KerningPairType kp : fonts.get(0).kerning) {
if (kp.char1 == c1 && kp.char2 == c2) {
return resize(kp.advance);
}
}
return 0;
}
@Override
public int getGlyphWidth(int glyphIndex) {
return resize(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 double 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<Tag> tags) {
FontType ft = fonts.get(0);
StringBuilder ret = new StringBuilder(ft.glyphInfo.size());
for (GlyphInfoType gi : ft.glyphInfo) {
ret.append((char) gi.glyphCode);
}
return ret.toString();
}
@Override
public RECT getGlyphBounds(int glyphIndex) {
GlyphType gt = fonts.get(0).glyphs.get(glyphIndex);
return new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3]));
}
public SHAPE resizeShape(SHAPE shp) {
SHAPE ret = new SHAPE();
ret.numFillBits = 1;
ret.numLineBits = 0;
List<SHAPERECORD> recs = new ArrayList<>();
for (SHAPERECORD r : shp.shapeRecords) {
SHAPERECORD c = r.clone();
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;
}
protected int resize(double val) {
FontType ft = fonts.get(0);
return (int) Math.round(val * 1024.0 / ft.nominalSize);
}
@Override
public FontTag toClassicFont() {
DefineFont2Tag ret = new DefineFont2Tag(swf);
ret.fontId = getFontId();
ret.fontFlagsBold = isBold();
ret.fontFlagsItalic = isItalic();
ret.fontFlagsWideOffsets = true;
ret.fontFlagsWideCodes = true;
ret.fontFlagsHasLayout = true;
ret.fontAscent = (getAscent());
ret.fontDescent = (getDescent());
ret.fontLeading = (getLeading());
ret.fontAdvanceTable = new ArrayList<>();
ret.fontBoundsTable = new ArrayList<>();
ret.codeTable = new ArrayList<>();
ret.glyphShapeTable = new ArrayList<>();
List<SHAPE> shp = getGlyphShapeTable();
for (int g = 0; g < shp.size(); g++) {
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
ret.codeTable.add((int) glyphToChar(g));
SHAPE shpX = resizeShape(shp.get(g));
ret.glyphShapeTable.add(shpX);
ret.fontBoundsTable.add(getGlyphBounds(g));
}
ret.fontName = getFontNameIntag();
ret.languageCode = new LANGCODE(1);
ret.fontKerningTable = new ArrayList<>();
FontType ft = fonts.get(0);
for (int i = 0; i < ft.kerning.size(); i++) {
KERNINGRECORD kr = new KERNINGRECORD();
kr.fontKerningAdjustment = resize(ft.kerning.get(i).advance);
kr.fontKerningCode1 = ft.kerning.get(i).char1;
kr.fontKerningCode2 = ft.kerning.get(i).char2;
ret.fontKerningTable.add(kr);
}
return ret;
}
@Override
public boolean hasLayout() {
return true;
}
}

View File

@@ -33,6 +33,8 @@ public class DefineExternalGradient extends Tag {
public static final int ID = 1003;
public static final String NAME = "DefineExternalGradient";
public static final int BITMAP_FORMAT_DEFAULT = 0;
public static final int BITMAP_FORMAT_TGA = 1;
@@ -78,7 +80,7 @@ public class DefineExternalGradient extends Tag {
* @throws IOException
*/
public DefineExternalGradient(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineExternalGradient", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -33,6 +33,8 @@ public class DefineExternalImage extends Tag {
public static final int ID = 1001;
public static final String NAME = "DefineExternalImage";
public int characterId;
public int bitmapFormat;
@@ -81,7 +83,7 @@ public class DefineExternalImage extends Tag {
* @throws IOException
*/
public DefineExternalImage(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineExternalImage", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -33,6 +33,8 @@ public class DefineExternalImage2 extends Tag {
public static final int ID = 1009;
public static final String NAME = "DefineExternalImage2";
public long characterId;
public int bitmapFormat;
@@ -91,7 +93,7 @@ public class DefineExternalImage2 extends Tag {
* @throws IOException
*/
public DefineExternalImage2(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineExternalImage2", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -33,6 +33,8 @@ public class DefineExternalSound extends Tag {
public static final int ID = 1006;
public static final String NAME = "DefineExternalSound";
public int characterId;
public int soundFormat;
@@ -91,7 +93,7 @@ public class DefineExternalSound extends Tag {
* @throws IOException
*/
public DefineExternalSound(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineExternalSound", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -33,6 +33,8 @@ public class DefineExternalStreamSound extends Tag {
public static final int ID = 1007;
public static final String NAME = "DefineExternalStreamSound";
public int soundFormat;
public int bits;
@@ -89,7 +91,7 @@ public class DefineExternalStreamSound extends Tag {
* @throws IOException
*/
public DefineExternalStreamSound(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineExternalStreamSound", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -33,6 +33,8 @@ public class DefineGradientMap extends Tag {
public static final int ID = 1004;
public static final String NAME = "DefineGradientMap";
public int[] indices;
/**
@@ -64,7 +66,7 @@ public class DefineGradientMap extends Tag {
* @throws IOException
*/
public DefineGradientMap(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineGradientMap", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -33,6 +33,8 @@ public class DefineSubImage extends Tag {
public static final int ID = 1008;
public static final String NAME = "DefineSubImage";
public int characterId;
public int imageCharacterId;
@@ -76,7 +78,7 @@ public class DefineSubImage extends Tag {
* @throws IOException
*/
public DefineSubImage(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "DefineSubImage", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -35,6 +35,8 @@ public class ExporterInfo extends Tag {
public static final int ID = 1000;
public static final String NAME = "ExporterInfo";
//Version (1.10 will be encoded as 0x10A)
public int version;
@@ -100,7 +102,7 @@ public class ExporterInfo extends Tag {
* @throws IOException
*/
public ExporterInfo(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "ExporterInfo", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}

View File

@@ -38,6 +38,8 @@ public class FontTextureInfo extends Tag {
public static final int ID = 1002;
public static final String NAME = "FontTextureInfo";
public long textureID;
public int textureFormat;
@@ -104,7 +106,7 @@ public class FontTextureInfo extends Tag {
* @throws IOException
*/
public FontTextureInfo(SWFInputStream sis, ByteArrayRange data) throws IOException {
super(sis.getSwf(), ID, "FontTextureInfo", data);
super(sis.getSwf(), ID, NAME, data);
readData(sis, data, 0, false, false, false);
}