better font name handling

kerning moved to FontHelper
This commit is contained in:
Jindra Petřík
2014-10-26 12:36:56 +01:00
parent bcfb4a1c01
commit 093d17a055
24 changed files with 683 additions and 245 deletions

View File

@@ -271,8 +271,7 @@ public final class SWF implements TreeItem, Timelined {
public Map<Integer, CharacterTag> characters = new HashMap<>();
public List<ABCContainerTag> abcList;
public JPEGTablesTag jtt;
public Map<Integer, String> sourceFontFamiliesMap = new HashMap<>();
public Map<Integer, String> sourceFontFacesMap = new HashMap<>();
public Map<Integer, String> sourceFontNamesMap = new HashMap<>();
public static final double unitDivisor = 20;
private static final Logger logger = Logger.getLogger(SWF.class.getName());

View File

@@ -452,7 +452,7 @@ public class Configuration {
recentFiles.set(Helper.joinStrings(recentFilesArray, "::"));
}
public static Map<String, String> getFontIdToFamilyMap() {
public static Map<String, String> getFontToNameMap() {
String fonts = fontPairing.get();
if (fonts == null) {
return new HashMap<>();
@@ -467,39 +467,20 @@ public class Configuration {
}
return result;
}
public static Map<String, String> getFontIdToFaceMap() {
String fonts = fontPairing.get();
if (fonts == null) {
return new HashMap<>();
}
Map<String, String> result = new HashMap<>();
for (String pair : fonts.split("::")) {
if (!pair.isEmpty()) {
String[] splittedPair = pair.split("=");
result.put(splittedPair[0], splittedPair.length < 3 ? "" : splittedPair[2]);
}
}
return result;
}
public static void addFontPair(String fileName, int fontId, String fontName, String installedFontFamily, String installedFontFace) {
public static void addFontPair(String fileName, int fontId, String fontName, String installedName) {
String key = fileName + "_" + fontId + "_" + fontName;
Map<String, String> fontPairs = getFontIdToFamilyMap();
fontPairs.put(key, installedFontFamily);
fontPairs.put(fontName, installedFontFamily);
Map<String, String> fontPairs = getFontToNameMap();
fontPairs.put(key, installedName);
fontPairs.put(fontName, installedName);
Map<String, String> facePairs = getFontIdToFaceMap();
facePairs.put(key, installedFontFace);
facePairs.put(fontName, installedFontFace);
StringBuilder sb = new StringBuilder();
int i = 0;
for (Entry<String, String> pair : fontPairs.entrySet()) {
if (i != 0) {
sb.append("::");
}
sb.append(pair.getKey()).append("=").append(pair.getValue()).append("=").append(facePairs.containsKey(pair.getKey()) ? facePairs.get(pair.getKey()) : "");
sb.append(pair.getKey()).append("=").append(pair.getValue());
i++;
}
fontPairing.set(sb.toString());

View File

@@ -120,7 +120,7 @@ public class FontExporter {
ttfFile = File.createTempFile("ffdec_export", ".ttf");
}
Fontastic f = new Fontastic(t.getFontName(), ttfFile);
Fontastic f = new Fontastic(t.getFontNameIntag(), ttfFile);
String cop = t.getCopyright();
f.getEngine().setCopyrightYear(cop == null ? "" : cop);

View File

@@ -17,12 +17,26 @@
package com.jpexs.decompiler.flash.helpers;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.GraphicsEnvironment;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.TextAttribute;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.AttributedCharacterIterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.swing.JPanel;
/**
*
@@ -30,6 +44,11 @@ import java.util.Map;
*/
public class FontHelper {
private static Object getFontManager() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> clFmFactory = Class.forName("sun.font.FontManagerFactory");
return clFmFactory.getDeclaredMethod("getInstance").invoke(null);
}
/**
* Gets all available fonts in the system
*
@@ -40,24 +59,27 @@ public class FontHelper {
Font fonts[] = null;
try {
Class<?> clFmFactory = Class.forName("sun.font.FontManagerFactory");
Object fm = clFmFactory.getDeclaredMethod("getInstance").invoke(null);
Object fm = getFontManager();
Class<?> clFm = Class.forName("sun.font.SunFontManager");
//Delete cached installed names
Field inField = clFm.getDeclaredField("installedNames");
inField.setAccessible(true);
inField.set(null, null);
inField.setAccessible(false);
//Delete cached family names
Field allFamField = clFm.getDeclaredField("allFamilies");
allFamField.setAccessible(true);
allFamField.set(fm, null);
allFamField.setAccessible(false);
//Delete cached fonts
Field allFonField = clFm.getDeclaredField("allFonts");
allFonField.setAccessible(true);
allFonField.set(fm, null);
allFonField.setAccessible(false);
fonts = (Font[]) clFm.getDeclaredMethod("getAllInstalledFonts").invoke(fm);
} catch (Throwable ex) {
@@ -67,7 +89,7 @@ public class FontHelper {
fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
}
for (Font f : fonts) {
String fam = f.getFamily(Locale.getDefault());
String fam = f.getFamily(Locale.ENGLISH);
//Do not want Java logical fonts
if (Arrays.asList("Dialog", "DialogInput", "Monospaced", "Serif", "SansSerif").contains(fam)) {
continue;
@@ -75,21 +97,327 @@ public class FontHelper {
if (!ret.containsKey(fam)) {
ret.put(fam, new HashMap<String, Font>());
}
String face = getFontFace(f);
ret.get(f.getFamily()).put(face, f);
ret.get(fam).put(f.getFontName(Locale.ENGLISH), f);
}
return ret;
}
public static String getFontFace(Font f) {
String fam = f.getFamily(Locale.getDefault());
String face = f.getFontName(Locale.getDefault());
if (face.startsWith(fam)) {
face = face.substring(fam.length()).trim();
/**
* Gets kerning offset for two characters of the font
*
* @param font Font
* @param char1 First character
* @param char2 Second character
* @return offset
*/
public static int getFontCharsKerning(Font font, char char1, char char2) {
char[] chars = new char[]{char1, char2};
Map<AttributedCharacterIterator.Attribute, Object> withKerningAttrs = new HashMap<>();
withKerningAttrs.put(TextAttribute.FONT, font);
withKerningAttrs.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
Font withKerningFont = Font.getFont(withKerningAttrs);
GlyphVector withKerningVector = withKerningFont.layoutGlyphVector((new JPanel()).getFontMetrics(withKerningFont).getFontRenderContext(), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
int withKerningX = withKerningVector.getGlyphLogicalBounds(1).getBounds().x;
Map<AttributedCharacterIterator.Attribute, Object> noKerningAttrs = new HashMap<>();
noKerningAttrs.put(TextAttribute.FONT, font);
noKerningAttrs.put(TextAttribute.KERNING, 0);
Font noKerningFont = Font.getFont(noKerningAttrs);
GlyphVector noKerningVector = noKerningFont.layoutGlyphVector((new JPanel()).getFontMetrics(noKerningFont).getFontRenderContext(), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
int noKerningX = noKerningVector.getGlyphLogicalBounds(1).getBounds().x;
return withKerningX - noKerningX;
}
/**
* Gets all kerning pairs of a Font. It is very slow.
*
* @param font
* @param size
* @return
*/
public static List<KerningPair> getFontKerningPairs(Font font, int size) {
File fontFile = getFontFile(font);
if (fontFile != null && fontFile.getName().toLowerCase().endsWith(".ttf")) {
KerningLoader k = new KerningLoader();
try {
return k.loadFromTTF(fontFile, size);
} catch (IOException | FontFormatException ex) {
//ignore
}
}
if (face.startsWith(".")) {
face = face.substring(1);
List<KerningPair> ret = new ArrayList<>();
List<Character> availableChars = new ArrayList<>();
for (char c1 = 0; c1 < Character.MAX_VALUE; c1++) {
if (font.canDisplay((int) c1)) {
availableChars.add(c1);
}
}
for (char c1 : availableChars) {
ret.addAll(getFontKerningPairsOneChar(availableChars, font, c1));
}
return ret;
}
private static List<KerningPair> getFontKerningPairsOneChar(List<Character> availableChars, Font font, char firstChar) {
List<KerningPair> ret = new ArrayList<>();
char[] chars = new char[availableChars.size() * 2];
for (int i = 0; i < availableChars.size(); i++) {
chars[i * 2] = firstChar;
chars[i * 2 + 1] = availableChars.get(i);
}
Map<AttributedCharacterIterator.Attribute, Object> withKerningAttrs = new HashMap<>();
withKerningAttrs.put(TextAttribute.FONT, font);
withKerningAttrs.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
Font withKerningFont = Font.getFont(withKerningAttrs);
GlyphVector withKerningVector = withKerningFont.layoutGlyphVector((new JPanel()).getFontMetrics(withKerningFont).getFontRenderContext(), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
int withKerningX[] = new int[availableChars.size()];
for (int i = 0; i < availableChars.size(); i++) {
withKerningX[i] = withKerningVector.getGlyphLogicalBounds(i * 2 + 1).getBounds().x;
}
Map<AttributedCharacterIterator.Attribute, Object> noKerningAttrs = new HashMap<>();
noKerningAttrs.put(TextAttribute.FONT, font);
noKerningAttrs.put(TextAttribute.KERNING, 0);
Font noKerningFont = Font.getFont(noKerningAttrs);
GlyphVector noKerningVector = noKerningFont.layoutGlyphVector((new JPanel()).getFontMetrics(noKerningFont).getFontRenderContext(), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
for (int i = 0; i < availableChars.size(); i++) {
int noKerningX = noKerningVector.getGlyphLogicalBounds(i * 2 + 1).getBounds().x;
int kerning = withKerningX[i] - noKerningX;
if (kerning > 0) {
ret.add(new KerningPair(firstChar, availableChars.get(i), kerning));
}
}
return ret;
}
public static class KerningPair {
public char char1;
public char char2;
public int kerning;
public KerningPair(char char1, char char2, int kerning) {
this.char1 = char1;
this.char2 = char2;
this.kerning = kerning;
}
@Override
public int hashCode() {
int hash = 3;
hash = 67 * hash + this.char1;
hash = 67 * hash + this.char2;
hash = 67 * hash + this.kerning;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final KerningPair other = (KerningPair) obj;
if (this.char1 != other.char1) {
return false;
}
if (this.char2 != other.char2) {
return false;
}
if (this.kerning != other.kerning) {
return false;
}
return true;
}
@Override
public String toString() {
return "'" + char1 + "','" + char2 + "' => " + kerning;
}
}
private static Object getFont2d(Font f) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Object fm = getFontManager();
return Class.forName("sun.font.FontManager").getDeclaredMethod("findFont2D", String.class, int.class, int.class).invoke(fm, f.getFontName(), f.getStyle(), 2/*LOGICAL_FALLBACK*/);
}
public static File getFontFile(Font f) {
try {
Class pfClass = Class.forName("sun.font.PhysicalFont");
Field platName = pfClass.getDeclaredField("platName");
platName.setAccessible(true);
String fontPath = (String) platName.get(getFont2d(f));
platName.setAccessible(false);
return new File(fontPath);
} catch (Throwable e) {
return null;
}
}
private static Map<Integer, Character> getFontGlyphToCharMap(Font f) {
Map<Integer, Character> ret = new HashMap<>();
FontRenderContext frc = new FontRenderContext(null, true, false);
for (char i = 0; i < Character.MAX_VALUE; i++) {
if (f.canDisplay(i)) {
GlyphVector gv = f.createGlyphVector(frc, new char[]{i});
ret.put(gv.getGlyphCode(0), i);
}
}
return ret;
}
private static class KerningLoader {
private int size = -1;
private float scale;
private long bytePosition;
private long headOffset = -1;
private long kernOffset = -1;
private Font font;
private Map<Integer, Character> charmap;
public List<KerningPair> loadFromTTF(File file, int size) throws IOException, FontFormatException {
font = Font.createFont(Font.TRUETYPE_FONT, file);
charmap = getFontGlyphToCharMap(font);
InputStream input = new FileInputStream(file);
List<KerningPair> ret = new ArrayList<>();
this.size = size;
if (input == null) {
throw new IllegalArgumentException("input cannot be null.");
}
readTableDirectory(input);
if (headOffset == -1) {
throw new IOException("HEAD table not found.");
}
if (kernOffset == -1) {
return ret;
}
if (headOffset < kernOffset) {
readHEAD(input);
readKERN(input, ret);
} else {
readKERN(input, ret);
readHEAD(input);
}
input.close();
for (KerningPair kp : ret) {
kp.kerning *= scale;
}
return ret;
}
private void readTableDirectory(InputStream input) throws IOException {
skip(input, 4);
int tableCount = readUnsignedShort(input);
skip(input, 6);
byte[] tagBytes = new byte[4];
for (int i = 0; i < tableCount; i++) {
tagBytes[0] = readByte(input);
tagBytes[1] = readByte(input);
tagBytes[2] = readByte(input);
tagBytes[3] = readByte(input);
skip(input, 4);
long offset = readUnsignedLong(input);
skip(input, 4);
String tag = new String(tagBytes, "ISO-8859-1");
if (tag.equals("head")) {
headOffset = offset;
if (kernOffset != -1) {
break;
}
} else if (tag.equals("kern")) {
kernOffset = offset;
if (headOffset != -1) {
break;
}
}
}
}
private void readHEAD(InputStream input) throws IOException {
seek(input, headOffset + 2 * 4 + 2 * 4 + 2);
int unitsPerEm = readUnsignedShort(input);
scale = (float) size / unitsPerEm;
}
private void readKERN(InputStream input, List<KerningPair> ret) throws IOException {
seek(input, kernOffset + 2);
for (int subTableCount = readUnsignedShort(input); subTableCount > 0; subTableCount--) {
skip(input, 2 * 2);
int tupleIndex = readUnsignedShort(input);
if (!((tupleIndex & 1) != 0) || (tupleIndex & 2) != 0 || (tupleIndex & 4) != 0) {
return;
}
if (tupleIndex >> 8 != 0) {
continue;
}
int kerningCount = readUnsignedShort(input);
skip(input, 3 * 2);
while (kerningCount-- > 0) {
int firstGlyphCode = readUnsignedShort(input);
int secondGlyphCode = readUnsignedShort(input);
int offset = readShort(input);
ret.add(new KerningPair(charmap.get(firstGlyphCode), charmap.get(secondGlyphCode), offset));
}
}
}
private int readUnsignedByte(InputStream input) throws IOException {
bytePosition++;
int b = input.read();
if (b == -1) {
throw new EOFException("Unexpected end of file.");
}
return b;
}
private byte readByte(InputStream input) throws IOException {
return (byte) readUnsignedByte(input);
}
private int readUnsignedShort(InputStream input) throws IOException {
return (readUnsignedByte(input) << 8) + readUnsignedByte(input);
}
private short readShort(InputStream input) throws IOException {
return (short) readUnsignedShort(input);
}
private long readUnsignedLong(InputStream input) throws IOException {
long value = readUnsignedByte(input);
value = (value << 8) + readUnsignedByte(input);
value = (value << 8) + readUnsignedByte(input);
value = (value << 8) + readUnsignedByte(input);
return value;
}
private void skip(InputStream input, long skip) throws IOException {
while (skip > 0) {
long skipped = input.skip(skip);
if (skipped <= 0) {
break;
}
bytePosition += skipped;
skip -= skipped;
}
}
private void seek(InputStream input, long position) throws IOException {
skip(input, position - bytePosition);
}
return face;
}
}

View File

@@ -296,7 +296,7 @@ public class DefineFont2Tag extends FontTag {
}
@Override
public String getFontName() {
public String getFontNameIntag() {
String ret = fontName;
if (ret.contains("" + (char) 0)) {
ret = ret.substring(0, ret.indexOf(0));

View File

@@ -284,7 +284,7 @@ public class DefineFont3Tag extends FontTag {
}
@Override
public String getFontName() {
public String getFontNameIntag() {
String ret = fontName;
if (ret.contains("" + (char) 0)) {
ret = ret.substring(0, ret.indexOf(0));

View File

@@ -173,7 +173,7 @@ public class DefineFontTag extends FontTag {
}
@Override
public String getFontName() {
public String getFontNameIntag() {
ensureFontInfo();
if (fontInfo2Tag != null) {
return fontInfo2Tag.fontName;

View File

@@ -43,6 +43,7 @@ import java.awt.font.FontRenderContext;
import java.awt.font.GlyphMetrics;
import java.awt.font.GlyphVector;
import java.awt.geom.Area;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -76,7 +77,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
public abstract int getGlyphWidth(int glyphIndex);
public abstract String getFontName();
public abstract String getFontNameIntag();
public abstract boolean isSmall();
@@ -103,8 +104,25 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
public abstract int getDescent();
public abstract int getLeading();
public String getFontName(){
DefineFontNameTag fontNameTag = getFontNameTag();
if(fontNameTag == null){
return getFontNameIntag();
}
return fontNameTag.fontName;
}
public String getFontCopyright(){
DefineFontNameTag fontNameTag = getFontNameTag();
if(fontNameTag == null){
return "";
}
return fontNameTag.fontCopyright;
}
public static Map<String, Map<String, Font>> installedFonts;
public static Map<String, Map<String, Font>> installedFontsByFamily;
public static Map<String,Font> installedFontsByName;
public static String defaultFontName;
@@ -142,7 +160,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
if (className != null) {
nameAppend = ": " + className;
}
String fontName = getFontName();
String fontName = getFontNameIntag();
if (fontName != null) {
nameAppend = ": " + fontName;
}
@@ -150,12 +168,12 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
}
public String getSystemFontName() {
Map<String, String> fontPairs = Configuration.getFontIdToFamilyMap();
String key = swf.getShortFileName() + "_" + getFontId() + "_" + getFontName();
Map<String, String> fontPairs = Configuration.getFontToNameMap();
String key = swf.getShortFileName() + "_" + getFontId() + "_" + getFontNameIntag();
if (fontPairs.containsKey(key)) {
return fontPairs.get(key);
}
key = getFontName();
key = getFontNameIntag();
if (fontPairs.containsKey(key)) {
return fontPairs.get(key);
}
@@ -206,52 +224,59 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
}
public static void reload() {
installedFonts = FontHelper.getInstalledFonts();
if (installedFonts.containsKey("Times New Roman")) {
installedFontsByFamily = FontHelper.getInstalledFonts();
installedFontsByName = new HashMap<>();
for(String fam:installedFontsByFamily.keySet()){
for(String nam:installedFontsByFamily.get(fam).keySet()){
installedFontsByName.put(nam, installedFontsByFamily.get(fam).get(nam));
}
}
if (installedFontsByFamily.containsKey("Times New Roman")) {
defaultFontName = "Times New Roman";
} else if (installedFonts.containsKey("Arial")) {
} else if (installedFontsByFamily.containsKey("Arial")) {
defaultFontName = "Arial";
} else {
defaultFontName = installedFonts.keySet().iterator().next();
defaultFontName = installedFontsByFamily.keySet().iterator().next();
}
}
public static String getFontNameWithFallback(String fontName) {
if (installedFonts.containsKey(fontName)) {
if (installedFontsByFamily.containsKey(fontName)) {
return fontName;
}
if (installedFonts.containsKey("Times New Roman")) {
if (installedFontsByFamily.containsKey("Times New Roman")) {
return "Times New Roman";
}
if (installedFonts.containsKey("Arial")) {
if (installedFontsByFamily.containsKey("Arial")) {
return "Arial";
}
//First font
return installedFonts.keySet().iterator().next();
return installedFontsByFamily.keySet().iterator().next();
}
public static String isFontFamilyInstalled(String fontFamily) {
if (installedFonts.containsKey(fontFamily)) {
if (installedFontsByFamily.containsKey(fontFamily)) {
return fontFamily;
}
if (fontFamily.contains("_")) {
String beforeUnderscore = fontFamily.substring(0, fontFamily.indexOf('_'));
if (installedFonts.containsKey(beforeUnderscore)) {
if (installedFontsByFamily.containsKey(beforeUnderscore)) {
return beforeUnderscore;
}
}
return null;
}
public static String findInstalledFontFamily(String fontFamily) {
if (installedFonts.containsKey(fontFamily)) {
return fontFamily;
public static String findInstalledFontName(String fontName) {
if (installedFontsByName.containsKey(fontName)) {
return fontName;
}
if (fontFamily.contains("_")) {
String beforeUnderscore = fontFamily.substring(0, fontFamily.indexOf('_'));
if (installedFonts.containsKey(beforeUnderscore)) {
if (fontName.contains("_")) {
String beforeUnderscore = fontName.substring(0, fontName.indexOf('_'));
if (installedFontsByName.containsKey(beforeUnderscore)) {
return beforeUnderscore;
}
}
@@ -294,7 +319,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
@Override
public String getCharacterExportFileName() {
return super.getCharacterExportFileName() + "_" + getFontName();
return super.getCharacterExportFileName() + "_" + getFontNameIntag();
}
public DefineFontNameTag getFontNameTag() {

View File

@@ -26,11 +26,11 @@ import java.util.Map;
public class MissingCharacterHandler {
public boolean handle(FontTag font, char character) {
String fontName = font.getFontName();
if (!FontTag.installedFonts.containsKey(fontName)) {
String fontName = font.getFontNameIntag();
if (!FontTag.installedFontsByFamily.containsKey(fontName)) {
return false;
}
Map<String, Font> faces = FontTag.installedFonts.get(fontName);
Map<String, Font> faces = FontTag.installedFontsByFamily.get(fontName);
Font f = null;
for (String face : faces.keySet()) {

View File

@@ -143,7 +143,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
glyphs = font.getGlyphShapeTable();
if (!font.hasLayout()) {
String fontName = FontTag.getFontNameWithFallback(font.getFontName());
String fontName = FontTag.getFontNameWithFallback(font.getFontNameIntag());
aFont = new Font(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor));
fontMetrics = graphics.getFontMetrics(aFont);
LineMetrics lm = fontMetrics.getLineMetrics("A", graphics);
@@ -417,7 +417,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
Element textElement = exporter.createElement("text");
textElement.setAttribute("font-size", Double.toString(rat * 1024));
textElement.setAttribute("font-family", font.getFontName());
textElement.setAttribute("font-family", font.getFontNameIntag());
textElement.setAttribute("textLength", Double.toString(totalAdvance / SWF.unitDivisor));
textElement.setAttribute("lengthAdjust", "spacing");
textElement.setTextContent(text.toString());
@@ -432,7 +432,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
exporter.addToGroup(textElement);
FontExportMode fontExportMode = FontExportMode.WOFF;
exporter.addStyle(font.getFontName(), new FontExporter().exportFont(font, fontExportMode), fontExportMode);
exporter.addStyle(font.getFontNameIntag(), new FontExporter().exportFont(font, fontExportMode), fontExportMode);
if (hasOffset) {
exporter.endGroup();
@@ -458,7 +458,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
}
if (charId == null) {
charId = exporter.getUniqueId(Helper.getValidHtmlId("font_" + font.getFontName() + "_" + ch));
charId = exporter.getUniqueId(Helper.getValidHtmlId("font_" + font.getFontNameIntag() + "_" + ch));
exporter.createDefGroup(null, charId);
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, shape, exporter, null, colorTransform, zoom);
shapeExporter.export();

View File

@@ -117,7 +117,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
}
@Override
public String getFontName() {
public String getFontNameIntag() {
String ret = "";
for (int i = 0; i < fonts.size(); i++) {
if (i > 0) {
@@ -380,7 +380,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag {
ret.glyphShapeTable.add(shpX);
ret.fontBoundsTable.add(getGlyphBounds(g));
}
ret.fontName = getFontName();
ret.fontName = getFontNameIntag();
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,18 +12,14 @@
* 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;
import com.jpexs.decompiler.flash.helpers.FontHelper;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import java.awt.Font;
import java.awt.Font;
import java.awt.font.GlyphVector;
import java.io.Serializable;
import java.io.Serializable;
import java.text.AttributedCharacterIterator;
import java.util.HashMap;
import java.util.Map;
/**
* Represents 24-bit red, green, blue value
@@ -58,48 +54,10 @@ public class KERNINGRECORD implements Serializable {
public KERNINGRECORD(Font font, char char1, char char2) {
fontKerningCode1 = char1;
fontKerningCode2 = char2;
fontKerningCode2 = char2;
fontKerningAdjustment = FontHelper.getFontCharsKerning(font, char1, char2);
}
public KERNINGRECORD(String fontName, int fontStyle, int fontSize, char char1, char char2) {
fontKerningCode1 = char1;
fontKerningCode2 = char2;
fontKerningAdjustment = KERNINGRECORD.getSystemFontKerning(fontName, fontSize, fontStyle, char1, char2);
}
public static int getSystemFontKerning(Font font, char char1, char char2) {
return getSystemFontKerning(font.getFamily(), font.getSize(), font.getStyle(), char1, char2);
}
public static int getSystemFontKerning(String fontName, int fontSize, int fontStyle, char char1, char char2) {
char[] chars = new char[]{char1, char2};
Map<AttributedCharacterIterator.Attribute, Object> withKerningAttrs = new HashMap<>();
withKerningAttrs.put(TextAttribute.FAMILY, fontName);
if ((fontStyle & Font.BOLD) == Font.BOLD) {
withKerningAttrs.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
}
if ((fontStyle & Font.ITALIC) == Font.ITALIC) {
withKerningAttrs.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
}
withKerningAttrs.put(TextAttribute.SIZE, (float) fontSize);
withKerningAttrs.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
Font withKerningFont = Font.getFont(withKerningAttrs);
GlyphVector withKerningVector = withKerningFont.layoutGlyphVector((new JPanel()).getFontMetrics(withKerningFont).getFontRenderContext(), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
int withKerningX = withKerningVector.getGlyphLogicalBounds(1).getBounds().x;
Map<AttributedCharacterIterator.Attribute, Object> noKerningAttrs = new HashMap<>();
noKerningAttrs.put(TextAttribute.FAMILY, fontName);
if ((fontStyle & Font.BOLD) == Font.BOLD) {
noKerningAttrs.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
}
if ((fontStyle & Font.ITALIC) == Font.ITALIC) {
noKerningAttrs.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
}
noKerningAttrs.put(TextAttribute.SIZE, (float) fontSize);
Font noKerningFont = Font.getFont(noKerningAttrs);
GlyphVector noKerningVector = noKerningFont.layoutGlyphVector((new JPanel()).getFontMetrics(noKerningFont).getFontRenderContext(), chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
int noKerningX = noKerningVector.getGlyphLogicalBounds(1).getBounds().x;
return withKerningX - noKerningX;
}

View File

@@ -1950,7 +1950,7 @@ public class XFLConverter {
}
}
if (fontName == null) {
fontName = font.getFontName();
fontName = font.getFontNameIntag();
}
int fontStyle = font.getFontStyle();
String installedFont;
@@ -2451,7 +2451,7 @@ public class XFLConverter {
}
}
if ((fontName == null) && (font != null)) {
fontName = font.getFontName();
fontName = font.getFontNameIntag();
}
int fontStyle = 0;
if (font != null) {
@@ -2609,7 +2609,7 @@ public class XFLConverter {
}
if (ft != null) {
if (fontName == null) {
fontName = ft.getFontName();
fontName = ft.getFontNameIntag();
}
italic = ft.isItalic();
bold = ft.isBold();
@@ -3261,7 +3261,7 @@ public class XFLConverter {
}
if (ft != null) {
if (fontName == null) {
fontName = ft.getFontName();
fontName = ft.getFontNameIntag();
}
italic = ft.isItalic();
bold = ft.isBold();
@@ -3343,7 +3343,7 @@ public class XFLConverter {
if (tag instanceof FontTag) {
FontTag ft = (FontTag) tag;
String fontName = null;
if (f.equals(ft.getFontName())) {
if (f.equals(ft.getFontNameIntag())) {
for (Tag u : tags) {
if (u instanceof DefineFontNameTag) {
if (((DefineFontNameTag) u).fontId == ft.getFontId()) {
@@ -3352,7 +3352,7 @@ public class XFLConverter {
}
}
if (fontName == null) {
fontName = ft.getFontName();
fontName = ft.getFontNameIntag();
}
String installedFont;
if ((installedFont = FontTag.isFontFamilyInstalled(fontName)) != null) {