#1075 Lenght of DefineText is more larger than original when DefineText is saved: detect letter spacing

This commit is contained in:
honfika@gmail.com
2015-12-20 11:12:32 +01:00
parent da2d824e9c
commit 300022acc7
5 changed files with 81 additions and 51 deletions

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
@@ -181,16 +182,30 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
}
public String getSystemFontName() {
Map<String, String> fontPairs = Configuration.getFontToNameMap();
String key = swf.getShortFileName() + "_" + getFontId() + "_" + getFontNameIntag();
if (fontPairs.containsKey(key)) {
return fontPairs.get(key);
int fontId = getFontId();
String selectedFont = swf.sourceFontNamesMap.get(fontId);
if (selectedFont == null) {
SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(swf.getShortFileName());
String key = fontId + "_" + getFontNameIntag();
if (swfConf != null) {
selectedFont = swfConf.fontPairingMap.get(key);
}
}
key = getFontNameIntag();
if (fontPairs.containsKey(key)) {
return fontPairs.get(key);
if (selectedFont == null) {
selectedFont = Configuration.getFontToNameMap().get(getFontNameIntag());
}
return defaultFontName;
if (selectedFont != null && FontTag.installedFontsByName.containsKey(selectedFont)) {
return selectedFont;
}
// findInstalledFontName always returns an available font name
return FontTag.findInstalledFontName(getFontName());
}
public Font getSystemFont() {
return FontTag.installedFontsByName.get(getSystemFontName());
}
protected void shiftGlyphIndices(int fontId, int startIndex) {

View File

@@ -261,6 +261,12 @@ public abstract class StaticTextTag extends TextTag {
writer.append("font ").append(rec.fontId).newLine();
writer.append("height ").append(rec.textHeight).newLine();
}
if (fnt != null) {
int letterSpacing = detectLetterSpacing(rec, fnt, rec.textHeight);
if (letterSpacing != 0) {
writer.append("letterspacing ").append(letterSpacing).newLine();
}
}
if (rec.styleFlagsHasColor) {
if (getTextNum() == 1) {
writer.append("color ").append(rec.textColor.toHexRGB()).newLine();
@@ -296,8 +302,8 @@ public abstract class StaticTextTag extends TextTag {
RGBA colorA = null;
int fontId = -1;
int textHeight = -1;
int letterSpacing = 0;
FontTag font = null;
String fontName = null;
Integer x = null;
Integer y = null;
int currentX = 0;
@@ -342,7 +348,6 @@ public abstract class StaticTextTag extends TextTag {
}
font = (FontTag) ft;
fontName = font.getSystemFontName();
} catch (NumberFormatException nfe) {
throw new TextParseException("Invalid font id - number expected. Found: " + paramValue, lexer.yyline());
}
@@ -354,6 +359,13 @@ public abstract class StaticTextTag extends TextTag {
throw new TextParseException("Invalid font height - number expected. Found: " + paramValue, lexer.yyline());
}
break;
case "letterspacing":
try {
letterSpacing = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new TextParseException("Invalid font letter spacing - number expected. Found: " + paramValue, lexer.yyline());
}
break;
case "x":
try {
x = Integer.parseInt(paramValue);
@@ -527,17 +539,7 @@ public abstract class StaticTextTag extends TextTag {
GLYPHENTRY ge = new GLYPHENTRY();
ge.glyphIndex = font.charToGlyph(c);
int advance;
if (font.hasLayout()) {
int kerningAdjustment = 0;
if (nextChar != null) {
kerningAdjustment = font.getCharKerningAdjustment(c, nextChar);
}
advance = (int) Math.round(((double) textHeight * (font.getGlyphAdvance(ge.glyphIndex) + kerningAdjustment)) / (font.getDivider() * 1024.0));
} else {
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
}
int advance = getAdvance(font, ge.glyphIndex, textHeight, c, nextChar) + letterSpacing;
ge.glyphAdvance = advance;
tr.glyphEntries.add(ge);
@@ -568,6 +570,42 @@ public abstract class StaticTextTag extends TextTag {
return true;
}
private int getAdvance(FontTag font, int glyphIndex, int textHeight, char c, Character nextChar) {
int advance;
if (font.hasLayout()) {
int kerningAdjustment = 0;
if (nextChar != null) {
kerningAdjustment = font.getCharKerningAdjustment(c, nextChar);
}
advance = (int) Math.round(((double) textHeight * (font.getGlyphAdvance(glyphIndex) + kerningAdjustment)) / (font.getDivider() * 1024.0));
} else {
String fontName = font.getSystemFontName();
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
}
return advance;
}
private int detectLetterSpacing(TEXTRECORD textRecord, FontTag font, int textHeight) {
int totalLetterSpacing = 0;
List<GLYPHENTRY> glyphEntries = textRecord.glyphEntries;
for (int i = 0; i < glyphEntries.size(); i++) {
GLYPHENTRY glyph = glyphEntries.get(i);
GLYPHENTRY nextGlyph = null;
if (i + 1 < glyphEntries.size()) {
nextGlyph = glyphEntries.get(i + 1);
}
char c = font.glyphToChar(glyph.glyphIndex);
Character nextChar = nextGlyph == null ? null : font.glyphToChar(nextGlyph.glyphIndex);
int advance = getAdvance(font, glyph.glyphIndex, textHeight, c, nextChar);
int letterSpacing = glyph.glyphAdvance - advance;
totalLetterSpacing += letterSpacing;
}
return (int) Math.round(totalLetterSpacing / glyphEntries.size());
}
@Override
public void getNeededCharacters(Set<Integer> needed) {
for (TEXTRECORD tr : textRecords) {