diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java index 0320de9c8..1f7698640 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyDeclStrings.java @@ -1,79 +1,79 @@ -package com.jpexs.decompiler.flash.iggy; - -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 IggyDeclStrings implements StructureInterface { - - @IggyFieldType(DataType.uint64_t) - long one; - //@IggyFieldType(DataType.uint32_t) - //long size; - @IggyArrayFieldType(value = DataType.uint8_t, count = 3) - byte xxx[]; - @IggyArrayFieldType(value = DataType.uint8_t, countField = "size") - byte data[]; - byte padd[]; - @IggyFieldType(DataType.uint64_t) - long one2; - @IggyFieldType(DataType.uint64_t) - long zero; - - public byte[] getData() { - return data; - } - - public void setData(byte[] data) { - this.data = data; - } - - public IggyDeclStrings(ReadDataStreamInterface stream) throws IOException { - readFromDataStream(stream); - } - - @Override - public void readFromDataStream(ReadDataStreamInterface s) throws IOException { - one = s.readUI64(); - long size = s.readUI32(); - xxx = s.readBytes(3); - data = s.readBytes((int) size); - if ((15 + size) % 8 != 0) { - padd = s.readBytes((int) (((15 + size) / 8 + 1) * 8 - 15 - size)); - } else { - padd = new byte[0]; - } - one = s.readUI64(); - if (one != 1) { - throw new IOException("Wrong iggy font format (declend)!"); - } - zero = s.readUI64(); - } - - @Override - public void writeToDataStream(WriteDataStreamInterface s) throws IOException { - IggyIndexBuilder ib = s.getIndexing(); - s.writeUI64(one); - s.writeUI32(data.length); - ib.writeLengthCustom(15, new int[]{0x00, 0x08}, new int[]{2, 5}); - s.writeBytes(xxx); - s.writeBytes(data); - ib.writeLengthUI32(data.length); - if ((15 + data.length) % 8 != 0) { - byte[] padd = new byte[((int) (((15 + data.length) / 8 + 1) * 8 - 15 - data.length))]; - s.writeBytes(padd); - } - ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE); - s.writeUI64(one); - s.writeUI64(zero); - } - -} +package com.jpexs.decompiler.flash.iggy; + +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 IggyDeclStrings implements StructureInterface { + + @IggyFieldType(DataType.uint64_t) + long one; + //@IggyFieldType(DataType.uint32_t) + //long size; + @IggyArrayFieldType(value = DataType.uint8_t, count = 3) + byte xxx[]; + @IggyArrayFieldType(value = DataType.uint8_t, countField = "size") + byte data[]; + byte padd[]; + @IggyFieldType(DataType.uint64_t) + long one2; + @IggyFieldType(DataType.uint64_t) + long zero; + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public IggyDeclStrings(ReadDataStreamInterface stream) throws IOException { + readFromDataStream(stream); + } + + @Override + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + one = s.readUI64(); + long size = s.readUI32(); + xxx = s.readBytes(3); + data = s.readBytes((int) size); + if ((15 + size) % 8 != 0) { + padd = s.readBytes((int) (((15 + size) / 8 + 1) * 8 - 15 - size)); + } else { + padd = new byte[0]; + } + one = s.readUI64(); + if (one != 1) { + throw new IOException("Wrong iggy font format (declend)!"); + } + zero = s.readUI64(); + } + + @Override + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + IggyIndexBuilder ib = s.getIndexing(); + s.writeUI64(one); + s.writeUI32(data.length); + ib.writeLengthCustom(15, new int[]{0x00, 0x08}, new int[]{2, 5}); + s.writeBytes(xxx); + s.writeBytes(data); + ib.writeLengthUI32(data.length); + if ((15 + data.length) % 8 != 0) { + byte[] padd = new byte[((int) (((15 + data.length) / 8 + 1) * 8 - 15 - data.length))]; + s.writeBytes(padd); + } + ib.writeConstLength(IggyIndexBuilder.CONST_SEQUENCE_SIZE); + s.writeUI64(one); + s.writeUI64(zero); + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java index 290e51513..492812d56 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggySwf.java @@ -22,7 +22,6 @@ public class IggySwf implements StructureInterface { String name; private List fonts = new ArrayList<>(); - // private List font_data_addresses = new ArrayList<>(); private List add_fonts = new ArrayList<>(); // private List add_font_data_addresses = new ArrayList<>(); @@ -34,7 +33,6 @@ public class IggySwf implements StructureInterface { } private List texts = new ArrayList<>(); - //private List text_data_addresses = new ArrayList<>(); private List add_texts = new ArrayList<>(); //private List add_text_data_addresses = new ArrayList<>(); @@ -42,7 +40,6 @@ public class IggySwf implements StructureInterface { //private byte font_add_data[]; //private List font_additional_size = new ArrayList<>(); private IggyFontBinInfo font_bin_info[]; - private List sequenceNames = new ArrayList<>(); //private List sequenceValues = new ArrayList<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java index 221d3daa9..e5a66a861 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyText.java @@ -1,198 +1,198 @@ -package com.jpexs.decompiler.flash.iggy; - -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.SeekMode; -import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; -import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; -import java.io.IOException; - -/** - * - * @author JPEXS - */ -public class IggyText implements StructureInterface { - - public static final int STRUCT_SIZE = 104; - - public static final int ID = 0xFF06; - - @IggyFieldType(DataType.uint16_t) - int type; // Tag type - @IggyFieldType(DataType.uint16_t) - int textIndex; - @IggyArrayFieldType(value = DataType.uint8_t, count = 28) - byte zeroone[]; - @IggyFieldType(DataType.float_t) - float par1; - @IggyFieldType(DataType.float_t) - float par2; - @IggyFieldType(DataType.float_t) - float par3; - @IggyFieldType(DataType.float_t) - float par4; - @IggyFieldType(DataType.uint16_t) - int enum_hex; - - //Guessed - boolean hasText; - boolean wordWrap; - boolean multiline; - boolean password; - boolean readOnly; - boolean hasTextColor; - boolean hasMaxLength; - boolean hasFont; - boolean hasFontClass; - boolean autosize; - boolean hasLayout; - boolean noSelect; - boolean border; - boolean wasStatic; - boolean html; - boolean useOutlines; - - @IggyFieldType(DataType.uint16_t) - int fontIndex; - @IggyFieldType(DataType.uint32_t) - long zero; - @IggyFieldType(DataType.uint64_t) - long one; - @IggyArrayFieldType(value = DataType.uint8_t, count = 32) - byte[] some; // same for different fonts - long ofs_name; - - @IggyArrayFieldType(value = DataType.wchar_t) - String initialText; //till end of info file? - - public IggyText(int type, int order_in_iggy_file, byte[] zeroone, float par1, float par2, float par3, float par4, int enum_hex, int for_which_font_order_in_iggyfile, long zero, long one, byte[] some, long offset_of_name, String name) { - this.type = type; - this.textIndex = order_in_iggy_file; - this.zeroone = zeroone; - this.par1 = par1; - this.par2 = par2; - this.par3 = par3; - this.par4 = par4; - this.enum_hex = enum_hex; - this.fontIndex = for_which_font_order_in_iggyfile; - this.zero = zero; - this.one = one; - this.some = some; - this.initialText = name; - } - - public IggyText(ReadDataStreamInterface stream) throws IOException { - this.readFromDataStream(stream); - } - - @Override - public void readFromDataStream(ReadDataStreamInterface s) throws IOException { - - type = s.readUI16(); - //characterId - iggy Id - textIndex = s.readUI16(); - zeroone = s.readBytes(28); - - //bounds?: - par1 = s.readFloat(); - par2 = s.readFloat(); - par3 = s.readFloat(); - par4 = s.readFloat(); - - enum_hex = s.readUI16(); - fontIndex = s.readUI16(); //fontId - zero = s.readUI32(); - one = s.readUI64(); //01CB FF33 3333 - some = s.readBytes(32); // [6] => 40, [24] => 8 - ofs_name = s.readUI64(); - long name_address = ofs_name + s.position() - 8; - s.seek(name_address, SeekMode.SET); - initialText = s.readWChar(); - s.pad8bytes(); - } - - @Override - public void writeToDataStream(WriteDataStreamInterface s) throws IOException { - s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_TEXT_DATA_SIZE); - s.writeUI16(type); - s.writeUI16(textIndex); - s.writeBytes(zeroone); - s.writeFloat(par1); - s.writeFloat(par2); - s.writeFloat(par3); - s.writeFloat(par4); - s.writeUI16(enum_hex); - s.writeUI16(fontIndex); - s.writeUI32(zero); - s.writeUI64(one); - s.writeBytes(some); - s.writeUI64(ofs_name); - long name_address = ofs_name + s.position() - 8; - s.seek(name_address, SeekMode.SET); - s.writeWChar(initialText); - s.pad8bytes(); - - s.getIndexing().write16bitArray(initialText.length() + 1); - s.getIndexing().pad8bytes(); - - } - - public int getType() { - return type; - } - - public int getTextIndex() { - return textIndex; - } - - public byte[] getZeroone() { - return zeroone; - } - - public float getPar1() { - return par1; - } - - public float getPar2() { - return par2; - } - - public float getPar3() { - return par3; - } - - public float getPar4() { - return par4; - } - - public int getEnum_hex() { - return enum_hex; - } - - public int getFontIndex() { - return fontIndex; - } - - public long getZero() { - return zero; - } - - public long getOne() { - return one; - } - - public byte[] getSome() { - return some; - } - - public String getInitialText() { - return initialText; - } - - public void setInitialText(String initialText) { - this.initialText = initialText; - } - -} +package com.jpexs.decompiler.flash.iggy; + +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.SeekMode; +import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; +import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public class IggyText implements StructureInterface { + + public static final int STRUCT_SIZE = 104; + + public static final int ID = 0xFF06; + + @IggyFieldType(DataType.uint16_t) + int type; // Tag type + @IggyFieldType(DataType.uint16_t) + int textIndex; + @IggyArrayFieldType(value = DataType.uint8_t, count = 28) + byte zeroone[]; + @IggyFieldType(DataType.float_t) + float par1; + @IggyFieldType(DataType.float_t) + float par2; + @IggyFieldType(DataType.float_t) + float par3; + @IggyFieldType(DataType.float_t) + float par4; + @IggyFieldType(DataType.uint16_t) + int enum_hex; + + //Guessed + boolean hasText; + boolean wordWrap; + boolean multiline; + boolean password; + boolean readOnly; + boolean hasTextColor; + boolean hasMaxLength; + boolean hasFont; + boolean hasFontClass; + boolean autosize; + boolean hasLayout; + boolean noSelect; + boolean border; + boolean wasStatic; + boolean html; + boolean useOutlines; + + @IggyFieldType(DataType.uint16_t) + int fontIndex; + @IggyFieldType(DataType.uint32_t) + long zero; + @IggyFieldType(DataType.uint64_t) + long one; + @IggyArrayFieldType(value = DataType.uint8_t, count = 32) + byte[] some; // same for different fonts + long ofs_name; + + @IggyArrayFieldType(value = DataType.wchar_t) + String initialText; //till end of info file? + + public IggyText(int type, int order_in_iggy_file, byte[] zeroone, float par1, float par2, float par3, float par4, int enum_hex, int for_which_font_order_in_iggyfile, long zero, long one, byte[] some, long offset_of_name, String name) { + this.type = type; + this.textIndex = order_in_iggy_file; + this.zeroone = zeroone; + this.par1 = par1; + this.par2 = par2; + this.par3 = par3; + this.par4 = par4; + this.enum_hex = enum_hex; + this.fontIndex = for_which_font_order_in_iggyfile; + this.zero = zero; + this.one = one; + this.some = some; + this.initialText = name; + } + + public IggyText(ReadDataStreamInterface stream) throws IOException { + this.readFromDataStream(stream); + } + + @Override + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + + type = s.readUI16(); + //characterId - iggy Id + textIndex = s.readUI16(); + zeroone = s.readBytes(28); + + //bounds?: + par1 = s.readFloat(); + par2 = s.readFloat(); + par3 = s.readFloat(); + par4 = s.readFloat(); + + enum_hex = s.readUI16(); + fontIndex = s.readUI16(); //fontId + zero = s.readUI32(); + one = s.readUI64(); //01CB FF33 3333 + some = s.readBytes(32); // [6] => 40, [24] => 8 + ofs_name = s.readUI64(); + long name_address = ofs_name + s.position() - 8; + s.seek(name_address, SeekMode.SET); + initialText = s.readWChar(); + s.pad8bytes(); + } + + @Override + public void writeToDataStream(WriteDataStreamInterface s) throws IOException { + s.getIndexing().writeConstLength(IggyIndexBuilder.CONST_TEXT_DATA_SIZE); + s.writeUI16(type); + s.writeUI16(textIndex); + s.writeBytes(zeroone); + s.writeFloat(par1); + s.writeFloat(par2); + s.writeFloat(par3); + s.writeFloat(par4); + s.writeUI16(enum_hex); + s.writeUI16(fontIndex); + s.writeUI32(zero); + s.writeUI64(one); + s.writeBytes(some); + s.writeUI64(ofs_name); + long name_address = ofs_name + s.position() - 8; + s.seek(name_address, SeekMode.SET); + s.writeWChar(initialText); + s.pad8bytes(); + + s.getIndexing().write16bitArray(initialText.length() + 1); + s.getIndexing().pad8bytes(); + + } + + public int getType() { + return type; + } + + public int getTextIndex() { + return textIndex; + } + + public byte[] getZeroone() { + return zeroone; + } + + public float getPar1() { + return par1; + } + + public float getPar2() { + return par2; + } + + public float getPar3() { + return par3; + } + + public float getPar4() { + return par4; + } + + public int getEnum_hex() { + return enum_hex; + } + + public int getFontIndex() { + return fontIndex; + } + + public long getZero() { + return zero; + } + + public long getOne() { + return one; + } + + public byte[] getSome() { + return some; + } + + public String getInitialText() { + return initialText; + } + + public void setInitialText(String initialText) { + this.initialText = initialText; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java index 658c0dd29..d1c486619 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggyToSwfConvertor.java @@ -1,271 +1,271 @@ -package com.jpexs.decompiler.flash.iggy.conversion; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFCompression; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.iggy.IggyShape; -import com.jpexs.decompiler.flash.iggy.IggyCharKerning; -import com.jpexs.decompiler.flash.iggy.IggyShapeNode; -import com.jpexs.decompiler.flash.iggy.IggyCharOffset; -import com.jpexs.decompiler.flash.iggy.IggyCharAdvances; -import com.jpexs.decompiler.flash.iggy.IggyDeclStrings; -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; -import com.jpexs.decompiler.flash.tags.DoABC2Tag; -import com.jpexs.decompiler.flash.tags.EndTag; -import com.jpexs.decompiler.flash.tags.FileAttributesTag; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.RGBA; -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 com.jpexs.helpers.ByteArrayRange; -import java.awt.Color; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * WIP - * - * @author JPEXS - */ -public class IggyToSwfConvertor { - - public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException { - 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 exportSwfToFile(IggyFile file, File outputFile) throws IOException { - try (FileOutputStream fos = new FileOutputStream(outputFile)) { - exportSwf(file, fos); - } - } - - public static void exportSwf(IggyFile file, OutputStream output) throws IOException { - SWF swf = getSwf(file); - swf.saveTo(output); - } - - private static int makeLengthsEm(double val) { - return (int) (val * 1024.0); - } - - private static int makeLengthsTwip(double val) { - return (int) (val * SWF.unitDivisor); - } - - public static SWF getSwf(IggyFile file) { - SWF swf = new SWF(); - swf.compression = SWFCompression.NONE; - swf.frameCount = 1; //FIXME!! - swf.frameRate = file.getSwfFrameRate(); - swf.gfx = false; - swf.displayRect = new RECT( - makeLengthsTwip(file.getSwfXMin()), - makeLengthsTwip(file.getSwfXMax()), - makeLengthsTwip(file.getSwfYMin()), - makeLengthsTwip(file.getSwfYMax())); - swf.version = 10; //FIXME - - FileAttributesTag fat = new FileAttributesTag(swf); - fat.actionScript3 = true; - fat.hasMetadata = false; - fat.useNetwork = false; - swf.addTag(fat); - IggySwf iggySwf = file.getSwf(); - - int currentCharId = 0; - Map fontIndex2CharId = new HashMap<>(); - - for (int fontIndex = 0; fontIndex < iggySwf.getFonts().size(); fontIndex++) { - IggyFont iggyFont = iggySwf.getFonts().get(fontIndex); - DefineFont2Tag fontTag = new DefineFont2Tag(swf); - currentCharId++; - fontIndex2CharId.put(fontIndex, currentCharId); - fontTag.fontID = currentCharId; - /*System.out.println("==================="); - System.out.println("xscale: " + iggyFont.getXscale()); //80 - System.out.println("yscale: " + iggyFont.getYscale()); //19 - - System.out.println("unk_float1: " + iggyFont.getUnk_float()[0]); - System.out.println("unk_float2: " + iggyFont.getUnk_float()[1]); - System.out.println("unk_float3: " + iggyFont.getUnk_float()[2]); - System.out.println("unk_float4: " + iggyFont.getUnk_float()[3]); - System.out.println("unk_float5: " + iggyFont.getUnk_float()[4]); - System.out.println("what_2: " + iggyFont.getWhat_2()); - System.out.println("what_3: " + iggyFont.getWhat_3());*/ - - fontTag.fontKerningTable = new ArrayList<>(); - IggyCharKerning ker = iggyFont.getCharKernings(); - if (ker != null) { - for (int i = 0; i < ker.getKernCount(); i++) { - int kerningCode1 = ker.getCharsA().get(i); - int kerningCode2 = ker.getCharsA().get(i); - int kerningOffset = ker.getKerningOffsets().get(i); - fontTag.fontKerningTable.add(new KERNINGRECORD(kerningCode1, kerningCode2, kerningOffset)); - } - } - - fontTag.fontFlagsWideCodes = true; - fontTag.fontFlagsWideOffsets = true; - fontTag.fontAscent = iggyFont.getAscent(); - fontTag.fontDescent = iggyFont.getDescent(); - fontTag.fontLeading = iggyFont.getLeading(); - fontTag.codeTable = new ArrayList<>(); - fontTag.fontName = iggyFont.getName(); - fontTag.glyphShapeTable = new ArrayList<>(); - fontTag.fontBoundsTable = new ArrayList<>(); - fontTag.fontAdvanceTable = new ArrayList<>(); - fontTag.fontFlagsHasLayout = true; - IggyCharAdvances advanceValues = iggyFont.getCharAdvances(); - for (int i = 0; i < iggyFont.getCharacterCount(); i++) { - int code = iggyFont.getCharIndices().getChars().get(i); - fontTag.codeTable.add(code); - IggyShape glyph = iggyFont.getChars().get(i); - SHAPE shp; - if (glyph != null) { - shp = IggyShapeToSwfConvertor.convertCharToShape(glyph); - fontTag.fontBoundsTable.add(shp.getBounds()); - } else { - shp = new SHAPE(); - shp.shapeRecords = new ArrayList<>(); - shp.shapeRecords.add(new EndShapeRecord()); - fontTag.fontBoundsTable.add(new RECT()); //?? - } - fontTag.glyphShapeTable.add(shp); - - fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i))); - - } - fontTag.setModified(true); - swf.addTag(fontTag); - } - - Map textIndex2CharId = new HashMap<>(); - - for (int textIndex = 0; textIndex < iggySwf.getTexts().size(); textIndex++) { - IggyText iggyText = iggySwf.getTexts().get(textIndex); - DefineEditTextTag textTag = new DefineEditTextTag(swf); - currentCharId++; - textIndex2CharId.put(textIndex, currentCharId); - textTag.characterID = currentCharId; - textTag.hasText = true; - textTag.initialText = iggyText.getInitialText(); - textTag.html = true; - textTag.noSelect = true; - textTag.wasStatic = true; - textTag.hasFont = false; - textTag.hasFontClass = false; - textTag.hasMaxLength = false; - //textTag.multiline = true; - //textTag.wordWrap = true; - //textTag.hasTextColor = true; - //textTag.textColor = new RGBA(Color.black); - //textTag.fontHeight = 40; //?? - textTag.readOnly = true; - textTag.bounds = new RECT( - makeLengthsTwip(iggyText.getPar1()), - makeLengthsTwip(iggyText.getPar3()), - makeLengthsTwip(iggyText.getPar2()), - makeLengthsTwip(iggyText.getPar4()) - ); - - //textTag.hasFont = true; - //textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex()); - textTag.setModified(true); - swf.addTag(textTag); - } - - IggyDeclStrings declStrings = iggySwf.getDeclStrings(); - if (declStrings != null) { - byte[] abcData = declStrings.getData(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - baos.write(new byte[]{1, 0, 0, 0, 0, 0x10, 0, 0x2E}); - baos.write(abcData); - } catch (IOException ex) { - //should not happen - } - byte[] fullAbcTagData = baos.toByteArray(); - try { - DoABC2Tag nabc = new DoABC2Tag(new SWFInputStream(swf, fullAbcTagData), new ByteArrayRange(fullAbcTagData)); - nabc.setModified(true); - swf.addTag(nabc); - } catch (IOException ex) { - //ignore - } - - } - - swf.addTag( - new EndTag(swf)); - swf.setModified( - true); - - return swf; - } - - public static void main(String[] args) { - - if (args.length < 2 || (args[0].isEmpty() || args[1].isEmpty())) { - System.err.println("Invalid arguments"); - System.err.println("Usage: iggy-extract.bat file.iggy d:/outdir/"); - System.exit(1); - } - - File file = new File(args[0]); - if (!file.exists()) { - System.err.println("FAIL: Input file: " + file.getAbsolutePath() + " does not exist."); - System.exit(1); - } - File outDir = new File(args[1]); - if (!outDir.exists()) { - if (!outDir.mkdirs()) { - System.err.println("FAIL: Cannot create output directory"); - System.exit(1); - } - } - - try { - System.out.print("(1/2) Loading file " + args[0] + "..."); - IggyFile iggyFile = new IggyFile(new File(args[0])); - System.out.println("OK"); - System.out.print("(2/2) Exporting SWF files to " + args[1] + "..."); - exportAllSwfsToDir(iggyFile, new File(args[1])); - System.out.println("OK"); - System.out.println("All finished sucessfully."); - System.exit(0); - } catch (IOException ex) { - System.out.println("FAIL"); - System.err.println("Error while converting: " + ex.getMessage()); - System.exit(1); - } - } -} +package com.jpexs.decompiler.flash.iggy.conversion; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFCompression; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.iggy.IggyShape; +import com.jpexs.decompiler.flash.iggy.IggyCharKerning; +import com.jpexs.decompiler.flash.iggy.IggyShapeNode; +import com.jpexs.decompiler.flash.iggy.IggyCharOffset; +import com.jpexs.decompiler.flash.iggy.IggyCharAdvances; +import com.jpexs.decompiler.flash.iggy.IggyDeclStrings; +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; +import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.tags.EndTag; +import com.jpexs.decompiler.flash.tags.FileAttributesTag; +import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; +import com.jpexs.decompiler.flash.types.RECT; +import com.jpexs.decompiler.flash.types.RGBA; +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 com.jpexs.helpers.ByteArrayRange; +import java.awt.Color; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * WIP + * + * @author JPEXS + */ +public class IggyToSwfConvertor { + + public static void exportAllSwfsToDir(IggyFile file, File outputDir) throws IOException { + 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 exportSwfToFile(IggyFile file, File outputFile) throws IOException { + try (FileOutputStream fos = new FileOutputStream(outputFile)) { + exportSwf(file, fos); + } + } + + public static void exportSwf(IggyFile file, OutputStream output) throws IOException { + SWF swf = getSwf(file); + swf.saveTo(output); + } + + private static int makeLengthsEm(double val) { + return (int) (val * 1024.0); + } + + private static int makeLengthsTwip(double val) { + return (int) (val * SWF.unitDivisor); + } + + public static SWF getSwf(IggyFile file) { + SWF swf = new SWF(); + swf.compression = SWFCompression.NONE; + swf.frameCount = 1; //FIXME!! + swf.frameRate = file.getSwfFrameRate(); + swf.gfx = false; + swf.displayRect = new RECT( + makeLengthsTwip(file.getSwfXMin()), + makeLengthsTwip(file.getSwfXMax()), + makeLengthsTwip(file.getSwfYMin()), + makeLengthsTwip(file.getSwfYMax())); + swf.version = 10; //FIXME + + FileAttributesTag fat = new FileAttributesTag(swf); + fat.actionScript3 = true; + fat.hasMetadata = false; + fat.useNetwork = false; + swf.addTag(fat); + IggySwf iggySwf = file.getSwf(); + + int currentCharId = 0; + Map fontIndex2CharId = new HashMap<>(); + + for (int fontIndex = 0; fontIndex < iggySwf.getFonts().size(); fontIndex++) { + IggyFont iggyFont = iggySwf.getFonts().get(fontIndex); + DefineFont2Tag fontTag = new DefineFont2Tag(swf); + currentCharId++; + fontIndex2CharId.put(fontIndex, currentCharId); + fontTag.fontID = currentCharId; + /*System.out.println("==================="); + System.out.println("xscale: " + iggyFont.getXscale()); //80 + System.out.println("yscale: " + iggyFont.getYscale()); //19 + + System.out.println("unk_float1: " + iggyFont.getUnk_float()[0]); + System.out.println("unk_float2: " + iggyFont.getUnk_float()[1]); + System.out.println("unk_float3: " + iggyFont.getUnk_float()[2]); + System.out.println("unk_float4: " + iggyFont.getUnk_float()[3]); + System.out.println("unk_float5: " + iggyFont.getUnk_float()[4]); + System.out.println("what_2: " + iggyFont.getWhat_2()); + System.out.println("what_3: " + iggyFont.getWhat_3());*/ + + fontTag.fontKerningTable = new ArrayList<>(); + IggyCharKerning ker = iggyFont.getCharKernings(); + if (ker != null) { + for (int i = 0; i < ker.getKernCount(); i++) { + int kerningCode1 = ker.getCharsA().get(i); + int kerningCode2 = ker.getCharsA().get(i); + int kerningOffset = ker.getKerningOffsets().get(i); + fontTag.fontKerningTable.add(new KERNINGRECORD(kerningCode1, kerningCode2, kerningOffset)); + } + } + + fontTag.fontFlagsWideCodes = true; + fontTag.fontFlagsWideOffsets = true; + fontTag.fontAscent = iggyFont.getAscent(); + fontTag.fontDescent = iggyFont.getDescent(); + fontTag.fontLeading = iggyFont.getLeading(); + fontTag.codeTable = new ArrayList<>(); + fontTag.fontName = iggyFont.getName(); + fontTag.glyphShapeTable = new ArrayList<>(); + fontTag.fontBoundsTable = new ArrayList<>(); + fontTag.fontAdvanceTable = new ArrayList<>(); + fontTag.fontFlagsHasLayout = true; + IggyCharAdvances advanceValues = iggyFont.getCharAdvances(); + for (int i = 0; i < iggyFont.getCharacterCount(); i++) { + int code = iggyFont.getCharIndices().getChars().get(i); + fontTag.codeTable.add(code); + IggyShape glyph = iggyFont.getChars().get(i); + SHAPE shp; + if (glyph != null) { + shp = IggyShapeToSwfConvertor.convertCharToShape(glyph); + fontTag.fontBoundsTable.add(shp.getBounds()); + } else { + shp = new SHAPE(); + shp.shapeRecords = new ArrayList<>(); + shp.shapeRecords.add(new EndShapeRecord()); + fontTag.fontBoundsTable.add(new RECT()); //?? + } + fontTag.glyphShapeTable.add(shp); + + fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i))); + + } + fontTag.setModified(true); + swf.addTag(fontTag); + } + + Map textIndex2CharId = new HashMap<>(); + + for (int textIndex = 0; textIndex < iggySwf.getTexts().size(); textIndex++) { + IggyText iggyText = iggySwf.getTexts().get(textIndex); + DefineEditTextTag textTag = new DefineEditTextTag(swf); + currentCharId++; + textIndex2CharId.put(textIndex, currentCharId); + textTag.characterID = currentCharId; + textTag.hasText = true; + textTag.initialText = iggyText.getInitialText(); + textTag.html = true; + textTag.noSelect = true; + textTag.wasStatic = true; + textTag.hasFont = false; + textTag.hasFontClass = false; + textTag.hasMaxLength = false; + //textTag.multiline = true; + //textTag.wordWrap = true; + //textTag.hasTextColor = true; + //textTag.textColor = new RGBA(Color.black); + //textTag.fontHeight = 40; //?? + textTag.readOnly = true; + textTag.bounds = new RECT( + makeLengthsTwip(iggyText.getPar1()), + makeLengthsTwip(iggyText.getPar3()), + makeLengthsTwip(iggyText.getPar2()), + makeLengthsTwip(iggyText.getPar4()) + ); + + //textTag.hasFont = true; + //textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex()); + textTag.setModified(true); + swf.addTag(textTag); + } + + IggyDeclStrings declStrings = iggySwf.getDeclStrings(); + if (declStrings != null) { + byte[] abcData = declStrings.getData(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + baos.write(new byte[]{1, 0, 0, 0, 0, 0x10, 0, 0x2E}); + baos.write(abcData); + } catch (IOException ex) { + //should not happen + } + byte[] fullAbcTagData = baos.toByteArray(); + try { + DoABC2Tag nabc = new DoABC2Tag(new SWFInputStream(swf, fullAbcTagData), new ByteArrayRange(fullAbcTagData)); + nabc.setModified(true); + swf.addTag(nabc); + } catch (IOException ex) { + //ignore + } + + } + + swf.addTag( + new EndTag(swf)); + swf.setModified( + true); + + return swf; + } + + public static void main(String[] args) { + + if (args.length < 2 || (args[0].isEmpty() || args[1].isEmpty())) { + System.err.println("Invalid arguments"); + System.err.println("Usage: iggy-extract.bat file.iggy d:/outdir/"); + System.exit(1); + } + + File file = new File(args[0]); + if (!file.exists()) { + System.err.println("FAIL: Input file: " + file.getAbsolutePath() + " does not exist."); + System.exit(1); + } + File outDir = new File(args[1]); + if (!outDir.exists()) { + if (!outDir.mkdirs()) { + System.err.println("FAIL: Cannot create output directory"); + System.exit(1); + } + } + + try { + System.out.print("(1/2) Loading file " + args[0] + "..."); + IggyFile iggyFile = new IggyFile(new File(args[0])); + System.out.println("OK"); + System.out.print("(2/2) Exporting SWF files to " + args[1] + "..."); + exportAllSwfsToDir(iggyFile, new File(args[1])); + System.out.println("OK"); + System.out.println("All finished sucessfully."); + System.exit(0); + } catch (IOException ex) { + System.out.println("FAIL"); + System.err.println("Error while converting: " + ex.getMessage()); + System.exit(1); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java index fb04a79fa..c4ea8a91e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/SwfToIggyConvertor.java @@ -1,210 +1,210 @@ -package com.jpexs.decompiler.flash.iggy.conversion; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFOutputStream; -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.iggy.IggySwf; -import com.jpexs.decompiler.flash.iggy.IggyText; -import com.jpexs.decompiler.flash.tags.DefineEditTextTag; -import com.jpexs.decompiler.flash.tags.DefineFont2Tag; -import com.jpexs.decompiler.flash.tags.DoABC2Tag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.SHAPE; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class SwfToIggyConvertor { - - private static float normalizeLengths(int val) { - return (val / 1024f); - } - - public static void updateIggy(IggySwf iggySwf, SWF swf) throws IOException { - List fontTags = new ArrayList<>(); - List textTags = new ArrayList<>(); - List abcTags = new ArrayList<>(); - - for (Tag t : swf.getTags()) { - if (t instanceof DefineFont2Tag) { - fontTags.add((DefineFont2Tag) t); - } - if (t instanceof DefineEditTextTag) { - textTags.add((DefineEditTextTag) t); - } - if (t instanceof DoABC2Tag) { - abcTags.add((DoABC2Tag) t); - } - } - if (abcTags.size() > 1) { - throw new IOException("Cannot save more than one ABC tag"); - } - int fontCount = iggySwf.getFonts().size(); - if (fontCount != fontTags.size()) { - throw new IOException("Font count is different from original iggy file"); - } - for (int i = 0; i < fontCount; i++) { - IggyFont iggyFont = iggySwf.getFonts().get(i); - DefineFont2Tag fontTag = fontTags.get(i); - SwfToIggyConvertor.updateIggyFont(iggyFont, fontTag); - } - - int textCount = iggySwf.getTexts().size(); - if (textCount != textTags.size()) { - throw new IOException("Text count is different from original iggy file"); - } - for (int i = 0; i < textCount; i++) { - IggyText iggyText = iggySwf.getTexts().get(i); - DefineEditTextTag textTag = textTags.get(i); - SwfToIggyConvertor.updateIggyText(iggyText, textTag); - } - if (!abcTags.isEmpty()) { - DoABC2Tag abcTag = abcTags.get(0); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte abcTagData[] = abcTag.getData(); - byte declData[] = Arrays.copyOfRange(abcTagData, 4/*UI32 flags*/ + 1 /*empty string as name*/ + 3 /*versions, leaving one zero intact*/, abcTagData.length); - iggySwf.getDeclStrings().setData(declData); - } - } - - public static void updateIggyText(IggyText iggyText, DefineEditTextTag textTag) { - iggyText.setInitialText(textTag.initialText); - } - - 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 charOffsets = new ArrayList<>(); - - List glyphs = new ArrayList<>(); - - for (SHAPE s : fontTag.glyphShapeTable) { - glyphs.add(SwfShapeToIggyConvertor.convertShape(s)); - } - - List chars = new ArrayList<>(); - for (int code : fontTag.codeTable) { - chars.add((char) code); - } - IggyCharIndices codePoints = new IggyCharIndices(chars); - List scales = new ArrayList<>(); - for (int adv : fontTag.fontAdvanceTable) { - scales.add(normalizeLengths(adv)); - } - IggyCharAdvances charScales = new IggyCharAdvances(scales); - List charA = new ArrayList<>(); - List charB = new ArrayList<>(); - List 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); - } - - 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 charOffsets = new ArrayList<>(); - List glyphs = new ArrayList<>(); - List chars = new ArrayList<>(); - for (int code : fontTag.codeTable) { - chars.add((char) code); - } - IggyCharIndices codePoints = new IggyCharIndices(chars); - List scales = new ArrayList<>(); - for (int adv : fontTag.fontAdvanceTable) { - scales.add((float) adv); - } - IggyCharAdvances charScales = new IggyCharAdvances(scales); - List charA = new ArrayList<>(); - List charB = new ArrayList<>(); - List 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; - } -} +package com.jpexs.decompiler.flash.iggy.conversion; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFOutputStream; +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.iggy.IggySwf; +import com.jpexs.decompiler.flash.iggy.IggyText; +import com.jpexs.decompiler.flash.tags.DefineEditTextTag; +import com.jpexs.decompiler.flash.tags.DefineFont2Tag; +import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.KERNINGRECORD; +import com.jpexs.decompiler.flash.types.SHAPE; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class SwfToIggyConvertor { + + private static float normalizeLengths(int val) { + return (val / 1024f); + } + + public static void updateIggy(IggySwf iggySwf, SWF swf) throws IOException { + List fontTags = new ArrayList<>(); + List textTags = new ArrayList<>(); + List abcTags = new ArrayList<>(); + + for (Tag t : swf.getTags()) { + if (t instanceof DefineFont2Tag) { + fontTags.add((DefineFont2Tag) t); + } + if (t instanceof DefineEditTextTag) { + textTags.add((DefineEditTextTag) t); + } + if (t instanceof DoABC2Tag) { + abcTags.add((DoABC2Tag) t); + } + } + if (abcTags.size() > 1) { + throw new IOException("Cannot save more than one ABC tag"); + } + int fontCount = iggySwf.getFonts().size(); + if (fontCount != fontTags.size()) { + throw new IOException("Font count is different from original iggy file"); + } + for (int i = 0; i < fontCount; i++) { + IggyFont iggyFont = iggySwf.getFonts().get(i); + DefineFont2Tag fontTag = fontTags.get(i); + SwfToIggyConvertor.updateIggyFont(iggyFont, fontTag); + } + + int textCount = iggySwf.getTexts().size(); + if (textCount != textTags.size()) { + throw new IOException("Text count is different from original iggy file"); + } + for (int i = 0; i < textCount; i++) { + IggyText iggyText = iggySwf.getTexts().get(i); + DefineEditTextTag textTag = textTags.get(i); + SwfToIggyConvertor.updateIggyText(iggyText, textTag); + } + if (!abcTags.isEmpty()) { + DoABC2Tag abcTag = abcTags.get(0); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte abcTagData[] = abcTag.getData(); + byte declData[] = Arrays.copyOfRange(abcTagData, 4/*UI32 flags*/ + 1 /*empty string as name*/ + 3 /*versions, leaving one zero intact*/, abcTagData.length); + iggySwf.getDeclStrings().setData(declData); + } + } + + public static void updateIggyText(IggyText iggyText, DefineEditTextTag textTag) { + iggyText.setInitialText(textTag.initialText); + } + + 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 charOffsets = new ArrayList<>(); + + List glyphs = new ArrayList<>(); + + for (SHAPE s : fontTag.glyphShapeTable) { + glyphs.add(SwfShapeToIggyConvertor.convertShape(s)); + } + + List chars = new ArrayList<>(); + for (int code : fontTag.codeTable) { + chars.add((char) code); + } + IggyCharIndices codePoints = new IggyCharIndices(chars); + List scales = new ArrayList<>(); + for (int adv : fontTag.fontAdvanceTable) { + scales.add(normalizeLengths(adv)); + } + IggyCharAdvances charScales = new IggyCharAdvances(scales); + List charA = new ArrayList<>(); + List charB = new ArrayList<>(); + List 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); + } + + 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 charOffsets = new ArrayList<>(); + List glyphs = new ArrayList<>(); + List chars = new ArrayList<>(); + for (int code : fontTag.codeTable) { + chars.add((char) code); + } + IggyCharIndices codePoints = new IggyCharIndices(chars); + List scales = new ArrayList<>(); + for (int adv : fontTag.fontAdvanceTable) { + scales.add((float) adv); + } + IggyCharAdvances charScales = new IggyCharAdvances(scales); + List charA = new ArrayList<>(); + List charB = new ArrayList<>(); + List 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; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java index 10437853f..08dd54c43 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java @@ -1,188 +1,188 @@ -/* - * 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.treeitems; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFContainerItem; -import com.jpexs.decompiler.flash.SWFSourceInfo; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -/** - * - * @author JPEXS - */ -public class SWFList implements List, SWFContainerItem { - - public String name; - - public SWFBundle bundle; - - public SWFSourceInfo sourceInfo; - - public List swfs = new ArrayList<>(); - - public boolean isBundle() { - return bundle != null; - } - - @Override - public SWF getSwf() { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public String toString() { - if (isBundle()) { - return name; - } else { - return swfs.get(0).getFileTitle(); - } - } - - @Override - public Iterator iterator() { - return swfs.iterator(); - } - - @Override - public int size() { - return swfs.size(); - } - - @Override - public boolean isEmpty() { - return swfs.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return swfs.contains(o); - } - - @Override - public Object[] toArray() { - return swfs.toArray(); - } - - @Override - public T[] toArray(T[] ts) { - return swfs.toArray(ts); - } - - @Override - public boolean add(SWF e) { - return swfs.add(e); - } - - @Override - public boolean remove(Object o) { - return swfs.remove(o); - } - - @Override - public boolean containsAll(Collection clctn) { - return swfs.containsAll(clctn); - } - - @Override - public boolean addAll(Collection clctn) { - return swfs.addAll(clctn); - } - - @Override - public boolean removeAll(Collection clctn) { - return swfs.removeAll(clctn); - } - - @Override - public boolean retainAll(Collection clctn) { - return swfs.retainAll(clctn); - } - - @Override - public void clear() { - swfs.clear(); - } - - @Override - public boolean addAll(int i, Collection clctn) { - return swfs.addAll(i, clctn); - } - - @Override - public SWF get(int i) { - if (i < 0 || i >= swfs.size()) { - return null; - } - return swfs.get(i); - } - - @Override - public SWF set(int i, SWF e) { - return swfs.set(i, e); - } - - @Override - public void add(int i, SWF e) { - swfs.add(i, e); - } - - @Override - public SWF remove(int i) { - return swfs.remove(i); - } - - @Override - public int indexOf(Object o) { - return swfs.indexOf(0); - } - - @Override - public int lastIndexOf(Object o) { - return swfs.lastIndexOf(o); - } - - @Override - public ListIterator listIterator() { - return swfs.listIterator(); - } - - @Override - public ListIterator listIterator(int i) { - return swfs.listIterator(i); - } - - @Override - public List subList(int i, int i1) { - return swfs.subList(i, i1); - } - - @Override - public boolean isModified() { - for (SWF s : swfs) { - if (s.isModified()) { - return true; - } - } - return 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.treeitems; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFBundle; +import com.jpexs.decompiler.flash.SWFContainerItem; +import com.jpexs.decompiler.flash.SWFSourceInfo; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +/** + * + * @author JPEXS + */ +public class SWFList implements List, SWFContainerItem { + + public String name; + + public SWFBundle bundle; + + public SWFSourceInfo sourceInfo; + + public List swfs = new ArrayList<>(); + + public boolean isBundle() { + return bundle != null; + } + + @Override + public SWF getSwf() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String toString() { + if (isBundle()) { + return name; + } else { + return swfs.get(0).getFileTitle(); + } + } + + @Override + public Iterator iterator() { + return swfs.iterator(); + } + + @Override + public int size() { + return swfs.size(); + } + + @Override + public boolean isEmpty() { + return swfs.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return swfs.contains(o); + } + + @Override + public Object[] toArray() { + return swfs.toArray(); + } + + @Override + public T[] toArray(T[] ts) { + return swfs.toArray(ts); + } + + @Override + public boolean add(SWF e) { + return swfs.add(e); + } + + @Override + public boolean remove(Object o) { + return swfs.remove(o); + } + + @Override + public boolean containsAll(Collection clctn) { + return swfs.containsAll(clctn); + } + + @Override + public boolean addAll(Collection clctn) { + return swfs.addAll(clctn); + } + + @Override + public boolean removeAll(Collection clctn) { + return swfs.removeAll(clctn); + } + + @Override + public boolean retainAll(Collection clctn) { + return swfs.retainAll(clctn); + } + + @Override + public void clear() { + swfs.clear(); + } + + @Override + public boolean addAll(int i, Collection clctn) { + return swfs.addAll(i, clctn); + } + + @Override + public SWF get(int i) { + if (i < 0 || i >= swfs.size()) { + return null; + } + return swfs.get(i); + } + + @Override + public SWF set(int i, SWF e) { + return swfs.set(i, e); + } + + @Override + public void add(int i, SWF e) { + swfs.add(i, e); + } + + @Override + public SWF remove(int i) { + return swfs.remove(i); + } + + @Override + public int indexOf(Object o) { + return swfs.indexOf(0); + } + + @Override + public int lastIndexOf(Object o) { + return swfs.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return swfs.listIterator(); + } + + @Override + public ListIterator listIterator(int i) { + return swfs.listIterator(i); + } + + @Override + public List subList(int i, int i1) { + return swfs.subList(i, i1); + } + + @Override + public boolean isModified() { + for (SWF s : swfs) { + if (s.isModified()) { + return true; + } + } + return false; + } +}