mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 20:20:46 +00:00
Added #1799 Text tags editor has new parameter [space xxx] specifying exact letter advance value (add to the font advance + calculated letterspacing)
Changed #802 - FLA export - calculating letterspacing on text with fonts without layout is now optional and turned off by default XFL converter - do not convert shapes twice Shape fixer - intersections - ignore problems
This commit is contained in:
@@ -966,7 +966,11 @@ public final class Configuration {
|
||||
|
||||
@ConfigurationDefaultBoolean(true)
|
||||
@ConfigurationCategory("ui")
|
||||
public static ConfigurationItem<Boolean> displayAs3PCodePanel = null;
|
||||
public static ConfigurationItem<Boolean> displayAs3PCodePanel = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("export")
|
||||
public static ConfigurationItem<Boolean> flaExportUseMappedFontLayout = null;
|
||||
|
||||
private enum OSId {
|
||||
WINDOWS, OSX, UNIX
|
||||
|
||||
@@ -207,7 +207,13 @@ public class Intersections {
|
||||
)
|
||||
);
|
||||
|
||||
List<Double> roots = poly.getRoots();
|
||||
List<Double> roots;
|
||||
try {
|
||||
roots = poly.getRoots();
|
||||
} catch (RuntimeException rex) {
|
||||
//Y values of bounds must be of opposite sign. ??fixme??
|
||||
return result;
|
||||
}
|
||||
for (double s : roots) {
|
||||
if (0 <= s && s <= 1) {
|
||||
Polynomial xp = new Polynomial(Arrays.asList(
|
||||
|
||||
@@ -252,6 +252,7 @@ public abstract class StaticTextTag extends TextTag {
|
||||
writer.append("]");
|
||||
int textHeight = 12;
|
||||
for (TEXTRECORD rec : textRecords) {
|
||||
int letterSpacing = 0;
|
||||
if (rec.styleFlagsHasFont || rec.styleFlagsHasColor || rec.styleFlagsHasXOffset || rec.styleFlagsHasYOffset) {
|
||||
writer.append("[").newLine();
|
||||
if (rec.styleFlagsHasFont) {
|
||||
@@ -264,7 +265,7 @@ public abstract class StaticTextTag extends TextTag {
|
||||
textHeight = rec.textHeight;
|
||||
}
|
||||
if (fnt != null && !ignoreLetterSpacing) {
|
||||
int letterSpacing = detectLetterSpacing(rec, fnt, textHeight);
|
||||
letterSpacing = detectLetterSpacing(rec, fnt, textHeight);
|
||||
if (letterSpacing != 0) {
|
||||
writer.append("letterspacing ").append(letterSpacing).newLine();
|
||||
}
|
||||
@@ -288,7 +289,24 @@ public abstract class StaticTextTag extends TextTag {
|
||||
if (fnt == null) {
|
||||
writer.append(AppResources.translate("fontNotFound").replace("%fontId%", Integer.toString(rec.fontId)));
|
||||
} else {
|
||||
writer.hilightSpecial(Helper.escapeActionScriptString(rec.getText(fnt)).replace("[", "\\[").replace("]", "\\]"), HighlightSpecialType.TEXT);
|
||||
for (int i = 0; i < rec.glyphEntries.size(); i++) {
|
||||
GLYPHENTRY ge = rec.glyphEntries.get(i);
|
||||
char c = fnt.glyphToChar(ge.glyphIndex);
|
||||
String sc = ("" + c).replace("[", "\\[").replace("]", "\\]");
|
||||
writer.hilightSpecial(sc, HighlightSpecialType.TEXT);
|
||||
|
||||
if (!ignoreLetterSpacing) {
|
||||
Character nextChar = null;
|
||||
if (i + 1 < rec.glyphEntries.size()) {
|
||||
nextChar = fnt.glyphToChar(ge.glyphIndex);
|
||||
}
|
||||
int advance = getAdvance(fnt, ge.glyphIndex, textHeight, c, nextChar);
|
||||
int delta = ge.glyphAdvance - advance;
|
||||
if (delta != letterSpacing) {
|
||||
writer.append("[space " + (delta - letterSpacing) + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new HighlightedText(writer);
|
||||
@@ -458,6 +476,20 @@ public abstract class StaticTextTag extends TextTag {
|
||||
throw new TextParseException("Invalid translatey value - number expected. Found: " + paramValue, lexer.yyline());
|
||||
}
|
||||
break;
|
||||
case "space":
|
||||
try {
|
||||
int space = Integer.parseInt(paramValue);
|
||||
if (textRecords.isEmpty()) {
|
||||
throw new TextParseException("space parameter must be placed after some text", lexer.yyline());
|
||||
}
|
||||
TEXTRECORD lastRecord = textRecords.get(textRecords.size() - 1);
|
||||
if (!lastRecord.glyphEntries.isEmpty()) {
|
||||
lastRecord.glyphEntries.get(lastRecord.glyphEntries.size() - 1).glyphAdvance += space;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new TextParseException("Invalid space value - number expected. Found: " + paramValue, lexer.yyline());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new TextParseException("Unrecognized parameter name: " + paramName, lexer.yyline());
|
||||
}
|
||||
@@ -580,35 +612,54 @@ public abstract class StaticTextTag extends TextTag {
|
||||
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));
|
||||
advance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(fontName, font.getFontStyle(), (int) (textHeight / SWF.unitDivisor), c, nextChar));
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
||||
|
||||
public static int detectLetterSpacing(TEXTRECORD textRecord, FontTag font, int textHeight) {
|
||||
int totalLetterSpacing = 0;
|
||||
public static int detectLetterSpacing(TEXTRECORD textRecord, FontTag font, int textHeight) {
|
||||
int minLetterSpacing = Integer.MAX_VALUE;
|
||||
int numNegatives = 0;
|
||||
List<GLYPHENTRY> glyphEntries = textRecord.glyphEntries;
|
||||
|
||||
if (glyphEntries.isEmpty()) {
|
||||
|
||||
if (glyphEntries.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < glyphEntries.size(); i++) {
|
||||
int numMin = 0;
|
||||
for (int i = 0; i < glyphEntries.size() - 1; i++) {
|
||||
GLYPHENTRY glyph = glyphEntries.get(i);
|
||||
GLYPHENTRY nextGlyph = null;
|
||||
/*GLYPHENTRY nextGlyph = null;
|
||||
if (i + 1 < glyphEntries.size()) {
|
||||
nextGlyph = glyphEntries.get(i + 1);
|
||||
}
|
||||
|
||||
}*/
|
||||
GLYPHENTRY nextGlyph = glyphEntries.get(i + 1);
|
||||
char c = font.glyphToChar(glyph.glyphIndex);
|
||||
Character nextChar = nextGlyph == null ? null : font.glyphToChar(nextGlyph.glyphIndex);
|
||||
//Character nextChar = nextGlyph == null ? null : font.glyphToChar(nextGlyph.glyphIndex);
|
||||
Character nextChar = font.glyphToChar(nextGlyph.glyphIndex);
|
||||
int advance = getAdvance(font, glyph.glyphIndex, textHeight, c, nextChar);
|
||||
int letterSpacing = glyph.glyphAdvance - advance;
|
||||
totalLetterSpacing += letterSpacing;
|
||||
//System.err.println("advance between char "+c+" and "+nextChar+": advance = " + advance + " glyphAdvance="+glyph.glyphAdvance+" delta:"+letterSpacing);
|
||||
if (letterSpacing < 0) {
|
||||
numNegatives++;
|
||||
}
|
||||
if (letterSpacing == minLetterSpacing) {
|
||||
numMin++;
|
||||
}
|
||||
if (letterSpacing < minLetterSpacing) {
|
||||
minLetterSpacing = letterSpacing;
|
||||
numMin = 1;
|
||||
}
|
||||
}
|
||||
if (minLetterSpacing < 0 && numNegatives < glyphEntries.size() / 2) { //a hack, use negative letterspacing only when 50% letters use it
|
||||
minLetterSpacing = 0;
|
||||
}
|
||||
if (numMin == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) Math.round(totalLetterSpacing / glyphEntries.size());
|
||||
return minLetterSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -346,17 +346,22 @@ public abstract class TextTag extends DrawableTag {
|
||||
if (nextEntry != null) {
|
||||
kerningAdjustment = font.getGlyphKerningAdjustment(entry.glyphIndex, nextEntry.glyphIndex);
|
||||
}
|
||||
defaultAdvance = (int) (Math.round(textHeight * (font.getGlyphAdvance(entry.glyphIndex) + kerningAdjustment) / (1024.0 * font.getDivider())));
|
||||
defaultAdvance = (int) (Math.round(textHeight * (font.getGlyphAdvance(entry.glyphIndex) + kerningAdjustment) / (1024.0 * font.getDivider())));
|
||||
|
||||
} else {
|
||||
defaultAdvance = (int) Math.round(SWF.unitDivisor * FontTag.getSystemFontAdvance(aFont, font.glyphToChar(entry.glyphIndex), nextEntry == null ? null : font.glyphToChar(nextEntry.glyphIndex)));
|
||||
}
|
||||
int newLetterSpacing = adv - defaultAdvance;
|
||||
if (e == 0 || e == rec.glyphEntries.size() - 1) {
|
||||
if (rec.glyphEntries.size() == 1) {
|
||||
letterSpacing = 0;
|
||||
if (!font.hasLayout() && !Configuration.flaExportUseMappedFontLayout.get()) {
|
||||
letterSpacing = 0;
|
||||
} else {
|
||||
int newLetterSpacing = adv - defaultAdvance;
|
||||
if (e == 0 || e == rec.glyphEntries.size() - 1) {
|
||||
if (rec.glyphEntries.size() == 1) {
|
||||
letterSpacing = 0;
|
||||
}
|
||||
} else if (newLetterSpacing < letterSpacing) {
|
||||
letterSpacing = newLetterSpacing;
|
||||
}
|
||||
} else if (newLetterSpacing < letterSpacing) {
|
||||
letterSpacing = newLetterSpacing;
|
||||
}
|
||||
x += adv;
|
||||
}
|
||||
|
||||
@@ -570,8 +570,15 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
private static boolean shapeHasMultiLayers(SWF swf, HashMap<Integer, CharacterTag> characters, MATRIX mat, int shapeNum, List<SHAPERECORD> shapeRecords, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStyles) throws XMLStreamException {
|
||||
List<String> layers = getShapeLayers(swf, characters, mat, shapeNum, shapeRecords, fillStyles, lineStyles, false);
|
||||
return layers.size() > 1;
|
||||
for (SHAPERECORD rec: shapeRecords) {
|
||||
if (rec instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr = (StyleChangeRecord) rec;
|
||||
if (scr.stateNewStyles) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void convertShape(SWF swf, HashMap<Integer, CharacterTag> characters, MATRIX mat, int shapeNum, List<SHAPERECORD> shapeRecords, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStyles, boolean morphshape, boolean useLayers, XFLXmlWriter writer) throws XMLStreamException {
|
||||
@@ -1636,6 +1643,7 @@ public class XFLConverter {
|
||||
Reference<Integer> nextClipId = new Reference<>(-1);
|
||||
writer.writeStartElement("symbols");
|
||||
for (int ch : characters.keySet()) {
|
||||
//System.err.println("converting " + ch);
|
||||
CharacterTag symbol = characters.get(ch);
|
||||
if ((symbol instanceof ShapeTag) && nonLibraryShapes.contains(symbol.getCharacterId())) {
|
||||
continue; //shapes with 1 ocurrence and single layer are not added to library
|
||||
|
||||
Reference in New Issue
Block a user