mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 14:58:24 +00:00
Saving correct font data offsets
This commit is contained in:
@@ -20,6 +20,11 @@ public class IggyCharAdvances implements StructureInterface {
|
||||
return advances;
|
||||
}
|
||||
|
||||
public IggyCharAdvances(List<Float> advances) {
|
||||
this.advances = advances;
|
||||
this.charCount = advances.size();
|
||||
}
|
||||
|
||||
public IggyCharAdvances(ReadDataStreamInterface stream, long charCount) throws IOException {
|
||||
this.charCount = charCount;
|
||||
readFromDataStream(stream);
|
||||
|
||||
@@ -25,6 +25,12 @@ public class IggyCharIndices implements StructureInterface {
|
||||
|
||||
private long charCount;
|
||||
|
||||
public IggyCharIndices(List<Character> chars) {
|
||||
this.chars = chars;
|
||||
this.charCount = chars.size();
|
||||
padd = 0;
|
||||
}
|
||||
|
||||
public IggyCharIndices(ReadDataStreamInterface stream, long charCount) throws IOException {
|
||||
this.charCount = charCount;
|
||||
readFromDataStream(stream);
|
||||
|
||||
@@ -36,6 +36,16 @@ public class IggyCharKerning implements StructureInterface {
|
||||
return kerningOffsets;
|
||||
}
|
||||
|
||||
public IggyCharKerning(List<Character> charsA, List<Character> charsB, List<Short> kerningOffsets) {
|
||||
if ((charsA.size() != charsB.size()) || (charsB.size() != kerningOffsets.size())) {
|
||||
throw new RuntimeException("sizes of charsA, charsB and offsets must match");
|
||||
}
|
||||
this.kernCount = charsA.size();
|
||||
this.charsA = charsA;
|
||||
this.charsB = charsB;
|
||||
this.kerningOffsets = kerningOffsets;
|
||||
}
|
||||
|
||||
public IggyCharKerning(ReadDataStreamInterface stream, long kernCount) throws IOException {
|
||||
this.kernCount = kernCount;
|
||||
readFromDataStream(stream);
|
||||
|
||||
@@ -38,15 +38,15 @@ public class IggyCharOffset implements StructureInterface {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
public IggyCharOffset(long zero, int ischar1, int ischar2, long zero2, int xscale, int yscale, long zero3, long offset) {
|
||||
this.zero = zero;
|
||||
public IggyCharOffset(int ischar1, int ischar2, int xscale, int yscale) {
|
||||
this.zero = 0;
|
||||
this.ischar1 = ischar1;
|
||||
this.ischar2 = ischar2;
|
||||
this.zero2 = zero2;
|
||||
this.zero2 = 0;
|
||||
this.xscale = xscale;
|
||||
this.yscale = yscale;
|
||||
this.zero3 = zero3;
|
||||
this.offset = offset;
|
||||
this.zero3 = 0;
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,63 +35,25 @@ public class IggyFile implements StructureInterface {
|
||||
|
||||
final static Logger LOGGER = Logger.getLogger(IggyFile.class.getName());
|
||||
|
||||
private File originalFile;
|
||||
private IggyHeader header;
|
||||
private List<IggySubFileEntry> subFileEntries = new ArrayList<>();
|
||||
private List<byte[]> subFileEntriesData = new ArrayList<>();
|
||||
|
||||
private List<IggySwf> iggySwfs = new ArrayList<>();
|
||||
private IggySwf iggySwf;
|
||||
|
||||
public static final int FIRST_TAG_POSITION = 3;
|
||||
|
||||
public void replaceFontTag(int targetSwfIndex, int fontIndex, IggyFont newFont) throws IOException {
|
||||
IggySwf iggySwf = iggySwfs.get(targetSwfIndex);
|
||||
iggySwf.replaceFontTag(fontIndex, newFont);
|
||||
|
||||
IggyIndexBuilder indexStream = new IggyIndexBuilder();
|
||||
DataStreamInterface flashStream = new TemporaryDataStream();
|
||||
flashStream.setIndexing(indexStream);
|
||||
iggySwf.writeToDataStream(flashStream);
|
||||
byte flashData[] = flashStream.getAllBytes();
|
||||
int swfIndex = 0;
|
||||
int offsetChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
if (swfIndex == targetSwfIndex) {
|
||||
byte indexData[] = indexStream.getIndexBytes();
|
||||
long newLen = indexData.length;
|
||||
long oldLen = entry.size;
|
||||
entry.size = newLen;
|
||||
entry.size2 = newLen;
|
||||
offsetChange += (newLen - oldLen);
|
||||
subFileEntriesData.set(i, indexData);
|
||||
}
|
||||
swfIndex++;
|
||||
}
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
if (swfIndex == targetSwfIndex) {
|
||||
long newLen = flashData.length;
|
||||
long oldLen = entry.size;
|
||||
entry.size = newLen;
|
||||
entry.size2 = newLen;
|
||||
offsetChange += (newLen - oldLen);
|
||||
subFileEntriesData.set(i, flashData);
|
||||
}
|
||||
}
|
||||
}
|
||||
public IggySwf getSwf() {
|
||||
return iggySwf;
|
||||
}
|
||||
|
||||
public IggySwf getSwf(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex);
|
||||
public int getFontCount() {
|
||||
return iggySwf.fonts.size();
|
||||
}
|
||||
|
||||
public int getFontCount(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).fonts.size();
|
||||
}
|
||||
|
||||
public IggyFont getFont(int swfIndex, int fontId) {
|
||||
return iggySwfs.get(swfIndex).fonts.get(fontId);
|
||||
public IggyFont getFont(int fontId) {
|
||||
return iggySwf.fonts.get(fontId);
|
||||
}
|
||||
|
||||
public IggyFile(String filePath) throws IOException {
|
||||
@@ -99,11 +61,16 @@ public class IggyFile implements StructureInterface {
|
||||
}
|
||||
|
||||
public IggyFile(File file) throws IOException {
|
||||
this.originalFile = file;
|
||||
try (ReadDataStreamInterface stream = new RandomAccessFileDataStream(file)) {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public File getOriginalFile() {
|
||||
return originalFile;
|
||||
}
|
||||
|
||||
public IggyHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
@@ -200,8 +167,7 @@ public class IggyFile implements StructureInterface {
|
||||
File outFile = new File(outFileName);
|
||||
IggyFile iggyFile = new IggyFile(inFile);
|
||||
extractIggyFile(inFile, extractDirOrig);
|
||||
IggySwf iswf = iggyFile.getSwf(0);
|
||||
iggyFile.replaceSwf(0, iswf);
|
||||
iggyFile.updateFlashEntry();
|
||||
outFile.delete();
|
||||
try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) {
|
||||
iggyFile.writeToDataStream(outputStream);
|
||||
@@ -620,32 +586,28 @@ public class IggyFile implements StructureInterface {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getSwfCount() {
|
||||
return iggySwfs.size();
|
||||
public String getSwfName() {
|
||||
return iggySwf.getName();
|
||||
}
|
||||
|
||||
public String getSwfName(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).getName();
|
||||
public long getSwfXMin() {
|
||||
return iggySwf.getHdr().getXMin();
|
||||
}
|
||||
|
||||
public long getSwfXMin(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).getHdr().getXMin();
|
||||
public long getSwfYMin() {
|
||||
return iggySwf.getHdr().getYMin();
|
||||
}
|
||||
|
||||
public long getSwfYMin(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).getHdr().getYMin();
|
||||
public long getSwfXMax() {
|
||||
return iggySwf.getHdr().getXMax();
|
||||
}
|
||||
|
||||
public long getSwfXMax(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).getHdr().getXMax();
|
||||
public long getSwfYMax() {
|
||||
return iggySwf.getHdr().getYMax();
|
||||
}
|
||||
|
||||
public long getSwfYMax(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).getHdr().getYMax();
|
||||
}
|
||||
|
||||
public float getSwfFrameRate(int swfIndex) {
|
||||
return iggySwfs.get(swfIndex).getHdr().getFrameRate();
|
||||
public float getSwfFrameRate() {
|
||||
return iggySwf.getHdr().getFrameRate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -667,11 +629,8 @@ public class IggyFile implements StructureInterface {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean replaceSwf(int targetSwfIndex, IggySwf iggySwf) throws IOException {
|
||||
public boolean updateFlashEntry() throws IOException {
|
||||
|
||||
if (targetSwfIndex < 0 || targetSwfIndex >= getSwfCount()) {
|
||||
throw new ArrayIndexOutOfBoundsException("No such SWF file index");
|
||||
}
|
||||
byte replacementData[];
|
||||
byte replacementIndexData[];
|
||||
IggyIndexBuilder ib = new IggyIndexBuilder();
|
||||
@@ -685,21 +644,17 @@ public class IggyFile implements StructureInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
//IggyIndexParser.parseIndex(true, new TemporaryDataStream(replacementIndexData), new ArrayList<>(), new ArrayList<>());
|
||||
int swfIndex = 0;
|
||||
long offsetsChange = 0;
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
entry.offset += offsetsChange;
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
if (swfIndex == targetSwfIndex) {
|
||||
long oldSize = entry.size;
|
||||
long newSize = replacementData.length;
|
||||
entry.size = newSize;
|
||||
entry.size2 = newSize;
|
||||
offsetsChange = offsetsChange + (newSize - oldSize); //entries after this one will have modified offsets
|
||||
subFileEntriesData.set(i, replacementData);
|
||||
}
|
||||
long oldSize = entry.size;
|
||||
long newSize = replacementData.length;
|
||||
entry.size = newSize;
|
||||
entry.size2 = newSize;
|
||||
offsetsChange = offsetsChange + (newSize - oldSize); //entries after this one will have modified offsets
|
||||
subFileEntriesData.set(i, replacementData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,7 +669,8 @@ public class IggyFile implements StructureInterface {
|
||||
for (int i = 0; i < subFileEntries.size(); i++) {
|
||||
IggySubFileEntry entry = subFileEntries.get(i);
|
||||
if (entry.type == IggySubFileEntry.TYPE_FLASH) {
|
||||
iggySwfs.add(new IggySwf(new TemporaryDataStream(getEntryData(i))));
|
||||
iggySwf = new IggySwf(new TemporaryDataStream(getEntryData(i)));
|
||||
break;
|
||||
}
|
||||
/*if (entry.type == IggySubFileEntry.TYPE_INDEX) {
|
||||
IggyIndexParser.parseIndex(true, new TemporaryDataStream(getEntryData(i)), new ArrayList<>(), new ArrayList<>());
|
||||
@@ -736,6 +692,13 @@ public class IggyFile implements StructureInterface {
|
||||
parseEntries();
|
||||
}
|
||||
|
||||
public void saveChanges() throws IOException {
|
||||
updateFlashEntry();
|
||||
try (RandomAccessFileDataStream raf = new RandomAccessFileDataStream(originalFile)) {
|
||||
writeToDataStream(raf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface stream) throws IOException {
|
||||
header.writeToDataStream(stream);
|
||||
|
||||
@@ -99,6 +99,67 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
private long decl_strings_address;
|
||||
private long type_fonts_address;
|
||||
|
||||
private long base_ofs_pos;
|
||||
private long sequence_end_ofs_pos;
|
||||
private long font_end_ofs_pos;
|
||||
private long sequence_start1_ofs_pos;
|
||||
private long sequence_start2_ofs_pos;
|
||||
private long sequence_start3_ofs_pos;
|
||||
private long names_ofs_pos;
|
||||
private long unk78_ofs_pos;
|
||||
private long last_section_ofs_pos;
|
||||
private long flash_filename_ofs_pos;
|
||||
private long decl_strings_ofs_pos;
|
||||
private long type_fonts_ofs_pos;
|
||||
|
||||
public long getBase_ofs_pos() {
|
||||
return base_ofs_pos;
|
||||
}
|
||||
|
||||
public long getSequence_end_ofs_pos() {
|
||||
return sequence_end_ofs_pos;
|
||||
}
|
||||
|
||||
public long getFont_end_ofs_pos() {
|
||||
return font_end_ofs_pos;
|
||||
}
|
||||
|
||||
public long getSequence_start1_ofs_pos() {
|
||||
return sequence_start1_ofs_pos;
|
||||
}
|
||||
|
||||
public long getSequence_start2_ofs_pos() {
|
||||
return sequence_start2_ofs_pos;
|
||||
}
|
||||
|
||||
public long getSequence_start3_ofs_pos() {
|
||||
return sequence_start3_ofs_pos;
|
||||
}
|
||||
|
||||
public long getNames_ofs_pos() {
|
||||
return names_ofs_pos;
|
||||
}
|
||||
|
||||
public long getUnk78_ofs_pos() {
|
||||
return unk78_ofs_pos;
|
||||
}
|
||||
|
||||
public long getLast_section_ofs_pos() {
|
||||
return last_section_ofs_pos;
|
||||
}
|
||||
|
||||
public long getFlash_filename_ofs_pos() {
|
||||
return flash_filename_ofs_pos;
|
||||
}
|
||||
|
||||
public long getDecl_strings_ofs_pos() {
|
||||
return decl_strings_ofs_pos;
|
||||
}
|
||||
|
||||
public long getType_fonts_ofs_pos() {
|
||||
return type_fonts_ofs_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all addresses by inserting gap
|
||||
*
|
||||
@@ -146,6 +207,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
}
|
||||
|
||||
public long getSequenceStartAddress2() {
|
||||
return sequence_start_address2;
|
||||
}
|
||||
|
||||
public long getSequenceStartAddress3() {
|
||||
return sequence_start_address3;
|
||||
}
|
||||
|
||||
@@ -175,21 +240,27 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
|
||||
base_ofs_pos = stream.position();
|
||||
off_base = stream.readUI64();
|
||||
base_address = off_base == 1 ? 0 : off_base + stream.position() - 8;
|
||||
|
||||
sequence_end_ofs_pos = stream.position();
|
||||
off_sequence_end = stream.readUI64();
|
||||
sequence_end_address = off_sequence_end == 1 ? 0 : off_sequence_end + stream.position() - 8;
|
||||
|
||||
font_end_ofs_pos = stream.position();
|
||||
off_font_end = stream.readUI64();
|
||||
font_end_address = off_font_end == 1 ? 0 : off_font_end + stream.position() - 8;
|
||||
|
||||
sequence_start1_ofs_pos = stream.position();
|
||||
off_sequence_start1 = stream.readUI64();
|
||||
sequence_start_address1 = off_sequence_start1 == 1 ? 0 : off_sequence_start1 + stream.position() - 8;
|
||||
|
||||
sequence_start2_ofs_pos = stream.position();
|
||||
off_sequence_start2 = stream.readUI64();
|
||||
sequence_start_address2 = off_sequence_start2 == 1 ? 0 : off_sequence_start2 + stream.position() - 8;
|
||||
|
||||
sequence_start3_ofs_pos = stream.position();
|
||||
off_sequence_start3 = stream.readUI64();
|
||||
sequence_start_address3 = off_sequence_start3 == 1 ? 0 : off_sequence_start3 + stream.position() - 8;
|
||||
|
||||
@@ -209,23 +280,29 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
|
||||
imported_guid = stream.readUI64();
|
||||
my_guid = stream.readUI64();
|
||||
|
||||
names_ofs_pos = stream.position();
|
||||
off_names = stream.readUI64();
|
||||
names_address = off_names == 1 ? 0 : off_names + stream.position() - 8;
|
||||
|
||||
unk78_ofs_pos = stream.position();
|
||||
off_unk78 = stream.readUI64();
|
||||
unk78_address = off_unk78 == 1 ? 0 : off_unk78 + stream.position() - 8;
|
||||
|
||||
unk80 = stream.readUI64(); //Maybe number of imports/names pointed by names_offset
|
||||
|
||||
last_section_ofs_pos = stream.position();
|
||||
off_last_section = stream.readUI64();
|
||||
last_section_address = off_last_section == 1 ? 0 : off_last_section + stream.position() - 8;
|
||||
|
||||
flash_filename_ofs_pos = stream.position();
|
||||
off_flash_filename = stream.readUI64();
|
||||
flash_filename_address = off_flash_filename == 1 ? 0 : off_flash_filename + stream.position() - 8;
|
||||
|
||||
decl_strings_ofs_pos = stream.position();
|
||||
off_decl_strings = stream.readUI64(); //relative offset to as3 code (16 bytes header + abc blob)
|
||||
decl_strings_address = off_decl_strings == 1 ? 0 : off_decl_strings + stream.position() - 8;
|
||||
|
||||
type_fonts_ofs_pos = stream.position();
|
||||
off_type_of_fonts = stream.readUI64(); //relative offset to as3 file names table (or classes names or whatever)
|
||||
type_fonts_address = off_type_of_fonts == 1 ? 0 : off_type_of_fonts + stream.position() - 8;
|
||||
|
||||
|
||||
@@ -108,9 +108,7 @@ public class IggyFont extends IggyTag {
|
||||
IggyCharAdvances charScales;
|
||||
IggyCharKerning charKernings;
|
||||
|
||||
byte[] padTo4byteBoundary;
|
||||
|
||||
public IggyFont(int type, int fontId, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long kern_count, float[] unk_float, long zero_padd, long what_2, long zero_padd_2, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48a, byte[] zeroes48b, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List<IggyCharOffset> charOffsets, List<IggyShape> glyphs, IggyCharIndices codePoints, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) {
|
||||
public IggyFont(int type, int fontId, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long kern_count, float[] unk_float, long zero_padd, long what_2, long zero_padd_2, long one_padd, int xscale, int yscale, long zero_padd_3, float ssr1, float ssr2, long char_count, long zero_padd_4, long what_3, byte[] zeroes48a, byte[] zeroes48b, float sss1, long one_padd2, float sss2, long one_padd3, float sss3, long one_padd4, float sss4, long one_padd5, String name, List<IggyCharOffset> charOffsets, List<IggyShape> glyphs, IggyCharIndices codePoints, IggyCharAdvances charScales, IggyCharKerning charKernings) {
|
||||
this.type = type;
|
||||
this.fontId = fontId;
|
||||
this.zeroone = zeroone;
|
||||
@@ -149,7 +147,6 @@ public class IggyFont extends IggyTag {
|
||||
this.codePoints = codePoints;
|
||||
this.charScales = charScales;
|
||||
this.charKernings = charKernings;
|
||||
this.padTo4byteBoundary = padTo4byteBoundary;
|
||||
}
|
||||
|
||||
public IggyFont(ReadDataStreamInterface stream) throws IOException {
|
||||
@@ -276,8 +273,10 @@ public class IggyFont extends IggyTag {
|
||||
}
|
||||
glyphs = new ArrayList<>();
|
||||
for (int i = 0; i < char_count; i++) {
|
||||
//System.err.println("read char " + (i + 1) + "/" + char_count);
|
||||
long addr = charAddresses.get(i);
|
||||
if (addr != 0) {
|
||||
//System.err.println("read chars at offset " + addr);
|
||||
s.seek(addr, SeekMode.SET);
|
||||
glyphs.add(new IggyShape(s));
|
||||
} else {
|
||||
@@ -506,4 +505,108 @@ public class IggyFont extends IggyTag {
|
||||
return String.format("IggyFontTag (%04X)", ID);
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setFontId(int fontId) {
|
||||
this.fontId = fontId;
|
||||
}
|
||||
|
||||
public void setCharCount2(int char_count2) {
|
||||
this.char_count2 = char_count2;
|
||||
}
|
||||
|
||||
public void setAscent(int ascent) {
|
||||
this.ascent = ascent;
|
||||
}
|
||||
|
||||
public void setDescent(int descent) {
|
||||
this.descent = descent;
|
||||
}
|
||||
|
||||
public void setLeading(int leading) {
|
||||
this.leading = leading;
|
||||
}
|
||||
|
||||
public void setFlags(long flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public void setUnkFloat(float[] unk_float) {
|
||||
this.unk_float = unk_float;
|
||||
}
|
||||
|
||||
public void setWhat2(long what_2) {
|
||||
this.what_2 = what_2;
|
||||
}
|
||||
|
||||
public void setXScale(int xscale) {
|
||||
this.xscale = xscale;
|
||||
}
|
||||
|
||||
public void setYScale(int yscale) {
|
||||
this.yscale = yscale;
|
||||
}
|
||||
|
||||
public void setSsr1(float ssr1) {
|
||||
this.ssr1 = ssr1;
|
||||
}
|
||||
|
||||
public void setSsr2(float ssr2) {
|
||||
this.ssr2 = ssr2;
|
||||
}
|
||||
|
||||
public void setCharCount(long char_count) {
|
||||
this.char_count = char_count;
|
||||
}
|
||||
|
||||
public void setWhat3(long what_3) {
|
||||
this.what_3 = what_3;
|
||||
}
|
||||
|
||||
public void setSubName(String subName) {
|
||||
this.subName = subName;
|
||||
}
|
||||
|
||||
public void setSss1(float sss1) {
|
||||
this.sss1 = sss1;
|
||||
}
|
||||
|
||||
public void setSss2(float sss2) {
|
||||
this.sss2 = sss2;
|
||||
}
|
||||
|
||||
public void setSss3(float sss3) {
|
||||
this.sss3 = sss3;
|
||||
}
|
||||
|
||||
public void setSss4(float sss4) {
|
||||
this.sss4 = sss4;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setCharOffsets(List<IggyCharOffset> charOffsets) {
|
||||
this.charOffsets = charOffsets;
|
||||
}
|
||||
|
||||
public void setGlyphs(List<IggyShape> glyphs) {
|
||||
this.glyphs = glyphs;
|
||||
}
|
||||
|
||||
public void setCodePoints(IggyCharIndices codePoints) {
|
||||
this.codePoints = codePoints;
|
||||
}
|
||||
|
||||
public void setCharScales(IggyCharAdvances charScales) {
|
||||
this.charScales = charScales;
|
||||
}
|
||||
|
||||
public void setCharKernings(IggyCharKerning charKernings) {
|
||||
this.charKernings = charKernings;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class IggyFontBinInfo implements StructureInterface {
|
||||
public static final int STRUCT_SIZE = 96;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long size_of_this_info = 96;
|
||||
long size_of_this_info = STRUCT_SIZE;
|
||||
@IggyFieldType(value = DataType.uint16_t, count = 4)
|
||||
int font_specific[];
|
||||
@IggyFieldType(DataType.float_t)
|
||||
|
||||
@@ -21,10 +21,10 @@ public class IggyFontTypeInfo implements StructureInterface {
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
long font_info_num;
|
||||
|
||||
private long local_name_address;
|
||||
private long local_name_ofs_pos;
|
||||
|
||||
public long getLocal_name_address() {
|
||||
return local_name_address;
|
||||
public long getLocal_name_ofs_pos() {
|
||||
return local_name_ofs_pos;
|
||||
}
|
||||
|
||||
public IggyFontTypeInfo(ReadDataStreamInterface s) throws IOException {
|
||||
@@ -34,39 +34,15 @@ public class IggyFontTypeInfo implements StructureInterface {
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
zero = s.readUI64();
|
||||
local_name_ofs_pos = s.position();
|
||||
ofs_local_name = s.readUI64();
|
||||
local_name_address = ofs_local_name + s.position() - 8;
|
||||
font_info_num = s.readUI64();
|
||||
}
|
||||
|
||||
public String readFontInfo(ReadDataStreamInterface s) throws IOException {
|
||||
long pos = s.position();
|
||||
s.seek(local_name_address, SeekMode.SET);
|
||||
StringBuilder inf_font_builder = new StringBuilder();
|
||||
while (true) {
|
||||
char c = (char) s.readUI16();
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
inf_font_builder.append(c);
|
||||
}
|
||||
s.seek(pos, SeekMode.SET);
|
||||
return inf_font_builder.toString();
|
||||
}
|
||||
|
||||
public void writeFontInfo(String info_name, WriteDataStreamInterface s) throws IOException {
|
||||
long pos = s.position();
|
||||
s.seek(local_name_address, SeekMode.SET);
|
||||
for (int i = 0; i < info_name.length(); i++) {
|
||||
s.writeUI16(info_name.charAt(i));
|
||||
}
|
||||
s.writeUI16(0);
|
||||
s.seek(pos, SeekMode.SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
s.writeUI64(zero);
|
||||
local_name_ofs_pos = s.position();
|
||||
s.writeUI64(ofs_local_name);
|
||||
s.writeUI64(font_info_num);
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.jpexs.decompiler.flash.iggy;
|
||||
|
||||
import static com.jpexs.decompiler.flash.iggy.IggyFontBinInfo.STRUCT_SIZE;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyArrayFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.IggyIndexBuilder;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.StructureInterface;
|
||||
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySequence implements StructureInterface {
|
||||
|
||||
public static final int STRUCT_SIZE = 16;
|
||||
|
||||
@IggyArrayFieldType(value = DataType.uint64_t, count = 2)
|
||||
public long onepadd[];
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
public long local_seq_offset;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
public long zero;
|
||||
|
||||
@IggyFieldType(DataType.wchar_t)
|
||||
public String sequence_name;
|
||||
|
||||
@IggyFieldType(DataType.uint64_t)
|
||||
public long zero2;
|
||||
|
||||
// wchar_t sequencname[(sequenceendaddress-sequencestartaddress-localseqoffset)/2];
|
||||
// if((sequenceendaddress-sequencestartaddress)%8!=0) byte padd[((sequenceendaddress-sequencestartaddress)/8+1)*8-(sequenceendaddress-sequencestartaddress)];
|
||||
public IggySequence(ReadDataStreamInterface stream) throws IOException {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
onepadd = new long[2];
|
||||
for (int i = 0; i < onepadd.length; i++) {
|
||||
onepadd[i] = s.readUI64();
|
||||
}
|
||||
//sequence start
|
||||
local_seq_offset = s.readUI64();
|
||||
zero = s.readUI64();
|
||||
sequence_name = s.readWChar();
|
||||
s.pad8bytes();
|
||||
zero2 = s.readUI64(); //zero2
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
|
||||
IggyIndexBuilder ib = s.getIndexing();
|
||||
ib.writeLengthCustom(16, new int[]{0x00}, new int[]{2});
|
||||
for (int i = 0; i < onepadd.length; i++) {
|
||||
s.writeUI64(onepadd[i]);
|
||||
}
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
s.writeUI64(local_seq_offset);
|
||||
s.writeUI64(zero);
|
||||
ib.write16bitArray(sequence_name.length() + 1);
|
||||
s.writeWChar(sequence_name);
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
s.writeUI64(zero2);
|
||||
}
|
||||
}
|
||||
@@ -69,18 +69,18 @@ public class IggyShape implements StructureInterface {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
|
||||
public IggyShape(float minx, float miny, float maxx, float maxy, long advance, long count, long one, long one2, long one3, long one4, long two1, List<IggyShapeNode> nodes) {
|
||||
public IggyShape(float minx, float miny, float maxx, float maxy, List<IggyShapeNode> nodes) {
|
||||
this.minx = minx;
|
||||
this.miny = miny;
|
||||
this.maxx = maxx;
|
||||
this.maxy = maxy;
|
||||
this.unk = advance;
|
||||
this.count = count;
|
||||
this.one = one;
|
||||
this.one2 = one2;
|
||||
this.one3 = one3;
|
||||
this.one4 = one4;
|
||||
this.two1 = two1;
|
||||
this.unk = 0; //??
|
||||
this.one = 1;
|
||||
this.one2 = 1;
|
||||
this.one3 = 1;
|
||||
this.one4 = 1;
|
||||
this.two1 = 2;
|
||||
this.count = nodes.size();
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,16 +45,17 @@ public class IggyShapeNode implements StructureInterface {
|
||||
|
||||
private boolean first;
|
||||
|
||||
public IggyShapeNode(float x1, float y1, float x2, float y2, int node_type, int node_subtype, int zer1, int zer2, long isstart) {
|
||||
this.targetX = x1;
|
||||
this.targetY = y1;
|
||||
this.controlX = x2;
|
||||
this.controlY = y2;
|
||||
public IggyShapeNode(float targetX, float targetY, float controlX, float controlY, int node_type, int node_subtype, boolean first) {
|
||||
this.targetX = targetX;
|
||||
this.targetY = targetY;
|
||||
this.controlX = controlX;
|
||||
this.controlY = controlY;
|
||||
this.node_type = node_type;
|
||||
this.node_subtype = node_subtype;
|
||||
this.zer1 = zer1;
|
||||
this.zer2 = zer2;
|
||||
this.isstart = isstart;
|
||||
this.zer1 = 0;
|
||||
this.zer2 = 0;
|
||||
this.first = first;
|
||||
this.isstart = first ? 0 : 1;
|
||||
}
|
||||
|
||||
public IggyShapeNode(ReadDataStreamInterface s, boolean first) throws IOException {
|
||||
@@ -98,19 +99,19 @@ public class IggyShapeNode implements StructureInterface {
|
||||
s.writeUI32(isstart);
|
||||
}
|
||||
|
||||
public float getX1() {
|
||||
public float getTargetX() {
|
||||
return targetX;
|
||||
}
|
||||
|
||||
public float getY1() {
|
||||
public float getTargetY() {
|
||||
return targetY;
|
||||
}
|
||||
|
||||
public float getX2() {
|
||||
public float getControlX() {
|
||||
return controlX;
|
||||
}
|
||||
|
||||
public float getY2() {
|
||||
public float getControlY() {
|
||||
return controlY;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ public class IggySwf implements StructureInterface {
|
||||
String name;
|
||||
|
||||
List<IggyFont> fonts = new ArrayList<>();
|
||||
private List<Long> font_data_addresses = new ArrayList<>();
|
||||
// private List<Long> font_data_addresses = new ArrayList<>();
|
||||
List<IggyFont> add_fonts = new ArrayList<>();
|
||||
private List<Long> add_font_data_addresses = new ArrayList<>();
|
||||
// private List<Long> add_font_data_addresses = new ArrayList<>();
|
||||
|
||||
private IggyFlashHeader64 hdr;
|
||||
|
||||
@@ -38,14 +38,16 @@ public class IggySwf implements StructureInterface {
|
||||
readFromDataStream(stream);
|
||||
}
|
||||
private List<IggyText> texts = new ArrayList<>();
|
||||
private List<Long> text_data_addresses = new ArrayList<>();
|
||||
//private List<Long> text_data_addresses = new ArrayList<>();
|
||||
private List<IggyText> add_texts = new ArrayList<>();
|
||||
private List<Long> add_text_data_addresses = new ArrayList<>();
|
||||
//private List<Long> add_text_data_addresses = new ArrayList<>();
|
||||
|
||||
private byte font_add_data[];
|
||||
private List<Long> font_additional_size = new ArrayList<>();
|
||||
//private byte font_add_data[];
|
||||
//private List<Long> font_additional_size = new ArrayList<>();
|
||||
private IggyFontBinInfo font_bin_info[];
|
||||
private IggySequence sequence;
|
||||
private List<String> sequenceNames = new ArrayList<>();
|
||||
//private List<Long> sequenceValues = new ArrayList<>();
|
||||
|
||||
private IggyFontTypeInfo type_info[];
|
||||
private String type_info_name[];
|
||||
private IggyDeclStrings decl_strings;
|
||||
@@ -56,36 +58,6 @@ public class IggySwf implements StructureInterface {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
public void replaceFontTag(int fontIndex, IggyFont newFont) throws IOException {
|
||||
/*long newLen;
|
||||
byte newData[];
|
||||
try (WriteDataStreamInterface stream = new TemporaryDataStream()) {
|
||||
newFont.writeToDataStream(stream);
|
||||
newData = stream.getAllBytes();
|
||||
newLen = newData.length;
|
||||
}
|
||||
|
||||
//FIXME
|
||||
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_new\\font" + fontIndex + ".bin", newData);
|
||||
|
||||
long oldLen = font_data_sizes[fontIndex];
|
||||
long diff = newLen - oldLen;
|
||||
if (diff != 0) {
|
||||
font_data_sizes[fontIndex] = newLen;
|
||||
for (int i = fontIndex; i < hdr.font_count; i++) {
|
||||
font_data_addresses[i] += diff;
|
||||
}
|
||||
for (int i = 0; i < text_addresses.size(); i++) {
|
||||
text_addresses.set(i, text_addresses.get(i) + diff);
|
||||
}
|
||||
for (int i = 0; i < font_add_off.size(); i++) {
|
||||
font_add_off.set(i, font_add_off.get(i) + diff);
|
||||
}
|
||||
}
|
||||
hdr.insertGapAfter(font_data_addresses[fontIndex], diff);
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
|
||||
this.hdr = new IggyFlashHeader64(s);
|
||||
@@ -97,7 +69,7 @@ public class IggySwf implements StructureInterface {
|
||||
if (pad8 > 8) {
|
||||
s.seek(pad8, SeekMode.CUR);
|
||||
}
|
||||
//here is offset [2] - 232
|
||||
//here is offset [2] - 232
|
||||
s.seek(hdr.getBaseAddress(), SeekMode.SET);
|
||||
s.readUI64(); //pad 1
|
||||
|
||||
@@ -121,12 +93,12 @@ public class IggySwf implements StructureInterface {
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
font_data_addresses.add(addr);
|
||||
//font_data_addresses.add(addr);
|
||||
fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
text_data_addresses.add(addr);
|
||||
//text_data_addresses.add(addr);
|
||||
texts.add(text);
|
||||
break;
|
||||
default:
|
||||
@@ -151,12 +123,12 @@ public class IggySwf implements StructureInterface {
|
||||
switch (kind) {
|
||||
case 22 /*FONT*/:
|
||||
IggyFont font = new IggyFont(s);
|
||||
add_font_data_addresses.add(addr);
|
||||
//add_font_data_addresses.add(addr);
|
||||
add_fonts.add(font);
|
||||
break;
|
||||
case 6 /*TEXT*/:
|
||||
IggyText text = new IggyText(s);
|
||||
add_text_data_addresses.add(addr);
|
||||
//add_text_data_addresses.add(addr);
|
||||
add_texts.add(text);
|
||||
break;
|
||||
default:
|
||||
@@ -164,91 +136,6 @@ public class IggySwf implements StructureInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
long offset = s.readUI64();
|
||||
font_data_addresses[i] = offset + s.position() - 8;
|
||||
long next_offset = s.readUI64();
|
||||
s.seek(-8, SeekMode.CUR);
|
||||
if (next_offset == 1) {
|
||||
font_data_sizes[i] = hdr.getFontEndAddress() - font_data_addresses[i];
|
||||
} else {
|
||||
font_data_sizes[i] = next_offset - offset + 8;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
long offset = s.readUI64();
|
||||
if (offset == 1) {
|
||||
break;
|
||||
}
|
||||
long text_addr = offset + s.position() - 8;
|
||||
text_addresses.add(text_addr);
|
||||
long next_offset = s.readUI64();
|
||||
s.seek(-8, SeekMode.CUR);
|
||||
if (next_offset == 1) {
|
||||
text_data_sizes.add(hdr.getFontEndAddress() - text_addr);
|
||||
break;
|
||||
} else {
|
||||
text_data_sizes.add(next_offset - offset + 8);
|
||||
}
|
||||
}
|
||||
s.readUI64(); //1
|
||||
|
||||
if (hdr.getImported_guid() != 0) {
|
||||
ofs_additional = s.readUI64();
|
||||
additional_address = ofs_additional + s.position() - 8;
|
||||
font_additional_addresses.add(additional_address);
|
||||
font_additional_size.add(hdr.getFontEndAddress() - font_additional_addresses.get(0));
|
||||
|
||||
if (s.readUI8(font_additional_addresses.get(0)) != 22) { //additional is not text
|
||||
// font je hozen mezi infa...
|
||||
for (int i = 0; i < text_addresses.size(); i++) { //walk all already read texts
|
||||
if (s.readUI8(text_addresses.get(i)) == 22) { //check if it's text
|
||||
long pomoff;
|
||||
long pomsize;
|
||||
pomoff = text_addresses.get(i);
|
||||
pomsize = text_data_sizes.get(i);
|
||||
text_addresses.set(i, font_additional_addresses.get(0));
|
||||
text_data_sizes.set(i, font_additional_size.get(0));
|
||||
font_additional_addresses.set(0, pomoff);
|
||||
font_additional_size.set(0, pomsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/* if (s.readUI8(s.position()) == 22) { //22 = Text
|
||||
byte[] textHdr = s.readBytes(IggyText.STRUCT_SIZE);
|
||||
String textStr = s.readWChar();
|
||||
s.pad8bytes();
|
||||
}*/
|
||||
//here is offset [3] - 744
|
||||
/* fonts = new ArrayList<>();
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
s.seek(font_data_addresses[i], SeekMode.SET);
|
||||
byte font_data[] = s.readBytes((int) font_data_sizes[i]);
|
||||
//FIXME
|
||||
//Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\extraxtdir_orig\\font" + i + ".bin", font_data);
|
||||
s.seek(-font_data_sizes[i], SeekMode.CUR);
|
||||
IggyFont font = new IggyFont(s);
|
||||
fonts.add(font);
|
||||
}
|
||||
|
||||
for (int i = 0;
|
||||
i < text_addresses.size();
|
||||
i++) {
|
||||
s.seek(text_addresses.get(i), SeekMode.SET);
|
||||
texts.add(new IggyText(s));
|
||||
//byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i));
|
||||
//text_data_bytes.add(text_data);
|
||||
}
|
||||
|
||||
if (hdr.getImported_guid()
|
||||
!= 0) {
|
||||
s.seek(font_additional_addresses.get(0), SeekMode.SET);
|
||||
font_add_data = s.readBytes((int) (long) font_additional_size.get(0));
|
||||
}*/
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
//here is offset [4] - 856 ?
|
||||
font_bin_info = new IggyFontBinInfo[(int) hdr.font_count];
|
||||
@@ -256,9 +143,33 @@ public class IggySwf implements StructureInterface {
|
||||
font_bin_info[i] = new IggyFontBinInfo(s);
|
||||
}
|
||||
|
||||
s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET);
|
||||
sequence = new IggySequence(s);
|
||||
sequenceNames = new ArrayList<>();
|
||||
|
||||
long seq_addresses[] = new long[]{hdr.getSequenceStartAddress1(), hdr.getSequenceStartAddress2(), hdr.getSequenceStartAddress3()};
|
||||
long seq_name_addresses[] = new long[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_addresses[i] == 0) {
|
||||
seq_name_addresses[i] = 0;
|
||||
//0
|
||||
} else {
|
||||
s.seek(seq_addresses[i], SeekMode.SET);
|
||||
long ofs_seq_name = s.readUI64();
|
||||
seq_name_addresses[i] = ofs_seq_name == 1 ? 0 : ofs_seq_name + s.position() - 8;
|
||||
s.readUI64(); //is this crucial?
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (seq_name_addresses[i] > 0) {
|
||||
s.seek(seq_name_addresses[i], SeekMode.SET);
|
||||
sequenceNames.add(s.readWChar());
|
||||
} else {
|
||||
sequenceNames.add(null);
|
||||
}
|
||||
}
|
||||
s.pad8bytes();
|
||||
|
||||
//sequence = new IggySequence(s);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
type_info = new IggyFontTypeInfo[(int) hdr.font_count];
|
||||
type_info_name = new String[(int) hdr.font_count];
|
||||
@@ -266,7 +177,8 @@ public class IggySwf implements StructureInterface {
|
||||
type_info[i] = new IggyFontTypeInfo(s);
|
||||
}
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info_name[i] = type_info[i].readFontInfo(s);
|
||||
s.seek(type_info[i].getLocal_name_ofs_pos() + type_info[i].ofs_local_name, SeekMode.SET);
|
||||
type_info_name[i] = s.readWChar();
|
||||
}
|
||||
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
@@ -290,64 +202,114 @@ public class IggySwf implements StructureInterface {
|
||||
ib.write16bitArray(name.length() + 1);
|
||||
ib.writeTwoPaddingBytes();
|
||||
ib.write64bitPointerArray(64);
|
||||
for (int i = 0; i < font_data_addresses.size(); i++) {
|
||||
long offset = font_data_addresses.get(i) - s.position();
|
||||
s.writeUI64(offset);
|
||||
long posBeforeOffsets = s.position();
|
||||
|
||||
final int FILL_LATER = 1;
|
||||
|
||||
List<Long> fontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
fontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
for (int i = 0; i < text_data_addresses.size(); i++) {
|
||||
long offset = text_data_addresses.get(i) - s.position();
|
||||
s.writeUI64(offset);
|
||||
List<Long> textPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
textPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(1);
|
||||
if (additional_address != 0) {
|
||||
long ofs_additional = additional_address - s.position();
|
||||
s.writeUI64(ofs_additional);
|
||||
|
||||
long addPosFillLater = s.position();
|
||||
s.writeUI64(FILL_LATER);
|
||||
long posAfter = posBeforeOffsets + 64 * 8;
|
||||
long curPos = s.position();
|
||||
long numLeft = posAfter - curPos;
|
||||
long ofsLeft = numLeft / 8;
|
||||
for (int i = 0; i < ofsLeft - 1; i++) {
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
|
||||
while (s.position() < font_data_addresses.get(0)) {
|
||||
s.writeUI64(1);
|
||||
}
|
||||
for (int i = 0; i < fonts.size(); i++) {
|
||||
s.seek(font_data_addresses.get(i), SeekMode.SET);
|
||||
s.setOlderOffsetToThisPos(fontPosFillLater.get(i));
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
s.seek(text_data_addresses.get(i), SeekMode.SET);
|
||||
s.setOlderOffsetToThisPos(textPosFillLater.get(i));
|
||||
texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
|
||||
if (hdr.getImported_guid() != 0) {
|
||||
if (!add_fonts.isEmpty() || !add_texts.isEmpty()) {
|
||||
s.setOlderOffsetToThisPos(addPosFillLater);
|
||||
|
||||
List<Long> addFontPosFillLater = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
s.seek(add_font_data_addresses.get(i), SeekMode.SET);
|
||||
fonts.get(i).writeToDataStream(s);
|
||||
addFontPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
List<Long> addTextPosFillLater = new ArrayList<>();
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
addTextPosFillLater.add(s.position());
|
||||
s.writeUI64(FILL_LATER);
|
||||
}
|
||||
s.writeUI64(FILL_LATER);
|
||||
for (int i = 0; i < add_fonts.size(); i++) {
|
||||
s.setOlderOffsetToThisPos(addFontPosFillLater.get(i));
|
||||
add_fonts.get(i).writeToDataStream(s);
|
||||
}
|
||||
for (int i = 0; i < add_texts.size(); i++) {
|
||||
s.seek(add_text_data_addresses.get(i), SeekMode.SET);
|
||||
texts.get(i).writeToDataStream(s);
|
||||
s.setOlderOffsetToThisPos(addTextPosFillLater.get(i));
|
||||
add_texts.get(i).writeToDataStream(s);
|
||||
}
|
||||
}
|
||||
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
|
||||
s.setOlderOffsetToThisPos(hdr.getFont_end_ofs_pos());
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_BIN_INFO_SIZE, hdr.font_count);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
font_bin_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
s.seek(hdr.getSequenceStartAddress1(), SeekMode.SET);
|
||||
sequence.writeToDataStream(s);
|
||||
long seq_ofs_pos[] = new long[]{hdr.getSequence_start1_ofs_pos(), hdr.getSequence_start2_ofs_pos(), hdr.getSequence_start3_ofs_pos()};
|
||||
long off_seq_expected[] = new long[]{hdr.off_sequence_start1, hdr.off_sequence_start2, hdr.off_sequence_start3};
|
||||
|
||||
long seq_name_fill_later[] = new long[3];
|
||||
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[0]);
|
||||
s.writeUI64(1);
|
||||
s.writeUI64(1);
|
||||
ib.writeLengthCustom(16, new int[]{0}, new int[]{2});
|
||||
|
||||
seq_name_fill_later[2] = s.position();
|
||||
s.setOlderOffsetToThisPos(seq_ofs_pos[2]);
|
||||
s.writeUI64(FILL_LATER);
|
||||
s.writeUI64(0);
|
||||
ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (sequenceNames.get(i) != null) {
|
||||
s.setOlderOffsetToThisPos(seq_name_fill_later[i]);
|
||||
ib.write16bitArray(sequenceNames.get(i).length() + 1);
|
||||
s.writeWChar(sequenceNames.get(i));
|
||||
}
|
||||
}
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
|
||||
ib.writeConstLengthArray(IggyIndexBuilder.CONST_TYPE_INFO_SIZE, hdr.font_count);
|
||||
s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
s.setOlderOffsetToThisPos(hdr.getType_fonts_ofs_pos());
|
||||
//s.seek(hdr.getTypeFontsAddress(), SeekMode.SET);
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
type_info[i].writeToDataStream(s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < hdr.font_count; i++) {
|
||||
ib.write16bitArray(type_info_name[i].length() + 1);
|
||||
type_info[i].writeFontInfo(type_info_name[i], s);
|
||||
s.setOlderOffsetToThisPos(type_info[i].getLocal_name_ofs_pos());
|
||||
s.writeWChar(type_info_name[i]);
|
||||
}
|
||||
s.pad8bytes();
|
||||
ib.pad8bytes();
|
||||
s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
|
||||
s.setOlderOffsetToThisPos(hdr.getDecl_strings_ofs_pos());
|
||||
//s.seek(hdr.getDeclStringsAddress(), SeekMode.SET);
|
||||
decl_strings.writeToDataStream(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLE;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyShapeToSwfConvertor {
|
||||
|
||||
private static int makeLengthsEmX(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
private static int makeLengthsEmY(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
public static SHAPE convertCharToShape(IggyShape igchar) {
|
||||
SHAPE shape = new SHAPE();
|
||||
List<SHAPERECORD> retList = new ArrayList<>();
|
||||
List<IggyShapeNode> ignodes = igchar.getNodes();
|
||||
|
||||
int prevX = 0;
|
||||
int prevY = 0;
|
||||
|
||||
for (IggyShapeNode ign : ignodes) {
|
||||
if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_MOVE) {
|
||||
StyleChangeRecord scr = new StyleChangeRecord();
|
||||
scr.stateMoveTo = true;
|
||||
prevX = scr.moveDeltaX = makeLengthsEmX(ign.getX1());
|
||||
prevY = scr.moveDeltaY = makeLengthsEmY(ign.getY1());
|
||||
scr.fillStyles = new FILLSTYLEARRAY();
|
||||
scr.lineStyles = new LINESTYLEARRAY();
|
||||
scr.calculateBits();
|
||||
retList.add(scr);
|
||||
} else {
|
||||
|
||||
int curX1 = makeLengthsEmX(ign.getX1());
|
||||
int curY1 = makeLengthsEmY(ign.getY1());
|
||||
|
||||
int curX2 = makeLengthsEmX(ign.getX2());
|
||||
int curY2 = makeLengthsEmY(ign.getY2());
|
||||
|
||||
if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_LINE_TO) {
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.deltaX = curX1 - prevX;
|
||||
ser.deltaY = curY1 - prevY;
|
||||
ser.generalLineFlag = true;
|
||||
ser.simplify();
|
||||
ser.calculateBits();
|
||||
prevX = curX1;
|
||||
prevY = curY1;
|
||||
retList.add(ser);
|
||||
} else if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_CURVE_POINT) {
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = curX2 - prevX;
|
||||
cer.controlDeltaY = curY2 - prevY;
|
||||
cer.anchorDeltaX = curX1 - curX2;
|
||||
cer.anchorDeltaY = curY1 - curY2;
|
||||
prevX = curX1;
|
||||
prevY = curY1;
|
||||
cer.calculateBits();
|
||||
retList.add(cer);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!retList.isEmpty()) {
|
||||
StyleChangeRecord init;
|
||||
if (retList.get(0) instanceof StyleChangeRecord) {
|
||||
init = (StyleChangeRecord) retList.get(0);
|
||||
} else {
|
||||
init = new StyleChangeRecord();
|
||||
retList.add(0, init);
|
||||
}
|
||||
init.stateFillStyle0 = true;
|
||||
init.fillStyle0 = 1;
|
||||
shape.numFillBits = 1;
|
||||
|
||||
} else {
|
||||
shape.numFillBits = 0;
|
||||
|
||||
}
|
||||
retList.add(new EndShapeRecord());
|
||||
shape.shapeRecords = retList;
|
||||
shape.numLineBits = 0;
|
||||
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLE;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggyShapeToSwfConvertor {
|
||||
|
||||
private static int makeLengthsEmX(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
private static int makeLengthsEmY(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
public static SHAPE convertCharToShape(IggyShape igchar) {
|
||||
SHAPE shape = new SHAPE();
|
||||
List<SHAPERECORD> retList = new ArrayList<>();
|
||||
List<IggyShapeNode> ignodes = igchar.getNodes();
|
||||
|
||||
int prevX = 0;
|
||||
int prevY = 0;
|
||||
|
||||
for (IggyShapeNode ign : ignodes) {
|
||||
if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_MOVE) {
|
||||
StyleChangeRecord scr = new StyleChangeRecord();
|
||||
scr.stateMoveTo = true;
|
||||
prevX = scr.moveDeltaX = makeLengthsEmX(ign.getTargetX());
|
||||
prevY = scr.moveDeltaY = makeLengthsEmY(ign.getTargetY());
|
||||
scr.fillStyles = new FILLSTYLEARRAY();
|
||||
scr.lineStyles = new LINESTYLEARRAY();
|
||||
scr.calculateBits();
|
||||
retList.add(scr);
|
||||
} else {
|
||||
|
||||
int curX1 = makeLengthsEmX(ign.getTargetX());
|
||||
int curY1 = makeLengthsEmY(ign.getTargetY());
|
||||
|
||||
int curX2 = makeLengthsEmX(ign.getControlX());
|
||||
int curY2 = makeLengthsEmY(ign.getControlY());
|
||||
|
||||
if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_LINE_TO) {
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.deltaX = curX1 - prevX;
|
||||
ser.deltaY = curY1 - prevY;
|
||||
ser.generalLineFlag = true;
|
||||
ser.simplify();
|
||||
ser.calculateBits();
|
||||
prevX = curX1;
|
||||
prevY = curY1;
|
||||
retList.add(ser);
|
||||
} else if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_CURVE_POINT) {
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = curX2 - prevX;
|
||||
cer.controlDeltaY = curY2 - prevY;
|
||||
cer.anchorDeltaX = curX1 - curX2;
|
||||
cer.anchorDeltaY = curY1 - curY2;
|
||||
prevX = curX1;
|
||||
prevY = curY1;
|
||||
cer.calculateBits();
|
||||
retList.add(cer);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!retList.isEmpty()) {
|
||||
StyleChangeRecord init;
|
||||
if (retList.get(0) instanceof StyleChangeRecord) {
|
||||
init = (StyleChangeRecord) retList.get(0);
|
||||
} else {
|
||||
init = new StyleChangeRecord();
|
||||
retList.add(0, init);
|
||||
}
|
||||
init.stateFillStyle0 = true;
|
||||
init.fillStyle0 = 1;
|
||||
shape.numFillBits = 1;
|
||||
|
||||
} else {
|
||||
shape.numFillBits = 0;
|
||||
|
||||
}
|
||||
retList.add(new EndShapeRecord());
|
||||
shape.shapeRecords = retList;
|
||||
shape.numLineBits = 0;
|
||||
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,104 +1,134 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import com.jpexs.helpers.ReReadableInputStream;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwfBundle implements SWFBundle {
|
||||
|
||||
private IggyFile iggyFile;
|
||||
|
||||
public IggySwfBundle(InputStream is) throws IOException {
|
||||
this(is, null);
|
||||
}
|
||||
|
||||
public IggySwfBundle(File filename) throws IOException {
|
||||
this(null, filename);
|
||||
}
|
||||
|
||||
protected IggySwfBundle(InputStream is, File filename) throws IOException {
|
||||
initBundle(is, filename);
|
||||
}
|
||||
|
||||
protected void initBundle(InputStream is, File filename) throws IOException {
|
||||
if (filename == null) {
|
||||
filename = File.createTempFile("bundle", ".iggy");
|
||||
Helper.saveStream(is, filename);
|
||||
}
|
||||
iggyFile = new IggyFile(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return iggyFile.getSwfCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> ret = new TreeSet<>();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ret.add(iggyFile.getSwfName(i));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int keyToSwfIndex(String key) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (key.equals(iggyFile.getSwfName(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Key " + key + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableInputStream getSWF(String key) throws IOException {
|
||||
SWF swf = IggyToSwfConvertor.getSwf(iggyFile, keyToSwfIndex(key));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
swf.saveTo(baos);
|
||||
MemoryInputStream mis = new MemoryInputStream(baos.toByteArray());
|
||||
return mis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SeekableInputStream> getAll() throws IOException {
|
||||
Map<String, SeekableInputStream> ret = new HashMap<>();
|
||||
for (String key : getKeys()) {
|
||||
ret.put(key, getSWF(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "iggy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true; //TODO: make writable
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putSWF(String key, InputStream is) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
}
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFBundle;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.MemoryInputStream;
|
||||
import com.jpexs.helpers.ReReadableInputStream;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class IggySwfBundle implements SWFBundle {
|
||||
|
||||
private IggyFile iggyFile;
|
||||
|
||||
public IggySwfBundle(InputStream is) throws IOException {
|
||||
this(is, null);
|
||||
}
|
||||
|
||||
public IggySwfBundle(File filename) throws IOException {
|
||||
this(null, filename);
|
||||
}
|
||||
|
||||
protected IggySwfBundle(InputStream is, File filename) throws IOException {
|
||||
initBundle(is, filename);
|
||||
}
|
||||
|
||||
protected void initBundle(InputStream is, File filename) throws IOException {
|
||||
if (filename == null) {
|
||||
filename = File.createTempFile("bundle", ".iggy");
|
||||
Helper.saveStream(is, filename);
|
||||
}
|
||||
iggyFile = new IggyFile(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys() {
|
||||
Set<String> ret = new TreeSet<>();
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ret.add(iggyFile.getSwfName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int keyToSwfIndex(String key) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (key.equals(iggyFile.getSwfName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Key " + key + " does not exist!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekableInputStream getSWF(String key) throws IOException {
|
||||
SWF swf = IggyToSwfConvertor.getSwf(iggyFile);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
swf.saveTo(baos);
|
||||
MemoryInputStream mis = new MemoryInputStream(baos.toByteArray());
|
||||
return mis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, SeekableInputStream> getAll() throws IOException {
|
||||
Map<String, SeekableInputStream> ret = new HashMap<>();
|
||||
for (String key : getKeys()) {
|
||||
ret.put(key, getSWF(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return "iggy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putSWF(String key, InputStream is) throws IOException {
|
||||
try {
|
||||
int swfIndex = 0;
|
||||
SWF swf = new SWF(is, false, false);
|
||||
List<DefineFont2Tag> fontTags = new ArrayList<>();
|
||||
for (CharacterTag ct : swf.getCharacters().values()) {
|
||||
if (ct instanceof DefineFont2Tag) {
|
||||
fontTags.add((DefineFont2Tag) ct);
|
||||
}
|
||||
}
|
||||
int fontCount = iggyFile.getFontCount();
|
||||
if (fontCount != fontTags.size()) {
|
||||
throw new IOException("Font count is different from original iggy file");
|
||||
}
|
||||
for (int i = 0; i < fontCount; i++) {
|
||||
IggyFont iggyFont = iggyFile.getFont(i);
|
||||
DefineFont2Tag fontTag = fontTags.get(i);
|
||||
SwfToIggyConvertor.updateIggyFont(iggyFont, fontTag);
|
||||
}
|
||||
iggyFile.saveChanges();
|
||||
return true;
|
||||
} catch (InterruptedException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharAdvances;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFile;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.iggy.IggySwf;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyText;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
@@ -44,56 +45,42 @@ import java.util.Set;
|
||||
*/
|
||||
public class IggyToSwfConvertor {
|
||||
|
||||
public static SWF[] getAllSwfs(IggyFile file) {
|
||||
SWF[] ret = new SWF[file.getSwfCount()];
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
ret[i] = getSwf(file, i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException {
|
||||
for (int swfIndex = 0; swfIndex < file.getSwfCount(); swfIndex++) {
|
||||
exportSwfToDir(file, swfIndex, outputDir);
|
||||
exportSwfToDir(file, outputDir);
|
||||
}
|
||||
|
||||
public static void exportSwfToDir(IggyFile file, File outputDir) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName()))) {
|
||||
exportSwf(file, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwfToDir(IggyFile file, int swfIndex, File outputDir) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(new File(outputDir, file.getSwfName(swfIndex)))) {
|
||||
exportSwf(file, swfIndex, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwfToFile(IggyFile file, int swfIndex, File outputFile) throws IOException {
|
||||
public static void exportSwfToFile(IggyFile file, File outputFile) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
|
||||
exportSwf(file, swfIndex, fos);
|
||||
exportSwf(file, fos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void exportSwf(IggyFile file, int swfIndex, OutputStream output) throws IOException {
|
||||
SWF swf = getSwf(file, swfIndex);
|
||||
public static void exportSwf(IggyFile file, OutputStream output) throws IOException {
|
||||
SWF swf = getSwf(file);
|
||||
swf.saveTo(output);
|
||||
}
|
||||
|
||||
private static int makeLengthsTwip(double val) {
|
||||
return (int) (val * SWF.unitDivisor);
|
||||
}
|
||||
|
||||
private static int makeLengthsEm(double val) {
|
||||
return (int) (val * 1024.0);
|
||||
}
|
||||
|
||||
public static SWF getSwf(IggyFile file, int swfIndex) {
|
||||
public static SWF getSwf(IggyFile file) {
|
||||
SWF swf = new SWF();
|
||||
swf.compression = SWFCompression.NONE;
|
||||
swf.frameCount = 1; //FIXME!!
|
||||
swf.frameRate = file.getSwfFrameRate(swfIndex);
|
||||
swf.frameRate = file.getSwfFrameRate();
|
||||
swf.gfx = false;
|
||||
swf.displayRect = new RECT(
|
||||
(int) (file.getSwfXMin(swfIndex) * SWF.unitDivisor),
|
||||
(int) (file.getSwfXMax(swfIndex) * SWF.unitDivisor),
|
||||
(int) (file.getSwfYMin(swfIndex) * SWF.unitDivisor),
|
||||
(int) (file.getSwfYMax(swfIndex) * SWF.unitDivisor));
|
||||
(int) (file.getSwfXMin() * SWF.unitDivisor),
|
||||
(int) (file.getSwfXMax() * SWF.unitDivisor),
|
||||
(int) (file.getSwfYMin() * SWF.unitDivisor),
|
||||
(int) (file.getSwfYMax() * SWF.unitDivisor));
|
||||
swf.version = 10; //FIXME
|
||||
|
||||
FileAttributesTag fat = new FileAttributesTag(swf);
|
||||
@@ -101,15 +88,14 @@ public class IggyToSwfConvertor {
|
||||
fat.hasMetadata = false;
|
||||
fat.useNetwork = false;
|
||||
swf.addTag(fat);
|
||||
|
||||
//Set<Integer> fontIndices = file.getFontIds(swfIndex);
|
||||
int fontCount = file.getFontCount(swfIndex);
|
||||
int fontCount = file.getFontCount();
|
||||
|
||||
int currentCharId = 0;
|
||||
Map<Integer, Integer> fontIndex2CharId = new HashMap<>();
|
||||
|
||||
for (int fontIndex = 0; fontIndex < fontCount; fontIndex++) {
|
||||
IggyFont iggyFont = file.getFont(swfIndex, fontIndex);
|
||||
IggyFont iggyFont = file.getFont(fontIndex);
|
||||
DefineFont2Tag fontTag = new DefineFont2Tag(swf);
|
||||
currentCharId++;
|
||||
fontIndex2CharId.put(fontIndex, currentCharId);
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SwfShapeToIggyConvertor {
|
||||
|
||||
private static float normalizeLengths(int val) {
|
||||
return (val / 1024f);
|
||||
}
|
||||
|
||||
public static IggyShape convertShape(SHAPE swfShape) {
|
||||
/*if (swfShape.shapeRecords.size() == 1) { //no glyphs, maybe space
|
||||
return null;
|
||||
}*/
|
||||
List<IggyShapeNode> nodes = new ArrayList<>();
|
||||
RECT bounds = swfShape.getBounds();
|
||||
boolean first = true;
|
||||
float curX = 0f;
|
||||
float curY = 0f;
|
||||
for (SHAPERECORD rec : swfShape.shapeRecords) {
|
||||
if (rec instanceof StraightEdgeRecord) {
|
||||
StraightEdgeRecord ser = (StraightEdgeRecord) rec;
|
||||
curX += normalizeLengths(ser.deltaX);
|
||||
curY += normalizeLengths(ser.deltaY);
|
||||
nodes.add(new IggyShapeNode(curX, curY, 0f, 0f, IggyShapeNode.NODE_TYPE_LINE_TO, 0, first));
|
||||
} else if (rec instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer = (CurvedEdgeRecord) rec;
|
||||
float controlX = curX + normalizeLengths(cer.controlDeltaX);
|
||||
float controlY = curY + normalizeLengths(cer.controlDeltaY);
|
||||
curX = curX + normalizeLengths(cer.controlDeltaX + cer.anchorDeltaX);
|
||||
curY = curY + normalizeLengths(cer.controlDeltaY + cer.anchorDeltaY);
|
||||
nodes.add(new IggyShapeNode(curX, curY, controlX, controlY, IggyShapeNode.NODE_TYPE_CURVE_POINT, 0, first));
|
||||
} else if (rec instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr = (StyleChangeRecord) rec;
|
||||
if (scr.stateMoveTo) {
|
||||
curX = normalizeLengths(scr.moveDeltaX);
|
||||
curY = normalizeLengths(scr.moveDeltaY);
|
||||
nodes.add(new IggyShapeNode(curX, curY, 0f, 0f, IggyShapeNode.NODE_TYPE_MOVE, 0, first));
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
IggyShape ret = new IggyShape(normalizeLengths(bounds.Xmin), normalizeLengths(bounds.Ymin), normalizeLengths(bounds.Xmax), normalizeLengths(bounds.Ymax), nodes);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.jpexs.decompiler.flash.iggy.conversion;
|
||||
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharAdvances;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharIndices;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharKerning;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFont;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
|
||||
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SwfToIggyConvertor {
|
||||
|
||||
private static float normalizeLengths(int val) {
|
||||
return (val / 1024f);
|
||||
}
|
||||
|
||||
public static void updateIggyFont(IggyFont iggyFont, DefineFont2Tag fontTag) {
|
||||
/*byte zeroone[] = new byte[28];
|
||||
zeroone[12] = 1;
|
||||
long flags = 65795;
|
||||
float unk_float[] = new float[]{
|
||||
-0.6484375f,
|
||||
-1.116211f,
|
||||
1.116211f,
|
||||
0.6679688f,
|
||||
0f
|
||||
};
|
||||
int xscale = 80;
|
||||
int yscale = 28;
|
||||
float ssr1 = 0.9f;
|
||||
float ssr2 = 0.3f;
|
||||
long what_2 = 33188160;
|
||||
long what_3 = 33600216;
|
||||
byte zeroes48a[] = new byte[48];
|
||||
byte zeroes48b[] = new byte[48];
|
||||
float sss1 = 1.1728859f;
|
||||
float sss2 = 1.1728706f;
|
||||
float sss3 = 1.1728821f;
|
||||
float sss4 = 1.1729145f;*/
|
||||
List<IggyCharOffset> charOffsets = new ArrayList<>();
|
||||
|
||||
List<IggyShape> glyphs = new ArrayList<>();
|
||||
|
||||
for (SHAPE s : fontTag.glyphShapeTable) {
|
||||
glyphs.add(SwfShapeToIggyConvertor.convertShape(s));
|
||||
}
|
||||
|
||||
List<Character> chars = new ArrayList<>();
|
||||
for (int code : fontTag.codeTable) {
|
||||
chars.add((char) code);
|
||||
}
|
||||
IggyCharIndices codePoints = new IggyCharIndices(chars);
|
||||
List<Float> scales = new ArrayList<>();
|
||||
for (int adv : fontTag.fontAdvanceTable) {
|
||||
scales.add(normalizeLengths(adv));
|
||||
}
|
||||
IggyCharAdvances charScales = new IggyCharAdvances(scales);
|
||||
List<Character> charA = new ArrayList<>();
|
||||
List<Character> charB = new ArrayList<>();
|
||||
List<Short> kernOffs = new ArrayList<>();
|
||||
|
||||
//IggyCharOffset
|
||||
for (KERNINGRECORD rec : fontTag.fontKerningTable) {
|
||||
charA.add((char) rec.fontKerningCode1);
|
||||
charB.add((char) rec.fontKerningCode2);
|
||||
kernOffs.add((short) rec.fontKerningAdjustment);
|
||||
}
|
||||
IggyCharKerning charKernings = new IggyCharKerning(charA, charB, kernOffs);
|
||||
|
||||
for (int i = 0; i < fontTag.getCharacterCount(); i++) {
|
||||
charOffsets.add(new IggyCharOffset(1, 0, 80, 19)); //XSCALE, YSCALE???
|
||||
}
|
||||
|
||||
iggyFont.setCharCount(fontTag.getCharacterCount());
|
||||
iggyFont.setCharCount2(fontTag.getCharacterCount());
|
||||
iggyFont.setAscent(fontTag.getAscent());
|
||||
iggyFont.setDescent(fontTag.getDescent());
|
||||
iggyFont.setLeading(fontTag.getLeading());
|
||||
iggyFont.setName(fontTag.getFontName());
|
||||
iggyFont.setCharOffsets(charOffsets);
|
||||
iggyFont.setGlyphs(glyphs);
|
||||
iggyFont.setCodePoints(codePoints);
|
||||
iggyFont.setCharScales(charScales);
|
||||
iggyFont.setCharKernings(charKernings);
|
||||
/*
|
||||
IggyFont iggyFont = new IggyFont(IggyFont.ID, 0, zeroone, fontTag.getCharacterCount(),
|
||||
fontTag.getAscent(), fontTag.getDescent(), fontTag.getLeading(), flags,
|
||||
fontTag.fontKerningTable.size(), unk_float, 0, what_2, 0, 1,
|
||||
xscale, yscale, 0, ssr1, ssr2, fontTag.getCharacterCount(), 0, what_3, zeroes48a, zeroes48b,
|
||||
sss1, 1, sss2, 1, sss3, 1, sss4, 1, fontTag.getFontName(),
|
||||
charOffsets, glyphs, codePoints, charScales, charKernings);
|
||||
*/
|
||||
}
|
||||
|
||||
public static IggyFont createIggyFont(DefineFont2Tag fontTag) {
|
||||
byte zeroone[] = new byte[28];
|
||||
zeroone[12] = 1;
|
||||
long flags = 65795;
|
||||
float unk_float[] = new float[]{
|
||||
-0.6484375f,
|
||||
-1.116211f,
|
||||
1.116211f,
|
||||
0.6679688f,
|
||||
0f
|
||||
};
|
||||
int xscale = 80;
|
||||
int yscale = 28;
|
||||
float ssr1 = 0.9f;
|
||||
float ssr2 = 0.3f;
|
||||
long what_2 = 33188160;
|
||||
long what_3 = 33600216;
|
||||
byte zeroes48a[] = new byte[48];
|
||||
byte zeroes48b[] = new byte[48];
|
||||
float sss1 = 1.1728859f;
|
||||
float sss2 = 1.1728706f;
|
||||
float sss3 = 1.1728821f;
|
||||
float sss4 = 1.1729145f;
|
||||
List<IggyCharOffset> charOffsets = new ArrayList<>();
|
||||
List<IggyShape> glyphs = new ArrayList<>();
|
||||
List<Character> chars = new ArrayList<>();
|
||||
for (int code : fontTag.codeTable) {
|
||||
chars.add((char) code);
|
||||
}
|
||||
IggyCharIndices codePoints = new IggyCharIndices(chars);
|
||||
List<Float> scales = new ArrayList<>();
|
||||
for (int adv : fontTag.fontAdvanceTable) {
|
||||
scales.add((float) adv);
|
||||
}
|
||||
IggyCharAdvances charScales = new IggyCharAdvances(scales);
|
||||
List<Character> charA = new ArrayList<>();
|
||||
List<Character> charB = new ArrayList<>();
|
||||
List<Short> kernOffs = new ArrayList<>();
|
||||
|
||||
for (KERNINGRECORD rec : fontTag.fontKerningTable) {
|
||||
charA.add((char) rec.fontKerningCode1);
|
||||
charB.add((char) rec.fontKerningCode2);
|
||||
kernOffs.add((short) rec.fontKerningAdjustment);
|
||||
}
|
||||
IggyCharKerning charKernings = new IggyCharKerning(charA, charB, kernOffs);
|
||||
|
||||
IggyFont iggyFont = new IggyFont(IggyFont.ID, 0, zeroone, fontTag.getCharacterCount(),
|
||||
fontTag.getAscent(), fontTag.getDescent(), fontTag.getLeading(), flags,
|
||||
fontTag.fontKerningTable.size(), unk_float, 0, what_2, 0, 1,
|
||||
xscale, yscale, 0, ssr1, ssr2, fontTag.getCharacterCount(), 0, what_3, zeroes48a, zeroes48b,
|
||||
sss1, 1, sss2, 1, sss3, 1, sss4, 1, fontTag.getFontName(),
|
||||
charOffsets, glyphs, codePoints, charScales, charKernings);
|
||||
return iggyFont;
|
||||
}
|
||||
}
|
||||
@@ -227,4 +227,15 @@ public abstract class AbstractDataStream implements DataStreamInterface {
|
||||
writeUI64(actual);
|
||||
seek(curPos, SeekMode.SET);
|
||||
}
|
||||
|
||||
public void setOlderOffsetToThisPosCheck(long savedPos, long expected) throws IOException {
|
||||
if (expected == 1) {
|
||||
return;
|
||||
}
|
||||
long curPos = position();
|
||||
long actual = curPos - savedPos;
|
||||
if (actual != expected) {
|
||||
throw new RuntimeException("Expected " + expected + " but found actual " + actual + ". Diff:" + ((actual - expected) > 0 ? "+" : "") + (actual - expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,20 +4,14 @@ import com.jpexs.decompiler.flash.iggy.IggyCharKerning;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyCharOffset;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFontBinInfo;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyFontTypeInfo;
|
||||
import com.jpexs.decompiler.flash.iggy.IggySequence;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShape;
|
||||
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
@@ -73,7 +67,7 @@ public class IggyIndexBuilder {
|
||||
private static final int CONST_VAL_GENERAL_FONT_INFO_SIZE = 112;
|
||||
private static final int CONST_VAL_GENERAL_FONT_INFO2_SIZE = 240;
|
||||
private static final int CONST_VAL_TEXT_DATA_SIZE = 104;
|
||||
private static final int CONST_VAL_SEQUENCE_SIZE = IggySequence.STRUCT_SIZE;
|
||||
private static final int CONST_VAL_SEQUENCE_SIZE = 16;
|
||||
|
||||
public static final int CONST_SHAPE_NODE_SIZE = 0;
|
||||
public static final int CONST_KERNING_RECORD_SIZE = 1;
|
||||
@@ -175,8 +169,12 @@ public class IggyIndexBuilder {
|
||||
long ret = 0;
|
||||
long rem = cnt;
|
||||
while (true) {
|
||||
if (rem == 0) {
|
||||
break;
|
||||
}
|
||||
if (rem == 1) {
|
||||
return writeIndex(constIndex, false, 0);
|
||||
ret += writeIndex(constIndex, false, 0);
|
||||
break;
|
||||
}
|
||||
if (rem <= 64) {
|
||||
ret += writeIndex(0x80 + (int) rem - 1, false, constIndex);
|
||||
@@ -307,10 +305,7 @@ public class IggyIndexBuilder {
|
||||
int index;
|
||||
|
||||
indexStream.writeUI8((int) val);
|
||||
if ((index = (int) val) < 0) {
|
||||
LOGGER.severe(String.format("< 0xC0: Cannot read index."));
|
||||
return 0;
|
||||
}
|
||||
index = (int) val;
|
||||
|
||||
if (index >= constTable.size()) {
|
||||
LOGGER.severe(String.format("< 0xC0: index is greater than index_table_size. %x > %x", index, constTable.size()));
|
||||
|
||||
@@ -21,6 +21,8 @@ public interface WriteDataStreamInterface extends AutoCloseable {
|
||||
|
||||
public void setOlderOffsetToThisPos(long savedPos) throws IOException;
|
||||
|
||||
public void setOlderOffsetToThisPosCheck(long savedPos, long expected) throws IOException;
|
||||
|
||||
public boolean writeUI64(long val) throws IOException;
|
||||
|
||||
public boolean writeSI64(long val) throws IOException;
|
||||
|
||||
Reference in New Issue
Block a user