better Flash player integration using JavactiveX library

Issue #701 TTF file import/replace - still needs locales, better integration
Issue #702 Fixed GFX font export size
This commit is contained in:
Jindra Petřík
2014-10-22 08:22:36 +02:00
parent af29b2b4b2
commit d841b374c2
19 changed files with 262 additions and 540 deletions

View File

@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.RetryTask;
import com.jpexs.decompiler.flash.RunnableIOEx;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.exporters.modes.FontExportMode;
import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
import com.jpexs.decompiler.flash.exporters.shape.PathExporter;
@@ -108,9 +109,12 @@ public class FontExporter {
return new byte[0];
}
public void exportFont(final FontTag t, FontExportMode mode, File file) throws IOException {
public void exportFont(FontTag ft, FontExportMode mode, File file) throws IOException {
final FontTag t = ft.toClassicFont();
List<SHAPE> shapes = t.getGlyphShapeTable();
final double divider = t.getDivider();
File ttfFile = file;
if (mode == FontExportMode.WOFF) {
@@ -122,9 +126,10 @@ public class FontExporter {
f.getEngine().setCopyrightYear(cop == null ? "" : cop);
f.setAuthor(ApplicationInfo.shortApplicationVerName);
f.setVersion("1.0");
f.setAscender(t.getAscent() / t.getDivider());
f.setDescender(t.getDescent() / t.getDivider());
f.setVersion("1.0");
f.setAscender(Math.round(t.getAscent() / divider));
f.setDescender(Math.round(t.getDescent() / divider));
for (int i = 0; i < shapes.size(); i++) {
SHAPE s = shapes.get(i);
@@ -132,11 +137,11 @@ public class FontExporter {
PathExporter seb = new PathExporter(s, new ColorTransform()) {
private double transformX(double x) {
return Math.ceil((double) (x / t.getDivider()));
return Math.ceil((double) (x / divider));
}
private double transformY(double y) {
return -Math.ceil((double) (y / t.getDivider()));
return -Math.ceil((double) (y / divider));
}
List<FPoint> path = new ArrayList<>();
@@ -178,9 +183,9 @@ public class FontExporter {
final FGlyph g = f.addGlyph(c);
double adv = t.getGlyphAdvance(i);
if (adv != -1) {
g.setAdvanceWidth((int) adv);
g.setAdvanceWidth((int) Math.round(adv / divider));
} else {
g.setAdvanceWidth(t.getGlyphWidth(i) / t.getDivider() + 100);
g.setAdvanceWidth((int)Math.round(t.getGlyphWidth(i) / divider + 100));
}
for (FPoint[] cnt : contours) {
if (cnt.length == 0) {

View File

@@ -260,7 +260,7 @@ public class DefineEditTextTag extends TextTag {
char firstChar = size.charAt(0);
if (firstChar != '+' && firstChar != '-') {
int fontSize = Integer.parseInt(size);
style.fontHeight = fontSize * (style.font == null ? 1 : style.font.getDivider());
style.fontHeight = (int)Math.round(fontSize * (style.font == null ? 1 : style.font.getDivider()));
style.fontLeading = leading;
} else {
// todo: parse relative sizes
@@ -824,7 +824,7 @@ public class DefineEditTextTag extends TextTag {
kerningAdjustment = font.getGlyphKerningAdjustment(ge.glyphIndex, font.charToGlyph(nextChar));
kerningAdjustment /= font.getDivider();
}
advance = (int) Math.round(font.getDivider() * Math.round((double) lastStyle.fontHeight * (font.getGlyphAdvance(ge.glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0)));
advance = (int) Math.round(Math.round((double) lastStyle.fontHeight * (font.getGlyphAdvance(ge.glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0)));
} else {
String fontName = FontTag.defaultFontName;
int fontStyle = font == null ? 0 : font.getFontStyle();

View File

@@ -97,6 +97,14 @@ public class DefineFont2Tag extends FontTag {
return glyphShapeTable.get(glyphIndex).getBounds().getWidth();
}
@Override
public RECT getGlyphBounds(int glyphIndex) {
return fontBoundsTable.get(glyphIndex);
}
@Override
public double getGlyphAdvance(int glyphIndex) {
if (fontFlagsHasLayout) {
@@ -340,7 +348,7 @@ public class DefineFont2Tag extends FontTag {
}
@Override
public int getDivider() {
public double getDivider() {
return 1;
}
@@ -369,10 +377,10 @@ public class DefineFont2Tag extends FontTag {
}
@Override
public void addCharacter(char character, String fontName) {
public void addCharacter(char character, Font font) {
int fontStyle = getFontStyle();
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character);
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, fontStyle, (int)Math.round(getDivider() * 1024), character);
int code = (int) character;
int pos = -1;

View File

@@ -95,7 +95,7 @@ public class DefineFont3Tag extends FontTag {
@Override
public double getGlyphAdvance(int glyphIndex) {
if (fontFlagsHasLayout && glyphIndex != -1) {
return fontAdvanceTable.get(glyphIndex) / SWF.unitDivisor;
return fontAdvanceTable.get(glyphIndex);
} else {
return -1;
}
@@ -334,7 +334,7 @@ public class DefineFont3Tag extends FontTag {
}
@Override
public int getDivider() {
public double getDivider() {
return 20;
}
@@ -363,7 +363,7 @@ public class DefineFont3Tag extends FontTag {
}
@Override
public void addCharacter(char character, String fontName) {
public void addCharacter(char character, Font font) {
//Font Align Zones will be removed as adding new character zones is not supported:-(
for (int i = 0; i < swf.tags.size(); i++) {
@@ -377,7 +377,7 @@ public class DefineFont3Tag extends FontTag {
}
}
int fontStyle = getFontStyle();
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, getDivider() * 1024, character);
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, fontStyle, (int)Math.round(getDivider() * 1024), character);
int code = (int) character;
int pos = -1;
boolean exists = false;
@@ -433,6 +433,13 @@ public class DefineFont3Tag extends FontTag {
return fontFlagsHasLayout;
}
@Override
public RECT getGlyphBounds(int glyphIndex) {
return fontBoundsTable.get(glyphIndex);
}
@Override
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
if (glyphIndex == -1 || nextGlyphIndex == -1) {

View File

@@ -20,11 +20,13 @@ import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.helpers.ByteArrayRange;
import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -260,13 +262,13 @@ public class DefineFontTag extends FontTag {
}
@Override
public int getDivider() {
public double getDivider() {
return 1;
}
@Override
public void addCharacter(char character, String fontName) {
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, getFontStyle(), getDivider() * 1024, character);
public void addCharacter(char character, Font font) {
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, getFontStyle(), (int)Math.round(getDivider() * 1024), character);
List<Integer> codeTable = new ArrayList<>();
ensureFontInfo();
if (fontInfoTag != null) {
@@ -322,4 +324,5 @@ public class DefineFontTag extends FontTag {
public int getGlyphKerningAdjustment(int glyphIndex, int nextGlyphIndex) {
return 0;
}
}

View File

@@ -389,7 +389,7 @@ public class DefineText2Tag extends TextTag {
if (nextChar != null) {
kerningAdjustment = font.getGlyphKerningAdjustment(tr.glyphEntries[i].glyphIndex, font.charToGlyph(nextChar));
}
advance = (int) Math.round(font.getDivider() * ((double) textHeight * font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0));
advance = (int) Math.round(((double) textHeight * (font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex) + kerningAdjustment)) / (font.getDivider() * 1024.0));
} else {
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
}

View File

@@ -395,7 +395,7 @@ public class DefineTextTag extends TextTag {
if (nextChar != null) {
kerningAdjustment = font.getGlyphKerningAdjustment(tr.glyphEntries[i].glyphIndex, font.charToGlyph(nextChar));
}
advance = (int) Math.round(font.getDivider() * ((double) textHeight * font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex) + kerningAdjustment) / (font.getDivider() * 1024.0));
advance = (int) Math.round(((double) textHeight * (font.getGlyphAdvance(tr.glyphEntries[i].glyphIndex + kerningAdjustment))) / (font.getDivider() * 1024.0));
} else {
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
}

View File

@@ -22,18 +22,29 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
import com.jpexs.decompiler.flash.helpers.FontHelper;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.DefineFontNameTag;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
import com.jpexs.decompiler.flash.types.KERNINGRECORD;
import com.jpexs.decompiler.flash.types.LANGCODE;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import com.jpexs.decompiler.flash.types.gfx.FontType;
import com.jpexs.decompiler.flash.types.gfx.GlyphInfoType;
import com.jpexs.decompiler.flash.types.gfx.GlyphType;
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 com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.SerializableImage;
import java.awt.Color;
import java.awt.Font;
@@ -43,11 +54,15 @@ import java.awt.font.FontRenderContext;
import java.awt.font.GlyphMetrics;
import java.awt.font.GlyphVector;
import java.awt.geom.Area;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
@@ -65,7 +80,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
public abstract List<SHAPE> getGlyphShapeTable();
public abstract void addCharacter(char character, String fontName);
public abstract void addCharacter(char character, Font font);
public abstract char glyphToChar(int glyphIndex);
@@ -97,7 +112,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
public abstract void setItalic(boolean value);
public abstract int getDivider();
public abstract double getDivider();
public abstract int getAscent();
@@ -338,4 +353,16 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
sb.append("\t}\r\n");
return sb.toString();
}
public RECT getGlyphBounds(int glyphIndex) {
return getGlyphShapeTable().get(glyphIndex).getBounds();
}
public FontTag toClassicFont() {
return this;
}
}

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags.base;
import java.awt.Font;
@@ -32,7 +33,7 @@ public class MissingCharacterHandler {
if (!f.canDisplay(character)) {
return false;
}
}
font.addCharacter(character, f);
return true;
}
}

View File

@@ -144,10 +144,12 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
}
@Override
public void addCharacter(char character, String fontName) {
public void addCharacter(char character, Font cfont) {
int fontStyle = getFontStyle();
FontType font = fonts.get(0);
SHAPE shp = SHAPERECORD.systemFontCharacterToSHAPE(fontName, fontStyle, (int) (SWF.unitDivisor * font.nominalSize), character);
double d = 1; //1024/font.nominalSize;
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(cfont, fontStyle, (int) (SWF.unitDivisor * font.nominalSize * d), character);
int code = (int) character;
int pos = -1;
@@ -169,7 +171,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
shiftGlyphIndices(fontId, pos);
}
Font fnt = new Font(fontName, fontStyle, font.nominalSize);
Font fnt = cfont.deriveFont(fontStyle, Math.round(font.nominalSize * d));
int advance = (int) Math.round(fnt.createGlyphVector((new JPanel()).getFontMetrics(fnt).getFontRenderContext(), "" + character).getGlyphMetrics(0).getAdvanceX());
if (!exists) {
font.glyphInfo.add(pos, new GlyphInfoType(code, advance, 0));
@@ -278,7 +280,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
}
@Override
public int getDivider() {
public double getDivider() {
return 1;
}
@@ -307,17 +309,13 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
return ret;
}
private int resizemultiplier() {
FontType ft = fonts.get(0);
return (int) Math.round(1024.0 / ft.nominalSize);
@Override
public RECT getGlyphBounds(int glyphIndex) {
GlyphType gt = fonts.get(0).glyphs.get(glyphIndex);
return new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3]));
}
private int resize(int val) {
int ret = val * resizemultiplier();
return ret;
}
private SHAPE resize(SHAPE shp) {
public SHAPE resizeShape(SHAPE shp) {
SHAPE ret = new SHAPE();
ret.numFillBits = 1;
ret.numLineBits = 0;
@@ -350,36 +348,39 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
return ret;
}
protected int resize(double val) {
FontType ft = fonts.get(0);
return (int) Math.round(val * 1024.0 / ft.nominalSize);
}
@Override
public FontTag toClassicFont() {
try {
DefineFont2Tag ret = new DefineFont2Tag(swf);
ret.fontId = fontId;
ret.fontId = getFontId();
ret.fontFlagsBold = isBold();
ret.fontFlagsItalic = isItalic();
ret.fontFlagsWideOffsets = true;
ret.fontFlagsWideCodes = true;
ret.fontFlagsHasLayout = true;
FontType ft = fonts.get(0);
ret.fontAscent = resize(ft.ascent);
ret.fontDescent = resize(ft.descent);
ret.fontLeading = resize(ft.leading);
ret.fontAscent = (getAscent());
ret.fontDescent = (getDescent());
ret.fontLeading = (getLeading());
ret.fontAdvanceTable = new ArrayList<>();
ret.fontBoundsTable = new ArrayList<>();
ret.codeTable = new ArrayList<>();
ret.glyphShapeTable = new ArrayList<>();
ret.numGlyphs = ft.glyphInfo.size();
SHAPE shpA = SHAPERECORD.systemFontCharacterToSHAPE("Times New Roman", 0, getDivider() * 1024, 'A');
for (GlyphInfoType gi : ft.glyphInfo) {
ret.fontAdvanceTable.add(resize(gi.advanceX));
ret.codeTable.add(gi.glyphCode);
}
List<SHAPE> shp = getGlyphShapeTable();
ret.numGlyphs = shp.size();
for (int g = 0; g < shp.size(); g++) {
ret.fontAdvanceTable.add(resize(getGlyphAdvance(g)));
ret.codeTable.add((int) glyphToChar(g));
for (GlyphType gt : ft.glyphs) {
SHAPE shpX = resize(gt.toSHAPE());
ret.glyphShapeTable.add(shpX); //
ret.fontBoundsTable.add(new RECT(resize(gt.boundingBox[0]), resize(gt.boundingBox[1]), resize(gt.boundingBox[2]), resize(gt.boundingBox[3])));
SHAPE shpX = resizeShape(shp.get(g));
ret.glyphShapeTable.add(shpX);
ret.fontBoundsTable.add(getGlyphBounds(g));
}
ret.fontName = ft.fontName;
ret.fontName = getFontName();
ret.languageCode = new LANGCODE(1);
ret.fontKerningTable = new KERNINGRECORD[0];/*new KERNINGRECORD[ft.kerning.size()];
for(int i=0;i<ft.kerning.size();i++){

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.types.shaperecords;
import com.jpexs.decompiler.flash.SWF;
@@ -233,13 +234,17 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
}
public static SHAPE systemFontCharacterToSHAPE(final String fontName, final int fontStyle, int fontSize, char character) {
return fontCharacterToSHAPE(new Font(FontTag.getFontNameWithFallback(fontName),Font.PLAIN,10), fontStyle, fontSize, character);
}
public static SHAPE fontCharacterToSHAPE(final Font font, final int fontStyle, int fontSize, char character) {
int multiplier = 1;
if (fontSize > 1024) {
multiplier = fontSize / 1024;
fontSize = 1024;
}
List<SHAPERECORD> retList = new ArrayList<>();
List<SHAPERECORD> retList = new ArrayList<>();
Font f = font.deriveFont(fontStyle, fontSize);
GlyphVector v = f.createGlyphVector((new JPanel()).getFontMetrics(f).getFontRenderContext(), "" + character);
Shape shp = v.getOutline();
double[] points = new double[6];