Correct advance values, refactorings

This commit is contained in:
Jindra Petřík
2016-11-26 11:15:58 +01:00
parent 6659b4921c
commit 44a6fe740a
7 changed files with 189 additions and 94 deletions

View File

@@ -8,21 +8,25 @@ import java.util.List;
*
* @author JPEXS
*/
public class IggyCharScales implements StructureInterface {
public class IggyCharAdvances implements StructureInterface {
List<Float> scales;
List<Float> advances;
private long charCount;
public IggyCharScales(AbstractDataStream stream, long charCount) throws IOException {
public List<Float> getScales() {
return advances;
}
public IggyCharAdvances(AbstractDataStream stream, long charCount) throws IOException {
this.charCount = charCount;
readFromDataStream(stream);
}
@Override
public void readFromDataStream(AbstractDataStream stream) throws IOException {
scales = new ArrayList<>();
advances = new ArrayList<>();
for (int i = 0; i < charCount; i++) {
scales.add(stream.readFloat());
advances.add(stream.readFloat());
}
}

View File

@@ -72,12 +72,12 @@ public class IggyCharOffset implements StructureInterface {
return zero;
}
public int getIschar1() {
return ischar1;
public boolean isChar1() {
return ischar1 > 0;
}
public int getIschar2() {
return ischar2;
public boolean isChar2() {
return ischar2 > 0;
}
public long getZero2() {

View File

@@ -91,14 +91,14 @@ public class IggyFont implements StructureInterface {
String name;
List<IggyCharOffset> charOffsets;
List<IggyChar> glyphs;
List<IggyShape> glyphs;
IggyCharIndices codePoints;
IggyCharScales charScales;
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[] 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<IggyChar> chars, IggyCharIndices charIndices, IggyCharScales 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[] 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) {
this.type = type;
this.fontId = order_in_iggy_file;
this.zeroone = zeroone;
@@ -223,12 +223,7 @@ public class IggyFont implements StructureInterface {
glyphs = new ArrayList<>();
for (int i = 0; i < char_count; i++) {
long offset = charOffsets.get(i).offset;
if (offset > 0) {
glyphs.add(new IggyChar(s, offset));
} else {
s.seek(1, SeekMode.CUR);
glyphs.add(null);
}
glyphs.add(new IggyShape(s, offset));
}
}
if (start_of_char_index != 0) {
@@ -237,7 +232,7 @@ public class IggyFont implements StructureInterface {
}
if (start_of_scale != 0) {
s.seek(start_of_scale, SeekMode.SET);
charScales = new IggyCharScales(s, char_count);
charScales = new IggyCharAdvances(s, char_count);
}
if (start_of_kern != 0) {
s.seek(start_of_kern, SeekMode.SET);
@@ -274,7 +269,7 @@ public class IggyFont implements StructureInterface {
return name;
}
public List<IggyChar> getChars() {
public List<IggyShape> getChars() {
return glyphs;
}
@@ -282,7 +277,7 @@ public class IggyFont implements StructureInterface {
return codePoints;
}
public IggyCharScales getCharScales() {
public IggyCharAdvances getCharAdvances() {
return charScales;
}

View File

@@ -10,20 +10,20 @@ import java.util.logging.Logger;
*
* @author JPEXS
*/
public class IggyChar implements StructureInterface {
public class IggyShape implements StructureInterface {
private static Logger LOGGER = Logger.getLogger(IggyChar.class.getName());
private static Logger LOGGER = Logger.getLogger(IggyShape.class.getName());
@IggyFieldType(DataType.float_t)
float minx;
float minx; //bearing X - this is the horizontal distance from the current pen position to the glyph's left bbox edge.
@IggyFieldType(DataType.float_t)
float miny;
float miny; //bearing Y - this is the vertical distance from the baseline to the top of the glyph's bbox.
@IggyFieldType(DataType.float_t)
float maxx;
float maxx; //advanceX - bearingX
@IggyFieldType(DataType.float_t)
float maxy;
float maxy; //advanceY - bearingY
@IggyFieldType(DataType.uint64_t)
long advance; // stejny vetsinou - napr. 48 - JP: to by mohlo byt advance
long unk; // stejny vetsinou - napr. 48 - JP: to by mohlo byt advance
@IggyFieldType(DataType.uint64_t)
long count;
@IggyFieldType(DataType.uint64_t)
@@ -37,21 +37,37 @@ public class IggyChar implements StructureInterface {
@IggyFieldType(DataType.uint32_t)
long two1; // 2
List<IggyCharNode> nodes;
public float getBearingX() {
return minx;
}
public float getBearingY() {
return miny;
}
public float getWidth() {
return maxx - minx;
}
public float getHeight() {
return maxy - miny;
}
List<IggyShapeNode> nodes;
private long offset;
public IggyChar(AbstractDataStream stream, long offset) throws IOException {
public IggyShape(AbstractDataStream stream, long offset) throws IOException {
this.offset = offset;
readFromDataStream(stream);
}
public IggyChar(float minx, float miny, float maxx, float maxy, long advance, long count, long one, long one2, long one3, long one4, long two1, List<IggyCharNode> nodes) {
public IggyShape(float minx, float miny, float maxx, float maxy, long advance, long count, long one, long one2, long one3, long one4, long two1, List<IggyShapeNode> nodes) {
this.minx = minx;
this.miny = miny;
this.maxx = maxx;
this.maxy = maxy;
this.advance = advance;
this.unk = advance;
this.count = count;
this.one = one;
this.one2 = one2;
@@ -68,7 +84,7 @@ public class IggyChar implements StructureInterface {
miny = s.readFloat();
maxx = s.readFloat();
maxy = s.readFloat();
advance = s.readUI64();
unk = s.readUI64();
count = s.readUI64();
one = s.readUI64();
one2 = s.readUI64();
@@ -82,7 +98,7 @@ public class IggyChar implements StructureInterface {
nodes = new ArrayList<>();
for (int i = 0; i < count; i++) {
nodes.add(new IggyCharNode(s, i == 0));
nodes.add(new IggyShapeNode(s, i == 0));
}
}
@@ -108,8 +124,8 @@ public class IggyChar implements StructureInterface {
return maxy;
}
public long getAdvance() {
return advance;
public long getUnk() {
return unk;
}
public long getOne() {
@@ -132,7 +148,7 @@ public class IggyChar implements StructureInterface {
return two1;
}
public List<IggyCharNode> getNodes() {
public List<IggyShapeNode> getNodes() {
return nodes;
}

View File

@@ -9,9 +9,9 @@ import java.util.logging.Logger;
*
* @author JPEXS
*/
public class IggyCharNode implements StructureInterface {
public class IggyShapeNode implements StructureInterface {
private static Logger LOGGER = Logger.getLogger(IggyCharNode.class.getName());
private static Logger LOGGER = Logger.getLogger(IggyShapeNode.class.getName());
public static int NODE_TYPE_MOVE = 1;
public static int NODE_TYPE_LINE_TO = 2;
@@ -38,7 +38,7 @@ public class IggyCharNode implements StructureInterface {
private boolean first;
public IggyCharNode(float x1, float y1, float x2, float y2, int node_type, int node_subtype, int zer1, int zer2, long isstart) {
public IggyShapeNode(float x1, float y1, float x2, float y2, int node_type, int node_subtype, int zer1, int zer2, long isstart) {
this.targetX = x1;
this.targetY = y1;
this.controlX = x2;
@@ -50,7 +50,7 @@ public class IggyCharNode implements StructureInterface {
this.isstart = isstart;
}
public IggyCharNode(AbstractDataStream s, boolean first) throws IOException {
public IggyShapeNode(AbstractDataStream s, boolean first) throws IOException {
this.first = first;
readFromDataStream(s);
}

View File

@@ -1,8 +1,8 @@
package com.jpexs.decompiler.flash.iggy.conversion;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.iggy.IggyChar;
import com.jpexs.decompiler.flash.iggy.IggyCharNode;
import com.jpexs.decompiler.flash.iggy.IggyShape;
import com.jpexs.decompiler.flash.iggy.IggyShapeNode;
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
import com.jpexs.decompiler.flash.types.LINESTYLE;
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
@@ -21,43 +21,39 @@ import java.util.List;
*
* @author JPEXS
*/
public class IggyCharToShapeConvertor {
public class IggyShapeToSwfConvertor {
private static int convertDistanceX(double val) {
private static int makeLengthsEm(double val) {
return (int) (val * 1024.0);
}
private static int convertDistanceY(double val) {
return (int) (val * 1024.0);
}
public static SHAPE convertCharToShape(IggyChar igchar) {
public static SHAPE convertCharToShape(IggyShape igchar) {
SHAPE shape = new SHAPE();
List<SHAPERECORD> retList = new ArrayList<>();
List<IggyCharNode> ignodes = igchar.getNodes();
List<IggyShapeNode> ignodes = igchar.getNodes();
int prevX = 0;
int prevY = 0;
for (IggyCharNode ign : ignodes) {
if (ign.getNodeType() == IggyCharNode.NODE_TYPE_MOVE) {
for (IggyShapeNode ign : ignodes) {
if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_MOVE) {
StyleChangeRecord scr = new StyleChangeRecord();
scr.stateMoveTo = true;
prevX = scr.moveDeltaX = convertDistanceX(ign.getX1());
prevY = scr.moveDeltaY = convertDistanceY(ign.getY1());
prevX = scr.moveDeltaX = makeLengthsEm(ign.getX1());
prevY = scr.moveDeltaY = makeLengthsEm(ign.getY1());
scr.fillStyles = new FILLSTYLEARRAY();
scr.lineStyles = new LINESTYLEARRAY();
scr.calculateBits();
retList.add(scr);
} else {
int curX1 = convertDistanceX(ign.getX1());
int curY1 = convertDistanceY(ign.getY1());
int curX1 = makeLengthsEm(ign.getX1());
int curY1 = makeLengthsEm(ign.getY1());
int curX2 = convertDistanceX(ign.getX2());
int curY2 = convertDistanceY(ign.getY2());
int curX2 = makeLengthsEm(ign.getX2());
int curY2 = makeLengthsEm(ign.getY2());
if (ign.getNodeType() == IggyCharNode.NODE_TYPE_LINE_TO) {
if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_LINE_TO) {
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = curX1 - prevX;
ser.deltaY = curY1 - prevY;
@@ -67,7 +63,7 @@ public class IggyCharToShapeConvertor {
prevX = curX1;
prevY = curY1;
retList.add(ser);
} else if (ign.getNodeType() == IggyCharNode.NODE_TYPE_CURVE_POINT) {
} else if (ign.getNodeType() == IggyShapeNode.NODE_TYPE_CURVE_POINT) {
CurvedEdgeRecord cer = new CurvedEdgeRecord();
cer.controlDeltaX = curX2 - prevX;
cer.controlDeltaY = curY2 - prevY;

View File

@@ -2,9 +2,11 @@ package com.jpexs.decompiler.flash.iggy.conversion;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFCompression;
import com.jpexs.decompiler.flash.iggy.IggyChar;
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.IggyFile;
import com.jpexs.decompiler.flash.iggy.IggyFont;
import com.jpexs.decompiler.flash.iggy.IggyText;
@@ -12,10 +14,17 @@ import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
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 java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
@@ -66,8 +75,84 @@ public class IggyToSwfConvertor {
swf.saveTo(output);
}
private static int makeLengthsCorrect(double val) {
return (int) (SWF.unitDivisor * val);
private static int makeLengthsTwip(double val) {
return (int) (val * SWF.unitDivisor);
}
private static int makeLengthsEm(double val) {
return (int) (val * 1024.0);
}
private static SHAPE createEmptyChar() {
SHAPE shape = new SHAPE();
List<SHAPERECORD> retList = new ArrayList<>();
{
StyleChangeRecord scr = new StyleChangeRecord();
scr.stateMoveTo = true;
scr.moveDeltaX = 0;
scr.moveDeltaY = 0;
scr.fillStyles = new FILLSTYLEARRAY();
scr.lineStyles = new LINESTYLEARRAY();
scr.calculateBits();
retList.add(scr);
}
/*{
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = 1024;
ser.deltaY = 0;
ser.generalLineFlag = true;
ser.simplify();
ser.calculateBits();
retList.add(ser);
}
{
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = 0;
ser.deltaY = -1024;
ser.generalLineFlag = true;
ser.simplify();
ser.calculateBits();
retList.add(ser);
}
{
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = -1024;
ser.deltaY = 0;
ser.generalLineFlag = true;
ser.simplify();
ser.calculateBits();
retList.add(ser);
}
{
StraightEdgeRecord ser = new StraightEdgeRecord();
ser.deltaX = 0;
ser.deltaY = 1024;
ser.generalLineFlag = true;
ser.simplify();
ser.calculateBits();
retList.add(ser);
}*/
StyleChangeRecord init;
if (!retList.isEmpty() && retList.get(0) instanceof StyleChangeRecord) {
init = (StyleChangeRecord) retList.get(0);
} else {
init = new StyleChangeRecord();
retList.add(0, init);
}
retList.add(new EndShapeRecord());
init.stateFillStyle1 = true;
init.fillStyle1 = 1;
shape.shapeRecords = retList;
shape.numFillBits = 1;
shape.numLineBits = 0;
return shape;
}
public static SWF getSwf(IggyFile file, int swfIndex) {
@@ -100,7 +185,7 @@ public class IggyToSwfConvertor {
currentCharId++;
fontIndex2CharId.put(fontIndex, currentCharId);
fontTag.fontID = currentCharId;
System.out.println("===================");
/*System.out.println("===================");
System.out.println("xscale: " + iggyFont.getXscale()); //80
System.out.println("yscale: " + iggyFont.getYscale()); //19
@@ -110,14 +195,8 @@ public class IggyToSwfConvertor {
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());
System.out.println("what_3: " + iggyFont.getWhat_3());*/
fontTag.fontFlagsHasLayout = true;
List<IggyCharOffset> offsets = iggyFont.getCharOffsets();
fontTag.fontAdvanceTable = new ArrayList<>();
for (int i = 0; i < offsets.size(); i++) {
fontTag.fontAdvanceTable.add((int) offsets.get(i).getXscale());
}
fontTag.fontKerningTable = new ArrayList<>();
IggyCharKerning ker = iggyFont.getCharKernings();
if (ker != null) {
@@ -137,21 +216,19 @@ public class IggyToSwfConvertor {
fontTag.codeTable = new ArrayList<>();
fontTag.fontName = iggyFont.getName();
fontTag.glyphShapeTable = new ArrayList<>();
fontTag.fontAdvanceTable = 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);
IggyChar chr = iggyFont.getChars().get(i);
if (chr != null) {
fontTag.codeTable.add(code);
SHAPE shp = IggyCharToShapeConvertor.convertCharToShape(chr);
fontTag.glyphShapeTable.add(shp);
fontTag.fontAdvanceTable.add((int) chr.getAdvance());
fontTag.fontBoundsTable.add(shp.getBounds());
IggyShape glyph = iggyFont.getChars().get(i);
fontTag.codeTable.add(code);
SHAPE shp = IggyShapeToSwfConvertor.convertCharToShape(glyph);
fontTag.glyphShapeTable.add(shp);
fontTag.fontBoundsTable.add(shp.getBounds());
fontTag.fontAdvanceTable.add(makeLengthsEm(advanceValues.getScales().get(i)));
}
//FIXME: handle spaces (with no vectors), etc.
}
fontTag.setModified(true);
swf.addTag(fontTag);
@@ -167,26 +244,33 @@ public class IggyToSwfConvertor {
textIndex2CharId.put(iggyText.getTextIndex(), currentCharId);
textTag.characterID = currentCharId;
textTag.hasText = true;
textTag.initialText = "A";//iggyText.getInitialText();
//textTag.html = true;
textTag.hasTextColor = true;
textTag.textColor = new RGBA(Color.black);
textTag.fontHeight = 20 * 40; //??
textTag.initialText = iggyText.getInitialText();
textTag.html = true;
textTag.noSelect = true;
textTag.wasStatic = true;
//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(
makeLengthsCorrect(iggyText.getPar3()),
makeLengthsCorrect(iggyText.getPar1()),
makeLengthsCorrect(iggyText.getPar4()),
makeLengthsCorrect(iggyText.getPar2())
makeLengthsTwip(iggyText.getPar3()),
makeLengthsTwip(iggyText.getPar1()),
makeLengthsTwip(iggyText.getPar4()),
makeLengthsTwip(iggyText.getPar2())
);
//textTag.hasFont = true;
//textTag.fontId = fontIndex2CharId.get(iggyText.getFontIndex());
textTag.setModified(true);
swf.addTag(textTag);
}
swf.addTag(new EndTag(swf));
swf.setModified(true);
swf.addTag(
new EndTag(swf));
swf.setModified(
true);
return swf;
}