read and write of fonts matched

This commit is contained in:
Jindra Petřík
2016-11-30 10:55:17 +01:00
parent 1fa6a69988
commit 48177bb534
7 changed files with 141 additions and 70 deletions

View File

@@ -17,7 +17,6 @@ public class IggyCharKerning implements StructureInterface {
List<Character> charsA;
List<Character> charsB;
List<Short> kerningOffsets;
long pad;
public long getKernCount() {
return kernCount;
@@ -50,7 +49,6 @@ public class IggyCharKerning implements StructureInterface {
charsB.add((char) stream.readUI16());
kerningOffsets.add((short) stream.readUI16());
}
pad = stream.readUI32();
}
@Override
@@ -60,7 +58,6 @@ public class IggyCharKerning implements StructureInterface {
stream.writeUI16(charsB.get(i));
stream.writeUI16(kerningOffsets.get(i));
}
stream.writeUI32(pad);
}
}

View File

@@ -30,8 +30,14 @@ public class IggyCharOffset implements StructureInterface {
@IggyFieldType(DataType.uint32_t)
long zero3;
@IggyFieldType(DataType.uint64_t)
private long address;
long offset;
public long getAddress() {
return address;
}
public IggyCharOffset(ReadDataStreamInterface stream) throws IOException {
readFromDataStream(stream);
}
@@ -56,12 +62,11 @@ public class IggyCharOffset implements StructureInterface {
xscale = stream.readUI16();
yscale = stream.readUI16();
zero3 = stream.readUI32();
long cur_position = stream.position();
long relative_offset = stream.readUI64();
offset = stream.readUI64();
if (ischar1 > 0) {
offset = cur_position + relative_offset;
address = offset + stream.position() - 8;
} else {
offset = 0;
address = 0;
LOGGER.finer(String.format("Empty char"));
}
}
@@ -75,11 +80,7 @@ public class IggyCharOffset implements StructureInterface {
stream.writeUI16(xscale);
stream.writeUI16(yscale);
stream.writeUI32(zero3);
if (ischar1 > 0) {
stream.writeUI64(offset - stream.position());
} else {
stream.writeUI64(1);
}
stream.writeUI64(offset);
}
public boolean hasGlyph() {

View File

@@ -7,6 +7,7 @@ import com.jpexs.decompiler.flash.iggy.streams.ReadDataStreamInterface;
import com.jpexs.decompiler.flash.iggy.streams.WriteDataStreamInterface;
import com.jpexs.decompiler.flash.iggy.streams.DataStreamInterface;
import com.jpexs.decompiler.flash.iggy.streams.TemporaryDataStream;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
@@ -186,7 +187,7 @@ public class IggyFile implements StructureInterface {
}
public static void main(String[] args) throws IOException {
String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy";
/*String inFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font.iggy";
String outFileName = "d:\\Dropbox\\jpexs-laptop\\iggi\\lib_loc_english_font2.iggy";
File inFile = new File(inFileName);
@@ -198,7 +199,7 @@ public class IggyFile implements StructureInterface {
outFile.delete();
try (RandomAccessFileDataStream outputStream = new RandomAccessFileDataStream(outFile)) {
iggyFile.writeToDataStream(outputStream);
}
}*/
}
private static void copyStream(InputStream is, OutputStream os) {
@@ -719,7 +720,6 @@ public class IggyFile implements StructureInterface {
for (int i = 0; i < subFileEntries.size(); i++) {
IggySubFileEntry entry = subFileEntries.get(i);
byte[] entryData = subFileEntriesData.get(i);
stream.seek(entry.offset, SeekMode.SET);
stream.writeBytes(entryData);
}

View File

@@ -95,7 +95,8 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
private long base_address;
private long sequence_end_address;
private long font_end_address;
private long sequence_start_address;
private long sequence_start_address1;
private long sequence_start_address2;
private long names_address;
private long unk78_address;
private long unk80_address;
@@ -146,8 +147,12 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
this.font_end_address = val;
}
public long getSequenceStartAddress() {
return sequence_start_address;
public long getSequenceStartAddress1() {
return sequence_start_address1;
}
public long getSequenceStartAddress2() {
return sequence_start_address2;
}
public long getNamesAddress() {
@@ -180,13 +185,14 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
@Override
public void readFromDataStream(ReadDataStreamInterface stream) throws IOException {
off_start = stream.readUI64();
/* 0:*/ off_start = stream.readUI64();
base_address = off_start + stream.position() - 8;
off_seq_end = stream.readUI64();
/* 8:*/ off_seq_end = stream.readUI64();
sequence_end_address = off_seq_end + stream.position() - 8;
off_font_end = stream.readUI64();
/* 10:*/ off_font_end = stream.readUI64();
font_end_address = off_font_end + stream.position() - 8;
off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times)
/* 18:*/ off_seq_start1 = stream.readUI64(); //to 1 padd occurence (2 times)
sequence_start_address1 = off_seq_start1 + stream.position() - 8;
pad_to_match = stream.readUI64();
if (pad_to_match != 1) {
throw new IOException("Wrong iggy file - no pad to match 1");
@@ -195,7 +201,7 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
if (off_seq_start1 != off_seq_start2) {
throw new IOException("Wrong iggy font format (sequence_start)!\n");
}
sequence_start_address = off_seq_start2 + stream.position() - 8;
sequence_start_address2 = off_seq_start2 + stream.position() - 8;
xmin = stream.readUI32();
ymin = stream.readUI32();
xmax = stream.readUI32();
@@ -243,10 +249,10 @@ public class IggyFlashHeader64 implements IggyFlashHeaderInterface {
stream.writeUI64(off_seq_end);
off_font_end = font_end_address - stream.position();
stream.writeUI64(off_font_end);
off_seq_start1 = sequence_start_address - stream.position();
off_seq_start1 = sequence_start_address1 - stream.position();
stream.writeUI64(off_seq_start1);
stream.writeUI64(pad_to_match);
off_seq_start2 = sequence_start_address - stream.position();
off_seq_start2 = sequence_start_address2 - stream.position();
stream.writeUI64(off_seq_start2);
stream.writeUI32(xmin);
stream.writeUI32(ymin);

View File

@@ -73,8 +73,14 @@ public class IggyFont extends IggyTag {
long zero_padd_4;
@IggyFieldType(DataType.uint64_t)
long what_3;
@IggyFieldType(value = DataType.uint8_t, count = 272)
byte[] zeroes;
@IggyFieldType(value = DataType.widechar_t, count = 40)
String subName = "";
@IggyFieldType(value = DataType.uint8_t, count = 48)
byte[] zeroes48a;
@IggyFieldType(value = DataType.uint8_t, count = 48)
byte[] zeroes48b;
@IggyFieldType(DataType.float_t)
float sss1;
@IggyFieldType(DataType.uint32_t)
@@ -103,7 +109,7 @@ public class IggyFont extends IggyTag {
byte[] padTo4byteBoundary;
public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, 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[] zeroes, 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> chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) {
public IggyFont(int type, int order_in_iggy_file, byte[] zeroone, int char_count2, int ascent, int descent, int leading, long flags, long start_of_char_struct, long start_of_char_index, long start_of_scale, long kern_count, float[] unk_float, long start_of_kern, long zero_padd, long what_2, long zero_padd_2, long start_of_name, 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[] zeroes48, 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> chars, IggyCharIndices charIndices, IggyCharAdvances charScales, IggyCharKerning charKernings, byte[] padTo4byteBoundary) {
this.type = type;
this.fontId = order_in_iggy_file;
this.zeroone = zeroone;
@@ -131,7 +137,7 @@ public class IggyFont extends IggyTag {
this.char_count = char_count;
this.zero_padd_4 = zero_padd_4;
this.what_3 = what_3;
this.zeroes = zeroes;
this.zeroes48a = zeroes48;
this.sss1 = sss1;
this.one_padd2 = one_padd2;
this.sss2 = sss2;
@@ -178,11 +184,11 @@ public class IggyFont extends IggyTag {
}
private long makeAbsOffset(ReadDataStreamInterface s, long offset) {
return offset == 1 ? 0 : s.position() - 8 + offset;
return offset == 1 ? 0 : offset + s.position() - 8;
}
private long makeAbsOffset(WriteDataStreamInterface s, long offset) {
return offset == 1 ? 0 : s.position() - 8 + offset;
return offset == 1 ? 0 : offset + s.position() - 8;
}
@Override
@@ -224,7 +230,20 @@ public class IggyFont extends IggyTag {
char_count = s.readUI32();
zero_padd_4 = s.readUI64();
what_3 = s.readUI64();
s.seek(basePos + 272, SeekMode.SET);
StringBuilder subNameBuilder = new StringBuilder();
boolean snFinish = false;
for (int i = 0; i < 20; i++) {
char c = (char) s.readUI16();
if (c == '\0') {
snFinish = true;
}
if (!snFinish) {
subNameBuilder.append(c);
}
}
subName = subNameBuilder.toString();
zeroes48a = s.readBytes(48);
sss1 = s.readFloat();
one_padd2 = s.readUI32();
sss2 = s.readFloat();
@@ -233,6 +252,8 @@ public class IggyFont extends IggyTag {
one_padd4 = s.readUI32();
sss4 = s.readFloat();
one_padd5 = s.readUI32();
zeroes48b = s.readBytes(48);
if (abs_start_of_name != 0) {
s.seek(abs_start_of_name, SeekMode.SET);
StringBuilder nameBuilder = new StringBuilder();
@@ -257,9 +278,10 @@ public class IggyFont extends IggyTag {
}
glyphs = new ArrayList<>();
for (int i = 0; i < char_count; i++) {
long offset = charOffsets.get(i).offset;
if (offset != 0) {
glyphs.add(new IggyShape(s, offset));
long addr = charOffsets.get(i).getAddress();
if (addr != 0) {
s.seek(addr, SeekMode.SET);
glyphs.add(new IggyShape(s));
} else {
glyphs.add(null);
}
@@ -315,7 +337,14 @@ public class IggyFont extends IggyTag {
s.writeUI32(char_count);
s.writeUI64(zero_padd_4);
s.writeUI64(what_3);
s.seek(272, SeekMode.SET);
for (int i = 0; i < 20; i++) {
if (i < subName.length()) {
s.writeUI16((char) subName.charAt(i));
} else {
s.writeUI16(0);
}
}
s.writeBytes(zeroes48a);
s.writeFloat(sss1);
s.writeUI32(one_padd2);
s.writeFloat(sss2);
@@ -324,6 +353,7 @@ public class IggyFont extends IggyTag {
s.writeUI32(one_padd4);
s.writeFloat(sss4);
s.writeUI32(one_padd5);
s.writeBytes(zeroes48b);
if (abs_start_of_name != 0) {
s.seek(abs_start_of_name, SeekMode.SET);
for (char c : name.toCharArray()) {
@@ -333,11 +363,14 @@ public class IggyFont extends IggyTag {
//align to 8 bytes boundary
int len = name.length() * 2 + 2;
int rem = 8 - (len % 8);
for (int i = 0; i < rem; i++) {
s.write(0);
int pad8 = 8 - (len % 8);
if (pad8 < 8) {
for (int i = 0; i < pad8; i++) {
s.write(0);
}
}
}
s.writeUI64(0); //pad zero
if (abs_start_of_char_struct != 0) {
s.seek(abs_start_of_char_struct, SeekMode.SET);
@@ -348,7 +381,7 @@ public class IggyFont extends IggyTag {
for (int i = 0; i < glyphs.size(); i++) {
IggyShape shp = glyphs.get(i);
if (shp != null) {
s.seek(charOffsets.get(i).offset, SeekMode.SET);
s.seek(charOffsets.get(i).getAddress(), SeekMode.SET);
shp.writeToDataStream(s);
}
}
@@ -368,6 +401,11 @@ public class IggyFont extends IggyTag {
s.seek(abs_start_of_kern, SeekMode.SET);
charKernings.writeToDataStream(s);
}
if ((s.position() - abs_start_of_char_index) % 8 != 0) {
byte padd[] = new byte[(int) (((s.position() - abs_start_of_char_index) / 8 + 1) * 8 - (s.position() - abs_start_of_char_index))];
s.writeBytes(padd);
}
}
public int getType() {

View File

@@ -60,10 +60,7 @@ public class IggyShape implements StructureInterface {
List<IggyShapeNode> nodes;
private long offset;
public IggyShape(ReadDataStreamInterface stream, long offset) throws IOException {
this.offset = offset;
public IggyShape(ReadDataStreamInterface stream) throws IOException {
readFromDataStream(stream);
}
@@ -84,7 +81,6 @@ public class IggyShape implements StructureInterface {
@Override
public void readFromDataStream(ReadDataStreamInterface s) throws IOException {
s.seek(offset, SeekMode.SET);
minx = s.readFloat();
miny = s.readFloat();
maxx = s.readFloat();
@@ -98,7 +94,7 @@ public class IggyShape implements StructureInterface {
two1 = s.readUI32();
if ((one != 1) || (one2 != 1) || (one3 != 1) || (one4 != 1) || (two1 != 2)) {
LOGGER.fine(String.format("Unique header at pos %d, one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", offset, one, one2, one3, one4, two1));
LOGGER.fine(String.format("Unique header at one: %d, one2: %d, one3: %d, one4: %d, two1: %d\n", one, one2, one3, one4, two1));
}
nodes = new ArrayList<>();

View File

@@ -7,6 +7,8 @@ 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 com.jpexs.helpers.Helper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -38,6 +40,8 @@ public class IggySwf implements StructureInterface {
private long font_data_sizes[];
private List<Long> text_addresses = new ArrayList<>();
private List<Long> text_data_sizes = new ArrayList<>();
private List<byte[]> text_data_bytes = new ArrayList<>();
private byte font_add_data[];
private List<Long> font_add_off = new ArrayList<>();
private List<Long> font_add_size = new ArrayList<>();
@@ -95,7 +99,7 @@ public class IggySwf implements StructureInterface {
s.seek(pad8, SeekMode.CUR);
//here is offset [2]
s.seek(hdr.getBaseAddress(), SeekMode.SET);
s.readUI64(); //one pad
s.readUI64(); //pad 1
font_data_addresses = new long[(int) hdr.font_count];
font_data_sizes = new long[(int) hdr.font_count];
@@ -113,6 +117,9 @@ public class IggySwf implements StructureInterface {
}
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();
@@ -124,13 +131,14 @@ public class IggySwf implements StructureInterface {
text_data_sizes.add(next_offset - offset);
}
}
s.readUI64(); //1
if (hdr.isImported()) { // tohle muze narusit iggy order, ale oni to pak stejne pocitaji dle infa
long additionalOffset = s.readUI64();
font_add_off.add(additionalOffset + s.position() - 8);
font_add_size.add(hdr.getFontEndAddress() - font_add_off.get(0));
if (s.readUI8(font_add_off.get(0)) != 22) { //22 = Text
for (int i = 0; i < hdr.font_count; i++) {
for (int i = 0; i < text_addresses.size(); i++) {
if (s.readUI8(text_addresses.get(i)) == 22) { //TEXT
long pomoff;
long pomsize;
@@ -144,27 +152,30 @@ public class IggySwf implements StructureInterface {
}
}
}
//long skipBytes = 840 - s.position();
fonts = new HashMap<>();
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]);
IggyFont font = new IggyFont(s);
fonts.put(i/*??*/, font);
fonts.put(i, font);
}
for (int i = 0; i < text_addresses.size(); i++) {
s.seek(text_addresses.get(i), SeekMode.SET);
byte text_data[] = s.readBytes((int) (long) text_data_sizes.get(i));
text_data_bytes.add(text_data);
}
if (hdr.isImported()) {
s.seek(font_add_off.get(0), SeekMode.SET);
byte font_add_data[] = s.readBytes((int) (long) font_add_size.get(0));
font_add_data = s.readBytes((int) (long) font_add_size.get(0));
}
s.seek(hdr.getFontEndAddress(), SeekMode.SET);
WriteDataStreamInterface outs = new TemporaryDataStream();
writeToDataStream(outs);
Helper.writeFile("d:\\Dropbox\\jpexs-laptop\\iggi\\parts\\swf_out.bin", outs.getAllBytes());
}
public String getName() {
@@ -172,25 +183,47 @@ public class IggySwf implements StructureInterface {
}
@Override
public void writeToDataStream(WriteDataStreamInterface st) throws IOException {
try (DataStreamInterface s = new TemporaryDataStream(allFontBytes)) {
hdr.writeToDataStream(s);
s.writeUI64(1);
for (int i = 0; i < font_data_addresses.length; i++) {
long offset = font_data_addresses[i] - s.position() + 8;
s.writeUI64(offset);
public void writeToDataStream(WriteDataStreamInterface s) throws IOException {
hdr.writeToDataStream(s);
for (int i = 0; i < name.length(); i++) {
s.writeUI16(name.charAt(i));
}
s.writeUI16(0);
int pad8 = 8 - (int) (s.position() % 8);
if (pad8 < 8) {
for (int i = 0; i < pad8; i++) {
s.write(0);
}
s.writeUI64(1);
for (int i = 0; i < text_addresses.size(); i++) {
long offset = text_addresses.get(i) - s.position() + 8;
s.writeUI64(offset);
}
s.writeUI64(1);
for (int i = 0; i < font_data_addresses.length; i++) {
long offset = font_data_addresses[i] - s.position();
s.writeUI64(offset);
}
for (int i = 0; i < text_addresses.size(); i++) {
long offset = text_addresses.get(i) - s.position();
s.writeUI64(offset);
}
s.writeUI64(1);
if (hdr.font_count > 0) {
while (s.position() < font_data_addresses[0]) {
s.writeUI64(1);
}
s.writeUI64(1);
s.seek(840, SeekMode.SET);
for (int i = 0; i < hdr.font_count; i++) {
fonts.get(i).writeToDataStream(s);
}
st.writeBytes(s.getAllBytes());
}
for (int i = 0; i < hdr.font_count; i++) {
s.seek(font_data_addresses[i], SeekMode.SET);
fonts.get(i).writeToDataStream(s);
}
for (int i = 0; i < text_data_bytes.size(); i++) {
s.seek(text_addresses.get(i), SeekMode.SET);
s.writeBytes(text_data_bytes.get(i));
}
if (hdr.isImported()) {
s.seek(font_add_off.get(0), SeekMode.SET);
s.writeBytes(font_add_data);
}
}