diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java index 3f2ab4ffd..564531c85 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyCharOffset.java @@ -82,6 +82,10 @@ public class IggyCharOffset implements StructureInterface { } } + public boolean hasGlyph() { + return offset > 0; + } + public long getZero() { return zero; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java index eef892111..19ee321a6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFile.java @@ -36,22 +36,79 @@ public class IggyFile implements StructureInterface { private List subFileEntriesData = new ArrayList<>(); private List headers = new ArrayList<>(); - private List flashDataReaders = new ArrayList<>(); + private List iggySwfs = new ArrayList<>(); + private List> indexTables = new ArrayList<>(); + private List> offsetTables = new ArrayList<>(); + private List indexDataStreams = new ArrayList<>(); + + public static final int FIRST_TAG_POSITION = 3; + + public void replaceTag(int swfIndex, int tagIndex, IggyTag newTag) throws IOException { + WriteDataStreamInterface stream = new TemporaryDataStream(); + newTag.writeToDataStream(stream); + + setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize()); + } + + public void saveTag(int swfIndex, IggyTag newTag) throws IOException { + WriteDataStreamInterface stream = new TemporaryDataStream(); + newTag.writeToDataStream(stream); + + int tagIndex = 0; + List taglist = iggySwfs.get(swfIndex).getTags(); + for (IggyTag t : taglist) { + if (t == newTag) { + break; + } + tagIndex++; + } + if (tagIndex < taglist.size()) { + setSwfItemLength(swfIndex, FIRST_TAG_POSITION + tagIndex, stream.totalSize()); + } else { + throw new IllegalArgumentException("Tag does not exists in this iggy file"); + } + } + + private boolean setSwfItemLength(int swfIndex, int itemindex, long newLength) { + DataStreamInterface stream = indexDataStreams.get(swfIndex); + + List offsetTable = offsetTables.get(swfIndex); + + long offset = offsetTable.get(itemindex); + long nextOffset = itemindex == offsetTable.size() - 1 ? stream.totalSize() : offsetTable.get(itemindex + 1); + long currentSize = nextOffset - offset; + try { + byte indexData[] = stream.getAllBytes(); + setItemLength(offset, header.is64(), indexData, newLength); + indexDataStreams.set(swfIndex, new TemporaryDataStream(indexData)); //TODO: optimize! + long lengthDelta = newLength - currentSize; + for (int i = itemindex + 1; i < offsetTable.size(); i++) { + offsetTable.set(i, offsetTable.get(i) + lengthDelta); + } + return true; + } catch (IOException ex) { + return false; + } + } + + public IggySwf getSwf(int swfIndex) { + return iggySwfs.get(swfIndex); + } public Set getFontIds(int swfIndex) { - return flashDataReaders.get(swfIndex).fonts.keySet(); + return iggySwfs.get(swfIndex).fonts.keySet(); } public IggyFont getFont(int swfIndex, int fontId) { - return flashDataReaders.get(swfIndex).fonts.get(fontId); + return iggySwfs.get(swfIndex).fonts.get(fontId); } public IggyText getText(int swfIndex, int textId) { - return flashDataReaders.get(swfIndex).texts.get(textId); + return iggySwfs.get(swfIndex).texts.get(textId); } public Set getTextIds(int swfIndex) { - return flashDataReaders.get(swfIndex).texts.keySet(); + return iggySwfs.get(swfIndex).texts.keySet(); } public IggyFile(String filePath) throws IOException { @@ -144,6 +201,9 @@ public class IggyFile implements StructureInterface { File inFile = new File(inFileName); File outFile = new File(outFileName); IggyFile iggyFile = new IggyFile(inFile); + IggySwf iswf = iggyFile.getSwf(0); + iggyFile.replaceSwf(0, iswf); + outFile.delete(); try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) { iggyFile.writeToDataStream(outputStream); } @@ -560,11 +620,11 @@ public class IggyFile implements StructureInterface { } public int getSwfCount() { - return flashDataReaders.size(); + return iggySwfs.size(); } public String getSwfName(int swfIndex) { - return flashDataReaders.get(swfIndex).getName(); + return iggySwfs.get(swfIndex).getName(); } public long getSwfXMin(int swfIndex) { @@ -594,6 +654,7 @@ public class IggyFile implements StructureInterface { } byte replacementData[]; try (DataStreamInterface stream = new TemporaryDataStream()) { + headers.get(targetSwfIndex).writeToDataStream(stream); iggySwf.writeToDataStream(stream); replacementData = stream.getAllBytes(); } catch (IOException ex) { @@ -611,6 +672,8 @@ public class IggyFile implements StructureInterface { long oldSize = entry.size; long newSize = replacementData.length; offsetsChange = offsetsChange + (newSize - oldSize); + entry.size = newSize; + entry.size2 = newSize; //entries after this one will have modified offsets } swfIndex++; @@ -621,8 +684,6 @@ public class IggyFile implements StructureInterface { } private void parseEntries() throws IOException { - List> indexTables = new ArrayList<>(); //TODO: use this for something ?? - List> offsetTables = new ArrayList<>(); List flashDataStreams = new ArrayList<>(); for (int i = 0; i < subFileEntries.size(); i++) { @@ -632,6 +693,7 @@ public class IggyFile implements StructureInterface { List indexTable = new ArrayList<>(); List offsets = new ArrayList<>(); IggyIndexParser.parseIndex(header.is64(), dataStream, indexTable, offsets); + indexDataStreams.add(dataStream); indexTables.add(indexTable); offsetTables.add(offsets); } else if (entry.type == IggySubFileEntry.TYPE_FLASH) { @@ -650,7 +712,7 @@ public class IggyFile implements StructureInterface { for (int swfIndex = 0; swfIndex < headers.size(); swfIndex++) { IggyFlashHeaderInterface hdr = headers.get(swfIndex); IggySwf dataReader = new IggySwf((IggyFlashHeader64) hdr, flashDataStreams.get(swfIndex), offsetTables.get(swfIndex)); - flashDataReaders.add(dataReader); + iggySwfs.add(dataReader); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java index 1cc8c1156..7700ca377 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFlashHeader64.java @@ -124,7 +124,37 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + stream.writeUI64(main_offset); + stream.writeUI64(as3_section_offset); + stream.writeUI64(unk_offset); + stream.writeUI64(unk_offset2); + stream.writeUI64(unk_offset3); + stream.writeUI64(unk_offset4); + stream.writeUI32(xmin); + stream.writeUI32(ymin); + stream.writeUI32(xmax); + stream.writeUI32(ymax); + stream.writeUI32(unk_40); + stream.writeUI32(unk_44); + stream.writeUI32(unk_48); + stream.writeUI32(unk_4C); + stream.writeUI32(unk_50); + stream.writeUI32(unk_54); + stream.writeFloat(frame_rate); + stream.writeUI32(unk_5C); + stream.writeUI64(fonts_offset); + stream.writeUI64(unk_68); + stream.writeUI64(names_offset); + stream.writeUI64(unk_offset5); + stream.writeUI64(unk_80); + stream.writeUI64(last_section_offset); + stream.writeUI64(unk_offset6); + stream.writeUI64(as3_code_offset); + stream.writeUI64(as3_names_offset); + stream.writeUI32(unk_A8); + stream.writeUI32(unk_AC); + stream.writeUI32(font_count); + stream.writeUI32(unk_B4); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java index e939b9c23..d209c2947 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyFont.java @@ -176,9 +176,13 @@ public class IggyFont extends IggyTag { } } + private long makeAbsOffset(ReadDataStreamInterface s, long offset) { + return offset == 1 ? 0 : s.position() - 8 + offset; + } + @Override - public void readFromDataStream(ReadDataStreamInterface stream) throws IOException { - TemporaryDataStream s = new TemporaryDataStream(stream.readBytes((int) (long) stream.available())); + public void readFromDataStream(ReadDataStreamInterface s) throws IOException { + long basePos = s.position(); type = s.readUI16(); fontId = s.readUI16(); zeroone = s.readBytes(28); @@ -187,19 +191,25 @@ public class IggyFont extends IggyTag { descent = s.readUI16(); leading = s.readUI16(); flags = s.readUI64(); - start_of_char_struct = readAbsoluteOffset(s); - start_of_char_index = readAbsoluteOffset(s); - start_of_scale = readAbsoluteOffset(s); + start_of_char_struct = s.readUI64(); + long abs_start_of_char_struct = makeAbsOffset(s, start_of_char_struct); + start_of_char_index = s.readUI64(); + long abs_start_of_char_index = makeAbsOffset(s, start_of_char_struct); + start_of_scale = s.readUI64(); + long abs_start_of_scale = makeAbsOffset(s, start_of_char_struct); + kern_count = s.readUI32(); unk_float = new float[5]; for (int i = 0; i < unk_float.length; i++) { unk_float[i] = s.readFloat(); } - start_of_kern = readAbsoluteOffset(s); + start_of_kern = s.readUI64(); + long abs_start_of_kern = makeAbsOffset(s, start_of_kern); zero_padd = s.readUI64(); what_2 = s.readUI64(); zero_padd_2 = s.readUI64(); - start_of_name = readAbsoluteOffset(s); + start_of_name = s.readUI64(); + long abs_start_of_name = makeAbsOffset(s, start_of_name); one_padd = s.readUI64(); xscale = s.readUI16(); yscale = s.readUI16(); @@ -209,7 +219,7 @@ public class IggyFont extends IggyTag { char_count = s.readUI32(); zero_padd_4 = s.readUI64(); what_3 = s.readUI64(); - s.seek(272, SeekMode.CUR); + s.seek(basePos + 272, SeekMode.SET); sss1 = s.readFloat(); one_padd2 = s.readUI32(); sss2 = s.readFloat(); @@ -218,8 +228,8 @@ public class IggyFont extends IggyTag { one_padd4 = s.readUI32(); sss4 = s.readFloat(); one_padd5 = s.readUI32(); - if (start_of_name != 0) { - s.seek(start_of_name, SeekMode.SET); + if (abs_start_of_name != 0) { + s.seek(abs_start_of_name, SeekMode.SET); StringBuilder nameBuilder = new StringBuilder(); int nameCharCnt = 0; do { @@ -234,8 +244,8 @@ public class IggyFont extends IggyTag { name = nameBuilder.toString(); } s.readUI64(); //pad zero - if (start_of_char_struct != 0) { - s.seek(start_of_char_struct, SeekMode.SET); + if (abs_start_of_char_struct != 0) { + s.seek(abs_start_of_char_struct, SeekMode.SET); charOffsets = new ArrayList<>(); for (int i = 0; i < char_count; i++) { charOffsets.add(new IggyCharOffset(s)); @@ -243,19 +253,23 @@ public class IggyFont extends IggyTag { glyphs = new ArrayList<>(); for (int i = 0; i < char_count; i++) { long offset = charOffsets.get(i).offset; - glyphs.add(new IggyShape(s, offset)); + if (offset != 0) { + glyphs.add(new IggyShape(s, offset)); + } else { + glyphs.add(null); + } } } - if (start_of_char_index != 0) { - s.seek(start_of_char_index, SeekMode.SET); + if (abs_start_of_char_index != 0) { + s.seek(abs_start_of_char_index, SeekMode.SET); codePoints = new IggyCharIndices(s, char_count); } - if (start_of_scale != 0) { - s.seek(start_of_scale, SeekMode.SET); + if (abs_start_of_scale != 0) { + s.seek(abs_start_of_scale, SeekMode.SET); charScales = new IggyCharAdvances(s, char_count); } - if (start_of_kern != 0) { - s.seek(start_of_kern, SeekMode.SET); + if (abs_start_of_kern != 0) { + s.seek(abs_start_of_kern, SeekMode.SET); charKernings = new IggyCharKerning(s, kern_count); } } @@ -270,18 +284,23 @@ public class IggyFont extends IggyTag { s.writeUI16(descent); s.writeUI16(leading); s.writeUI64(flags); - writeAbsoluteOffset(s, start_of_char_struct); - writeAbsoluteOffset(s, start_of_char_index); - writeAbsoluteOffset(s, start_of_scale); + long abs_start_of_char_struct = s.position() + start_of_char_struct; + s.writeUI64(start_of_char_struct); + long abs_start_of_char_index = s.position() + start_of_char_index; + s.writeUI64(start_of_char_index); + long abs_start_of_scale = s.position() + start_of_scale; + s.writeUI64(start_of_scale); s.writeUI32(kern_count); for (int i = 0; i < unk_float.length; i++) { s.writeFloat(unk_float[i]); } - writeAbsoluteOffset(s, start_of_kern); + long abs_start_of_kern = s.position() + start_of_kern; + s.writeUI64(start_of_kern); s.writeUI64(zero_padd); s.writeUI64(what_2); s.writeUI64(zero_padd_2); - writeAbsoluteOffset(s, start_of_name); + long abs_start_of_name = s.position() + start_of_name; + s.writeUI64(start_of_name); s.writeUI64(one_padd); s.writeUI16(xscale); s.writeUI16(yscale); @@ -291,10 +310,7 @@ public class IggyFont extends IggyTag { s.writeUI32(char_count); s.writeUI64(zero_padd_4); s.writeUI64(what_3); - //s.seek(272, SeekMode.CUR); - for (int i = 0; i < 272; i++) { - s.write(0); - } + s.seek(272, SeekMode.SET); s.writeFloat(sss1); s.writeUI32(one_padd2); s.writeFloat(sss2); @@ -303,7 +319,8 @@ public class IggyFont extends IggyTag { s.writeUI32(one_padd4); s.writeFloat(sss4); s.writeUI32(one_padd5); - if (start_of_name != 0) { + if (abs_start_of_name != 0) { + s.seek(abs_start_of_name, SeekMode.SET); for (char c : name.toCharArray()) { s.writeUI16(c); } @@ -317,25 +334,33 @@ public class IggyFont extends IggyTag { } } s.writeUI64(0); //pad zero - if (start_of_char_struct != 0) { + if (abs_start_of_char_struct != 0) { + s.seek(abs_start_of_char_struct, SeekMode.SET); //offsets of shapes for (IggyCharOffset ofs : charOffsets) { ofs.writeToDataStream(s); } - for (IggyShape shp : glyphs) { - shp.writeToDataStream(s); + for (int i = 0; i < glyphs.size(); i++) { + IggyShape shp = glyphs.get(i); + if (shp != null) { + s.seek(charOffsets.get(i).offset, SeekMode.SET); + shp.writeToDataStream(s); + } } } - if (start_of_char_index != 0) { + if (abs_start_of_char_index != 0) { + s.seek(abs_start_of_char_index, SeekMode.SET); for (char c : codePoints.chars) { s.writeUI16(c); } s.writeUI32(0); } - if (start_of_scale != 0) { + if (abs_start_of_scale != 0) { + s.seek(abs_start_of_scale, SeekMode.SET); charScales.writeToDataStream(s); } - if (start_of_kern != 0) { + if (abs_start_of_kern != 0) { + s.seek(abs_start_of_kern, SeekMode.SET); charKernings.writeToDataStream(s); } } @@ -413,4 +438,9 @@ public class IggyFont extends IggyTag { return ID; } + @Override + public String toString() { + return String.format("IggyFontTag (%04X)", ID); + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java index e7abed276..7fa2aa585 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyShape.java @@ -62,7 +62,7 @@ public class IggyShape implements StructureInterface { private long offset; - public IggyShape(AbstractDataStream stream, long offset) throws IOException { + public IggyShape(ReadDataStreamInterface stream, long offset) throws IOException { this.offset = offset; readFromDataStream(stream); } 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 ee54f21db..e6d85a4bf 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 @@ -6,7 +6,9 @@ import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface; import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface; import com.jpexs.decompiler.flash.iggy.annotations.IggyFieldType; import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface; +import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,17 +30,26 @@ public class IggySwf implements StructureInterface { private IggyFlashHeader64 header; private Map sizesOfOffsets; - private List allOffsets; + private List offsets; + private List tags = new ArrayList<>(); + + public List getTags() { + return tags; + } public IggySwf(IggyFlashHeader64 header, ReadDataStreamInterface stream, List offsets) throws IOException { this.header = header; + this.offsets = offsets; + calcSizesFromOffsets(); + readFromDataStream(stream); + } + + private void calcSizesFromOffsets() { sizesOfOffsets = new HashMap<>(); for (int i = 0; i < offsets.size() - 1; i++) { sizesOfOffsets.put(offsets.get(i), offsets.get(i + 1) - offsets.get(i)); } sizesOfOffsets.put(offsets.get(offsets.size() - 1), 0L); //Last offset has 0L length? - this.allOffsets = offsets; - readFromDataStream(stream); } @Override @@ -56,20 +67,25 @@ public class IggySwf implements StructureInterface { //here is offset[1] int pad8 = 8 - (int) (stream.position() % 8); stream.seek(pad8, SeekMode.CUR); - //here is offset [2] + //here is offset [2] fonts = new HashMap<>(); int fontIndex = 0; - for (int i = 2; i < allOffsets.size(); i++) { - long offset = allOffsets.get(i); + for (int ofs = 2; ofs < offsets.size(); ofs++) { + long offset = offsets.get(ofs); + if (offset < stream.position()) { + continue; + } stream.seek(offset, SeekMode.SET); int type = stream.readUI16(); stream.seek(-2, SeekMode.CUR); if (type == IggyFont.ID) { IggyFont font = new IggyFont(stream); fonts.put(fontIndex++, font); - } - if (type == IggyText.ID) { - //TODO: Texts - incomplete + tags.add(font); + } else if (ofs < offsets.size() - 1) { + int len = (int) (offsets.get(ofs + 1) - offsets.get(ofs)); + RawIggyPart rtag = new RawIggyPart(type, stream, len); + tags.add(rtag); } } } @@ -80,7 +96,29 @@ public class IggySwf implements StructureInterface { @Override public void writeToDataStream(WriteDataStreamInterface stream) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //TODO!!! + List newOffsets = new ArrayList<>(); + + try { + newOffsets.add(stream.position()); + for (int i = 0; i < name.length(); i++) { + stream.writeUI16(name.charAt(i)); + } + stream.writeUI16(0); + newOffsets.add(stream.position()); + long pad8 = 8 - (stream.position() % 8); + for (int i = 0; i < pad8; i++) { + stream.write(0); + } + newOffsets.add(stream.position()); + for (IggyTag tag : tags) { + tag.writeToDataStream(stream); + newOffsets.add(stream.position()); + } + } catch (IOException ex) { + //ignore + } + this.offsets = newOffsets; + calcSizesFromOffsets(); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java index c3a39aa6e..eeae0f3cb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/IggyTag.java @@ -9,4 +9,9 @@ import com.jpexs.decompiler.flash.iggy.streams.StructureInterface; public abstract class IggyTag implements StructureInterface { public abstract int getTagType(); + + @Override + public String toString() { + return String.format("IggyTag (%04X)", getTagType()); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyPart.java similarity index 81% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyPart.java index 81b57474b..9f1e0aeaa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/RawIggyPart.java @@ -8,13 +8,13 @@ import java.io.IOException; * * @author JPEXS */ -public class RawIggyTag extends IggyTag { +public class RawIggyPart extends IggyTag { byte[] rawData; int tagType; private int length; - public RawIggyTag(int tagType, ReadDataStreamInterface stream, int length) throws IOException { + public RawIggyPart(int tagType, ReadDataStreamInterface stream, int length) throws IOException { this.length = length; this.tagType = tagType; readFromDataStream(stream); 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 f48758673..7acf46afb 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 @@ -150,11 +150,20 @@ public class IggyToSwfConvertor { IggyCharAdvances advanceValues = iggyFont.getCharAdvances(); for (int i = 0; i < iggyFont.getCharacterCount(); i++) { int code = iggyFont.getCharIndices().getChars().get(i); - IggyShape glyph = iggyFont.getChars().get(i); fontTag.codeTable.add(code); - SHAPE shp = IggyShapeToSwfConvertor.convertCharToShape(glyph); + 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.fontBoundsTable.add(shp.getBounds()); + fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i))); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java index b341fc015..199dc8c93 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/RandomAccessFileDataStream.java @@ -5,6 +5,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -24,6 +26,15 @@ public class RandomAccessFileDataStream extends AbstractDataStream { raf = new RandomAccessFile(file, "rw"); } + @Override + public Long totalSize() { + try { + return raf.length(); + } catch (IOException ex) { + return null; + } + } + @Override public Long available() { try { @@ -51,6 +62,13 @@ public class RandomAccessFileDataStream extends AbstractDataStream { return val; } + @Override + public byte[] readBytes(int numBytes) throws IOException { + byte buf[] = new byte[numBytes]; + raf.readFully(buf); + return buf; + } + @Override public void seek(long pos, SeekMode mode) throws IOException { long newpos = pos; @@ -60,7 +78,11 @@ public class RandomAccessFileDataStream extends AbstractDataStream { newpos = raf.length() - pos; } if (newpos > raf.length()) { - throw new ArrayIndexOutOfBoundsException("Position outside bounds accessed: " + pos + ". Size: " + raf.length()); + raf.seek(raf.length()); + long curpos = raf.length(); + for (long i = curpos; i < newpos; i++) { + raf.write(0); + } } else if (newpos < 0) { throw new ArrayIndexOutOfBoundsException("Negative position accessed: " + pos); } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java index b9049c124..1b22ba523 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/ReadDataStreamInterface.java @@ -15,6 +15,8 @@ public interface ReadDataStreamInterface extends AutoCloseable { */ public Long available(); + public Long totalSize(); + public long position(); public long readUI64() throws IOException; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java index 2bcbd6872..1b3e47e61 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/WriteDataStreamInterface.java @@ -15,6 +15,8 @@ public interface WriteDataStreamInterface extends AutoCloseable { */ public Long available(); + public Long totalSize(); + public long position(); public boolean writeUI64(long val) throws IOException;