mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-07 17:40:30 +00:00
Saving files before refreshing line endings
This commit is contained in:
@@ -1,132 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ApplicationInfo {
|
||||
|
||||
public static final String APPLICATION_NAME = "JPEXS Free Flash Decompiler";
|
||||
|
||||
public static final String SHORT_APPLICATION_NAME = "FFDec";
|
||||
|
||||
public static final String VENDOR = "JPEXS";
|
||||
|
||||
public static String libraryVersion = "";
|
||||
|
||||
public static String version = "";
|
||||
|
||||
public static String revision = "";
|
||||
|
||||
public static int version_major = 4;
|
||||
|
||||
public static int version_minor = 0;
|
||||
|
||||
public static int version_release = 0;
|
||||
|
||||
public static int version_build = 0;
|
||||
|
||||
public static boolean nightly = false;
|
||||
|
||||
public static String applicationVerName;
|
||||
|
||||
public static String shortApplicationVerName;
|
||||
|
||||
public static final String PROJECT_PAGE = "https://www.free-decompiler.com/flash";
|
||||
|
||||
/**
|
||||
* URL for checking new updates
|
||||
*/
|
||||
public static String updateCheckUrl = "https://www.free-decompiler.com/flash/update/check/?currentVersion=<version>¤tRevision=<revision>¤tVersionMajor=<version.major>¤tVersionMinor=<version.minor>¤tVersionRelease=<version.release>¤tVersionBuild=<version.build>¤tNightly=<nightly>";
|
||||
|
||||
/**
|
||||
* URL for doing update
|
||||
*/
|
||||
public static String updateUrl = "https://www.free-decompiler.com/flash/update/update/?currentVersion=<version>¤tRevision=<revision>¤tVersionMajor=<version.major>¤tVersionMinor=<version.minor>¤tVersionRelease=<version.release>¤tVersionBuild=<version.build>¤tNightly=<nightly>";
|
||||
|
||||
static {
|
||||
loadProperties();
|
||||
loadLibraryVersion();
|
||||
}
|
||||
|
||||
private static void loadLibraryVersion() {
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
prop.load(SWF.class.getResourceAsStream("/project.properties"));
|
||||
String version = prop.getProperty("version");
|
||||
int version_build = Integer.parseInt(prop.getProperty("version.build"));
|
||||
boolean nightly = prop.getProperty("nightly").equals("true");
|
||||
if (nightly) {
|
||||
version = version + " nightly build " + version_build;
|
||||
}
|
||||
|
||||
libraryVersion = version;
|
||||
} catch (IOException | NullPointerException | NumberFormatException ex) {
|
||||
// ignore
|
||||
libraryVersion = "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadProperties() {
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
prop.load(ApplicationInfo.class.getResourceAsStream("/project.properties"));
|
||||
version = prop.getProperty("version");
|
||||
revision = prop.getProperty("build");
|
||||
version_major = Integer.parseInt(prop.getProperty("version.major"));
|
||||
version_minor = Integer.parseInt(prop.getProperty("version.minor"));
|
||||
version_release = Integer.parseInt(prop.getProperty("version.release"));
|
||||
version_build = Integer.parseInt(prop.getProperty("version.build"));
|
||||
nightly = prop.getProperty("nightly").equals("true");
|
||||
if (nightly) {
|
||||
version = version + " nightly build " + version_build;
|
||||
}
|
||||
} catch (IOException | NullPointerException | NumberFormatException ex) {
|
||||
// ignore
|
||||
version = "unknown";
|
||||
}
|
||||
try {
|
||||
updateCheckUrl = updateCheckUrl
|
||||
.replace("<revision>", URLEncoder.encode(revision, "UTF-8"))
|
||||
.replace("<version>", URLEncoder.encode(version, "UTF-8"))
|
||||
.replace("<version.major>", "" + version_major)
|
||||
.replace("<version.minor>", "" + version_minor)
|
||||
.replace("<version.release>", "" + version_release)
|
||||
.replace("<version.build>", "" + version_build)
|
||||
.replace("<nightly>", nightly ? "1" : "0");
|
||||
updateUrl = updateUrl
|
||||
.replace("<revision>", URLEncoder.encode(revision, "UTF-8"))
|
||||
.replace("<version>", URLEncoder.encode(version, "UTF-8"))
|
||||
.replace("<version.major>", "" + version_major)
|
||||
.replace("<version.minor>", "" + version_minor)
|
||||
.replace("<version.release>", "" + version_release)
|
||||
.replace("<version.build>", "" + version_build)
|
||||
.replace("<nightly>", nightly ? "1" : "0");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
|
||||
}
|
||||
applicationVerName = APPLICATION_NAME + " v." + version;
|
||||
shortApplicationVerName = SHORT_APPLICATION_NAME + " v." + version;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ApplicationInfo {
|
||||
|
||||
public static final String APPLICATION_NAME = "JPEXS Free Flash Decompiler";
|
||||
|
||||
public static final String SHORT_APPLICATION_NAME = "FFDec";
|
||||
|
||||
public static final String VENDOR = "JPEXS";
|
||||
|
||||
public static String libraryVersion = "";
|
||||
|
||||
public static String version = "";
|
||||
|
||||
public static String revision = "";
|
||||
|
||||
public static int version_major = 4;
|
||||
|
||||
public static int version_minor = 0;
|
||||
|
||||
public static int version_release = 0;
|
||||
|
||||
public static int version_build = 0;
|
||||
|
||||
public static boolean nightly = false;
|
||||
|
||||
public static String applicationVerName;
|
||||
|
||||
public static String shortApplicationVerName;
|
||||
|
||||
public static final String PROJECT_PAGE = "https://www.free-decompiler.com/flash";
|
||||
|
||||
/**
|
||||
* URL for checking new updates
|
||||
*/
|
||||
public static String updateCheckUrl = "https://www.free-decompiler.com/flash/update/check/?currentVersion=<version>¤tRevision=<revision>¤tVersionMajor=<version.major>¤tVersionMinor=<version.minor>¤tVersionRelease=<version.release>¤tVersionBuild=<version.build>¤tNightly=<nightly>";
|
||||
|
||||
/**
|
||||
* URL for doing update
|
||||
*/
|
||||
public static String updateUrl = "https://www.free-decompiler.com/flash/update/update/?currentVersion=<version>¤tRevision=<revision>¤tVersionMajor=<version.major>¤tVersionMinor=<version.minor>¤tVersionRelease=<version.release>¤tVersionBuild=<version.build>¤tNightly=<nightly>";
|
||||
|
||||
static {
|
||||
loadProperties();
|
||||
loadLibraryVersion();
|
||||
}
|
||||
|
||||
private static void loadLibraryVersion() {
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
prop.load(SWF.class.getResourceAsStream("/project.properties"));
|
||||
String version = prop.getProperty("version");
|
||||
int version_build = Integer.parseInt(prop.getProperty("version.build"));
|
||||
boolean nightly = prop.getProperty("nightly").equals("true");
|
||||
if (nightly) {
|
||||
version = version + " nightly build " + version_build;
|
||||
}
|
||||
|
||||
libraryVersion = version;
|
||||
} catch (IOException | NullPointerException | NumberFormatException ex) {
|
||||
// ignore
|
||||
libraryVersion = "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadProperties() {
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
prop.load(ApplicationInfo.class.getResourceAsStream("/project.properties"));
|
||||
version = prop.getProperty("version");
|
||||
revision = prop.getProperty("build");
|
||||
version_major = Integer.parseInt(prop.getProperty("version.major"));
|
||||
version_minor = Integer.parseInt(prop.getProperty("version.minor"));
|
||||
version_release = Integer.parseInt(prop.getProperty("version.release"));
|
||||
version_build = Integer.parseInt(prop.getProperty("version.build"));
|
||||
nightly = prop.getProperty("nightly").equals("true");
|
||||
if (nightly) {
|
||||
version = version + " nightly build " + version_build;
|
||||
}
|
||||
} catch (IOException | NullPointerException | NumberFormatException ex) {
|
||||
// ignore
|
||||
version = "unknown";
|
||||
}
|
||||
try {
|
||||
updateCheckUrl = updateCheckUrl
|
||||
.replace("<revision>", URLEncoder.encode(revision, "UTF-8"))
|
||||
.replace("<version>", URLEncoder.encode(version, "UTF-8"))
|
||||
.replace("<version.major>", "" + version_major)
|
||||
.replace("<version.minor>", "" + version_minor)
|
||||
.replace("<version.release>", "" + version_release)
|
||||
.replace("<version.build>", "" + version_build)
|
||||
.replace("<nightly>", nightly ? "1" : "0");
|
||||
updateUrl = updateUrl
|
||||
.replace("<revision>", URLEncoder.encode(revision, "UTF-8"))
|
||||
.replace("<version>", URLEncoder.encode(version, "UTF-8"))
|
||||
.replace("<version.major>", "" + version_major)
|
||||
.replace("<version.minor>", "" + version_minor)
|
||||
.replace("<version.release>", "" + version_release)
|
||||
.replace("<version.build>", "" + version_build)
|
||||
.replace("<nightly>", nightly ? "1" : "0");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
|
||||
}
|
||||
applicationVerName = APPLICATION_NAME + " v." + version;
|
||||
shortApplicationVerName = SHORT_APPLICATION_NAME + " v." + version;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,21 @@
|
||||
package com.jpexs.decompiler.flash.abc.types;
|
||||
|
||||
public class Float4 {
|
||||
|
||||
public float[] values = new float[4];
|
||||
|
||||
public Float4(float value1, float value2, float value3, float value4) {
|
||||
this.values = new float[]{value1, value2, value3, value4};
|
||||
}
|
||||
|
||||
public Float4(float[] values) {
|
||||
if (values == null || values.length < 4) {
|
||||
throw new IllegalArgumentException("Invalid values size");
|
||||
}
|
||||
this.values[0] = values[0];
|
||||
this.values[1] = values[1];
|
||||
this.values[2] = values[2];
|
||||
this.values[3] = values[3];
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.abc.types;
|
||||
|
||||
public class Float4 {
|
||||
|
||||
public float[] values = new float[4];
|
||||
|
||||
public Float4(float value1, float value2, float value3, float value4) {
|
||||
this.values = new float[]{value1, value2, value3, value4};
|
||||
}
|
||||
|
||||
public Float4(float[] values) {
|
||||
if (values == null || values.length < 4) {
|
||||
throw new IllegalArgumentException("Invalid values size");
|
||||
}
|
||||
this.values[0] = values[0];
|
||||
this.values[1] = values[1];
|
||||
this.values[2] = values[2];
|
||||
this.values[3] = values[3];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum DumpInfoSpecialType {
|
||||
NONE, ZLIB_DATA,
|
||||
TAG,
|
||||
ACTION_BYTES,
|
||||
ABC_BYTES, ABC_METHOD_BODY, ABC_CODE
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum DumpInfoSpecialType {
|
||||
NONE, ZLIB_DATA,
|
||||
TAG,
|
||||
ACTION_BYTES,
|
||||
ABC_BYTES, ABC_METHOD_BODY, ABC_CODE
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,138 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.importers.svg;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SvgPathReader {
|
||||
|
||||
private final String str;
|
||||
|
||||
private int pos;
|
||||
|
||||
public SvgPathReader(String str) {
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return pos < str.length();
|
||||
}
|
||||
|
||||
public char peek() {
|
||||
return str.charAt(pos);
|
||||
}
|
||||
|
||||
public char readChar() {
|
||||
char ch = str.charAt(pos);
|
||||
pos++;
|
||||
return ch;
|
||||
}
|
||||
|
||||
public char readCommand() {
|
||||
if (!hasNext()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
readWhiteSpaces();
|
||||
char ch = peek();
|
||||
char command = 0;
|
||||
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
|
||||
command = ch;
|
||||
pos++;
|
||||
readSeparators();
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
private void digitSequence() {
|
||||
while (hasNext()) {
|
||||
char ch = str.charAt(pos);
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
public double readDouble() {
|
||||
int startPos = pos;
|
||||
|
||||
readWhiteSpaces();
|
||||
char ch = str.charAt(pos);
|
||||
if (ch == '-') {
|
||||
pos++;
|
||||
}
|
||||
|
||||
digitSequence();
|
||||
ch = str.charAt(pos);
|
||||
if (ch == '.') {
|
||||
pos++;
|
||||
digitSequence();
|
||||
}
|
||||
|
||||
ch = str.charAt(pos);
|
||||
if (ch == 'e') {
|
||||
pos++;
|
||||
ch = str.charAt(pos);
|
||||
if (ch == '-') {
|
||||
pos++;
|
||||
}
|
||||
|
||||
digitSequence();
|
||||
}
|
||||
|
||||
boolean ok = false;
|
||||
try {
|
||||
double result = Double.parseDouble(str.substring(startPos, pos));
|
||||
readSeparators();
|
||||
ok = true;
|
||||
return result;
|
||||
} finally {
|
||||
if (!ok) {
|
||||
pos = startPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readWhiteSpaces() {
|
||||
while (hasNext()) {
|
||||
char ch = peek();
|
||||
if (ch != ' ' && ch != '\r' && ch != '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
readChar();
|
||||
}
|
||||
}
|
||||
|
||||
private void readSeparators() {
|
||||
while (hasNext()) {
|
||||
char ch = peek();
|
||||
if (ch != ' ' && ch != ',' && ch != '\r' && ch != '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
readChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.importers.svg;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SvgPathReader {
|
||||
|
||||
private final String str;
|
||||
|
||||
private int pos;
|
||||
|
||||
public SvgPathReader(String str) {
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return pos < str.length();
|
||||
}
|
||||
|
||||
public char peek() {
|
||||
return str.charAt(pos);
|
||||
}
|
||||
|
||||
public char readChar() {
|
||||
char ch = str.charAt(pos);
|
||||
pos++;
|
||||
return ch;
|
||||
}
|
||||
|
||||
public char readCommand() {
|
||||
if (!hasNext()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
readWhiteSpaces();
|
||||
char ch = peek();
|
||||
char command = 0;
|
||||
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
|
||||
command = ch;
|
||||
pos++;
|
||||
readSeparators();
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
private void digitSequence() {
|
||||
while (hasNext()) {
|
||||
char ch = str.charAt(pos);
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
public double readDouble() {
|
||||
int startPos = pos;
|
||||
|
||||
readWhiteSpaces();
|
||||
char ch = str.charAt(pos);
|
||||
if (ch == '-') {
|
||||
pos++;
|
||||
}
|
||||
|
||||
digitSequence();
|
||||
ch = str.charAt(pos);
|
||||
if (ch == '.') {
|
||||
pos++;
|
||||
digitSequence();
|
||||
}
|
||||
|
||||
ch = str.charAt(pos);
|
||||
if (ch == 'e') {
|
||||
pos++;
|
||||
ch = str.charAt(pos);
|
||||
if (ch == '-') {
|
||||
pos++;
|
||||
}
|
||||
|
||||
digitSequence();
|
||||
}
|
||||
|
||||
boolean ok = false;
|
||||
try {
|
||||
double result = Double.parseDouble(str.substring(startPos, pos));
|
||||
readSeparators();
|
||||
ok = true;
|
||||
return result;
|
||||
} finally {
|
||||
if (!ok) {
|
||||
pos = startPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readWhiteSpaces() {
|
||||
while (hasNext()) {
|
||||
char ch = peek();
|
||||
if (ch != ' ' && ch != '\r' && ch != '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
readChar();
|
||||
}
|
||||
}
|
||||
|
||||
private void readSeparators() {
|
||||
while (hasNext()) {
|
||||
char ch = peek();
|
||||
if (ch != ' ' && ch != ',' && ch != '\r' && ch != '\n') {
|
||||
return;
|
||||
}
|
||||
|
||||
readChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,239 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
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.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 3) //Note: GIF and PNG since version
|
||||
public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 35;
|
||||
|
||||
public static final String NAME = "DefineBitsJPEG3";
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange imageData;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange bitmapAlphaData;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsJPEG3Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
characterID = swf.getNextCharacterId();
|
||||
imageData = new ByteArrayRange(createEmptyImage());
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsJPEG3Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
this.imageData = new ByteArrayRange(imageData);
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param sis
|
||||
* @param data
|
||||
* @throws IOException
|
||||
*/
|
||||
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.readByteRangeEx(sis.available(), "bitmapAlphaData", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI32(imageData.getLength());
|
||||
sos.write(imageData);
|
||||
sos.write(bitmapAlphaData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
ImageHelper.write(img, ImageFormat.JPEG, bitmapDataOS);
|
||||
return bitmapDataOS.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
if (ImageTag.getImageFormat(data) == ImageFormat.JPEG) {
|
||||
BufferedImage image = ImageHelper.read(data);
|
||||
byte[] ba = new byte[image.getWidth() * image.getHeight()];
|
||||
for (int i = 0; i < ba.length; i++) {
|
||||
ba[i] = (byte) 255;
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(ba));
|
||||
} else {
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(new byte[0]));
|
||||
}
|
||||
|
||||
imageData = new ByteArrayRange(data);
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public byte[] getImageAlpha() throws IOException {
|
||||
return SWFInputStream.uncompressByteArray(bitmapAlphaData.getRangeData());
|
||||
}
|
||||
|
||||
public void setImageAlpha(byte[] data) throws IOException {
|
||||
ImageFormat fmt = ImageTag.getImageFormat(imageData);
|
||||
if (fmt != ImageFormat.JPEG) {
|
||||
throw new IOException("Only Jpeg can have alpha channel.");
|
||||
}
|
||||
|
||||
Dimension dimension = getImageDimension();
|
||||
if (data == null || data.length != dimension.getWidth() * dimension.getHeight()) {
|
||||
throw new IOException("Data length must match the size of the image.");
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(data));
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
ImageFormat fmt = getOriginalImageFormat();
|
||||
if (fmt == ImageFormat.JPEG && bitmapAlphaData.getLength() > 0) {
|
||||
fmt = ImageFormat.PNG; //transparency
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageTag.getImageFormat(imageData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
if (bitmapAlphaData.getLength() == 0) { // No alpha
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
try {
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
|
||||
BufferedImage image = ImageHelper.read(bis);
|
||||
if (image == null) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
|
||||
return null;
|
||||
}
|
||||
|
||||
SerializableImage img = new SerializableImage(image);
|
||||
if (bitmapAlphaData.getLength() == 0) {
|
||||
return img;
|
||||
}
|
||||
|
||||
byte[] alphaData = getImageAlpha();
|
||||
if (alphaData.length == 0) {
|
||||
return img;
|
||||
}
|
||||
|
||||
int width = img.getWidth();
|
||||
int height = img.getHeight();
|
||||
SerializableImage img2 = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
|
||||
int[] pixels2 = ((DataBufferInt) img2.getRaster().getDataBuffer()).getData();
|
||||
for (int i = 0; i < pixels.length; i++) {
|
||||
int a = alphaData[i] & 0xff;
|
||||
pixels2[i] = (pixels[i] & 0xffffff) | (a << 24);
|
||||
}
|
||||
|
||||
return img2;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
if (cachedImage != null) {
|
||||
return new Dimension(cachedImage.getWidth(), cachedImage.getHeight());
|
||||
}
|
||||
|
||||
try {
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
return ImageHelper.getDimesion(bis);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image dimension", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
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.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 3) //Note: GIF and PNG since version
|
||||
public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 35;
|
||||
|
||||
public static final String NAME = "DefineBitsJPEG3";
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange imageData;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange bitmapAlphaData;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsJPEG3Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
characterID = swf.getNextCharacterId();
|
||||
imageData = new ByteArrayRange(createEmptyImage());
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsJPEG3Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
this.imageData = new ByteArrayRange(imageData);
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param sis
|
||||
* @param data
|
||||
* @throws IOException
|
||||
*/
|
||||
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.readByteRangeEx(sis.available(), "bitmapAlphaData", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI32(imageData.getLength());
|
||||
sos.write(imageData);
|
||||
sos.write(bitmapAlphaData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
ImageHelper.write(img, ImageFormat.JPEG, bitmapDataOS);
|
||||
return bitmapDataOS.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
if (ImageTag.getImageFormat(data) == ImageFormat.JPEG) {
|
||||
BufferedImage image = ImageHelper.read(data);
|
||||
byte[] ba = new byte[image.getWidth() * image.getHeight()];
|
||||
for (int i = 0; i < ba.length; i++) {
|
||||
ba[i] = (byte) 255;
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(ba));
|
||||
} else {
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(new byte[0]));
|
||||
}
|
||||
|
||||
imageData = new ByteArrayRange(data);
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public byte[] getImageAlpha() throws IOException {
|
||||
return SWFInputStream.uncompressByteArray(bitmapAlphaData.getRangeData());
|
||||
}
|
||||
|
||||
public void setImageAlpha(byte[] data) throws IOException {
|
||||
ImageFormat fmt = ImageTag.getImageFormat(imageData);
|
||||
if (fmt != ImageFormat.JPEG) {
|
||||
throw new IOException("Only Jpeg can have alpha channel.");
|
||||
}
|
||||
|
||||
Dimension dimension = getImageDimension();
|
||||
if (data == null || data.length != dimension.getWidth() * dimension.getHeight()) {
|
||||
throw new IOException("Data length must match the size of the image.");
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(data));
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
ImageFormat fmt = getOriginalImageFormat();
|
||||
if (fmt == ImageFormat.JPEG && bitmapAlphaData.getLength() > 0) {
|
||||
fmt = ImageFormat.PNG; //transparency
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageTag.getImageFormat(imageData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
if (bitmapAlphaData.getLength() == 0) { // No alpha
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
try {
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
|
||||
BufferedImage image = ImageHelper.read(bis);
|
||||
if (image == null) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to load image");
|
||||
return null;
|
||||
}
|
||||
|
||||
SerializableImage img = new SerializableImage(image);
|
||||
if (bitmapAlphaData.getLength() == 0) {
|
||||
return img;
|
||||
}
|
||||
|
||||
byte[] alphaData = getImageAlpha();
|
||||
if (alphaData.length == 0) {
|
||||
return img;
|
||||
}
|
||||
|
||||
int width = img.getWidth();
|
||||
int height = img.getHeight();
|
||||
SerializableImage img2 = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
|
||||
int[] pixels2 = ((DataBufferInt) img2.getRaster().getDataBuffer()).getData();
|
||||
for (int i = 0; i < pixels.length; i++) {
|
||||
int a = alphaData[i] & 0xff;
|
||||
pixels2[i] = (pixels[i] & 0xffffff) | (a << 24);
|
||||
}
|
||||
|
||||
return img2;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
if (cachedImage != null) {
|
||||
return new Dimension(cachedImage.getWidth(), cachedImage.getHeight());
|
||||
}
|
||||
|
||||
try {
|
||||
int errorLength = hasErrorHeader(imageData) ? 4 : 0;
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos() + errorLength, imageData.getLength() - errorLength);
|
||||
return ImageHelper.getDimesion(bis);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image dimension", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,239 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
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.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 10)
|
||||
public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 90;
|
||||
|
||||
public static final String NAME = "DefineBitsJPEG4";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int deblockParam;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange imageData;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange bitmapAlphaData;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsJPEG4Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
characterID = swf.getNextCharacterId();
|
||||
imageData = new ByteArrayRange(createEmptyImage());
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsJPEG4Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
this.imageData = new ByteArrayRange(imageData);
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI32(imageData.getLength());
|
||||
sos.writeUI16(deblockParam);
|
||||
sos.write(imageData);
|
||||
sos.write(bitmapAlphaData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
ImageHelper.write(img, ImageFormat.JPEG, bitmapDataOS);
|
||||
return bitmapDataOS.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
if (ImageTag.getImageFormat(data) == ImageFormat.JPEG) {
|
||||
BufferedImage image = ImageHelper.read(data);
|
||||
byte[] ba = new byte[image.getWidth() * image.getHeight()];
|
||||
for (int i = 0; i < ba.length; i++) {
|
||||
ba[i] = (byte) 255;
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(ba));
|
||||
} else {
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(new byte[0]));
|
||||
}
|
||||
|
||||
imageData = new ByteArrayRange(data);
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public byte[] getImageAlpha() throws IOException {
|
||||
return SWFInputStream.uncompressByteArray(bitmapAlphaData.getRangeData());
|
||||
}
|
||||
|
||||
public void setImageAlpha(byte[] data) throws IOException {
|
||||
ImageFormat fmt = ImageTag.getImageFormat(imageData);
|
||||
if (fmt != ImageFormat.JPEG) {
|
||||
throw new IOException("Only Jpeg can have alpha channel.");
|
||||
}
|
||||
|
||||
Dimension dimension = getImageDimension();
|
||||
if (data == null || data.length != dimension.getWidth() * dimension.getHeight()) {
|
||||
throw new IOException("Data length must match the size of the image.");
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(data));
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
ImageFormat fmt = getOriginalImageFormat();
|
||||
if (fmt == ImageFormat.JPEG && bitmapAlphaData.getLength() > 0) {
|
||||
fmt = ImageFormat.PNG; //transparency
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageTag.getImageFormat(imageData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
if (bitmapAlphaData.getLength() == 0) { // No alpha
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
try {
|
||||
BufferedImage image = ImageHelper.read(new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength()));
|
||||
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) {
|
||||
return img;
|
||||
}
|
||||
|
||||
byte[] alphaData = getImageAlpha();
|
||||
if (alphaData.length == 0) {
|
||||
return img;
|
||||
}
|
||||
|
||||
int width = img.getWidth();
|
||||
int height = img.getHeight();
|
||||
SerializableImage img2 = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
|
||||
int[] pixels2 = ((DataBufferInt) img2.getRaster().getDataBuffer()).getData();
|
||||
for (int i = 0; i < pixels.length; i++) {
|
||||
int a = alphaData[i] & 0xff;
|
||||
pixels2[i] = (pixels[i] & 0xffffff) | (a << 24);
|
||||
}
|
||||
|
||||
return img2;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
if (cachedImage != null) {
|
||||
return new Dimension(cachedImage.getWidth(), cachedImage.getHeight());
|
||||
}
|
||||
|
||||
try {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
|
||||
return ImageHelper.getDimesion(bis);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image dimension", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
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.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 10)
|
||||
public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 90;
|
||||
|
||||
public static final String NAME = "DefineBitsJPEG4";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int deblockParam;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange imageData;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public ByteArrayRange bitmapAlphaData;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsJPEG4Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
characterID = swf.getNextCharacterId();
|
||||
imageData = new ByteArrayRange(createEmptyImage());
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsJPEG4Tag(SWF swf, ByteArrayRange data, int characterID, byte[] imageData) throws IOException {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
this.imageData = new ByteArrayRange(imageData);
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI32(imageData.getLength());
|
||||
sos.writeUI16(deblockParam);
|
||||
sos.write(imageData);
|
||||
sos.write(bitmapAlphaData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
ImageHelper.write(img, ImageFormat.JPEG, bitmapDataOS);
|
||||
return bitmapDataOS.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
if (ImageTag.getImageFormat(data) == ImageFormat.JPEG) {
|
||||
BufferedImage image = ImageHelper.read(data);
|
||||
byte[] ba = new byte[image.getWidth() * image.getHeight()];
|
||||
for (int i = 0; i < ba.length; i++) {
|
||||
ba[i] = (byte) 255;
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(ba));
|
||||
} else {
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(new byte[0]));
|
||||
}
|
||||
|
||||
imageData = new ByteArrayRange(data);
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public byte[] getImageAlpha() throws IOException {
|
||||
return SWFInputStream.uncompressByteArray(bitmapAlphaData.getRangeData());
|
||||
}
|
||||
|
||||
public void setImageAlpha(byte[] data) throws IOException {
|
||||
ImageFormat fmt = ImageTag.getImageFormat(imageData);
|
||||
if (fmt != ImageFormat.JPEG) {
|
||||
throw new IOException("Only Jpeg can have alpha channel.");
|
||||
}
|
||||
|
||||
Dimension dimension = getImageDimension();
|
||||
if (data == null || data.length != dimension.getWidth() * dimension.getHeight()) {
|
||||
throw new IOException("Data length must match the size of the image.");
|
||||
}
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(data));
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
ImageFormat fmt = getOriginalImageFormat();
|
||||
if (fmt == ImageFormat.JPEG && bitmapAlphaData.getLength() > 0) {
|
||||
fmt = ImageFormat.PNG; //transparency
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageTag.getImageFormat(imageData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
if (bitmapAlphaData.getLength() == 0) { // No alpha
|
||||
return new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
try {
|
||||
BufferedImage image = ImageHelper.read(new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength()));
|
||||
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) {
|
||||
return img;
|
||||
}
|
||||
|
||||
byte[] alphaData = getImageAlpha();
|
||||
if (alphaData.length == 0) {
|
||||
return img;
|
||||
}
|
||||
|
||||
int width = img.getWidth();
|
||||
int height = img.getHeight();
|
||||
SerializableImage img2 = new SerializableImage(width, height, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
|
||||
int[] pixels2 = ((DataBufferInt) img2.getRaster().getDataBuffer()).getData();
|
||||
for (int i = 0; i < pixels.length; i++) {
|
||||
int a = alphaData[i] & 0xff;
|
||||
pixels2[i] = (pixels[i] & 0xffffff) | (a << 24);
|
||||
}
|
||||
|
||||
return img2;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG4Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
if (cachedImage != null) {
|
||||
return new Dimension(cachedImage.getWidth(), cachedImage.getHeight());
|
||||
}
|
||||
|
||||
try {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength());
|
||||
return ImageHelper.getDimesion(bis);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image dimension", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,281 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 3)
|
||||
public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 36;
|
||||
|
||||
public static final String NAME = "DefineBitsLossless2";
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public int bitmapFormat;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapWidth;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapHeight;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
@Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED})
|
||||
public int bitmapColorTableSize;
|
||||
|
||||
public ByteArrayRange zlibBitmapData;
|
||||
|
||||
public static final int FORMAT_8BIT_COLORMAPPED = 3;
|
||||
|
||||
public static final int FORMAT_32BIT_ARGB = 5;
|
||||
|
||||
@HideInRawEdit
|
||||
private ALPHACOLORMAPDATA colorMapData;
|
||||
|
||||
@HideInRawEdit
|
||||
private ALPHABITMAPDATA bitmapData;
|
||||
|
||||
@Internal
|
||||
private boolean decompressed = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsLossless2Tag(SWF swf) {
|
||||
this(swf, null, swf.getNextCharacterId());
|
||||
}
|
||||
|
||||
public DefineBitsLossless2Tag(SWF swf, ByteArrayRange data, int characterID) {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
bitmapFormat = DefineBitsLossless2Tag.FORMAT_32BIT_ARGB;
|
||||
bitmapWidth = 1;
|
||||
bitmapHeight = 1;
|
||||
zlibBitmapData = new ByteArrayRange(createEmptyImage());
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsLossless2Tag(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");
|
||||
bitmapFormat = sis.readUI8("bitmapFormat");
|
||||
bitmapWidth = sis.readUI16("bitmapWidth");
|
||||
bitmapHeight = sis.readUI16("bitmapHeight");
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
bitmapColorTableSize = sis.readUI8("bitmapColorTableSize");
|
||||
}
|
||||
|
||||
zlibBitmapData = sis.readByteRangeEx(sis.available(), "zlibBitmapData", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI8(bitmapFormat);
|
||||
sos.writeUI16(bitmapWidth);
|
||||
sos.writeUI16(bitmapHeight);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
sos.writeUI8(bitmapColorTableSize);
|
||||
}
|
||||
sos.write(zlibBitmapData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
try {
|
||||
ALPHABITMAPDATA bitmapData = new ALPHABITMAPDATA();
|
||||
bitmapData.bitmapPixelData = new int[]{0xff000000};
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeALPHABITMAPDATA(bitmapData, FORMAT_32BIT_ARGB, 1, 1);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
return zlibOS.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsLossless2Tag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
SerializableImage image = new SerializableImage(ImageHelper.read(data));
|
||||
ALPHABITMAPDATA bitmapData = new ALPHABITMAPDATA();
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
bitmapData.bitmapPixelData = new int[width * height];
|
||||
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
for (int pos = 0; pos < pixels.length; pos++) {
|
||||
int argb = pixels[pos];
|
||||
int a = (argb >> 24) & 0xff;
|
||||
int r = (argb >> 16) & 0xff;
|
||||
int g = (argb >> 8) & 0xff;
|
||||
int b = argb & 0xff;
|
||||
|
||||
r = r * a / 255;
|
||||
g = g * a / 255;
|
||||
b = b * a / 255;
|
||||
|
||||
bitmapData.bitmapPixelData[pos] = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
||||
}
|
||||
|
||||
int format = FORMAT_32BIT_ARGB;
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeALPHABITMAPDATA(bitmapData, format, width, height);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
zlibBitmapData = new ByteArrayRange(zlibOS.toByteArray());
|
||||
bitmapFormat = format;
|
||||
bitmapWidth = width;
|
||||
bitmapHeight = height;
|
||||
decompressed = false;
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public ALPHACOLORMAPDATA getColorMapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return colorMapData;
|
||||
}
|
||||
|
||||
public ALPHABITMAPDATA getBitmapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return bitmapData;
|
||||
}
|
||||
|
||||
private void uncompressData() {
|
||||
try {
|
||||
byte[] uncompressedData = SWFInputStream.uncompressByteArray(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength());
|
||||
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
colorMapData = sis.readALPHACOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
|
||||
} else if (bitmapFormat == FORMAT_32BIT_ARGB) {
|
||||
bitmapData = sis.readALPHABITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
decompressed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
int[] pixels = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
|
||||
|
||||
ALPHACOLORMAPDATA colorMapData = null;
|
||||
ALPHABITMAPDATA bitmapData = null;
|
||||
if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED) {
|
||||
colorMapData = getColorMapData();
|
||||
}
|
||||
if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB) {
|
||||
bitmapData = getBitmapData();
|
||||
}
|
||||
int pos32aligned = 0;
|
||||
int pos = 0;
|
||||
for (int y = 0; y < bitmapHeight; y++) {
|
||||
for (int x = 0; x < bitmapWidth; x++) {
|
||||
int c = 0;
|
||||
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) {
|
||||
int colorTableIndex = colorMapData.colorMapPixelData[pos32aligned] & 0xff;
|
||||
if (colorTableIndex < colorMapData.colorTableRGB.length) {
|
||||
c = colorMapData.colorTableRGB[colorTableIndex];
|
||||
}
|
||||
}
|
||||
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB)) {
|
||||
c = bitmapData.bitmapPixelData[pos];
|
||||
}
|
||||
|
||||
pixels[pos] = c;
|
||||
pos32aligned++;
|
||||
pos++;
|
||||
}
|
||||
while ((pos32aligned % 4 != 0)) {
|
||||
pos32aligned++;
|
||||
}
|
||||
}
|
||||
|
||||
return bi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
return new Dimension(bitmapWidth, bitmapHeight);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 3)
|
||||
public class DefineBitsLossless2Tag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 36;
|
||||
|
||||
public static final String NAME = "DefineBitsLossless2";
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public int bitmapFormat;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapWidth;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapHeight;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
@Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED})
|
||||
public int bitmapColorTableSize;
|
||||
|
||||
public ByteArrayRange zlibBitmapData;
|
||||
|
||||
public static final int FORMAT_8BIT_COLORMAPPED = 3;
|
||||
|
||||
public static final int FORMAT_32BIT_ARGB = 5;
|
||||
|
||||
@HideInRawEdit
|
||||
private ALPHACOLORMAPDATA colorMapData;
|
||||
|
||||
@HideInRawEdit
|
||||
private ALPHABITMAPDATA bitmapData;
|
||||
|
||||
@Internal
|
||||
private boolean decompressed = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsLossless2Tag(SWF swf) {
|
||||
this(swf, null, swf.getNextCharacterId());
|
||||
}
|
||||
|
||||
public DefineBitsLossless2Tag(SWF swf, ByteArrayRange data, int characterID) {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
bitmapFormat = DefineBitsLossless2Tag.FORMAT_32BIT_ARGB;
|
||||
bitmapWidth = 1;
|
||||
bitmapHeight = 1;
|
||||
zlibBitmapData = new ByteArrayRange(createEmptyImage());
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsLossless2Tag(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");
|
||||
bitmapFormat = sis.readUI8("bitmapFormat");
|
||||
bitmapWidth = sis.readUI16("bitmapWidth");
|
||||
bitmapHeight = sis.readUI16("bitmapHeight");
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
bitmapColorTableSize = sis.readUI8("bitmapColorTableSize");
|
||||
}
|
||||
|
||||
zlibBitmapData = sis.readByteRangeEx(sis.available(), "zlibBitmapData", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI8(bitmapFormat);
|
||||
sos.writeUI16(bitmapWidth);
|
||||
sos.writeUI16(bitmapHeight);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
sos.writeUI8(bitmapColorTableSize);
|
||||
}
|
||||
sos.write(zlibBitmapData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
try {
|
||||
ALPHABITMAPDATA bitmapData = new ALPHABITMAPDATA();
|
||||
bitmapData.bitmapPixelData = new int[]{0xff000000};
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeALPHABITMAPDATA(bitmapData, FORMAT_32BIT_ARGB, 1, 1);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
return zlibOS.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsLossless2Tag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
SerializableImage image = new SerializableImage(ImageHelper.read(data));
|
||||
ALPHABITMAPDATA bitmapData = new ALPHABITMAPDATA();
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
bitmapData.bitmapPixelData = new int[width * height];
|
||||
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
for (int pos = 0; pos < pixels.length; pos++) {
|
||||
int argb = pixels[pos];
|
||||
int a = (argb >> 24) & 0xff;
|
||||
int r = (argb >> 16) & 0xff;
|
||||
int g = (argb >> 8) & 0xff;
|
||||
int b = argb & 0xff;
|
||||
|
||||
r = r * a / 255;
|
||||
g = g * a / 255;
|
||||
b = b * a / 255;
|
||||
|
||||
bitmapData.bitmapPixelData[pos] = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
||||
}
|
||||
|
||||
int format = FORMAT_32BIT_ARGB;
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeALPHABITMAPDATA(bitmapData, format, width, height);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
zlibBitmapData = new ByteArrayRange(zlibOS.toByteArray());
|
||||
bitmapFormat = format;
|
||||
bitmapWidth = width;
|
||||
bitmapHeight = height;
|
||||
decompressed = false;
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public ALPHACOLORMAPDATA getColorMapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return colorMapData;
|
||||
}
|
||||
|
||||
public ALPHABITMAPDATA getBitmapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return bitmapData;
|
||||
}
|
||||
|
||||
private void uncompressData() {
|
||||
try {
|
||||
byte[] uncompressedData = SWFInputStream.uncompressByteArray(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength());
|
||||
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
colorMapData = sis.readALPHACOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
|
||||
} else if (bitmapFormat == FORMAT_32BIT_ARGB) {
|
||||
bitmapData = sis.readALPHABITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
decompressed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
int[] pixels = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
|
||||
|
||||
ALPHACOLORMAPDATA colorMapData = null;
|
||||
ALPHABITMAPDATA bitmapData = null;
|
||||
if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED) {
|
||||
colorMapData = getColorMapData();
|
||||
}
|
||||
if (bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB) {
|
||||
bitmapData = getBitmapData();
|
||||
}
|
||||
int pos32aligned = 0;
|
||||
int pos = 0;
|
||||
for (int y = 0; y < bitmapHeight; y++) {
|
||||
for (int x = 0; x < bitmapWidth; x++) {
|
||||
int c = 0;
|
||||
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) {
|
||||
int colorTableIndex = colorMapData.colorMapPixelData[pos32aligned] & 0xff;
|
||||
if (colorTableIndex < colorMapData.colorTableRGB.length) {
|
||||
c = colorMapData.colorTableRGB[colorTableIndex];
|
||||
}
|
||||
}
|
||||
if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_32BIT_ARGB)) {
|
||||
c = bitmapData.bitmapPixelData[pos];
|
||||
}
|
||||
|
||||
pixels[pos] = c;
|
||||
pos32aligned++;
|
||||
pos++;
|
||||
}
|
||||
while ((pos32aligned % 4 != 0)) {
|
||||
pos32aligned++;
|
||||
}
|
||||
}
|
||||
|
||||
return bi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
return new Dimension(bitmapWidth, bitmapHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,281 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.BITMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.COLORMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 2)
|
||||
public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 20;
|
||||
|
||||
public static final String NAME = "DefineBitsLossless";
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public int bitmapFormat;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapWidth;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapHeight;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
@Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED})
|
||||
public int bitmapColorTableSize;
|
||||
|
||||
public ByteArrayRange zlibBitmapData;
|
||||
|
||||
public static final int FORMAT_8BIT_COLORMAPPED = 3;
|
||||
|
||||
public static final int FORMAT_15BIT_RGB = 4;
|
||||
|
||||
public static final int FORMAT_24BIT_RGB = 5;
|
||||
|
||||
@HideInRawEdit
|
||||
private COLORMAPDATA colorMapData;
|
||||
|
||||
@HideInRawEdit
|
||||
private BITMAPDATA bitmapData;
|
||||
|
||||
@Internal
|
||||
private boolean decompressed = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsLosslessTag(SWF swf) {
|
||||
this(swf, null, swf.getNextCharacterId());
|
||||
}
|
||||
|
||||
public DefineBitsLosslessTag(SWF swf, ByteArrayRange data, int characterID) {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
bitmapFormat = DefineBitsLosslessTag.FORMAT_24BIT_RGB;
|
||||
bitmapWidth = 1;
|
||||
bitmapHeight = 1;
|
||||
zlibBitmapData = new ByteArrayRange(createEmptyImage());
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsLosslessTag(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");
|
||||
bitmapFormat = sis.readUI8("bitmapFormat");
|
||||
bitmapWidth = sis.readUI16("bitmapWidth");
|
||||
bitmapHeight = sis.readUI16("bitmapHeight");
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
bitmapColorTableSize = sis.readUI8("bitmapColorTableSize");
|
||||
}
|
||||
|
||||
zlibBitmapData = sis.readByteRangeEx(sis.available(), "zlibBitmapData", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI8(bitmapFormat);
|
||||
sos.writeUI16(bitmapWidth);
|
||||
sos.writeUI16(bitmapHeight);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
sos.writeUI8(bitmapColorTableSize);
|
||||
}
|
||||
sos.write(zlibBitmapData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
try {
|
||||
BITMAPDATA bitmapData = new BITMAPDATA();
|
||||
bitmapData.bitmapPixelDataPix24 = new int[]{0xff000000};
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeBITMAPDATA(bitmapData, FORMAT_24BIT_RGB, 1, 1);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
return zlibOS.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsLosslessTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
SerializableImage image = new SerializableImage(ImageHelper.read(data));
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
bitmapData = new BITMAPDATA();
|
||||
bitmapData.bitmapPixelDataPix24 = new int[width * height];
|
||||
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
for (int pos = 0; pos < pixels.length; pos++) {
|
||||
// set the reserved bits to 0xff, because:
|
||||
// documentation says 0, but image is sometimes broken with 0, so there is 0xff, which works (maybe alpha?)
|
||||
int argb = pixels[pos] | 0xff000000;
|
||||
bitmapData.bitmapPixelDataPix24[pos] = argb;
|
||||
}
|
||||
|
||||
int format = FORMAT_24BIT_RGB;
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeBITMAPDATA(bitmapData, format, width, height);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
zlibBitmapData = new ByteArrayRange(zlibOS.toByteArray());
|
||||
bitmapFormat = format;
|
||||
bitmapWidth = width;
|
||||
bitmapHeight = height;
|
||||
decompressed = false;
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public COLORMAPDATA getColorMapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return colorMapData;
|
||||
}
|
||||
|
||||
public BITMAPDATA getBitmapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return bitmapData;
|
||||
}
|
||||
|
||||
private void uncompressData() {
|
||||
try {
|
||||
byte[] uncompressedData = SWFInputStream.uncompressByteArray(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength());
|
||||
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
|
||||
} else if ((bitmapFormat == FORMAT_15BIT_RGB) || (bitmapFormat == FORMAT_24BIT_RGB)) {
|
||||
bitmapData = sis.readBITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
decompressed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
int[] pixels = new int[bitmapWidth * bitmapHeight];
|
||||
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) {
|
||||
COLORMAPDATA colorMapData = getColorMapData();
|
||||
int pos32aligned = 0;
|
||||
int pos = 0;
|
||||
for (int y = 0; y < bitmapHeight; y++) {
|
||||
for (int x = 0; x < bitmapWidth; x++) {
|
||||
int c = 0;
|
||||
int colorTableIndex = colorMapData.colorMapPixelData[pos32aligned] & 0xff;
|
||||
if (colorTableIndex < colorMapData.colorTableRGB.length) {
|
||||
c = colorMapData.colorTableRGB[colorTableIndex];
|
||||
}
|
||||
|
||||
pixels[pos++] = c;
|
||||
pos32aligned++;
|
||||
}
|
||||
|
||||
while ((pos32aligned % 4 != 0)) {
|
||||
pos32aligned++;
|
||||
}
|
||||
}
|
||||
} else if ((bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) || (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB)) {
|
||||
BITMAPDATA bitmapData = getBitmapData();
|
||||
int pos = 0;
|
||||
int[] bitmapPixelData = null;
|
||||
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) {
|
||||
bitmapPixelData = bitmapData.bitmapPixelDataPix15;
|
||||
} else if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) {
|
||||
bitmapPixelData = bitmapData.bitmapPixelDataPix24;
|
||||
}
|
||||
|
||||
for (int y = 0; y < bitmapHeight; y++) {
|
||||
for (int x = 0; x < bitmapWidth; x++) {
|
||||
int c = bitmapPixelData[pos] | 0xff000000;
|
||||
pixels[pos++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_RGB, pixels);
|
||||
return bi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
return new Dimension(bitmapWidth, bitmapHeight);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.dumpview.DumpInfoSpecialType;
|
||||
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.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.BITMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.COLORMAPDATA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 2)
|
||||
public class DefineBitsLosslessTag extends ImageTag implements AloneTag {
|
||||
|
||||
public static final int ID = 20;
|
||||
|
||||
public static final String NAME = "DefineBitsLossless";
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
public int bitmapFormat;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapWidth;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int bitmapHeight;
|
||||
|
||||
@SWFType(BasicType.UI8)
|
||||
@Conditional(value = "bitmapFormat", options = {FORMAT_8BIT_COLORMAPPED})
|
||||
public int bitmapColorTableSize;
|
||||
|
||||
public ByteArrayRange zlibBitmapData;
|
||||
|
||||
public static final int FORMAT_8BIT_COLORMAPPED = 3;
|
||||
|
||||
public static final int FORMAT_15BIT_RGB = 4;
|
||||
|
||||
public static final int FORMAT_24BIT_RGB = 5;
|
||||
|
||||
@HideInRawEdit
|
||||
private COLORMAPDATA colorMapData;
|
||||
|
||||
@HideInRawEdit
|
||||
private BITMAPDATA bitmapData;
|
||||
|
||||
@Internal
|
||||
private boolean decompressed = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DefineBitsLosslessTag(SWF swf) {
|
||||
this(swf, null, swf.getNextCharacterId());
|
||||
}
|
||||
|
||||
public DefineBitsLosslessTag(SWF swf, ByteArrayRange data, int characterID) {
|
||||
super(swf, ID, NAME, data);
|
||||
this.characterID = characterID;
|
||||
bitmapFormat = DefineBitsLosslessTag.FORMAT_24BIT_RGB;
|
||||
bitmapWidth = 1;
|
||||
bitmapHeight = 1;
|
||||
zlibBitmapData = new ByteArrayRange(createEmptyImage());
|
||||
forceWriteAsLong = true;
|
||||
}
|
||||
|
||||
public DefineBitsLosslessTag(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");
|
||||
bitmapFormat = sis.readUI8("bitmapFormat");
|
||||
bitmapWidth = sis.readUI16("bitmapWidth");
|
||||
bitmapHeight = sis.readUI16("bitmapHeight");
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
bitmapColorTableSize = sis.readUI8("bitmapColorTableSize");
|
||||
}
|
||||
|
||||
zlibBitmapData = sis.readByteRangeEx(sis.available(), "zlibBitmapData", DumpInfoSpecialType.ZLIB_DATA, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterID);
|
||||
sos.writeUI8(bitmapFormat);
|
||||
sos.writeUI16(bitmapWidth);
|
||||
sos.writeUI16(bitmapHeight);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
sos.writeUI8(bitmapColorTableSize);
|
||||
}
|
||||
sos.write(zlibBitmapData);
|
||||
}
|
||||
|
||||
private byte[] createEmptyImage() {
|
||||
try {
|
||||
BITMAPDATA bitmapData = new BITMAPDATA();
|
||||
bitmapData.bitmapPixelDataPix24 = new int[]{0xff000000};
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeBITMAPDATA(bitmapData, FORMAT_24BIT_RGB, 1, 1);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
return zlibOS.toByteArray();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(DefineBitsLosslessTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(byte[] data) throws IOException {
|
||||
SerializableImage image = new SerializableImage(ImageHelper.read(data));
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
bitmapData = new BITMAPDATA();
|
||||
bitmapData.bitmapPixelDataPix24 = new int[width * height];
|
||||
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
for (int pos = 0; pos < pixels.length; pos++) {
|
||||
// set the reserved bits to 0xff, because:
|
||||
// documentation says 0, but image is sometimes broken with 0, so there is 0xff, which works (maybe alpha?)
|
||||
int argb = pixels[pos] | 0xff000000;
|
||||
bitmapData.bitmapPixelDataPix24[pos] = argb;
|
||||
}
|
||||
|
||||
int format = FORMAT_24BIT_RGB;
|
||||
ByteArrayOutputStream bitmapDataOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos = new SWFOutputStream(bitmapDataOS, getVersion());
|
||||
sos.writeBITMAPDATA(bitmapData, format, width, height);
|
||||
ByteArrayOutputStream zlibOS = new ByteArrayOutputStream();
|
||||
SWFOutputStream sos2 = new SWFOutputStream(zlibOS, getVersion());
|
||||
sos2.writeBytesZlib(bitmapDataOS.toByteArray());
|
||||
zlibBitmapData = new ByteArrayRange(zlibOS.toByteArray());
|
||||
bitmapFormat = format;
|
||||
bitmapWidth = width;
|
||||
bitmapHeight = height;
|
||||
decompressed = false;
|
||||
clearCache();
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
public COLORMAPDATA getColorMapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return colorMapData;
|
||||
}
|
||||
|
||||
public BITMAPDATA getBitmapData() {
|
||||
if (!decompressed) {
|
||||
uncompressData();
|
||||
}
|
||||
return bitmapData;
|
||||
}
|
||||
|
||||
private void uncompressData() {
|
||||
try {
|
||||
byte[] uncompressedData = SWFInputStream.uncompressByteArray(zlibBitmapData.getArray(), zlibBitmapData.getPos(), zlibBitmapData.getLength());
|
||||
SWFInputStream sis = new SWFInputStream(swf, uncompressedData);
|
||||
if (bitmapFormat == FORMAT_8BIT_COLORMAPPED) {
|
||||
colorMapData = sis.readCOLORMAPDATA(bitmapColorTableSize, bitmapWidth, bitmapHeight, "colorMapData");
|
||||
} else if ((bitmapFormat == FORMAT_15BIT_RGB) || (bitmapFormat == FORMAT_24BIT_RGB)) {
|
||||
bitmapData = sis.readBITMAPDATA(bitmapFormat, bitmapWidth, bitmapHeight, "bitmapData");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
decompressed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFormat getOriginalImageFormat() {
|
||||
return ImageFormat.PNG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getOriginalImageData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializableImage getImage() {
|
||||
int[] pixels = new int[bitmapWidth * bitmapHeight];
|
||||
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) {
|
||||
COLORMAPDATA colorMapData = getColorMapData();
|
||||
int pos32aligned = 0;
|
||||
int pos = 0;
|
||||
for (int y = 0; y < bitmapHeight; y++) {
|
||||
for (int x = 0; x < bitmapWidth; x++) {
|
||||
int c = 0;
|
||||
int colorTableIndex = colorMapData.colorMapPixelData[pos32aligned] & 0xff;
|
||||
if (colorTableIndex < colorMapData.colorTableRGB.length) {
|
||||
c = colorMapData.colorTableRGB[colorTableIndex];
|
||||
}
|
||||
|
||||
pixels[pos++] = c;
|
||||
pos32aligned++;
|
||||
}
|
||||
|
||||
while ((pos32aligned % 4 != 0)) {
|
||||
pos32aligned++;
|
||||
}
|
||||
}
|
||||
} else if ((bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) || (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB)) {
|
||||
BITMAPDATA bitmapData = getBitmapData();
|
||||
int pos = 0;
|
||||
int[] bitmapPixelData = null;
|
||||
if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) {
|
||||
bitmapPixelData = bitmapData.bitmapPixelDataPix15;
|
||||
} else if (bitmapFormat == DefineBitsLosslessTag.FORMAT_24BIT_RGB) {
|
||||
bitmapPixelData = bitmapData.bitmapPixelDataPix24;
|
||||
}
|
||||
|
||||
for (int y = 0; y < bitmapHeight; y++) {
|
||||
for (int x = 0; x < bitmapWidth; x++) {
|
||||
int c = bitmapPixelData[pos] | 0xff000000;
|
||||
pixels[pos++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SerializableImage bi = new SerializableImage(bitmapWidth, bitmapHeight, SerializableImage.TYPE_INT_RGB, pixels);
|
||||
return bi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getImageDimension() {
|
||||
return new Dimension(bitmapWidth, bitmapHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,291 +1,291 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.action.Action;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer;
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ButtonAction;
|
||||
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.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Cache;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Defines a button character
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 1)
|
||||
public class DefineButtonTag extends ButtonTag implements ASMSourceContainer {
|
||||
|
||||
public static final int ID = 7;
|
||||
|
||||
public static final String NAME = "DefineButton";
|
||||
|
||||
/**
|
||||
* ID for this character
|
||||
*/
|
||||
@SWFType(BasicType.UI16)
|
||||
public int buttonId;
|
||||
|
||||
/**
|
||||
* Characters that make up the button
|
||||
*/
|
||||
public List<BUTTONRECORD> characters;
|
||||
|
||||
/**
|
||||
* Actions to perform
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
/**
|
||||
* 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", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(buttonId);
|
||||
sos.writeBUTTONRECORDList(characters, false);
|
||||
sos.write(getActionBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return buttonId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.buttonId = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BUTTONRECORD> getRecords() {
|
||||
return characters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ButtonAction> getSubItems() {
|
||||
return Arrays.asList(new ButtonAction(this));
|
||||
}
|
||||
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
}
|
||||
|
||||
public void setModified() {
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@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) {
|
||||
Cache<CharacterTag, RECT> cache = swf == null ? null : swf.getRectCache();
|
||||
RECT ret = cache == null ? null : cache.get(this);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cache != null) {
|
||||
cache.put(this, rect);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackAsMenu() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumFrames() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTimeline(Timeline timeline) {
|
||||
DefineButtonCxformTag cxformTag = (DefineButtonCxformTag) swf.getCharacterIdTag(buttonId, DefineButtonCxformTag.ID);
|
||||
ColorTransform clrTrans = cxformTag == null ? null : cxformTag.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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.action.Action;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer;
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ButtonAction;
|
||||
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.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Cache;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Defines a button character
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 1)
|
||||
public class DefineButtonTag extends ButtonTag implements ASMSourceContainer {
|
||||
|
||||
public static final int ID = 7;
|
||||
|
||||
public static final String NAME = "DefineButton";
|
||||
|
||||
/**
|
||||
* ID for this character
|
||||
*/
|
||||
@SWFType(BasicType.UI16)
|
||||
public int buttonId;
|
||||
|
||||
/**
|
||||
* Characters that make up the button
|
||||
*/
|
||||
public List<BUTTONRECORD> characters;
|
||||
|
||||
/**
|
||||
* Actions to perform
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
/**
|
||||
* 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", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(buttonId);
|
||||
sos.writeBUTTONRECORDList(characters, false);
|
||||
sos.write(getActionBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return buttonId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.buttonId = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BUTTONRECORD> getRecords() {
|
||||
return characters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ButtonAction> getSubItems() {
|
||||
return Arrays.asList(new ButtonAction(this));
|
||||
}
|
||||
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
}
|
||||
|
||||
public void setModified() {
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@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) {
|
||||
Cache<CharacterTag, RECT> cache = swf == null ? null : swf.getRectCache();
|
||||
RECT ret = cache == null ? null : cache.get(this);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cache != null) {
|
||||
cache.put(this, rect);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackAsMenu() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumFrames() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTimeline(Timeline timeline) {
|
||||
DefineButtonCxformTag cxformTag = (DefineButtonCxformTag) swf.getCharacterIdTag(buttonId, DefineButtonCxformTag.ID);
|
||||
ColorTransform clrTrans = cxformTag == null ? null : cxformTag.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,229 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Point;
|
||||
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.RenderContext;
|
||||
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.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 8)
|
||||
public class DefineScalingGridTag extends Tag implements CharacterIdTag {
|
||||
|
||||
public static final int ID = 78;
|
||||
|
||||
public static final String NAME = "DefineScalingGrid";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int characterId;
|
||||
|
||||
public RECT splitter;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterId);
|
||||
sos.writeRECT(splitter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.characterId = characterId;
|
||||
}
|
||||
|
||||
private static double roundPixels(double v) {
|
||||
return v; //Math.rint(v / SWF.unitDivisor) * SWF.unitDivisor;
|
||||
}
|
||||
|
||||
private static double roundPixels20(double v) {
|
||||
return Math.rint(v / SWF.unitDivisor) * SWF.unitDivisor;
|
||||
}
|
||||
|
||||
private static Matrix rectToRectMatrix(ExportRectangle fromRect, ExportRectangle toRect) {
|
||||
Matrix toOrigin = Matrix.getTranslateInstance(roundPixels(-fromRect.xMin), roundPixels(-fromRect.yMin));
|
||||
Matrix scale = new Matrix();
|
||||
scale.scaleX = roundPixels(toRect.getWidth()) / roundPixels(fromRect.getWidth());
|
||||
scale.scaleY = roundPixels(toRect.getHeight()) / roundPixels(fromRect.getHeight());
|
||||
Matrix toDest = Matrix.getTranslateInstance(roundPixels(toRect.xMin), roundPixels(toRect.yMin));
|
||||
return toOrigin.preConcatenate(scale).preConcatenate(toDest);
|
||||
}
|
||||
|
||||
public RECT getRect() {
|
||||
Shape s = getOutline(0, 0, 0, new RenderContext(), new Matrix(), new Matrix(), true);
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
Rectangle r = s.getBounds();
|
||||
return new RECT(r.x, r.x + r.width, r.y, r.y + r.height);
|
||||
}
|
||||
|
||||
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, Matrix prevTransform, boolean stroked) {
|
||||
CharacterTag ct = swf.getCharacter(characterId);
|
||||
if (ct == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(ct instanceof DrawableTag)) {
|
||||
return null;
|
||||
}
|
||||
double[] coords = new double[6];
|
||||
|
||||
DrawableTag dt = (DrawableTag) ct;
|
||||
Shape path = dt.getOutline(frame, time, ratio, renderContext, transformation, stroked);
|
||||
PathIterator iterator = path.getPathIterator(new AffineTransform());
|
||||
GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
|
||||
ExportRectangle boundsRect = new ExportRectangle(dt.getRect());
|
||||
ExportRectangle scalingGrid = new ExportRectangle(splitter);
|
||||
|
||||
ExportRectangle[] sourceRect = new ExportRectangle[9];
|
||||
ExportRectangle[] targetRect = new ExportRectangle[9];
|
||||
Matrix[] transforms = new Matrix[9];
|
||||
|
||||
getSlices(transformation.transform(boundsRect), boundsRect, scalingGrid, sourceRect, targetRect, transforms);
|
||||
|
||||
while (!iterator.isDone()) {
|
||||
int type = iterator.currentSegment(coords);
|
||||
for (int i = 0; i < 6; i += 2) {
|
||||
double x = coords[i];
|
||||
double y = coords[i + 1];
|
||||
for (int s = 0; s < 9; s++) {
|
||||
Point p = new Point(x, y);
|
||||
if (sourceRect[s].contains(p)) {
|
||||
p = transforms[s].transform(p);
|
||||
coords[i] = p.x;
|
||||
coords[i + 1] = p.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
gp.moveTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
gp.lineTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
gp.quadTo(coords[0], coords[1], coords[2], coords[3]);
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
gp.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
gp.closePath();
|
||||
break;
|
||||
}
|
||||
iterator.next();
|
||||
}
|
||||
return gp;
|
||||
}
|
||||
|
||||
public static void getSlices(ExportRectangle targetBounds, ExportRectangle boundsRect, ExportRectangle scalingGrid, ExportRectangle[] sourceRect, ExportRectangle[] targetRect, Matrix[] transforms) {
|
||||
|
||||
double[] src_x = new double[]{boundsRect.xMin, scalingGrid.xMin, scalingGrid.xMax, boundsRect.xMax};
|
||||
double[] dst_x = new double[]{targetBounds.xMin, targetBounds.xMin + scalingGrid.xMin, targetBounds.xMax - (boundsRect.xMax - scalingGrid.xMax), targetBounds.xMax};
|
||||
|
||||
double[] src_y = new double[]{boundsRect.yMin, scalingGrid.yMin, scalingGrid.yMax, boundsRect.yMax};
|
||||
double[] dst_y = new double[]{targetBounds.yMin, targetBounds.yMin + scalingGrid.yMin, targetBounds.yMax - (boundsRect.yMax - scalingGrid.yMax), targetBounds.yMax};
|
||||
|
||||
int pos = 0;
|
||||
for (int sy = 0; sy < 3; sy++) {
|
||||
for (int sx = 0; sx < 3; sx++) {
|
||||
sourceRect[pos] = new ExportRectangle(src_x[sx], src_y[sy], src_x[sx + 1], src_y[sy + 1]);
|
||||
targetRect[pos] = new ExportRectangle(dst_x[sx], dst_y[sy], dst_x[sx + 1], dst_y[sy + 1]);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < targetRect.length; i++) {
|
||||
|
||||
/* sourceRect[i].xMax = roundPixels20(sourceRect[i].xMax);
|
||||
sourceRect[i].yMax = roundPixels20(sourceRect[i].yMax);
|
||||
sourceRect[i].xMin = roundPixels20(sourceRect[i].xMin);
|
||||
sourceRect[i].yMin = roundPixels20(sourceRect[i].yMin);
|
||||
*/
|
||||
//System.out.println("source[" + i + "]=" + sourceRect[i]);
|
||||
//System.out.println("target[" + i + "]=" + targetRect[i]);
|
||||
|
||||
/*targetRect[i].xMax = roundPixels20(targetRect[i].xMax);
|
||||
targetRect[i].yMax = roundPixels20(targetRect[i].yMax);
|
||||
targetRect[i].xMin = roundPixels20(targetRect[i].xMin);
|
||||
targetRect[i].yMin = roundPixels20(targetRect[i].yMin);
|
||||
*/
|
||||
transforms[i] = rectToRectMatrix(sourceRect[i], targetRect[i]);
|
||||
|
||||
targetRect[i].xMax = Math.rint(targetRect[i].xMax / SWF.unitDivisor);
|
||||
targetRect[i].yMax = Math.rint(targetRect[i].yMax / SWF.unitDivisor);
|
||||
targetRect[i].xMin = Math.rint(targetRect[i].xMin / SWF.unitDivisor);
|
||||
targetRect[i].yMin = Math.rint(targetRect[i].yMin / SWF.unitDivisor);
|
||||
|
||||
//targetRect[i].xMax += maxStroke;
|
||||
//Round to pixel boundary
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Point;
|
||||
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.RenderContext;
|
||||
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.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 8)
|
||||
public class DefineScalingGridTag extends Tag implements CharacterIdTag {
|
||||
|
||||
public static final int ID = 78;
|
||||
|
||||
public static final String NAME = "DefineScalingGrid";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int characterId;
|
||||
|
||||
public RECT splitter;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(characterId);
|
||||
sos.writeRECT(splitter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.characterId = characterId;
|
||||
}
|
||||
|
||||
private static double roundPixels(double v) {
|
||||
return v; //Math.rint(v / SWF.unitDivisor) * SWF.unitDivisor;
|
||||
}
|
||||
|
||||
private static double roundPixels20(double v) {
|
||||
return Math.rint(v / SWF.unitDivisor) * SWF.unitDivisor;
|
||||
}
|
||||
|
||||
private static Matrix rectToRectMatrix(ExportRectangle fromRect, ExportRectangle toRect) {
|
||||
Matrix toOrigin = Matrix.getTranslateInstance(roundPixels(-fromRect.xMin), roundPixels(-fromRect.yMin));
|
||||
Matrix scale = new Matrix();
|
||||
scale.scaleX = roundPixels(toRect.getWidth()) / roundPixels(fromRect.getWidth());
|
||||
scale.scaleY = roundPixels(toRect.getHeight()) / roundPixels(fromRect.getHeight());
|
||||
Matrix toDest = Matrix.getTranslateInstance(roundPixels(toRect.xMin), roundPixels(toRect.yMin));
|
||||
return toOrigin.preConcatenate(scale).preConcatenate(toDest);
|
||||
}
|
||||
|
||||
public RECT getRect() {
|
||||
Shape s = getOutline(0, 0, 0, new RenderContext(), new Matrix(), new Matrix(), true);
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
Rectangle r = s.getBounds();
|
||||
return new RECT(r.x, r.x + r.width, r.y, r.y + r.height);
|
||||
}
|
||||
|
||||
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, Matrix prevTransform, boolean stroked) {
|
||||
CharacterTag ct = swf.getCharacter(characterId);
|
||||
if (ct == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(ct instanceof DrawableTag)) {
|
||||
return null;
|
||||
}
|
||||
double[] coords = new double[6];
|
||||
|
||||
DrawableTag dt = (DrawableTag) ct;
|
||||
Shape path = dt.getOutline(frame, time, ratio, renderContext, transformation, stroked);
|
||||
PathIterator iterator = path.getPathIterator(new AffineTransform());
|
||||
GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
|
||||
ExportRectangle boundsRect = new ExportRectangle(dt.getRect());
|
||||
ExportRectangle scalingGrid = new ExportRectangle(splitter);
|
||||
|
||||
ExportRectangle[] sourceRect = new ExportRectangle[9];
|
||||
ExportRectangle[] targetRect = new ExportRectangle[9];
|
||||
Matrix[] transforms = new Matrix[9];
|
||||
|
||||
getSlices(transformation.transform(boundsRect), boundsRect, scalingGrid, sourceRect, targetRect, transforms);
|
||||
|
||||
while (!iterator.isDone()) {
|
||||
int type = iterator.currentSegment(coords);
|
||||
for (int i = 0; i < 6; i += 2) {
|
||||
double x = coords[i];
|
||||
double y = coords[i + 1];
|
||||
for (int s = 0; s < 9; s++) {
|
||||
Point p = new Point(x, y);
|
||||
if (sourceRect[s].contains(p)) {
|
||||
p = transforms[s].transform(p);
|
||||
coords[i] = p.x;
|
||||
coords[i + 1] = p.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
gp.moveTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
gp.lineTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
gp.quadTo(coords[0], coords[1], coords[2], coords[3]);
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
gp.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
gp.closePath();
|
||||
break;
|
||||
}
|
||||
iterator.next();
|
||||
}
|
||||
return gp;
|
||||
}
|
||||
|
||||
public static void getSlices(ExportRectangle targetBounds, ExportRectangle boundsRect, ExportRectangle scalingGrid, ExportRectangle[] sourceRect, ExportRectangle[] targetRect, Matrix[] transforms) {
|
||||
|
||||
double[] src_x = new double[]{boundsRect.xMin, scalingGrid.xMin, scalingGrid.xMax, boundsRect.xMax};
|
||||
double[] dst_x = new double[]{targetBounds.xMin, targetBounds.xMin + scalingGrid.xMin, targetBounds.xMax - (boundsRect.xMax - scalingGrid.xMax), targetBounds.xMax};
|
||||
|
||||
double[] src_y = new double[]{boundsRect.yMin, scalingGrid.yMin, scalingGrid.yMax, boundsRect.yMax};
|
||||
double[] dst_y = new double[]{targetBounds.yMin, targetBounds.yMin + scalingGrid.yMin, targetBounds.yMax - (boundsRect.yMax - scalingGrid.yMax), targetBounds.yMax};
|
||||
|
||||
int pos = 0;
|
||||
for (int sy = 0; sy < 3; sy++) {
|
||||
for (int sx = 0; sx < 3; sx++) {
|
||||
sourceRect[pos] = new ExportRectangle(src_x[sx], src_y[sy], src_x[sx + 1], src_y[sy + 1]);
|
||||
targetRect[pos] = new ExportRectangle(dst_x[sx], dst_y[sy], dst_x[sx + 1], dst_y[sy + 1]);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < targetRect.length; i++) {
|
||||
|
||||
/* sourceRect[i].xMax = roundPixels20(sourceRect[i].xMax);
|
||||
sourceRect[i].yMax = roundPixels20(sourceRect[i].yMax);
|
||||
sourceRect[i].xMin = roundPixels20(sourceRect[i].xMin);
|
||||
sourceRect[i].yMin = roundPixels20(sourceRect[i].yMin);
|
||||
*/
|
||||
//System.out.println("source[" + i + "]=" + sourceRect[i]);
|
||||
//System.out.println("target[" + i + "]=" + targetRect[i]);
|
||||
|
||||
/*targetRect[i].xMax = roundPixels20(targetRect[i].xMax);
|
||||
targetRect[i].yMax = roundPixels20(targetRect[i].yMax);
|
||||
targetRect[i].xMin = roundPixels20(targetRect[i].xMin);
|
||||
targetRect[i].yMin = roundPixels20(targetRect[i].yMin);
|
||||
*/
|
||||
transforms[i] = rectToRectMatrix(sourceRect[i], targetRect[i]);
|
||||
|
||||
targetRect[i].xMax = Math.rint(targetRect[i].xMax / SWF.unitDivisor);
|
||||
targetRect[i].yMax = Math.rint(targetRect[i].yMax / SWF.unitDivisor);
|
||||
targetRect[i].xMin = Math.rint(targetRect[i].xMin / SWF.unitDivisor);
|
||||
targetRect[i].yMin = Math.rint(targetRect[i].yMin / SWF.unitDivisor);
|
||||
|
||||
//targetRect[i].xMax += maxStroke;
|
||||
//Round to pixel boundary
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,371 +1,371 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.annotations.SWFVersion;
|
||||
import com.jpexs.decompiler.flash.types.sound.MP3FRAME;
|
||||
import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA;
|
||||
import com.jpexs.decompiler.flash.types.sound.SoundExportFormat;
|
||||
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.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
|
||||
*/
|
||||
@SWFVersion(from = 1)
|
||||
public class DefineSoundTag extends CharacterTag implements SoundTag {
|
||||
|
||||
public static final int ID = 14;
|
||||
|
||||
public static final String NAME = "DefineSound";
|
||||
|
||||
@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;
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return soundId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.soundId = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundExportFormat getExportFormat() {
|
||||
if (soundFormat == SoundFormat.FORMAT_MP3) {
|
||||
return SoundExportFormat.MP3;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_ADPCM) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_NELLYMOSER || soundFormat == SoundFormat.FORMAT_NELLYMOSER16KHZ || soundFormat == SoundFormat.FORMAT_NELLYMOSER8KHZ) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
return SoundExportFormat.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<ByteArrayRange> getRawSoundData() {
|
||||
List<ByteArrayRange> ret = new ArrayList<>();
|
||||
if (soundFormat == SoundFormat.FORMAT_MP3) {
|
||||
ret.add(soundData.getSubRange(2, soundData.getLength() - 2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.add(soundData);
|
||||
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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getTagInfo(TagInfo tagInfo) {
|
||||
super.getTagInfo(tagInfo);
|
||||
SoundFormat soundFormat = getSoundFormat();
|
||||
tagInfo.addInfo("general", "codecName", soundFormat.getFormatName());
|
||||
tagInfo.addInfo("general", "exportFormat", soundFormat.getNativeExportFormat());
|
||||
tagInfo.addInfo("general", "samplingRate", soundFormat.samplingRate);
|
||||
tagInfo.addInfo("general", "stereo", soundFormat.stereo);
|
||||
tagInfo.addInfo("general", "sampleCount", soundSampleCount);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.annotations.SWFVersion;
|
||||
import com.jpexs.decompiler.flash.types.sound.MP3FRAME;
|
||||
import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA;
|
||||
import com.jpexs.decompiler.flash.types.sound.SoundExportFormat;
|
||||
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.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
|
||||
*/
|
||||
@SWFVersion(from = 1)
|
||||
public class DefineSoundTag extends CharacterTag implements SoundTag {
|
||||
|
||||
public static final int ID = 14;
|
||||
|
||||
public static final String NAME = "DefineSound";
|
||||
|
||||
@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;
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return soundId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.soundId = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundExportFormat getExportFormat() {
|
||||
if (soundFormat == SoundFormat.FORMAT_MP3) {
|
||||
return SoundExportFormat.MP3;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_ADPCM) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
if (soundFormat == SoundFormat.FORMAT_NELLYMOSER || soundFormat == SoundFormat.FORMAT_NELLYMOSER16KHZ || soundFormat == SoundFormat.FORMAT_NELLYMOSER8KHZ) {
|
||||
return SoundExportFormat.WAV;
|
||||
}
|
||||
return SoundExportFormat.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<ByteArrayRange> getRawSoundData() {
|
||||
List<ByteArrayRange> ret = new ArrayList<>();
|
||||
if (soundFormat == SoundFormat.FORMAT_MP3) {
|
||||
ret.add(soundData.getSubRange(2, soundData.getLength() - 2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.add(soundData);
|
||||
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());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getTagInfo(TagInfo tagInfo) {
|
||||
super.getTagInfo(tagInfo);
|
||||
SoundFormat soundFormat = getSoundFormat();
|
||||
tagInfo.addInfo("general", "codecName", soundFormat.getFormatName());
|
||||
tagInfo.addInfo("general", "exportFormat", soundFormat.getNativeExportFormat());
|
||||
tagInfo.addInfo("general", "samplingRate", soundFormat.samplingRate);
|
||||
tagInfo.addInfo("general", "stereo", soundFormat.stereo);
|
||||
tagInfo.addInfo("general", "sampleCount", soundSampleCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,146 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
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.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Defines a series of ActionScript 3 bytecodes to be executed
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 9)
|
||||
public class DoABC2Tag extends Tag implements ABCContainerTag {
|
||||
|
||||
public static final int ID = 82;
|
||||
|
||||
public static final String NAME = "DoABC2";
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DoABC2Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
name = "New DoABC";
|
||||
abc = new ABC(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param sis
|
||||
* @param data
|
||||
* @throws IOException
|
||||
*/
|
||||
public DoABC2Tag(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", DumpInfoSpecialType.ABC_BYTES, null);
|
||||
abc = new ABC(ais, swf, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI32(flags);
|
||||
sos.writeString(name);
|
||||
abc.saveToStream(sos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ABC getABC() {
|
||||
return abc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return super.getName() + " (" + name + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ABCContainerTag o) {
|
||||
if (o instanceof DoABC2Tag) {
|
||||
DoABC2Tag n = (DoABC2Tag) 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-2016 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.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
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.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Defines a series of ActionScript 3 bytecodes to be executed
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 9)
|
||||
public class DoABC2Tag extends Tag implements ABCContainerTag {
|
||||
|
||||
public static final int ID = 82;
|
||||
|
||||
public static final String NAME = "DoABC2";
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DoABC2Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
name = "New DoABC";
|
||||
abc = new ABC(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param sis
|
||||
* @param data
|
||||
* @throws IOException
|
||||
*/
|
||||
public DoABC2Tag(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", DumpInfoSpecialType.ABC_BYTES, null);
|
||||
abc = new ABC(ais, swf, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI32(flags);
|
||||
sos.writeString(name);
|
||||
abc.saveToStream(sos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ABC getABC() {
|
||||
return abc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return super.getName() + " (" + name + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ABCContainerTag o) {
|
||||
if (o instanceof DoABC2Tag) {
|
||||
DoABC2Tag n = (DoABC2Tag) 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,253 +1,253 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.ConstantPoolTooBigException;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
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.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 6)
|
||||
public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
|
||||
|
||||
public static final int ID = 59;
|
||||
|
||||
public static final String NAME = "DoInitAction";
|
||||
|
||||
/**
|
||||
* Identifier of Sprite
|
||||
*/
|
||||
@SWFType(BasicType.UI16)
|
||||
public int spriteId = 0;
|
||||
|
||||
/**
|
||||
* List of actions to perform
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
@Internal
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DoInitActionTag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
actionBytes = ByteArrayRange.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(spriteId);
|
||||
sos.write(getActionBytes());
|
||||
//sos.write(Action.actionsToBytes(actions, true, version));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return SWF.getCachedActionList(this, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
SWF.uncache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPools(List<List<String>> constantPools) throws ConstantPoolTooBigException {
|
||||
Action.setConstantPools(this, constantPools, false);
|
||||
}
|
||||
|
||||
@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 == null ? "" : swf.getExportName(spriteId);
|
||||
if (expName == null || expName.isEmpty()) {
|
||||
return super.getExportFileName();
|
||||
}
|
||||
String[] pathParts = expName.contains(".") ? expName.split("\\.") : 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 = expName.contains(".") ? expName.split("\\.") : 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceTag(Tag t) {
|
||||
//nothing
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.ConstantPoolTooBigException;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
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.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 6)
|
||||
public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
|
||||
|
||||
public static final int ID = 59;
|
||||
|
||||
public static final String NAME = "DoInitAction";
|
||||
|
||||
/**
|
||||
* Identifier of Sprite
|
||||
*/
|
||||
@SWFType(BasicType.UI16)
|
||||
public int spriteId = 0;
|
||||
|
||||
/**
|
||||
* List of actions to perform
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
@Internal
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param swf
|
||||
*/
|
||||
public DoInitActionTag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
actionBytes = ByteArrayRange.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
* @param sos SWF output stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(spriteId);
|
||||
sos.write(getActionBytes());
|
||||
//sos.write(Action.actionsToBytes(actions, true, version));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return SWF.getCachedActionList(this, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
SWF.uncache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPools(List<List<String>> constantPools) throws ConstantPoolTooBigException {
|
||||
Action.setConstantPools(this, constantPools, false);
|
||||
}
|
||||
|
||||
@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 == null ? "" : swf.getExportName(spriteId);
|
||||
if (expName == null || expName.isEmpty()) {
|
||||
return super.getExportFileName();
|
||||
}
|
||||
String[] pathParts = expName.contains(".") ? expName.split("\\.") : 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 = expName.contains(".") ? expName.split("\\.") : 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceTag(Tag t) {
|
||||
//nothing
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,345 +1,345 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.types;
|
||||
|
||||
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.ConstantPoolTooBigException;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Actions to execute at particular button events
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class BUTTONCONDACTION implements ASMSource, Serializable {
|
||||
|
||||
private SWF swf;
|
||||
|
||||
private Tag tag;
|
||||
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
// Constructor for Generic tag editor.
|
||||
public BUTTONCONDACTION() {
|
||||
swf = null;
|
||||
tag = null;
|
||||
actionBytes = new ByteArrayRange(SWFInputStream.BYTE_ARRAY_EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
public BUTTONCONDACTION(SWF swf, SWFInputStream sis, Tag tag) throws IOException {
|
||||
this.swf = swf;
|
||||
this.tag = tag;
|
||||
int condActionSize = sis.readUI16("condActionSize");
|
||||
isLast = condActionSize <= 0;
|
||||
condIdleToOverDown = sis.readUB(1, "condIdleToOverDown") == 1;
|
||||
condOutDownToIdle = sis.readUB(1, "condOutDownToIdle") == 1;
|
||||
condOutDownToOverDown = sis.readUB(1, "condOutDownToOverDown") == 1;
|
||||
condOverDownToOutDown = sis.readUB(1, "condOverDownToOutDown") == 1;
|
||||
condOverDownToOverUp = sis.readUB(1, "condOverDownToOverUp") == 1;
|
||||
condOverUpToOverDown = sis.readUB(1, "condOverUpToOverDown") == 1;
|
||||
condOverUpToIddle = sis.readUB(1, "condOverUpToIddle") == 1;
|
||||
condIdleToOverUp = sis.readUB(1, "condIdleToOverUp") == 1;
|
||||
condKeyPress = (int) sis.readUB(7, "condKeyPress");
|
||||
condOverDownToIdle = sis.readUB(1, "condOverDownToIdle") == 1;
|
||||
actionBytes = sis.readByteRangeEx(condActionSize <= 0 ? sis.available() : condActionSize - 4, "actionBytes", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this BUTTONCONDACTION last in the list?
|
||||
*/
|
||||
@Internal
|
||||
public boolean isLast;
|
||||
|
||||
/**
|
||||
* Idle to OverDown
|
||||
*/
|
||||
public boolean condIdleToOverDown;
|
||||
|
||||
/**
|
||||
* OutDown to Idle
|
||||
*/
|
||||
public boolean condOutDownToIdle;
|
||||
|
||||
/**
|
||||
* OutDown to OverDown
|
||||
*/
|
||||
public boolean condOutDownToOverDown;
|
||||
|
||||
/**
|
||||
* OverDown to OutDown
|
||||
*/
|
||||
public boolean condOverDownToOutDown;
|
||||
|
||||
/**
|
||||
* OverDown to OverUp
|
||||
*/
|
||||
public boolean condOverDownToOverUp;
|
||||
|
||||
/**
|
||||
* OverUp to OverDown
|
||||
*/
|
||||
public boolean condOverUpToOverDown;
|
||||
|
||||
/**
|
||||
* OverUp to Idle
|
||||
*/
|
||||
public boolean condOverUpToIddle;
|
||||
|
||||
/**
|
||||
* Idle to OverUp
|
||||
*/
|
||||
public boolean condIdleToOverUp;
|
||||
|
||||
/**
|
||||
* @since SWF 4 key code
|
||||
*/
|
||||
@SWFType(value = BasicType.UB, count = 7)
|
||||
@Conditional(minSwfVersion = 4)
|
||||
public int condKeyPress;
|
||||
|
||||
/**
|
||||
* OverDown to Idle
|
||||
*/
|
||||
public boolean condOverDownToIdle;
|
||||
|
||||
/**
|
||||
* Actions to perform in byte array
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
/**
|
||||
* Sets actions associated with this object
|
||||
*
|
||||
* @param actions Action list
|
||||
*/
|
||||
/*public void setActions(List<Action> actions) {
|
||||
this.actions = actions;
|
||||
}*/
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BUTTONCONDACTION";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return SWF.getCachedActionList(this, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
SWF.uncache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPools(List<List<String>> constantPools) throws ConstantPoolTooBigException {
|
||||
Action.setConstantPools(this, constantPools, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified() {
|
||||
if (tag != null) {
|
||||
tag.setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
if (tag != null) {
|
||||
return tag.isModified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
private String getHeader(boolean asFilename) {
|
||||
List<String> events = new ArrayList<>();
|
||||
if (condOverUpToOverDown) {
|
||||
events.add("press");
|
||||
}
|
||||
if (condOverDownToOverUp) {
|
||||
events.add("release");
|
||||
}
|
||||
if (condOutDownToIdle) {
|
||||
events.add("releaseOutside");
|
||||
}
|
||||
if (condIdleToOverUp) {
|
||||
events.add("rollOver");
|
||||
}
|
||||
if (condOverUpToIddle) {
|
||||
events.add("rollOut");
|
||||
}
|
||||
if (condOverDownToOutDown) {
|
||||
events.add("dragOut");
|
||||
}
|
||||
if (condOutDownToOverDown) {
|
||||
events.add("dragOver");
|
||||
}
|
||||
if (condKeyPress > 0) {
|
||||
if (asFilename) {
|
||||
events.add("keyPress " + Helper.makeFileName(CLIPACTIONRECORD.keyToString(condKeyPress).replace("<", "").replace(">", "")) + "");
|
||||
} else {
|
||||
events.add("keyPress \"" + CLIPACTIONRECORD.keyToString(condKeyPress) + "\"");
|
||||
}
|
||||
}
|
||||
String onStr = "";
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
if (i > 0) {
|
||||
onStr += ", ";
|
||||
}
|
||||
onStr += events.get(i);
|
||||
}
|
||||
return "on(" + onStr + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
|
||||
writer.appendNoHilight(getHeader(false));
|
||||
writer.appendNoHilight("{").newLine();
|
||||
return writer.indent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
|
||||
writer.unindent();
|
||||
return writer.appendNoHilight("}").newLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrefixLineCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String removePrefixAndSuffix(String source) {
|
||||
return Helper.unindentRows(1, 1, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExportFileName() {
|
||||
return getHeader(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getSourceTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceTag(Tag t) {
|
||||
this.tag = t;
|
||||
this.swf = t.getSwf();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.types;
|
||||
|
||||
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.ConstantPoolTooBigException;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Actions to execute at particular button events
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class BUTTONCONDACTION implements ASMSource, Serializable {
|
||||
|
||||
private SWF swf;
|
||||
|
||||
private Tag tag;
|
||||
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
// Constructor for Generic tag editor.
|
||||
public BUTTONCONDACTION() {
|
||||
swf = null;
|
||||
tag = null;
|
||||
actionBytes = new ByteArrayRange(SWFInputStream.BYTE_ARRAY_EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
public BUTTONCONDACTION(SWF swf, SWFInputStream sis, Tag tag) throws IOException {
|
||||
this.swf = swf;
|
||||
this.tag = tag;
|
||||
int condActionSize = sis.readUI16("condActionSize");
|
||||
isLast = condActionSize <= 0;
|
||||
condIdleToOverDown = sis.readUB(1, "condIdleToOverDown") == 1;
|
||||
condOutDownToIdle = sis.readUB(1, "condOutDownToIdle") == 1;
|
||||
condOutDownToOverDown = sis.readUB(1, "condOutDownToOverDown") == 1;
|
||||
condOverDownToOutDown = sis.readUB(1, "condOverDownToOutDown") == 1;
|
||||
condOverDownToOverUp = sis.readUB(1, "condOverDownToOverUp") == 1;
|
||||
condOverUpToOverDown = sis.readUB(1, "condOverUpToOverDown") == 1;
|
||||
condOverUpToIddle = sis.readUB(1, "condOverUpToIddle") == 1;
|
||||
condIdleToOverUp = sis.readUB(1, "condIdleToOverUp") == 1;
|
||||
condKeyPress = (int) sis.readUB(7, "condKeyPress");
|
||||
condOverDownToIdle = sis.readUB(1, "condOverDownToIdle") == 1;
|
||||
actionBytes = sis.readByteRangeEx(condActionSize <= 0 ? sis.available() : condActionSize - 4, "actionBytes", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this BUTTONCONDACTION last in the list?
|
||||
*/
|
||||
@Internal
|
||||
public boolean isLast;
|
||||
|
||||
/**
|
||||
* Idle to OverDown
|
||||
*/
|
||||
public boolean condIdleToOverDown;
|
||||
|
||||
/**
|
||||
* OutDown to Idle
|
||||
*/
|
||||
public boolean condOutDownToIdle;
|
||||
|
||||
/**
|
||||
* OutDown to OverDown
|
||||
*/
|
||||
public boolean condOutDownToOverDown;
|
||||
|
||||
/**
|
||||
* OverDown to OutDown
|
||||
*/
|
||||
public boolean condOverDownToOutDown;
|
||||
|
||||
/**
|
||||
* OverDown to OverUp
|
||||
*/
|
||||
public boolean condOverDownToOverUp;
|
||||
|
||||
/**
|
||||
* OverUp to OverDown
|
||||
*/
|
||||
public boolean condOverUpToOverDown;
|
||||
|
||||
/**
|
||||
* OverUp to Idle
|
||||
*/
|
||||
public boolean condOverUpToIddle;
|
||||
|
||||
/**
|
||||
* Idle to OverUp
|
||||
*/
|
||||
public boolean condIdleToOverUp;
|
||||
|
||||
/**
|
||||
* @since SWF 4 key code
|
||||
*/
|
||||
@SWFType(value = BasicType.UB, count = 7)
|
||||
@Conditional(minSwfVersion = 4)
|
||||
public int condKeyPress;
|
||||
|
||||
/**
|
||||
* OverDown to Idle
|
||||
*/
|
||||
public boolean condOverDownToIdle;
|
||||
|
||||
/**
|
||||
* Actions to perform in byte array
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
/**
|
||||
* Sets actions associated with this object
|
||||
*
|
||||
* @param actions Action list
|
||||
*/
|
||||
/*public void setActions(List<Action> actions) {
|
||||
this.actions = actions;
|
||||
}*/
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BUTTONCONDACTION";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return SWF.getCachedActionList(this, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
SWF.uncache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPools(List<List<String>> constantPools) throws ConstantPoolTooBigException {
|
||||
Action.setConstantPools(this, constantPools, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified() {
|
||||
if (tag != null) {
|
||||
tag.setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
if (tag != null) {
|
||||
return tag.isModified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
private String getHeader(boolean asFilename) {
|
||||
List<String> events = new ArrayList<>();
|
||||
if (condOverUpToOverDown) {
|
||||
events.add("press");
|
||||
}
|
||||
if (condOverDownToOverUp) {
|
||||
events.add("release");
|
||||
}
|
||||
if (condOutDownToIdle) {
|
||||
events.add("releaseOutside");
|
||||
}
|
||||
if (condIdleToOverUp) {
|
||||
events.add("rollOver");
|
||||
}
|
||||
if (condOverUpToIddle) {
|
||||
events.add("rollOut");
|
||||
}
|
||||
if (condOverDownToOutDown) {
|
||||
events.add("dragOut");
|
||||
}
|
||||
if (condOutDownToOverDown) {
|
||||
events.add("dragOver");
|
||||
}
|
||||
if (condKeyPress > 0) {
|
||||
if (asFilename) {
|
||||
events.add("keyPress " + Helper.makeFileName(CLIPACTIONRECORD.keyToString(condKeyPress).replace("<", "").replace(">", "")) + "");
|
||||
} else {
|
||||
events.add("keyPress \"" + CLIPACTIONRECORD.keyToString(condKeyPress) + "\"");
|
||||
}
|
||||
}
|
||||
String onStr = "";
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
if (i > 0) {
|
||||
onStr += ", ";
|
||||
}
|
||||
onStr += events.get(i);
|
||||
}
|
||||
return "on(" + onStr + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) {
|
||||
writer.appendNoHilight(getHeader(false));
|
||||
writer.appendNoHilight("{").newLine();
|
||||
return writer.indent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
|
||||
writer.unindent();
|
||||
return writer.appendNoHilight("}").newLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrefixLineCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String removePrefixAndSuffix(String source) {
|
||||
return Helper.unindentRows(1, 1, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExportFileName() {
|
||||
return getHeader(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getSourceTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceTag(Tag t) {
|
||||
this.tag = t;
|
||||
this.swf = t.getSwf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,301 +1,301 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.types;
|
||||
|
||||
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.ConstantPoolTooBigException;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Event handler
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class CLIPACTIONRECORD implements ASMSource, Serializable {
|
||||
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
public static String keyToString(int key) {
|
||||
if ((key < CLIPACTIONRECORD.KEYNAMES.length) && (key > 0) && (CLIPACTIONRECORD.KEYNAMES[key] != null)) {
|
||||
return CLIPACTIONRECORD.KEYNAMES[key];
|
||||
} else {
|
||||
return "" + (char) key;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String[] KEYNAMES = {
|
||||
null,
|
||||
"<Left>",
|
||||
"<Right>",
|
||||
"<Home>",
|
||||
"<End>",
|
||||
"<Insert>",
|
||||
"<Delete>",
|
||||
null,
|
||||
"<Backspace>",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"<Enter>",
|
||||
"<Up>",
|
||||
"<Down>",
|
||||
"<PageUp>",
|
||||
"<PageDown>",
|
||||
"<Tab>",
|
||||
"<Escape>",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"<Space>"
|
||||
};
|
||||
|
||||
@Internal
|
||||
private SWF swf;
|
||||
|
||||
@Internal
|
||||
private Tag tag;
|
||||
|
||||
// Constructor for Generic tag editor. TODO:Handle this somehow better
|
||||
public CLIPACTIONRECORD() {
|
||||
swf = null;
|
||||
tag = null;
|
||||
eventFlags = new CLIPEVENTFLAGS();
|
||||
actionBytes = ByteArrayRange.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
public CLIPACTIONRECORD(SWF swf, SWFInputStream sis, Tag tag) throws IOException {
|
||||
this.swf = swf;
|
||||
this.tag = tag;
|
||||
eventFlags = sis.readCLIPEVENTFLAGS("eventFlags");
|
||||
if (eventFlags.isClear()) {
|
||||
return;
|
||||
}
|
||||
long actionRecordSize = sis.readUI32("actionRecordSize");
|
||||
if (eventFlags.clipEventKeyPress) {
|
||||
keyCode = sis.readUI8("keyCode");
|
||||
actionRecordSize--;
|
||||
}
|
||||
actionBytes = sis.readByteRangeEx(actionRecordSize, "actionBytes", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Events to which this handler applies
|
||||
*/
|
||||
public CLIPEVENTFLAGS eventFlags;
|
||||
|
||||
/**
|
||||
* If EventFlags contain ClipEventKeyPress: Key code to trap
|
||||
*/
|
||||
@Conditional("eventFlags.clipEventKeyPress")
|
||||
public int keyCode;
|
||||
|
||||
/**
|
||||
* Actions to perform
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return eventFlags.getHeader(keyCode, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns header with events converted to string
|
||||
*
|
||||
* @return String representation of events
|
||||
*/
|
||||
public String getHeader() {
|
||||
String ret;
|
||||
ret = eventFlags.toString();
|
||||
if (eventFlags.clipEventKeyPress) {
|
||||
ret = ret.replace("keyPress", "keyPress<" + keyCode + ">");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return SWF.getCachedActionList(this, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
SWF.uncache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPools(List<List<String>> constantPools) throws ConstantPoolTooBigException {
|
||||
Action.setConstantPools(this, constantPools, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified() {
|
||||
if (tag != null) {
|
||||
tag.setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
if (tag != null) {
|
||||
return tag.isModified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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) {
|
||||
writer.appendNoHilight(eventFlags.getHeader(keyCode, false));
|
||||
writer.appendNoHilight("{").newLine();
|
||||
return writer.indent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
|
||||
writer.unindent();
|
||||
return writer.appendNoHilight("}").newLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrefixLineCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String removePrefixAndSuffix(String source) {
|
||||
return Helper.unindentRows(1, 1, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExportFileName() {
|
||||
return eventFlags.getHeader(keyCode, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getSourceTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceTag(Tag t) {
|
||||
this.tag = t;
|
||||
this.swf = t.getSwf();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2016 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.types;
|
||||
|
||||
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.ConstantPoolTooBigException;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Event handler
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class CLIPACTIONRECORD implements ASMSource, Serializable {
|
||||
|
||||
private String scriptName = "-";
|
||||
|
||||
@Override
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
public static String keyToString(int key) {
|
||||
if ((key < CLIPACTIONRECORD.KEYNAMES.length) && (key > 0) && (CLIPACTIONRECORD.KEYNAMES[key] != null)) {
|
||||
return CLIPACTIONRECORD.KEYNAMES[key];
|
||||
} else {
|
||||
return "" + (char) key;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String[] KEYNAMES = {
|
||||
null,
|
||||
"<Left>",
|
||||
"<Right>",
|
||||
"<Home>",
|
||||
"<End>",
|
||||
"<Insert>",
|
||||
"<Delete>",
|
||||
null,
|
||||
"<Backspace>",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"<Enter>",
|
||||
"<Up>",
|
||||
"<Down>",
|
||||
"<PageUp>",
|
||||
"<PageDown>",
|
||||
"<Tab>",
|
||||
"<Escape>",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"<Space>"
|
||||
};
|
||||
|
||||
@Internal
|
||||
private SWF swf;
|
||||
|
||||
@Internal
|
||||
private Tag tag;
|
||||
|
||||
// Constructor for Generic tag editor. TODO:Handle this somehow better
|
||||
public CLIPACTIONRECORD() {
|
||||
swf = null;
|
||||
tag = null;
|
||||
eventFlags = new CLIPEVENTFLAGS();
|
||||
actionBytes = ByteArrayRange.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
public CLIPACTIONRECORD(SWF swf, SWFInputStream sis, Tag tag) throws IOException {
|
||||
this.swf = swf;
|
||||
this.tag = tag;
|
||||
eventFlags = sis.readCLIPEVENTFLAGS("eventFlags");
|
||||
if (eventFlags.isClear()) {
|
||||
return;
|
||||
}
|
||||
long actionRecordSize = sis.readUI32("actionRecordSize");
|
||||
if (eventFlags.clipEventKeyPress) {
|
||||
keyCode = sis.readUI8("keyCode");
|
||||
actionRecordSize--;
|
||||
}
|
||||
actionBytes = sis.readByteRangeEx(actionRecordSize, "actionBytes", DumpInfoSpecialType.ACTION_BYTES, sis.getPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Events to which this handler applies
|
||||
*/
|
||||
public CLIPEVENTFLAGS eventFlags;
|
||||
|
||||
/**
|
||||
* If EventFlags contain ClipEventKeyPress: Key code to trap
|
||||
*/
|
||||
@Conditional("eventFlags.clipEventKeyPress")
|
||||
public int keyCode;
|
||||
|
||||
/**
|
||||
* Actions to perform
|
||||
*/
|
||||
@HideInRawEdit
|
||||
public ByteArrayRange actionBytes;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return eventFlags.getHeader(keyCode, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns header with events converted to string
|
||||
*
|
||||
* @return String representation of events
|
||||
*/
|
||||
public String getHeader() {
|
||||
String ret;
|
||||
ret = eventFlags.toString();
|
||||
if (eventFlags.clipEventKeyPress) {
|
||||
ret = ret.replace("keyPress", "keyPress<" + keyCode + ">");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
return SWF.getCachedActionList(this, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActions(List<Action> actions) {
|
||||
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getActionBytes() {
|
||||
return actionBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionBytes(byte[] actionBytes) {
|
||||
this.actionBytes = new ByteArrayRange(actionBytes);
|
||||
SWF.uncache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantPools(List<List<String>> constantPools) throws ConstantPoolTooBigException {
|
||||
Action.setConstantPools(this, constantPools, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified() {
|
||||
if (tag != null) {
|
||||
tag.setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
if (tag != null) {
|
||||
return tag.isModified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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) {
|
||||
writer.appendNoHilight(eventFlags.getHeader(keyCode, false));
|
||||
writer.appendNoHilight("{").newLine();
|
||||
return writer.indent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) {
|
||||
writer.unindent();
|
||||
return writer.appendNoHilight("}").newLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrefixLineCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String removePrefixAndSuffix(String source) {
|
||||
return Helper.unindentRows(1, 1, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExportFileName() {
|
||||
return eventFlags.getHeader(keyCode, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getSourceTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSourceTag(Tag t) {
|
||||
this.tag = t;
|
||||
this.swf = t.getSwf();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user