Issue #395 Reading GFx tags, displaying DefineCompactedFont

This commit is contained in:
Jindra Pet��k
2013-09-22 16:35:11 +02:00
parent 31f527582c
commit dfb334116b
26 changed files with 1964 additions and 6 deletions
@@ -166,6 +166,7 @@ public class SWFInputStream extends InputStream {
return readNoBitReset();
} catch (EndOfStreamException ex) {
Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, null, ex);
System.exit(1);
}
return -1;
}
@@ -953,6 +954,36 @@ public class SWFInputStream extends InputStream {
case 94:
ret = new PlaceObject4Tag(swf, data, version, pos);
break;
case 1000:
ret = new GFxExporterInfoTag(swf, data, version, pos);
break;
case 1001:
ret = new GFxDefineExternalImage(swf, data, version, pos);
break;
case 1002:
ret = new GFxFontTextureInfo(swf, data, version, pos);
break;
case 1003:
ret = new GFxDefineExternalGradient(swf, data, version, pos);
break;
case 1004:
ret = new GFxDefineGradientMap(swf, data, version, pos);
break;
case 1005:
ret = new GFxDefineCompactedFont(swf, data, version, pos);
break;
case 1006:
ret = new GFxDefineExternalSound(swf, data, version, pos);
break;
case 1007:
ret = new GFxDefineExternalStreamSound(swf, data, version, pos);
break;
case 1008:
ret = new GFxDefineSubImage(swf, data, version, pos);
break;
case 1009:
ret = new GFxDefineExternalImage2(swf, data, version, pos);
break;
default:
ret = new Tag(swf, tag.getId(), "Unknown", data, pos);
}
@@ -43,7 +43,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
@Override
public String convertHeader(Trait parent, String path, List<ABCContainerTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int scriptIndex, int classIndex, boolean highlight, List<String> fullyQualifiedNames, boolean parallel) {
String modifier = getModifiers(abcTags, abc, isStatic) + " ";
String modifier = getModifiers(abcTags, abc, isStatic) + " ";
MethodBody body = abc.findBody(method_info);
if (body == null) {
modifier = "native " + modifier;
@@ -67,6 +67,7 @@ import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.EndTag;
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
import com.jpexs.decompiler.flash.tags.GFxDefineCompactedFont;
import com.jpexs.decompiler.flash.tags.JPEGTablesTag;
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
@@ -1801,7 +1802,8 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
if ((t instanceof DefineFontTag)
|| (t instanceof DefineFont2Tag)
|| (t instanceof DefineFont3Tag)
|| (t instanceof DefineFont4Tag)) {
|| (t instanceof DefineFont4Tag)
|| (t instanceof GFxDefineCompactedFont)) {
return "font";
}
if ((t instanceof DefineTextTag)
@@ -0,0 +1,133 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.gfx.FontType;
import com.jpexs.decompiler.flash.types.gfx.GFxInputStream;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
*
* @author JPEXS
*/
public class GFxDefineCompactedFont extends CharacterTag implements DrawableTag {
public static final int ID = 1005;
public int fontId;
public List<FontType> fonts;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
return super.getData(version);
/*ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
//sos.write
} catch (IOException e) {
}
return baos.toByteArray();*/
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineCompactedFont(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineCompactedFont", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
fontId = sis.readUI16();
fonts = new ArrayList<>();
while (sis.available() > 0) {
fonts.add(new FontType(new GFxInputStream(sis)));
}
}
@Override
public BufferedImage toImage(int frame, List<Tag> tags, RECT displayRect, HashMap<Integer, CharacterTag> characters, Stack<Integer> visited) {
List<SHAPE> shapes = new ArrayList<>();
for (FontType f : fonts) {
shapes.addAll(f.getGlyphShapes());
}
return SHAPERECORD.shapeListToImage(shapes, 500, 500, Color.black);
}
@Override
public Point getImagePos(int frame, HashMap<Integer, CharacterTag> characters, Stack<Integer> visited) {
return new Point(0, 0);
}
@Override
public int getNumFrames() {
return 1;
}
public String getFontName(List<Tag> tags) {
String ret = "";
for (int i = 0; i < fonts.size(); i++) {
if (i > 0) {
ret += ", ";
}
ret += fonts.get(i).fontName;
}
return ret;
}
@Override
public String getName(List<Tag> tags) {
String nameAppend = "";
String fontName = getFontName(tags);
if (fontName != null) {
nameAppend = ": " + fontName;
}
return name + " (" + getCharacterId() + nameAppend + ")";
}
@Override
public int getCharacterId() {
return fontId;
}
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineExternalGradient extends Tag {
public static final int ID = 1003;
public static final int BITMAP_FORMAT_DEFAULT = 0;
public static final int BITMAP_FORMAT_TGA = 1;
public static final int BITMAP_FORMAT_DDS = 2;
public int gradientId;
public int bitmapsFormat;
public int gradientSize;
public String fileName;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(gradientId);
sos.writeUI16(bitmapsFormat);
sos.writeUI16(gradientSize);
byte fileNameBytes[] = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineExternalGradient(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineExternalGradient", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
gradientId = sis.readUI16();
bitmapsFormat = sis.readUI16();
gradientSize = sis.readUI16();
int fileNameLen = sis.readUI8();
fileName = new String(sis.readBytes(fileNameLen));
}
}
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineExternalImage extends Tag {
public static final int ID = 1001;
public int characterId;
public int bitmapFormat;
public int targetWidth;
public int targetHeight;
public String fileName;
public static final int BITMAP_FORMAT_DEFAULT = 0;
public static final int BITMAP_FORMAT_TGA = 1;
public static final int BITMAP_FORMAT_DDS = 2;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(characterId);
sos.writeUI16(bitmapFormat);
sos.writeUI16(targetWidth);
sos.writeUI16(targetHeight);
byte fileNameBytes[] = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineExternalImage(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineExternalImage", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
characterId = sis.readUI16();
bitmapFormat = sis.readUI16();
targetWidth = sis.readUI16();
targetHeight = sis.readUI16();
int fileNameLen = sis.readUI8();
fileName = new String(sis.readBytes(fileNameLen));
}
}
@@ -0,0 +1,87 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineExternalImage2 extends Tag {
public static final int ID = 1009;
public long characterId;
public int bitmapFormat;
public int targetWidth;
public int targetHeight;
public String fileName;
public static final int BITMAP_FORMAT_DEFAULT = 0;
public static final int BITMAP_FORMAT_TGA = 1;
public static final int BITMAP_FORMAT_DDS = 2;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI32(characterId);
sos.writeUI16(bitmapFormat);
sos.writeUI16(targetWidth);
sos.writeUI16(targetHeight);
byte fileNameBytes[] = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineExternalImage2(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineExternalImage2", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
characterId = sis.readUI32();
bitmapFormat = sis.readUI16();
targetWidth = sis.readUI16();
targetHeight = sis.readUI16();
int fileNameLen = sis.readUI8();
fileName = new String(sis.readBytes(fileNameLen));
}
}
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineExternalSound extends Tag {
public static final int ID = 1006;
public int characterId;
public int soundFormat;
public int bits;
public int channels;
public long sampleRate;
public long sampleCount;
public long seekSample;
public String exportName;
public String fileName;
public static final int SOUND_FORMAT_WAV = 0;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(characterId);
sos.writeUI16(soundFormat);
sos.writeUI16(bits);
sos.writeUI16(channels);
sos.writeUI32(sampleRate);
sos.writeUI32(sampleCount);
sos.writeUI32(seekSample);
byte[] exportNameBytes = exportName.getBytes();
sos.writeUI8(exportNameBytes.length);
sos.write(exportNameBytes);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineExternalSound(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineExternalSound", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
characterId = sis.readUI16();
soundFormat = sis.readUI16();
bits = sis.readUI16();
channels = sis.readUI16();
sampleRate = sis.readUI32();
sampleCount = sis.readUI32();
seekSample = sis.readUI32();
int exportNameLen = sis.readUI8();
exportName = new String(sis.readBytes(exportNameLen));
int fileNameLen = sis.readUI8();
fileName = new String(sis.readBytes(fileNameLen));
}
}
@@ -0,0 +1,98 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineExternalStreamSound extends Tag {
public static final int ID = 1007;
public int soundFormat;
public int bits;
public int channels;
public long sampleRate;
public long sampleCount;
public long seekSample;
public long startFrame;
public long lastFrame;
public String fileName;
public static final int SOUND_FORMAT_WAV = 0;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(soundFormat);
sos.writeUI16(bits);
sos.writeUI16(channels);
sos.writeUI32(sampleRate);
sos.writeUI32(sampleCount);
sos.writeUI32(seekSample);
sos.writeUI32(startFrame);
sos.writeUI32(lastFrame);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineExternalStreamSound(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineExternalStreamSound", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
soundFormat = sis.readUI16();
bits = sis.readUI16();
channels = sis.readUI16();
sampleRate = sis.readUI32();
sampleCount = sis.readUI32();
seekSample = sis.readUI32();
startFrame = sis.readUI32();
lastFrame = sis.readUI32();
int fileNameLen = sis.readUI8();
fileName = new String(sis.readBytes(fileNameLen));
}
}
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineGradientMap extends Tag {
public static final int ID = 1004;
public int indices[];
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(indices.length);
for (int i = 0; i < indices.length; i++) {
sos.writeUI16(indices[i]);
}
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineGradientMap(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineGradientMap", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
int numGradients = sis.readUI16();
indices = new int[numGradients];
for (int i = 0; i < numGradients; i++) {
indices[i] = sis.readUI16();
}
}
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxDefineSubImage extends Tag {
public static final int ID = 1008;
public int characterId;
public int imageCharacterId;
public int x1;
public int y1;
public int x2;
public int y2;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(characterId);
sos.writeUI16(imageCharacterId);
sos.writeUI16(x1);
sos.writeUI16(y1);
sos.writeUI16(x2);
sos.writeUI16(y2);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxDefineSubImage(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "DefineSubImage", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
characterId = sis.readUI16();
imageCharacterId = sis.readUI16();
x1 = sis.readUI16();
y1 = sis.readUI16();
x2 = sis.readUI16();
y2 = sis.readUI16();
}
}
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxExporterInfoTag extends Tag {
public static final int ID = 1000;
//Version (1.10 will be encoded as 0x10A)
public int version;
//Version 1.10 (0x10A) and above - flags
public long flags;
public int bitmapFormat;
public byte[] prefix;
public String swfName;
public static final int BITMAP_FORMAT_TGA = 1;
public static final int BITMAP_FORMAT_DDS = 2;
public static final int FLAG_CONTAINS_GLYPH_TEXTURES = 1;
public static final int FLAG_GLYPHS_STRIPPED_FROM_DEFINEFONT = 2;
public static final int FLAG_GRADIENT_IMAGES_EXPORTED = 4;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI16(version);
if (version >= 0x10a) {
sos.writeUI32(flags);
}
sos.writeUI16(bitmapFormat);
sos.writeUI8(prefix.length);
sos.write(prefix);
byte swfNameBytes[] = swfName.getBytes();
sos.writeUI8(swfNameBytes.length);
sos.write(swfNameBytes);
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxExporterInfoTag(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "ExporterInfo", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
version = sis.readUI16();
if (version >= 0x10a) {
flags = sis.readUI32();
}
bitmapFormat = sis.readUI16();
int prefixLen = sis.readUI8();
prefix = sis.readBytes(prefixLen);
int swfNameLen = sis.readUI8();
swfName = new String(sis.readBytes(swfNameLen));
}
}
@@ -0,0 +1,116 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.types.gfx.FONTINFO;
import com.jpexs.decompiler.flash.types.gfx.GFxInputStream;
import com.jpexs.decompiler.flash.types.gfx.TEXGLYPH;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
*
*
* @author JPEXS
*/
public class GFxFontTextureInfo extends Tag {
public static final int ID = 1002;
public long textureID;
public int textureFormat;
public String fileName;
public int textureWidth;
public int textureHeight;
public int padPixels;
public int nominalGlyphSz;
public TEXGLYPH texGlyphs[];
public FONTINFO fonts[];
public static final int TEXTURE_FORMAT_DEFAULT = 0;
public static final int TEXTURE_FORMAT_TGA = 1;
public static final int TEXTURE_FORMAT_DDS = 2;
/**
* Gets data bytes
*
* @param version SWF version
* @return Bytes of data
*/
@Override
public byte[] getData(int version) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = baos;
SWFOutputStream sos = new SWFOutputStream(os, version);
try {
sos.writeUI32(textureID);
sos.writeUI16(textureFormat);
byte fileNameBytes[] = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeUI16(textureWidth);
sos.writeUI16(textureHeight);
sos.writeUI8(padPixels);
sos.writeUI16(nominalGlyphSz);
sos.writeUI16(texGlyphs.length);
for (int i = 0; i < texGlyphs.length; i++) {
texGlyphs[i].write(sos);
}
sos.writeUI16(fonts.length);
for (int i = 0; i < fonts.length; i++) {
fonts[i].write(sos);
}
} catch (IOException e) {
}
return baos.toByteArray();
}
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos
* @throws IOException
*/
public GFxFontTextureInfo(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "FontTextureInfo", data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
textureID = sis.readUI32();
textureFormat = sis.readUI16();
int fileNameLen = sis.readUI8();
fileName = new String(sis.readBytes(fileNameLen));
textureWidth = sis.readUI16();
textureHeight = sis.readUI16();
padPixels = sis.readUI8();
nominalGlyphSz = sis.readUI16();
int numTexGlyphs = sis.readUI16();
texGlyphs = new TEXGLYPH[numTexGlyphs];
for (int i = 0; i < numTexGlyphs; i++) {
texGlyphs[i] = new TEXGLYPH(new GFxInputStream(sis));
}
int numFonts = sis.readUI16();
fonts = new FONTINFO[numFonts];
for (int i = 0; i < numFonts; i++) {
fonts[i] = new FONTINFO(new GFxInputStream(sis));
}
}
}
@@ -61,7 +61,7 @@ public class TagStub extends Tag {
* @throws IOException
*/
public TagStub(SWF swf, byte[] data, int version, long pos) throws IOException {
super(swf, ID, "", data, pos);
super(swf, ID, "" /*TODO:Insert name here*/, data, pos);
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version);
}
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.types;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.NeedsCharacters;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.List;
@@ -53,8 +54,8 @@ public class SHAPE implements NeedsCharacters {
return SHAPERECORD.shapeToSVG(shapeNum, null, null, numFillBits, numLineBits, shapeRecords);
}
public BufferedImage toImage(int shapeNum, List<Tag> tags) {
return SHAPERECORD.shapeToImage(tags, shapeNum, null, null,/* numFillBits, numLineBits, */ shapeRecords);
public BufferedImage toImage(int shapeNum, List<Tag> tags, Color defaultColor) {
return SHAPERECORD.shapeToImage(tags, shapeNum, null, null,/* numFillBits, numLineBits, */ shapeRecords, defaultColor);
}
public RECT getBounds() {
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class ContourType {
public int moveToX;
public int moveToY;
public EdgeType[] edges;
public boolean isReference;
public long reference;
public ContourType(GFxInputStream sis) throws IOException {
moveToX = sis.readSI15();
moveToY = sis.readSI15();
long numEdgesRef = sis.readUI30();
isReference = (numEdgesRef & 1) == 1;
numEdgesRef = numEdgesRef >> 1;
long oldPos = sis.getPos();
if (isReference) {
sis.setPos(numEdgesRef);
numEdgesRef = sis.readUI30();
numEdgesRef = numEdgesRef >> 1;
}
edges = new EdgeType[(int) numEdgesRef];
for (int i = 0; i < edges.length; i++) {
edges[i] = new EdgeType(sis);
}
if (isReference) {
sis.setPos(oldPos);
}
}
public List<SHAPERECORD> toSHAPERECORDS() {
int multiplier = 20;
List<SHAPERECORD> recs = new ArrayList<>();
StyleChangeRecord src = new StyleChangeRecord();
src.stateMoveTo = true;
src.moveDeltaX = moveToX * multiplier;
src.moveDeltaY = moveToY * multiplier;
recs.add(src);
for (EdgeType e : edges) {
recs.add(e.toSHAPERECORD());
}
return recs;
}
public void write(SWFOutputStream sos) throws IOException {
}
}
@@ -0,0 +1,267 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class EdgeType {
private static final int sizes[] = new int[]{1, 2, 1, 2, 1, 2, 3, 4, 2, 3, 4, 5, 6, 7, 8, 9};
private static final int Edge_H12 = 0; // 2 bytes
private static final int Edge_H20 = 1; // 3 bytes
private static final int Edge_V12 = 2; // 2 bytes
private static final int Edge_V20 = 3; // 3 bytes
private static final int Edge_L6 = 4; // 2 bytes
private static final int Edge_L10 = 5; // 3 bytes
private static final int Edge_L14 = 6; // 4 bytes
private static final int Edge_L18 = 7; // 5 bytes
private static final int Edge_C5 = 8; // 3 bytes
private static final int Edge_C7 = 9; // 4 bytes
private static final int Edge_C9 = 10; // 5 bytes
private static final int Edge_C11 = 11; // 6 bytes
private static final int Edge_C13 = 12; // 7 bytes
private static final int Edge_C15 = 13; // 8 bytes
private static final int Edge_C17 = 14; // 9 bytes
private static final int Edge_C19 = 15; // 10 bytes
private static final int Edge_HLine = 0;
private static final int Edge_VLine = 1;
private static final int Edge_Line = 2;
private static final int Edge_Quad = 3;
public int data[];
public byte raw[];
@Override
public String toString() {
String ret = "[Edge " + (raw[0] & 0xf) + " data:";
for (int i = 0; i < data.length; i++) {
if (i > 0) {
ret += ", ";
}
ret += "" + data[i];
}
ret += " raw: 0x";
for (int i = 0; i < raw.length; i++) {
if (i > 0) {
ret += "";
}
String h = Integer.toHexString(raw[i] & 0xff);
if (h.length() < 2) {
h = "0" + h;
}
ret += "" + h;
}
ret += "]";
return ret;
}
public EdgeType(GFxInputStream sis) throws IOException {
data = readEdge(sis);
/*if((raw[0]&0xf) == Edge_V20){
data[1] = 0;
}
if((raw[0]&0xf) == Edge_C17){
//System.out.println("========== 17 : "+toString()) ;
data[1] = 0;
data[2] = 0;
data[3] = 0;
data[4] = 0;
}*/
}
private byte[] readRawEdge(GFxInputStream sis) throws IOException {
int firstByte = sis.readUI8();
int nb = sizes[firstByte & 0xF];
byte ret[] = new byte[1 + nb];
ret[0] = (byte) firstByte;
int i;
for (i = 0; i < nb; i++) {
ret[i + 1] = (byte) sis.readUI8();
}
return ret;
}
private static int SInt8(int val) {
/*boolean sign = (val & 0x80) == 0x80;
val = val & 0x7F;
if (sign) {
val = -val;
}
return val;*/
return (byte) val;
}
public SHAPERECORD toSHAPERECORD() {
int multiplier = 20;
StraightEdgeRecord ser;
CurvedEdgeRecord cer;
switch (data[0]) {
case Edge_HLine:
ser = new StraightEdgeRecord();
ser.generalLineFlag = false;
ser.deltaX = data[1] * multiplier;
return ser;
case Edge_VLine:
ser = new StraightEdgeRecord();
ser.generalLineFlag = false;
ser.vertLineFlag = true;
ser.deltaY = data[1] * multiplier;
return ser;
case Edge_Line:
ser = new StraightEdgeRecord();
ser.generalLineFlag = true;
ser.deltaX = data[1] * multiplier;
ser.deltaY = data[2] * multiplier;
return ser;
case Edge_Quad:
cer = new CurvedEdgeRecord();
cer.controlDeltaX = data[1] * multiplier;
cer.controlDeltaY = data[2] * multiplier;
cer.anchorDeltaX = data[3] * multiplier;
cer.anchorDeltaY = data[4] * multiplier;
return cer;
}
return null;
}
private int[] readEdge(GFxInputStream sis) throws IOException {
raw = readRawEdge(sis);
int data[] = new int[5];
switch (raw[0] & 0xF) {
case Edge_H12:
data[0] = Edge_HLine;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8(raw[1] & 0xff) << 4);
break;
case Edge_H20:
data[0] = Edge_HLine;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8(raw[2] & 0xff) << 12);
break;
case Edge_V12:
data[0] = Edge_VLine;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8(raw[1] & 0xff) << 4);
break;
case Edge_V20:
data[0] = Edge_VLine;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8(raw[2] & 0xff) << 12);
break;
case Edge_L6:
data[0] = Edge_Line;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8((raw[1] & 0xff) << 6) >> 2);
data[2] = SInt8(raw[1] & 0xff) >> 2;
break;
case Edge_L10:
data[0] = Edge_Line;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8((raw[1] & 0xff) << 2) << 2);
data[2] = ((raw[1] & 0xff) >> 6) | (SInt8((raw[2] & 0xff)) << 2);
break;
case Edge_L14:
data[0] = Edge_Line;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8((raw[2] & 0xff) << 6) << 6);
data[2] = ((raw[2] & 0xff) >> 2) | (SInt8((raw[3] & 0xff)) << 6);
break;
case Edge_L18:
data[0] = Edge_Line;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8((raw[2] & 0xff) << 2) << 10);
data[2] = ((raw[2] & 0xff) >> 6) | ((raw[3] & 0xff) << 2) | (SInt8((raw[4] & 0xff)) << 10);
break;
case Edge_C5:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8((raw[1] & 0xff) << 7) >> 3);
data[2] = SInt8((raw[1] & 0xff) << 2) >> 3;
data[3] = ((raw[1] & 0xff) >> 6) | (SInt8((raw[2] & 0xff) << 5) >> 3);
data[4] = SInt8((raw[2] & 0xff)) >> 3;
break;
case Edge_C7:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8((raw[1] & 0xff) << 5) >> 1);
data[2] = ((raw[1] & 0xff) >> 3) | (SInt8((raw[2] & 0xff) << 6) >> 1);
data[3] = ((raw[2] & 0xff) >> 2) | (SInt8((raw[3] & 0xff) << 7) >> 1);
data[4] = SInt8(raw[3]) >> 1;
break;
case Edge_C9:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8((raw[1] & 0xff) << 3) << 1);
data[2] = ((raw[1] & 0xff) >> 5) | (SInt8((raw[2] & 0xff) << 2) << 1);
data[3] = ((raw[2] & 0xff) >> 6) | (SInt8((raw[3] & 0xff) << 1) << 1);
data[4] = ((raw[3] & 0xff) >> 7) | (SInt8(raw[4] & 0xff) << 1);
break;
case Edge_C11:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | (SInt8((raw[1] & 0xff) << 1) << 3);
data[2] = (raw[1] >> 7) | ((raw[2] & 0xff) << 1) | (SInt8((raw[3] & 0xff) << 6) << 3);
data[3] = ((raw[3] & 0xff) >> 2) | (SInt8((raw[4] & 0xff) << 3) << 3);
data[4] = ((raw[4] & 0xff) >> 5) | (SInt8(raw[5] & 0xff) << 3);
break;
case Edge_C13:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8((raw[2] & 0xff) << 7) << 5);
data[2] = ((raw[2] & 0xff) >> 1) | (SInt8((raw[3] & 0xff) << 2) << 5);
data[3] = ((raw[3] & 0xff) >> 6) | ((raw[4] & 0xff) << 2) | (SInt8((raw[5] & 0xff) << 5) << 5);
data[4] = ((raw[5] & 0xff) >> 3) | (SInt8(raw[6] & 0xff) << 5);
break;
case Edge_C15:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8((raw[2] & 0xff) << 5) << 7);
data[2] = ((raw[2] & 0xff) >> 3) | ((raw[3] & 0xff) << 5) | (SInt8((raw[4] & 0xff) << 6) << 7);
data[3] = ((raw[4] & 0xff) >> 2) | ((raw[5] & 0xff) << 6) | (SInt8((raw[6] & 0xff) << 7) << 7);
data[4] = ((raw[6] & 0xff) >> 1) | (SInt8((raw[7] & 0xff)) << 7);
break;
case Edge_C17:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8((raw[2] & 0xff) << 3) << 9);
data[2] = ((raw[2] & 0xff) >> 5) | ((raw[3] & 0xff) << 3) | (SInt8((raw[4] & 0xff) << 2) << 9);
data[3] = ((raw[4] & 0xff) >> 6) | ((raw[5] & 0xff) << 2) | (SInt8((raw[6] & 0xff) << 1) << 9);
data[4] = ((raw[6] & 0xff) >> 7) | ((raw[7] & 0xff) << 1) | (SInt8(raw[8] & 0xff) << 9);
break;
case Edge_C19:
data[0] = Edge_Quad;
data[1] = ((raw[0] & 0xff) >> 4) | ((raw[1] & 0xff) << 4) | (SInt8(raw[2] << 1) << 11);
data[2] = ((raw[2] & 0xff) >> 7) | ((raw[3] & 0xff) << 1) | ((raw[4] & 0xff) << 9) | (SInt8(raw[5] << 6) << 11);
data[3] = ((raw[5] & 0xff) >> 2) | ((raw[6] & 0xff) << 6) | (SInt8(raw[7] << 3) << 11);
data[4] = ((raw[7] & 0xff) >> 5) | ((raw[8] & 0xff) << 3) | (SInt8(raw[9]) << 11);
break;
}
return data;
}
public void write(SWFOutputStream sos) throws IOException {
}
}
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class FONTINFO {
public int fontId;
public GLYPHIDX glyphIndices[];
public FONTINFO(int fontId, int numGlyphs, GLYPHIDX[] glyphIndices) {
this.fontId = fontId;
this.glyphIndices = glyphIndices;
}
public FONTINFO(GFxInputStream sis) throws IOException {
fontId = sis.readUI16();
int numGlyphs = sis.readUI16();
glyphIndices = new GLYPHIDX[numGlyphs];
for (int i = 0; i < numGlyphs; i++) {
glyphIndices[i] = new GLYPHIDX(sis);
}
}
public void write(SWFOutputStream sos) throws IOException {
sos.writeUI16(fontId);
sos.writeUI16(glyphIndices.length);
for (int i = 0; i < glyphIndices.length; i++) {
glyphIndices[i].write(sos);
}
}
}
@@ -0,0 +1,90 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.types.SHAPE;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class FontType {
public static final int FF_Italic = 0x0001;
public static final int FF_Bold = 0x0002;
public String fontName;
public int flags;
public int nominalSize;
public int ascent;
public int descent;
public int leading;
public GlyphType[] glyphs;
public GlyphInfoType[] glyphInfo;
public KerningPairType[] kerning;
public FontType(GFxInputStream sis) throws IOException {
sis = new GFxInputStream(sis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//fontId = sis.readUI16();
int val;
while ((val = sis.readUI8()) > 0) {
baos.write(val);
}
fontName = new String(baos.toByteArray());
flags = sis.readUI16();
nominalSize = sis.readUI16();
ascent = sis.readSI16();
descent = sis.readSI16();
leading = sis.readSI16();
long numGlyphs = sis.readUI32();
long glyphBytesLen = sis.readUI32();
byte glyphBytes[] = new byte[(int) glyphBytesLen];
sis.read(glyphBytes);
glyphInfo = new GlyphInfoType[(int) numGlyphs];
for (int i = 0; i < numGlyphs; i++) {
glyphInfo[i] = new GlyphInfoType(sis);
}
long kerningTableSize = sis.readUI30();
kerning = new KerningPairType[((int) kerningTableSize)];
for (int i = 0; i < kerningTableSize; i++) {
kerning[i] = new KerningPairType(sis);
}
glyphs = new GlyphType[glyphInfo.length];
for (int i = 0; i < glyphInfo.length; i++) {
sis.setPos(glyphInfo[i].globalOffset);
glyphs[i] = new GlyphType(sis);
}
}
public List<SHAPE> getGlyphShapes() {
List<SHAPE> ret = new ArrayList<>();
for (GlyphType g : glyphs) {
ret.add(g.toSHAPE());
}
return ret;
}
public void write(SWFOutputStream sos) throws IOException {
}
}
@@ -0,0 +1,163 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.helpers.ReReadableInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class GFxInputStream extends InputStream {
private ReReadableInputStream is;
private static final int MaxUInt7 = (1 << 7) - 1;
public GFxInputStream(InputStream is) {
this.is = new ReReadableInputStream(is);
}
@Override
public int available() throws IOException {
return is.available();
}
public void setPos(long pos) throws IOException {
is.setPos(pos);
}
public long getPos() {
return is.getPos();
}
@Override
public int read() throws IOException {
return is.read();
}
public int readUI8() throws IOException {
return read();
}
public int readUI16() throws IOException {
return read() + (read() << 8);
}
/**
* Reads one SI16 (Signed 16bit integer) value from the stream
*
* @return SI16 value
* @throws IOException
*/
public int readSI16() throws IOException {
int uval = read() + (read() << 8);
if (uval >= 0x8000) {
return -(((~uval) & 0xffff) + 1);
} else {
return uval;
}
}
public long readUI32() throws IOException {
return (read() + (read() << 8) + (read() << 16) + (read() << 24)) & 0xffffffff;
}
public long readUI30() throws IOException {
long v;
int tb = readUI8();
long t = tb;
switch (tb & 3) {
case 0:
v = t >> 2;
return v;
case 1:
t = t >> 2;
v = t | (readUI8() << 6);
return v;
case 2:
t = t >> 2;
t = t | (readUI8() << 6);
v = t | (readUI8() << 14);
return v;
}
t = t >> 2;
t = t | (readUI8() << 6);
t = t | (readUI8() << 14);
v = t | (readUI8() << 22);
return v;
}
public float readFLOAT() throws IOException {
int val = (int) readUI32();
float ret = Float.intBitsToFloat(val);
return ret;
}
public int readSI8() throws IOException {
int uval = read();
if (uval >= 0x80) {
return -(((~uval) & 0xff) + 1);
} else {
return uval;
}
}
public int readSI15() throws IOException {
int t = readSI8();
int v;
if ((t & 1) == 0) {
v = t >> 1;
return v;
}
t = ((t >> 1) & MaxUInt7);
v = (t | (readSI8() << 7));
return v;
}
public int readUI15() throws IOException {
int t = readUI8();
int v;
if ((t & 1) == 0) {
v = t >> 1;
return v;
}
t = (t >> 1);
v = (t | (readUI8() << 7));
return v;
}
/**
* Reads bytes from the stream
*
* @param count Number of bytes to read
* @return Array of read bytes
* @throws IOException
*/
public byte[] readBytes(long count) throws IOException {
if (count <= 0) {
return new byte[0];
}
byte[] ret = new byte[(int) count];
for (int i = 0; i < count; i++) {
ret[i] = (byte) read();
}
return ret;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class GLYPHIDX {
public int indexInFont;
public int indexInTexture;
public GLYPHIDX(int indexInFont, int indexInTexture) {
this.indexInFont = indexInFont;
this.indexInTexture = indexInTexture;
}
public GLYPHIDX(GFxInputStream sis) throws IOException {
this.indexInFont = sis.readUI16();
this.indexInTexture = sis.readUI16();
}
public void write(SWFOutputStream sos) throws IOException {
sos.writeUI16(indexInFont);
sos.writeUI16(indexInTexture);
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class GlyphInfoType {
public int glyphCode;
public int advanceX;
public long globalOffset;
public GlyphInfoType(int glyphCode, int advance, int glyphPos) {
this.glyphCode = glyphCode;
this.advanceX = advance;
this.globalOffset = glyphPos;
}
public GlyphInfoType(GFxInputStream sis) throws IOException {
this.glyphCode = sis.readUI16();
this.advanceX = sis.readSI16();
this.globalOffset = sis.readUI32();
}
public void write(SWFOutputStream sos) throws IOException {
sos.writeUI16(glyphCode);
sos.writeSI16(advanceX);
sos.writeUI32(globalOffset);
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class GlyphType {
public int[] boundingBox;
public ContourType[] contours;
public GlyphType(GFxInputStream sis) throws IOException {
boundingBox = new int[4];
for (int i = 0; i < 4; i++) {
boundingBox[i] = sis.readSI15();
}
int numContours = sis.readUI15();
contours = new ContourType[numContours];
for (int i = 0; i < numContours; i++) {
contours[i] = new ContourType(sis);
}
}
public SHAPE toSHAPE() {
SHAPE shp = new SHAPE();
shp.numFillBits = 1;
shp.numLineBits = 1;
List<SHAPERECORD> recs = new ArrayList<>();
StyleChangeRecord scr = new StyleChangeRecord();
scr.fillStyle0 = 1;
scr.stateFillStyle0 = true;
recs.add(scr);
for (ContourType cnt : contours) {
recs.addAll(cnt.toSHAPERECORDS());
}
shp.shapeRecords = recs;
return shp;
}
public void write(SWFOutputStream sos) throws IOException {
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class KerningPairType {
public int char1;
public int char2;
public int advance;
public KerningPairType(int char1, int char2, int advance) {
this.char1 = char1;
this.char2 = char2;
this.advance = advance;
}
public KerningPairType(GFxInputStream sis) throws IOException {
this.char1 = sis.readUI16();
this.char2 = sis.readUI16();
this.advance = sis.readSI16();
}
public void write(SWFOutputStream sos) throws IOException {
sos.writeUI16(char1);
sos.writeUI16(char2);
sos.writeSI16(advance);
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types.gfx;
import com.jpexs.decompiler.flash.SWFOutputStream;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class TEXGLYPH {
public float uvBoundsLeft;
public float uvBoundsTop;
public float uvBoundsRight;
public float uvBoundsBottom;
public float uvOriginX;
public float uvOriginY;
public TEXGLYPH(float uvBoundsLeft, float uvBoundsTop, float uvBoundsRight, float uvBoundsBottom, float uvOriginX, float uvOriginY) {
this.uvBoundsLeft = uvBoundsLeft;
this.uvBoundsTop = uvBoundsTop;
this.uvBoundsRight = uvBoundsRight;
this.uvBoundsBottom = uvBoundsBottom;
this.uvOriginX = uvOriginX;
this.uvOriginY = uvOriginY;
}
public TEXGLYPH(GFxInputStream sis) throws IOException {
this.uvBoundsLeft = sis.readFLOAT();
this.uvBoundsTop = sis.readFLOAT();
this.uvBoundsRight = sis.readFLOAT();
this.uvBoundsBottom = sis.readFLOAT();
this.uvOriginX = sis.readFLOAT();
this.uvOriginY = sis.readFLOAT();
}
public void write(SWFOutputStream sos) throws IOException {
sos.writeFLOAT(uvBoundsLeft);
sos.writeFLOAT(uvBoundsTop);
sos.writeFLOAT(uvBoundsRight);
sos.writeFLOAT(uvBoundsBottom);
sos.writeFLOAT(uvOriginX);
sos.writeFLOAT(uvOriginY);
}
}
@@ -36,6 +36,7 @@ import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.LinearGradientPaint;
@@ -74,7 +75,7 @@ import javax.swing.JPanel;
*/
public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
private static final float DESCALE = 20; //20
private static final float DESCALE = 20;
@Override
public Set<Integer> getNeededCharacters() {
@@ -838,6 +839,46 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters {
return ret;
}
public static BufferedImage shapeListToImage(List<SHAPE> shapes, int prevWidth, int prevHeight, Color color) {
BufferedImage ret = new BufferedImage(prevWidth, prevHeight, BufferedImage.TYPE_INT_ARGB);
Graphics g = ret.getGraphics();
int p = 0;
List<BufferedImage> images = new ArrayList<>();
for (SHAPE s : shapes) {
images.add(s.toImage(1, new ArrayList<Tag>(), color));
}
int cols = (int) Math.ceil(Math.sqrt(images.size()));
int pos = 0;
int w2 = prevWidth / cols;
int h2 = prevHeight / cols;
loopy:
for (int y = 0; y < cols; y++) {
for (int x = 0; x < cols; x++) {
if (pos >= images.size()) {
break loopy;
}
int w1 = images.get(pos).getWidth();
int h1 = images.get(pos).getHeight();
int h = h1 * w2 / w1;
int w;
if (h > h2) {
w = w1 * h2 / h1;
h = h2;
} else {
w = w2;
}
int px = x * w2 + w2 / 2 - w / 2;
int py = y * h2 + h2 / 2 - h / 2;
g.drawImage(images.get(pos), px, py, px + w, py + h, 0, 0, w1, h1, null);
pos++;
}
}
return ret;
}
public static BufferedImage shapeToImage(List<Tag> tags, int shapeNum, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStylesList, List<SHAPERECORD> records, Color defaultColor) {
String key = "shape_" + records.hashCode() + "_" + (defaultColor == null ? "null" : defaultColor.hashCode());
if (cache.contains(key)) {