mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-28 10:26:35 +00:00
Fixed: #2545 FLA export - normalize font em square
This commit is contained in:
@@ -17,9 +17,17 @@
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.StaticTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.tags.dynamictext.CharacterWithStyle;
|
||||
import com.jpexs.decompiler.flash.tags.dynamictext.TextStyle;
|
||||
import com.jpexs.decompiler.flash.tags.text.xml.XmlException;
|
||||
import com.jpexs.decompiler.flash.tags.text.xml.XmlLexer;
|
||||
import com.jpexs.decompiler.flash.tags.text.xml.XmlParsedSymbol;
|
||||
import com.jpexs.decompiler.flash.tags.text.xml.XmlSymbolType;
|
||||
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
@@ -28,60 +36,67 @@ 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 java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Font size / orientation normalizer.
|
||||
* Does following:
|
||||
* - shrinks oversized fonts to 1024 em
|
||||
* - fixes vertically flipped fonts / texts
|
||||
* - fixes zero/1unit spaces font glyph advance
|
||||
* - fixes zero last glyph advance in texts
|
||||
*
|
||||
* Font size / orientation normalizer. Does following: - shrinks oversized fonts
|
||||
* to 1024 em - fixes vertically flipped fonts / texts - fixes zero/1unit spaces
|
||||
* font glyph advance - fixes zero last glyph advance in texts
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class FontNormalizer {
|
||||
|
||||
/**
|
||||
* Normalizes fonts in the SWF file in place.
|
||||
*
|
||||
* @param swf SWF
|
||||
*/
|
||||
public void normalizeFonts(SWF swf) {
|
||||
normalizeFonts(swf, true, new LinkedHashMap<>(), new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes fonts in the SWF file creating clones of font/text tags.
|
||||
*
|
||||
* @param swf SWF file
|
||||
* @param outFonts Modified fonts (clone) - fontId to fontTag
|
||||
* @param outTexts Modified texts (clone) - textId to textTag
|
||||
*/
|
||||
public void normalizeFonts(SWF swf, Map<Integer, FontTag> outFonts, Map<Integer, StaticTextTag> outTexts) {
|
||||
public void normalizeFonts(SWF swf, Map<Integer, FontTag> outFonts, Map<Integer, TextTag> outTexts) {
|
||||
normalizeFonts(swf, false, outFonts, outTexts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes fonts in the SWF file.
|
||||
*
|
||||
* @param swf SWF file
|
||||
* @param inPlace Modify tags in SWF file (true) or create clones (false)
|
||||
* @param outFonts Modified fonts - fontId to fontTag
|
||||
* @param outTexts Modified texts - textId to textTag
|
||||
*/
|
||||
public void normalizeFonts(SWF swf, boolean inPlace, Map<Integer, FontTag> outFonts, Map<Integer, StaticTextTag> outTexts) {
|
||||
public void normalizeFonts(SWF swf, boolean inPlace, Map<Integer, FontTag> outFonts, Map<Integer, TextTag> outTexts) {
|
||||
Map<Integer, CharacterTag> characters = swf.getCharacters(!inPlace);
|
||||
|
||||
Map<Integer, StaticTextTag> texts = new LinkedHashMap<>();
|
||||
Map<Integer, TextTag> texts = new LinkedHashMap<>();
|
||||
|
||||
for (int characterId : characters.keySet()) {
|
||||
CharacterTag character = characters.get(characterId);
|
||||
if (character instanceof StaticTextTag) {
|
||||
texts.put(characterId, (StaticTextTag) character);
|
||||
if (character instanceof TextTag) {
|
||||
texts.put(characterId, (TextTag) character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,21 +104,29 @@ public class FontNormalizer {
|
||||
Set<Integer> notInvertedFontIds = new LinkedHashSet<>();
|
||||
Set<Integer> fontIds = new LinkedHashSet<>();
|
||||
|
||||
for (StaticTextTag text : texts.values()) {
|
||||
boolean inverted = false;
|
||||
if (text.textMatrix != null) {
|
||||
if (text.textMatrix.scaleY < 0) {
|
||||
inverted = true;
|
||||
}
|
||||
for (TextTag text : texts.values()) {
|
||||
if (text instanceof DefineEditTextTag) {
|
||||
DefineEditTextTag detext = (DefineEditTextTag) text;
|
||||
fontIds.addAll(getDefineEditTextFonts(detext));
|
||||
}
|
||||
for (TEXTRECORD rec : text.textRecords) {
|
||||
if (rec.styleFlagsHasFont) {
|
||||
if (inverted) {
|
||||
invertedFontIds.add(rec.fontId);
|
||||
} else {
|
||||
notInvertedFontIds.add(rec.fontId);
|
||||
|
||||
if (text instanceof StaticTextTag) {
|
||||
StaticTextTag stext = (StaticTextTag) text;
|
||||
boolean inverted = false;
|
||||
if (stext.textMatrix != null) {
|
||||
if (stext.textMatrix.scaleY < 0) {
|
||||
inverted = true;
|
||||
}
|
||||
}
|
||||
for (TEXTRECORD rec : stext.textRecords) {
|
||||
if (rec.styleFlagsHasFont) {
|
||||
if (inverted) {
|
||||
invertedFontIds.add(rec.fontId);
|
||||
} else {
|
||||
notInvertedFontIds.add(rec.fontId);
|
||||
}
|
||||
fontIds.add(rec.fontId);
|
||||
}
|
||||
fontIds.add(rec.fontId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,61 +144,71 @@ public class FontNormalizer {
|
||||
}
|
||||
FontTag font = (FontTag) fontCharacter;
|
||||
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int maxY = Integer.MIN_VALUE;
|
||||
for (SHAPE shp : font.getGlyphShapeTable()) {
|
||||
RECT b = shp.getBounds(1);
|
||||
if (b.Ymin < minY) {
|
||||
minY = b.Ymin;
|
||||
}
|
||||
if (b.Ymax > maxY) {
|
||||
maxY = b.Ymax;
|
||||
}
|
||||
}
|
||||
int maxH = maxY - minY;
|
||||
|
||||
int originalEmSize = (int) Math.round(maxH / font.getDivider());
|
||||
double scale = 1.0;
|
||||
boolean willModify = false;
|
||||
if (originalEmSize > 1024) {
|
||||
scale = 1024.0 / originalEmSize;
|
||||
willModify = true;
|
||||
}
|
||||
if (invertedFontIds.contains(fontId)) {
|
||||
willModify = true;
|
||||
}
|
||||
|
||||
|
||||
double newScale = 1;
|
||||
|
||||
String systemFont = font.getSystemFontName();
|
||||
|
||||
List<SHAPE> shapes1 = font.getGlyphShapeTable();
|
||||
Double h = null;
|
||||
Double systemH = null;
|
||||
for (int i = 0; i < shapes1.size(); i++) {
|
||||
RECT b = shapes1.get(i).getBounds(1);
|
||||
h = b.getHeight() / font.getDivider();
|
||||
if (h <= 0) {
|
||||
continue;
|
||||
}
|
||||
char c = font.glyphToChar(i);
|
||||
Font f = new Font(systemFont, (font.isBold() ? Font.BOLD : 0) | (font.isItalic() ? Font.ITALIC : 0), 1000);
|
||||
if (!f.canDisplay(c)) {
|
||||
continue;
|
||||
}
|
||||
FontRenderContext frc = new FontRenderContext(null, true, true);
|
||||
GlyphVector gv = f.createGlyphVector(frc, new char[]{c});
|
||||
systemH = gv.getGlyphOutline(0).getBounds2D().getHeight();
|
||||
break;
|
||||
}
|
||||
|
||||
if (h != null && systemH != null) {
|
||||
newScale = systemH / h;
|
||||
willModify = true;
|
||||
}
|
||||
|
||||
final double scale = newScale;
|
||||
|
||||
int spaceGlyph = font.charToGlyph(' ');
|
||||
int nonBreakingSpaceGlyph = font.charToGlyph((char) 0xA0);
|
||||
|
||||
|
||||
if (spaceGlyph != -1 && font.getGlyphAdvance(spaceGlyph) <= 1) {
|
||||
willModify = true;
|
||||
}
|
||||
|
||||
|
||||
if (nonBreakingSpaceGlyph != -1 && font.getGlyphAdvance(nonBreakingSpaceGlyph) <= 1) {
|
||||
willModify = true;
|
||||
}
|
||||
|
||||
|
||||
if (!willModify) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//scale = 1;
|
||||
|
||||
fontNewScale.put(fontId, scale);
|
||||
FontTag font2;
|
||||
if (inPlace) {
|
||||
font2 = font;
|
||||
} else {
|
||||
} else {
|
||||
try {
|
||||
font2 = (FontTag) font.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
outFonts.put(fontId, font2);
|
||||
|
||||
outFonts.put(fontId, font2);
|
||||
|
||||
List<SHAPE> shapes = font2.getGlyphShapeTable();
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
@@ -199,110 +232,460 @@ public class FontNormalizer {
|
||||
font2.setAscent((int) Math.round(font2.getAscent() * scale));
|
||||
font2.setDescent((int) Math.round(font2.getDescent() * scale));
|
||||
font2.setLeading((int) Math.round(font2.getLeading() * scale));
|
||||
|
||||
|
||||
if (invertedFontIds.contains(fontId)) {
|
||||
int ascent = font2.getAscent();
|
||||
int descent = font2.getDescent();
|
||||
//switch ascent and descent
|
||||
font2.setAscent(descent);
|
||||
font2.setDescent(ascent);
|
||||
|
||||
|
||||
//what to do with leading?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (spaceGlyph != -1 && font.getGlyphAdvance(spaceGlyph) <= 1) {
|
||||
font2.setGlyphAdvance(spaceGlyph, 512);
|
||||
}
|
||||
|
||||
|
||||
if (nonBreakingSpaceGlyph != -1 && font.getGlyphAdvance(nonBreakingSpaceGlyph) <= 1) {
|
||||
font2.setGlyphAdvance(nonBreakingSpaceGlyph, 512);
|
||||
}
|
||||
|
||||
|
||||
font2.setModified(true);
|
||||
}
|
||||
|
||||
for (int textId : texts.keySet()) {
|
||||
int fontId = -1;
|
||||
int textHeight = 12 * 20;
|
||||
StaticTextTag text = texts.get(textId);
|
||||
StaticTextTag text2 = null;
|
||||
for (int i = 0; i < text.textRecords.size(); i++) {
|
||||
TEXTRECORD rec = text.textRecords.get(i);
|
||||
if (rec.styleFlagsHasFont) {
|
||||
fontId = rec.fontId;
|
||||
if (fontNewScale.containsKey(fontId) || invertedFontIds.contains(fontId)) {
|
||||
if (text2 == null) {
|
||||
if (inPlace) {
|
||||
text2 = text;
|
||||
} else {
|
||||
try {
|
||||
text2 = (StaticTextTag) text.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
break;
|
||||
if (texts.get(textId) instanceof DefineEditTextTag) {
|
||||
DefineEditTextTag text = (DefineEditTextTag) texts.get(textId);
|
||||
scaleDefineEditTextFonts(text, fontNewScale, inPlace, outTexts);
|
||||
} else if (texts.get(textId) instanceof StaticTextTag) {
|
||||
StaticTextTag text = (StaticTextTag) texts.get(textId);
|
||||
StaticTextTag text2 = null;
|
||||
for (int i = 0; i < text.textRecords.size(); i++) {
|
||||
TEXTRECORD rec = text.textRecords.get(i);
|
||||
if (rec.styleFlagsHasFont) {
|
||||
fontId = rec.fontId;
|
||||
if (fontNewScale.containsKey(fontId) || invertedFontIds.contains(fontId)) {
|
||||
if (text2 == null) {
|
||||
if (inPlace) {
|
||||
text2 = text;
|
||||
} else {
|
||||
try {
|
||||
text2 = (StaticTextTag) text.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
outTexts.put(textId, text2);
|
||||
text2.setModified(true);
|
||||
}
|
||||
outTexts.put(textId, text2);
|
||||
text2.setModified(true);
|
||||
}
|
||||
}
|
||||
textHeight = text.textRecords.get(i).textHeight;
|
||||
|
||||
if (fontNewScale.containsKey(fontId)) {
|
||||
text2.textRecords.get(i).textHeight /= fontNewScale.get(fontId);
|
||||
textHeight = text2.textRecords.get(i).textHeight;
|
||||
}
|
||||
if (invertedFontIds.contains(fontId)) {
|
||||
if (text2.textMatrix != null && text2.textMatrix.scaleY < 0) {
|
||||
text2.textMatrix.scaleY *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (invertedFontIds.contains(fontId)) {
|
||||
if (rec.styleFlagsHasYOffset) {
|
||||
text2.textRecords.get(i).yOffset = - rec.yOffset;
|
||||
}
|
||||
}
|
||||
if (!rec.glyphEntries.isEmpty() && rec.glyphEntries.get(rec.glyphEntries.size() - 1).glyphAdvance == 0) {
|
||||
FontTag font;
|
||||
if (outFonts.containsKey(fontId)) {
|
||||
font = outFonts.get(fontId);
|
||||
} else {
|
||||
font = swf.getFont(fontId);
|
||||
}
|
||||
if (font != null) {
|
||||
if (text2 == null) {
|
||||
if (inPlace) {
|
||||
text2 = text;
|
||||
} else {
|
||||
try {
|
||||
text2 = (StaticTextTag) text.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
outTexts.put(textId, text2);
|
||||
text2.setModified(true);
|
||||
}
|
||||
|
||||
GLYPHENTRY lastGlyphEntry = text2.textRecords.get(i).glyphEntries.get(rec.glyphEntries.size() - 1);
|
||||
lastGlyphEntry.glyphAdvance = (int) Math.round(font.getGlyphAdvance(lastGlyphEntry.glyphIndex) * textHeight / (1024.0 * font.getDivider()));
|
||||
textHeight = text.textRecords.get(i).textHeight;
|
||||
|
||||
if (i + 1 < text.textRecords.size()) {
|
||||
TEXTRECORD nextRec = text2.textRecords.get(i + 1);
|
||||
if (!nextRec.styleFlagsHasXOffset && !nextRec.glyphEntries.isEmpty()) {
|
||||
nextRec.glyphEntries.get(0).glyphAdvance -= lastGlyphEntry.glyphAdvance;
|
||||
if (fontNewScale.containsKey(fontId)) {
|
||||
text2.textRecords.get(i).textHeight = round20(text2.textRecords.get(i).textHeight / fontNewScale.get(fontId));
|
||||
textHeight = text2.textRecords.get(i).textHeight;
|
||||
}
|
||||
if (invertedFontIds.contains(fontId)) {
|
||||
if (text2.textMatrix != null && text2.textMatrix.scaleY < 0) {
|
||||
text2.textMatrix.scaleY *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (invertedFontIds.contains(fontId)) {
|
||||
if (rec.styleFlagsHasYOffset) {
|
||||
text2.textRecords.get(i).yOffset = -rec.yOffset;
|
||||
}
|
||||
}
|
||||
if (!rec.glyphEntries.isEmpty() && rec.glyphEntries.get(rec.glyphEntries.size() - 1).glyphAdvance == 0) {
|
||||
FontTag font;
|
||||
if (outFonts.containsKey(fontId)) {
|
||||
font = outFonts.get(fontId);
|
||||
} else {
|
||||
font = swf.getFont(fontId);
|
||||
}
|
||||
if (font != null) {
|
||||
if (text2 == null) {
|
||||
if (inPlace) {
|
||||
text2 = text;
|
||||
} else {
|
||||
try {
|
||||
text2 = (StaticTextTag) text.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
outTexts.put(textId, text2);
|
||||
text2.setModified(true);
|
||||
}
|
||||
|
||||
GLYPHENTRY lastGlyphEntry = text2.textRecords.get(i).glyphEntries.get(rec.glyphEntries.size() - 1);
|
||||
lastGlyphEntry.glyphAdvance = (int) Math.round(font.getGlyphAdvance(lastGlyphEntry.glyphIndex) * textHeight / (1024.0 * font.getDivider()));
|
||||
|
||||
if (i + 1 < text.textRecords.size()) {
|
||||
TEXTRECORD nextRec = text2.textRecords.get(i + 1);
|
||||
if (!nextRec.styleFlagsHasXOffset && !nextRec.glyphEntries.isEmpty()) {
|
||||
nextRec.glyphEntries.get(0).glyphAdvance -= lastGlyphEntry.glyphAdvance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
swf.clearShapeCache();
|
||||
}
|
||||
|
||||
private static int round20(double val) {
|
||||
return (int) Math.floor(val / 20.0) * 20;
|
||||
}
|
||||
|
||||
private Set<Integer> getDefineEditTextFonts(DefineEditTextTag text) {
|
||||
Set<Integer> ret = new LinkedHashSet<>();
|
||||
TextStyle style = new TextStyle();
|
||||
if (text.fontClass != null) {
|
||||
style.font = text.getSwf().getFontByClass(text.fontClass);
|
||||
} else {
|
||||
style.font = text.getSwf().getFont(text.fontId);
|
||||
}
|
||||
int fontId = text.getSwf().getCharacterId(style.font);
|
||||
ret.add(fontId);
|
||||
|
||||
if (text.html) {
|
||||
final Stack<TextStyle> styles = new Stack<>();
|
||||
styles.add(style);
|
||||
XmlLexer lexer = new XmlLexer(new StringReader(text.initialText));
|
||||
try {
|
||||
XmlParsedSymbol s = lexer.yylex();
|
||||
boolean inOpenTag = false;
|
||||
String attributeName = null;
|
||||
String tagName = null;
|
||||
Map<String, String> attributes = new LinkedHashMap<>();
|
||||
loops:
|
||||
while (s.type != XmlSymbolType.EOF) {
|
||||
switch (s.type) {
|
||||
case TAG_OPEN:
|
||||
inOpenTag = true;
|
||||
attributeName = null;
|
||||
tagName = (String) s.value;
|
||||
attributes.clear();
|
||||
break;
|
||||
case ATTRIBUTE:
|
||||
attributeName = (String) s.value;
|
||||
break;
|
||||
case ATTRIBUTE_VALUE:
|
||||
if (attributeName == null) {
|
||||
//Error
|
||||
break loops;
|
||||
}
|
||||
attributes.put(attributeName, (String) s.value);
|
||||
break;
|
||||
case TAG_OPEN_END:
|
||||
style = styles.peek();
|
||||
switch (tagName) {
|
||||
case "p":
|
||||
// todo: parse the following attribute:
|
||||
// align
|
||||
break;
|
||||
case "a":
|
||||
// todo: handle link - href, target attributes
|
||||
break;
|
||||
case "b":
|
||||
style = style.clone();
|
||||
style.bold = true;
|
||||
styles.add(style);
|
||||
break;
|
||||
case "i":
|
||||
style = style.clone();
|
||||
style.italic = true;
|
||||
styles.add(style);
|
||||
break;
|
||||
case "u":
|
||||
style = style.clone();
|
||||
style.underlined = true;
|
||||
styles.add(style);
|
||||
break;
|
||||
case "font":
|
||||
style = style.clone();
|
||||
String face = attributes.get("face");
|
||||
|
||||
if (face != null && face.length() > 0) {
|
||||
style.fontFace = face;
|
||||
}
|
||||
|
||||
String size = attributes.get("size");
|
||||
if (size != null && size.length() > 0) {
|
||||
|
||||
if (style.fontFace != null && text.useOutlines) {
|
||||
CharacterTag ct = text.getSwf().getCharacterByExportName(style.fontFace);
|
||||
if (ct != null && (ct instanceof FontTag)) {
|
||||
style.font = (FontTag) ct;
|
||||
} else {
|
||||
style.font = text.getSwf().getFontByNameInTag(style.fontFace, style.bold, style.italic);
|
||||
}
|
||||
if (style.font == null) {
|
||||
style.fontFace = null;
|
||||
} else {
|
||||
fontId = text.getSwf().getCharacterId(style.font);
|
||||
ret.add(fontId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
styles.add(style);
|
||||
break;
|
||||
}
|
||||
tagName = null;
|
||||
break;
|
||||
case TAG_CLOSE:
|
||||
tagName = (String) s.value;
|
||||
switch (tagName) {
|
||||
case "b":
|
||||
case "i":
|
||||
case "u":
|
||||
case "font":
|
||||
styles.pop();
|
||||
break;
|
||||
}
|
||||
tagName = null;
|
||||
break;
|
||||
}
|
||||
s = lexer.yylex();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
//Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (XmlException ex) {
|
||||
//Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
//ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void scaleDefineEditTextFonts(DefineEditTextTag text, Map<Integer, Double> fontNewScale, boolean inPlace, Map<Integer, TextTag> outTexts) {
|
||||
String str = "";
|
||||
TextStyle style = new TextStyle();
|
||||
if (text.fontClass != null) {
|
||||
style.font = text.getSwf().getFontByClass(text.fontClass);
|
||||
} else {
|
||||
style.font = text.getSwf().getFont(text.fontId);
|
||||
}
|
||||
int textId = text.getSwf().getCharacterId(text);
|
||||
int fontId = text.getSwf().getCharacterId(style.font);
|
||||
DefineEditTextTag text2 = null;
|
||||
if (fontNewScale.containsKey(fontId)) {
|
||||
if (inPlace) {
|
||||
text2 = text;
|
||||
} else {
|
||||
try {
|
||||
text2 = (DefineEditTextTag) text.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
text2.fontHeight = round20(text2.fontHeight / fontNewScale.get(fontId));
|
||||
outTexts.put(textId, text2);
|
||||
text2.setModified(true);
|
||||
}
|
||||
|
||||
style.fontHeight = text.fontHeight;
|
||||
style.fontLeading = text.leading;
|
||||
if (text.hasTextColor) {
|
||||
style.textColor = text.textColor;
|
||||
}
|
||||
if (text.hasText) {
|
||||
str = text.initialText;
|
||||
}
|
||||
style.leftMargin = text.leftMargin;
|
||||
final List<CharacterWithStyle> ret = new ArrayList<>();
|
||||
if (text.html) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
//SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
//SAXParser saxParser;
|
||||
final Stack<TextStyle> styles = new Stack<>();
|
||||
styles.add(style);
|
||||
XmlLexer lexer = new XmlLexer(new StringReader(text.initialText));
|
||||
try {
|
||||
XmlParsedSymbol s = lexer.yylex();
|
||||
boolean inOpenTag = false;
|
||||
String attributeName = null;
|
||||
String tagName = null;
|
||||
Map<String, String> attributes = new LinkedHashMap<>();
|
||||
loops:
|
||||
while (s.type != XmlSymbolType.EOF) {
|
||||
switch (s.type) {
|
||||
case TAG_OPEN:
|
||||
inOpenTag = true;
|
||||
attributeName = null;
|
||||
tagName = (String) s.value;
|
||||
attributes.clear();
|
||||
break;
|
||||
case ATTRIBUTE:
|
||||
attributeName = (String) s.value;
|
||||
break;
|
||||
case ATTRIBUTE_VALUE:
|
||||
if (attributeName == null) {
|
||||
//Error
|
||||
break loops;
|
||||
}
|
||||
attributes.put(attributeName, (String) s.value);
|
||||
break;
|
||||
case TAG_OPEN_END:
|
||||
style = styles.peek();
|
||||
switch (tagName) {
|
||||
case "p":
|
||||
// todo: parse the following attribute:
|
||||
// align
|
||||
break;
|
||||
case "a":
|
||||
// todo: handle link - href, target attributes
|
||||
break;
|
||||
case "b":
|
||||
style = style.clone();
|
||||
style.bold = true;
|
||||
styles.add(style);
|
||||
break;
|
||||
case "i":
|
||||
style = style.clone();
|
||||
style.italic = true;
|
||||
styles.add(style);
|
||||
break;
|
||||
case "u":
|
||||
style = style.clone();
|
||||
style.underlined = true;
|
||||
styles.add(style);
|
||||
break;
|
||||
case "font":
|
||||
style = style.clone();
|
||||
String face = attributes.get("face");
|
||||
|
||||
if (face != null && face.length() > 0) {
|
||||
style.fontFace = face;
|
||||
}
|
||||
|
||||
String size = attributes.get("size");
|
||||
if (size != null && size.length() > 0) {
|
||||
|
||||
if (style.fontFace != null && text.useOutlines) {
|
||||
CharacterTag ct = text.getSwf().getCharacterByExportName(style.fontFace);
|
||||
if (ct != null && (ct instanceof FontTag)) {
|
||||
style.font = (FontTag) ct;
|
||||
} else {
|
||||
style.font = text.getSwf().getFontByNameInTag(style.fontFace, style.bold, style.italic);
|
||||
}
|
||||
if (style.font == null) {
|
||||
style.fontFace = null;
|
||||
} else {
|
||||
fontId = text.getSwf().getCharacterId(style.font);
|
||||
|
||||
if (fontNewScale.containsKey(fontId)) {
|
||||
if (text2 == null) {
|
||||
if (inPlace) {
|
||||
text2 = text;
|
||||
} else {
|
||||
try {
|
||||
text2 = (DefineEditTextTag) text.cloneTag();
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
outTexts.put(textId, text2);
|
||||
text2.setModified(true);
|
||||
}
|
||||
|
||||
try {
|
||||
char firstChar = size.charAt(0);
|
||||
if (firstChar != '+' && firstChar != '-') {
|
||||
int fontSize = Integer.parseInt(size);
|
||||
//style.fontHeight = (int) Math.round(fontSize * SWF.unitDivisor);
|
||||
attributes.put("size", "" + Math.round(fontSize / fontNewScale.get(fontId)));
|
||||
} else {
|
||||
int fontSizeDelta = (int) Math.round(Integer.parseInt(size.substring(1)) * SWF.unitDivisor);
|
||||
attributes.put("size", "" + firstChar + Math.round(fontSizeDelta / fontNewScale.get(fontId)));
|
||||
/*if (firstChar == '+') {
|
||||
style.fontHeight = style.fontHeight + fontSizeDelta;
|
||||
} else {
|
||||
style.fontHeight = style.fontHeight - fontSizeDelta;
|
||||
}*/
|
||||
}
|
||||
style.fontLeading = text.leading;
|
||||
} catch (NumberFormatException nfe) {
|
||||
//do not change fontHeight or leading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
styles.add(style);
|
||||
break;
|
||||
}
|
||||
sb.append("<").append(tagName);
|
||||
for (String key : attributes.keySet()) {
|
||||
sb.append(" ").append(key).append("=").append("\"").append(attributes.get(key)).append("\"");
|
||||
}
|
||||
sb.append(">");
|
||||
tagName = null;
|
||||
break;
|
||||
case TAG_CLOSE:
|
||||
tagName = (String) s.value;
|
||||
switch (tagName) {
|
||||
case "b":
|
||||
case "i":
|
||||
case "u":
|
||||
case "font":
|
||||
styles.pop();
|
||||
break;
|
||||
}
|
||||
sb.append("</").append(tagName).append(">");
|
||||
tagName = null;
|
||||
break;
|
||||
|
||||
case ENTITY:
|
||||
sb.append("&").append(s.value).append(";");
|
||||
break;
|
||||
case CHARACTER:
|
||||
sb.append(s.value);
|
||||
break;
|
||||
}
|
||||
s = lexer.yylex();
|
||||
}
|
||||
if (text2 != null) {
|
||||
text2.initialText = sb.toString();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
//Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (XmlException ex) {
|
||||
//Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
//ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Percentile helper (p in <0,100>)
|
||||
private static double percentile(List<Double> values, double p) {
|
||||
if (values.isEmpty()) {
|
||||
return 0.0;
|
||||
}
|
||||
Collections.sort(values);
|
||||
double rank = (p / 100.0) * (values.size() - 1);
|
||||
int lo = (int) Math.floor(rank);
|
||||
int hi = (int) Math.ceil(rank);
|
||||
if (lo == hi) {
|
||||
return values.get(lo);
|
||||
}
|
||||
double w = rank - lo;
|
||||
return values.get(lo) * (1.0 - w) + values.get(hi) * w;
|
||||
}
|
||||
|
||||
private void transformSHAPE(Matrix matrix, SHAPE shape) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.FontExportMode;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.StaticTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.DynamicTextGlyphEntry;
|
||||
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
|
||||
@@ -71,7 +72,7 @@ public class DualPdfGraphics2D extends Graphics2D implements BlendModeSettable,
|
||||
private final Map<Integer, Font> existingFonts;
|
||||
|
||||
private Map<Integer, FontTag> normalizedFonts = new LinkedHashMap<>();
|
||||
private Map<Integer, StaticTextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
private Map<Integer, TextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
|
||||
public DualPdfGraphics2D(Graphics2D first, PDFGraphics second, Map<Integer, Font> existingFonts) {
|
||||
this.imageGraphics = first;
|
||||
@@ -694,7 +695,7 @@ public class DualPdfGraphics2D extends Graphics2D implements BlendModeSettable,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNormalizedFonts(Map<Integer, FontTag> normalizedFonts, Map<Integer, StaticTextTag> normalizedTexts) {
|
||||
public void setNormalizedFonts(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts) {
|
||||
this.normalizedFonts = normalizedFonts;
|
||||
this.normalizedTexts = normalizedTexts;
|
||||
}
|
||||
@@ -705,7 +706,7 @@ public class DualPdfGraphics2D extends Graphics2D implements BlendModeSettable,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, StaticTextTag> getNormalizedTexts() {
|
||||
public Map<Integer, TextTag> getNormalizedTexts() {
|
||||
return normalizedTexts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.RenderContext;
|
||||
import com.jpexs.decompiler.flash.tags.base.StaticTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||
@@ -324,7 +325,7 @@ public class FrameExporter {
|
||||
|
||||
FontNormalizer normalizer = new FontNormalizer();
|
||||
Map<Integer, FontTag> normalizedFonts = new LinkedHashMap<>();
|
||||
Map<Integer, StaticTextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
Map<Integer, TextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
normalizer.normalizeFonts(tim.timelined.getSwf(), normalizedFonts, normalizedTexts);
|
||||
|
||||
|
||||
@@ -608,7 +609,7 @@ public class FrameExporter {
|
||||
|
||||
FontNormalizer normalizer = new FontNormalizer();
|
||||
Map<Integer, FontTag> normalizedFonts = new LinkedHashMap<>();
|
||||
Map<Integer, StaticTextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
Map<Integer, TextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
normalizer.normalizeFonts(tim.timelined.getSwf(), normalizedFonts, normalizedTexts);
|
||||
|
||||
File f = new File(foutdir + File.separator + "frames.pdf");
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.exporters;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.StaticTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -26,10 +27,10 @@ import java.util.Map;
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface RequiresNormalizedFonts {
|
||||
public void setNormalizedFonts(Map<Integer, FontTag> normalizedFonts, Map<Integer, StaticTextTag> normalizedTexts);
|
||||
public void setNormalizedFonts(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts);
|
||||
|
||||
public Map<Integer, FontTag> getNormalizedFonts();
|
||||
|
||||
public Map<Integer, StaticTextTag> getNormalizedTexts();
|
||||
public Map<Integer, TextTag> getNormalizedTexts();
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.exporters.modes.FontExportMode;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.StaticTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.types.BlendMode;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
@@ -98,10 +99,10 @@ public class SVGExporter implements RequiresNormalizedFonts {
|
||||
private double zoom;
|
||||
|
||||
private Map<Integer, FontTag> normalizedFonts = new LinkedHashMap<>();
|
||||
private Map<Integer, StaticTextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
private Map<Integer, TextTag> normalizedTexts = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public void setNormalizedFonts(Map<Integer, FontTag> normalizedFonts, Map<Integer, StaticTextTag> normalizedTexts) {
|
||||
public void setNormalizedFonts(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts) {
|
||||
this.normalizedFonts = normalizedFonts;
|
||||
this.normalizedTexts = normalizedTexts;
|
||||
}
|
||||
@@ -112,7 +113,7 @@ public class SVGExporter implements RequiresNormalizedFonts {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, StaticTextTag> getNormalizedTexts() {
|
||||
public Map<Integer, TextTag> getNormalizedTexts() {
|
||||
return normalizedTexts;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.RequiresNormalizedFonts;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
@@ -326,8 +327,8 @@ public class DefineEditTextTag extends TextTag {
|
||||
case '\'':
|
||||
str = "'";
|
||||
break;
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
int lastHtmlSourcePos = -1;
|
||||
for (TEXTRECORD r : recs) {
|
||||
if (r instanceof AdvancedTextRecord) {
|
||||
@@ -616,7 +617,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
addCharacters(ret, txt, style);
|
||||
}
|
||||
};
|
||||
*/
|
||||
*/
|
||||
|
||||
XmlLexer lexer = new XmlLexer(new StringReader(str));
|
||||
try {
|
||||
@@ -803,7 +804,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
} catch (ParserConfigurationException | SAXException | IOException ex) {
|
||||
Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, "Error parsing text " + getCharacterId(), ex);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
} else {
|
||||
addCharacters(ret, str, style, 0);
|
||||
}
|
||||
@@ -1283,6 +1284,12 @@ public class DefineEditTextTag extends TextTag {
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) {
|
||||
int realTextId = getSwf().getCharacterId(this);
|
||||
if (exporter.getNormalizedTexts().containsKey(realTextId) && exporter.getNormalizedTexts().get(realTextId) instanceof DefineEditTextTag) {
|
||||
DefineEditTextTag normalizedText = (DefineEditTextTag) exporter.getNormalizedTexts().get(realTextId);
|
||||
normalizedText.render(TextRenderMode.SVG, null, exporter, null, new Matrix(), colorTransform, 1, 0, 0);
|
||||
return;
|
||||
}
|
||||
render(TextRenderMode.SVG, null, exporter, null, new Matrix(), colorTransform, 1, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1292,6 +1299,16 @@ public class DefineEditTextTag extends TextTag {
|
||||
}
|
||||
|
||||
private void render(TextRenderMode renderMode, SerializableImage image, SVGExporter svgExporter, StringBuilder htmlCanvasBuilder, Matrix transformation, ColorTransform colorTransform, double zoom, int selectionStart, int selectionEnd) {
|
||||
if (image.getGraphics() instanceof RequiresNormalizedFonts) {
|
||||
RequiresNormalizedFonts g = (RequiresNormalizedFonts) image.getGraphics();
|
||||
Map<Integer, TextTag> normalizedTexts = g.getNormalizedTexts();
|
||||
int realTextId = getSwf().getCharacterId(this);
|
||||
if (normalizedTexts.containsKey(realTextId) && normalizedTexts.get(realTextId) instanceof DefineEditTextTag && normalizedTexts.get(realTextId) != this) {
|
||||
DefineEditTextTag normalizedText = (DefineEditTextTag) normalizedTexts.get(realTextId);
|
||||
normalizedText.render(renderMode, image, svgExporter, htmlCanvasBuilder, transformation, colorTransform, zoom, selectionStart, selectionEnd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (border) {
|
||||
// border is always black, fill color is always white?
|
||||
RGB borderColor = new RGBA(Color.black);
|
||||
@@ -1606,7 +1623,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
txt = txt.replace("'", "'");
|
||||
return txt;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, String> getNameProperties() {
|
||||
Map<String, String> ret = super.getNameProperties();
|
||||
@@ -1616,4 +1633,5 @@ public class DefineEditTextTag extends TextTag {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -423,6 +423,18 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
* @return System font name
|
||||
*/
|
||||
public String getSystemFontName() {
|
||||
String ret = getSystemFontNameNoDefault();
|
||||
if (ret == null) {
|
||||
return defaultFontName;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets system font name without backup to default font
|
||||
* @return System font name
|
||||
*/
|
||||
public String getSystemFontNameNoDefault() {
|
||||
FontTag.ensureLoaded();
|
||||
int fontId = getCharacterId();
|
||||
String selectedFont = swf.sourceFontNamesMap.get(fontId);
|
||||
@@ -443,7 +455,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
}
|
||||
|
||||
// findInstalledFontName always returns an available font name
|
||||
return FontTag.findInstalledFontName(getFontName());
|
||||
return FontTag.findInstalledFontNameNoDefault(getFontName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,11 +676,11 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds installed font name.
|
||||
* Finds installed font name without backup to default font name
|
||||
* @param fontName Font name
|
||||
* @return Installed font name
|
||||
*/
|
||||
public static String findInstalledFontName(String fontName) {
|
||||
public static String findInstalledFontNameNoDefault(String fontName) {
|
||||
ensureLoaded();
|
||||
if (installedFontsByName.containsKey(fontName)) {
|
||||
return fontName;
|
||||
@@ -679,7 +691,20 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
return beforeUnderscore;
|
||||
}
|
||||
}
|
||||
return defaultFontName;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds installed font name.
|
||||
* @param fontName Font name
|
||||
* @return Installed font name
|
||||
*/
|
||||
public static String findInstalledFontName(String fontName) {
|
||||
String ret = findInstalledFontNameNoDefault(fontName);
|
||||
if (ret == null) {
|
||||
return defaultFontName;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1030,10 +1030,10 @@ public abstract class StaticTextTag extends TextTag {
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, ExportRectangle viewRectRaw, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) {
|
||||
if (image.getGraphics() instanceof RequiresNormalizedFonts) {
|
||||
RequiresNormalizedFonts g = (RequiresNormalizedFonts) image.getGraphics();
|
||||
Map<Integer, StaticTextTag> normalizedTexts = g.getNormalizedTexts();
|
||||
Map<Integer, TextTag> normalizedTexts = g.getNormalizedTexts();
|
||||
int realTextId = getSwf().getCharacterId(this);
|
||||
if (normalizedTexts.containsKey(realTextId)) {
|
||||
StaticTextTag normalizedText = normalizedTexts.get(realTextId);
|
||||
if (normalizedTexts.containsKey(realTextId) && normalizedTexts.get(realTextId) instanceof StaticTextTag) {
|
||||
StaticTextTag normalizedText = (StaticTextTag) normalizedTexts.get(realTextId);
|
||||
staticTextToImage(swf, normalizedText.textRecords, getTextNum(), image, normalizedText.textMatrix, transformation, colorTransform, renderContext.selectionText == this ? renderContext.selectionStart : 0, renderContext.selectionText == this ? renderContext.selectionEnd : 0);
|
||||
return;
|
||||
}
|
||||
@@ -1053,8 +1053,8 @@ public abstract class StaticTextTag extends TextTag {
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) {
|
||||
int realTextId = getSwf().getCharacterId(this);
|
||||
if (exporter.getNormalizedTexts().containsKey(realTextId)) {
|
||||
StaticTextTag normalizedText = exporter.getNormalizedTexts().get(realTextId);
|
||||
if (exporter.getNormalizedTexts().containsKey(realTextId) && exporter.getNormalizedTexts().get(realTextId) instanceof StaticTextTag) {
|
||||
StaticTextTag normalizedText = (StaticTextTag) exporter.getNormalizedTexts().get(realTextId);
|
||||
staticTextToSVG(swf, normalizedText.textRecords, getTextNum(), exporter, getRect(), normalizedText.textMatrix, colorTransform, exporter.getZoom(), transformation);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -386,9 +386,10 @@ public abstract class TextTag extends DrawableTag {
|
||||
* Gets text records attributes.
|
||||
* @param list Text records
|
||||
* @param swf SWF
|
||||
* @param normalizedFonts Normalized fonts
|
||||
* @return Text records attributes
|
||||
*/
|
||||
public static Map<String, Object> getTextRecordsAttributes(List<TEXTRECORD> list, SWF swf) {
|
||||
public static Map<String, Object> getTextRecordsAttributes(List<TEXTRECORD> list, SWF swf, Map<Integer, FontTag> normalizedFonts) {
|
||||
Map<String, Object> att = new HashMap<>();
|
||||
RECT textBounds = new RECT(Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE);
|
||||
FontTag font = null;
|
||||
@@ -416,8 +417,14 @@ public abstract class TextTag extends DrawableTag {
|
||||
if (rec.styleFlagsHasFont) {
|
||||
FontTag font2 = rec.getFont(swf);
|
||||
if (font2 != null) {
|
||||
|
||||
int fontId = swf.getCharacterId(font2);
|
||||
if (normalizedFonts.containsKey(fontId)) {
|
||||
font2 = normalizedFonts.get(fontId);
|
||||
}
|
||||
|
||||
font = font2;
|
||||
}
|
||||
}
|
||||
textHeight = rec.textHeight;
|
||||
if (font == null) {
|
||||
Logger.getLogger(TextTag.class.getName()).log(Level.SEVERE, "Font with id={0} was not found.", rec.fontId);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.xfl;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.FlashPlayerVersion;
|
||||
import com.jpexs.decompiler.flash.FontNormalizer;
|
||||
import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -1574,16 +1575,16 @@ public class XFLConverter {
|
||||
return date.getTime() / 1000;
|
||||
}
|
||||
|
||||
private void convertLibrary(Reference<Integer> lastItemIdNumber, Set<CharacterTag> charactersExportedInFirstFrame, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, Map<CharacterTag, String> characterVariables, Map<CharacterTag, String> characterClasses, Map<CharacterTag, ScriptPack> characterScriptPacks, List<CharacterTag> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<String, byte[]> files, HashMap<String, byte[]> datfiles, FLAVersion flaVersion, XFLXmlWriter writer, Map<PlaceObjectTypeTag, MultiLevelClip> placeToMaskedSymbol, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
private void convertLibrary(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts, Reference<Integer> lastItemIdNumber, Set<CharacterTag> charactersExportedInFirstFrame, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, Map<CharacterTag, String> characterVariables, Map<CharacterTag, String> characterClasses, Map<CharacterTag, ScriptPack> characterScriptPacks, List<CharacterTag> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<String, byte[]> files, HashMap<String, byte[]> datfiles, FLAVersion flaVersion, XFLXmlWriter writer, Map<PlaceObjectTypeTag, MultiLevelClip> placeToMaskedSymbol, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
statusStack.pushStatus("media");
|
||||
convertMedia(lastItemIdNumber, charactersExportedInFirstFrame, lastImportedId, characterNameMap, characterImportLinkageURL, characters, swf, characterVariables, characterClasses, tags, files, datfiles, writer, statusStack);
|
||||
statusStack.popStatus();
|
||||
statusStack.pushStatus("symbols");
|
||||
convertSymbols(lastItemIdNumber, charactersExportedInFirstFrame, characterImportLinkageURL, characters, lastImportedId, characterNameMap, swf, characterVariables, characterClasses, characterScriptPacks, nonLibraryShapes, backgroundColor, tags, files, flaVersion, writer, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, smallShapes);
|
||||
convertSymbols(normalizedFonts, normalizedTexts, lastItemIdNumber, charactersExportedInFirstFrame, characterImportLinkageURL, characters, lastImportedId, characterNameMap, swf, characterVariables, characterClasses, characterScriptPacks, nonLibraryShapes, backgroundColor, tags, files, flaVersion, writer, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, smallShapes);
|
||||
statusStack.popStatus();
|
||||
}
|
||||
|
||||
private void convertSymbols(Reference<Integer> lastItemIdNumber, Set<CharacterTag> charactersExportedInFirstFrame, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, Map<CharacterTag, String> characterVariables, Map<CharacterTag, String> characterClasses, Map<CharacterTag, ScriptPack> characterScriptPacks, List<CharacterTag> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<String, byte[]> files, FLAVersion flaVersion, XFLXmlWriter writer, Map<PlaceObjectTypeTag, MultiLevelClip> placeToMaskedSymbol, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
private void convertSymbols(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts, Reference<Integer> lastItemIdNumber, Set<CharacterTag> charactersExportedInFirstFrame, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, Map<CharacterTag, String> characterVariables, Map<CharacterTag, String> characterClasses, Map<CharacterTag, ScriptPack> characterScriptPacks, List<CharacterTag> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<String, byte[]> files, FLAVersion flaVersion, XFLXmlWriter writer, Map<PlaceObjectTypeTag, MultiLevelClip> placeToMaskedSymbol, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
//boolean hasSymbol = false;
|
||||
Reference<Integer> nextClipId = new Reference<>(-1);
|
||||
writer.writeStartElement("symbols");
|
||||
@@ -1759,7 +1760,11 @@ public class XFLConverter {
|
||||
statusStack.popStatus();
|
||||
} else if (character instanceof TextTag) {
|
||||
statusStack.pushStatus(character.toString());
|
||||
convertText(frame, new AccessibilityBag() /*???*/, null, (TextTag) character, matrix, filters, recCharWriter, characterImportLinkageURL, lastImportedId, characterNameMap, characters);
|
||||
int realCharacterId = swf.getCharacterId(character);
|
||||
if (normalizedTexts.containsKey(realCharacterId)) {
|
||||
character = normalizedTexts.get(realCharacterId);
|
||||
}
|
||||
convertText(normalizedFonts, frame, new AccessibilityBag() /*???*/, null, (TextTag) character, matrix, filters, recCharWriter, characterImportLinkageURL, lastImportedId, characterNameMap, characters);
|
||||
statusStack.popStatus();
|
||||
} else if (character instanceof DefineVideoStreamTag) {
|
||||
statusStack.pushStatus(character.toString());
|
||||
@@ -1827,9 +1832,9 @@ public class XFLConverter {
|
||||
}
|
||||
final ScriptPack spriteScriptPack = characterScriptPacks.containsKey(sprite) ? characterScriptPacks.get(sprite) : null;
|
||||
|
||||
extractMultilevelClips(characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, sprite.getTags(), swf.getCharacterId(sprite), writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
extractMultilevelClips(normalizedFonts, normalizedTexts, characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, sprite.getTags(), swf.getCharacterId(sprite), writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
|
||||
convertTimelines(characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), sprite, swf.getCharacterId(sprite), characterVariables.get(sprite), nonLibraryShapes, tags, sprite.getTags(), getSymbolName(lastImportedId, characterNameMap, swf, symbol), flaVersion, files, symbolStr, spriteScriptPack, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
convertTimelines(normalizedFonts, normalizedTexts, characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), sprite, swf.getCharacterId(sprite), characterVariables.get(sprite), nonLibraryShapes, tags, sprite.getTags(), getSymbolName(lastImportedId, characterNameMap, swf, symbol), flaVersion, files, symbolStr, spriteScriptPack, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
|
||||
} else if (symbol instanceof ShapeTag) {
|
||||
symbolStr.writeStartElement("timeline");
|
||||
@@ -1870,11 +1875,11 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
statusStack.pushStatus("extracting multilevel clips");
|
||||
extractMultilevelClips(characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, swf.getTags(), -1, writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
extractMultilevelClips(normalizedFonts, normalizedTexts, characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, swf.getTags(), -1, writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
statusStack.popStatus();
|
||||
|
||||
statusStack.pushStatus("converting multiusage morphshapes");
|
||||
extractMultiUsageMorphShapes(characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, writer, swf, nonLibraryShapes, flaVersion, files, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
extractMultiUsageMorphShapes(normalizedFonts, normalizedTexts, characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, writer, swf, nonLibraryShapes, flaVersion, files, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
statusStack.popStatus();
|
||||
/*if (hasSymbol) {
|
||||
|
||||
@@ -2522,7 +2527,7 @@ public class XFLConverter {
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
private static void convertFrames(AccessibilityBag accessibility, String symbolName, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, List<Integer> onlyFrames, int startFrame, int endFrame, String prevStr, String afterStr, List<CharacterTag> nonLibraryShapes, ReadOnlyTagList timelineTags, int depth, FLAVersion flaVersion, XFLXmlWriter writer, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
private static void convertFrames(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts, AccessibilityBag accessibility, String symbolName, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, List<Integer> onlyFrames, int startFrame, int endFrame, String prevStr, String afterStr, List<CharacterTag> nonLibraryShapes, ReadOnlyTagList timelineTags, int depth, FLAVersion flaVersion, XFLXmlWriter writer, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
Logger.getLogger(XFLConverter.class.getName()).log(Level.FINE, "Converting frames of {0}", symbolName);
|
||||
boolean lastIn = false;
|
||||
XFLXmlWriter writer2 = new XFLXmlWriter();
|
||||
@@ -2771,7 +2776,11 @@ public class XFLConverter {
|
||||
shapeTween = false;
|
||||
if (character instanceof TextTag) {
|
||||
statusStack.pushStatus(character.toString());
|
||||
convertText(frame, accessibility, instanceName, (TextTag) character, matrix, filters, elementsWriter, characterImportLinkageURL, lastImportedId, characterNameMap, characters);
|
||||
int realCharacterId = swf.getCharacterId(character);
|
||||
if (normalizedTexts.containsKey(realCharacterId)) {
|
||||
character = normalizedTexts.get(realCharacterId);
|
||||
}
|
||||
convertText(normalizedFonts, frame, accessibility, instanceName, (TextTag) character, matrix, filters, elementsWriter, characterImportLinkageURL, lastImportedId, characterNameMap, characters);
|
||||
statusStack.popStatus();
|
||||
} else if (character instanceof DefineVideoStreamTag) {
|
||||
convertVideoInstance(instanceName, matrix, (DefineVideoStreamTag) character, elementsWriter);
|
||||
@@ -3956,6 +3965,8 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
private void addExtractedClip(
|
||||
Map<Integer, FontTag> normalizedFonts,
|
||||
Map<Integer, TextTag> normalizedTexts,
|
||||
Map<CharacterTag, ScriptPack> characterScriptPacks,
|
||||
Reference<Integer> lastItemIdNumber,
|
||||
Reference<Integer> lastImportedId,
|
||||
@@ -3978,7 +3989,7 @@ public class XFLConverter {
|
||||
) throws XMLStreamException {
|
||||
XFLXmlWriter symbolStr = new XFLXmlWriter();
|
||||
|
||||
extractMultilevelClips(characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, timelineTags, spriteId, writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
extractMultilevelClips(normalizedFonts, normalizedTexts, characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, timelineTags, spriteId, writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
|
||||
if (nextClipId.getVal() < 0) {
|
||||
nextClipId.setVal(swf.getNextCharacterId());
|
||||
@@ -3996,7 +4007,7 @@ public class XFLConverter {
|
||||
"lastModified", Long.toString(getTimestamp(swf))});
|
||||
symbolStr.writeAttribute("symbolType", "graphic");
|
||||
|
||||
convertTimelines(characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), null, objectId, "", nonLibraryShapes, timelineTags, timelineTags, getMaskedSymbolName(objectId), flaVersion, files, symbolStr, null, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
convertTimelines(normalizedFonts, normalizedTexts, characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), null, objectId, "", nonLibraryShapes, timelineTags, timelineTags, getMaskedSymbolName(objectId), flaVersion, files, symbolStr, null, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
|
||||
symbolStr.writeEndElement(); // DOMSymbolItem
|
||||
String symbolStr2 = prettyFormatXML(symbolStr.toString());
|
||||
@@ -4072,6 +4083,8 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
private void extractMultiUsageMorphShapes(
|
||||
Map<Integer, FontTag> normalizedFonts,
|
||||
Map<Integer, TextTag> normalizedTexts,
|
||||
Map<CharacterTag, ScriptPack> characterScriptPacks,
|
||||
Reference<Integer> lastItemIdNumber,
|
||||
Reference<Integer> lastImportedId,
|
||||
@@ -4117,7 +4130,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
convertTimelines(characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), null, objectId, "", nonLibraryShapes, swf.getTags(), new ReadOnlyTagList(timelineTags), getSymbolName(lastImportedId, characterNameMap, swf, swf.getCharacter(objectId)), flaVersion, files, symbolStr, null, new HashMap<>(), new ArrayList<>(), statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
convertTimelines(normalizedFonts, normalizedTexts, characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), null, objectId, "", nonLibraryShapes, swf.getTags(), new ReadOnlyTagList(timelineTags), getSymbolName(lastImportedId, characterNameMap, swf, swf.getCharacter(objectId)), flaVersion, files, symbolStr, null, new HashMap<>(), new ArrayList<>(), statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
|
||||
symbolStr.writeEndElement(); // DOMSymbolItem
|
||||
String symbolStr2 = prettyFormatXML(symbolStr.toString());
|
||||
@@ -4138,6 +4151,8 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
private void extractMultilevelClips(
|
||||
Map<Integer, FontTag> normalizedFonts,
|
||||
Map<Integer, TextTag> normalizedTexts,
|
||||
Map<CharacterTag, ScriptPack> characterScriptPacks,
|
||||
Reference<Integer> lastItemIdNumber,
|
||||
Reference<Integer> lastImportedId,
|
||||
@@ -4369,7 +4384,7 @@ public class XFLConverter {
|
||||
//set timelined?
|
||||
delegatedTimeline.add(showFrame);
|
||||
}
|
||||
addExtractedClip(characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, new ReadOnlyTagList(delegatedTimeline), spriteId, writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
addExtractedClip(normalizedFonts, normalizedTexts, characterScriptPacks, lastItemIdNumber, lastImportedId, characterNameMap, new ReadOnlyTagList(delegatedTimeline), spriteId, writer, swf, nextClipId, nonLibraryShapes, backgroundColor, flaVersion, files, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
placeToMaskedSymbol.put(secondPlace, new MultiLevelClip(secondPlace, nextClipId.getVal(), numFrames));
|
||||
}
|
||||
}
|
||||
@@ -4391,7 +4406,7 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
//Note: symbolId argument might be a virtual symbol like MaskedSymbol
|
||||
private void convertTimelines(Map<CharacterTag, ScriptPack> characterScriptPacks, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, AbcIndexing abcIndex, CharacterTag sprite, int symbolId, String linkageIdentifier, List<CharacterTag> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, String spriteName, FLAVersion flaVersion, HashMap<String, byte[]> files, XFLXmlWriter writer, ScriptPack scriptPack, Map<PlaceObjectTypeTag, MultiLevelClip> placeToMaskedSymbol, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
private void convertTimelines(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts, Map<CharacterTag, ScriptPack> characterScriptPacks, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, AbcIndexing abcIndex, CharacterTag sprite, int symbolId, String linkageIdentifier, List<CharacterTag> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, String spriteName, FLAVersion flaVersion, HashMap<String, byte[]> files, XFLXmlWriter writer, ScriptPack scriptPack, Map<PlaceObjectTypeTag, MultiLevelClip> placeToMaskedSymbol, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
ScriptPack characterScriptPack = sprite == null ? null : characterScriptPacks.containsKey(sprite) ? characterScriptPacks.get(sprite) : null;
|
||||
|
||||
if (sprite == null && symbolId == -1) {
|
||||
@@ -4782,7 +4797,7 @@ public class XFLConverter {
|
||||
"color", randomOutlineColor(),
|
||||
"layerType", "mask",
|
||||
"locked", "true"});
|
||||
convertFrames(accessibility, symbolName, lastImportedId, characterNameMap, swf, depthToFramesList.get(po.getDepth()), clipFrame, lastFrame, "", "", nonLibraryShapes, sceneTimelineTags, po.getDepth(), flaVersion, writer, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
convertFrames(normalizedFonts, normalizedTexts, accessibility, symbolName, lastImportedId, characterNameMap, swf, depthToFramesList.get(po.getDepth()), clipFrame, lastFrame, "", "", nonLibraryShapes, sceneTimelineTags, po.getDepth(), flaVersion, writer, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
writer.writeEndElement();
|
||||
|
||||
int parentIndex = index;
|
||||
@@ -4804,7 +4819,7 @@ public class XFLConverter {
|
||||
handledClips.add(po2);
|
||||
|
||||
for (int ndx = po.getClipDepth() - 1; ndx > po2.getClipDepth(); ndx--) {
|
||||
boolean nonEmpty = writeLayer(accessibility, symbolName, lastImportedId, characterNameMap, swf, index, depthToFramesList.get(ndx), ndx, clipFrame, lastFrame, parentIndex, writer, nonLibraryShapes, sceneTimelineTags, flaVersion, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
boolean nonEmpty = writeLayer(normalizedFonts, normalizedTexts, accessibility, symbolName, lastImportedId, characterNameMap, swf, index, depthToFramesList.get(ndx), ndx, clipFrame, lastFrame, parentIndex, writer, nonLibraryShapes, sceneTimelineTags, flaVersion, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
for (int i = clipFrame; i <= lastFrame; i++) {
|
||||
depthToFramesList.get(ndx).remove((Integer) i);
|
||||
}
|
||||
@@ -4883,7 +4898,7 @@ public class XFLConverter {
|
||||
}
|
||||
|
||||
for (int nd = po.getClipDepth() - 1; nd > po.getDepth(); nd--) {
|
||||
boolean nonEmpty = writeLayer(accessibility, symbolName, lastImportedId, characterNameMap, swf, index, depthToFramesList.get(nd), nd, clipFrame, lastFrame, parentIndex, writer, nonLibraryShapes, sceneTimelineTags, flaVersion, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
boolean nonEmpty = writeLayer(normalizedFonts, normalizedTexts, accessibility, symbolName, lastImportedId, characterNameMap, swf, index, depthToFramesList.get(nd), nd, clipFrame, lastFrame, parentIndex, writer, nonLibraryShapes, sceneTimelineTags, flaVersion, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
for (int i = clipFrame; i <= lastFrame; i++) {
|
||||
depthToFramesList.get(nd).remove((Integer) i);
|
||||
}
|
||||
@@ -4920,7 +4935,7 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
boolean nonEmpty = writeLayer(accessibility, symbolName, lastImportedId, characterNameMap, swf, index, depthToFramesList.get(d), d, 0, Integer.MAX_VALUE, -1, writer, nonLibraryShapes, sceneTimelineTags, flaVersion, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
boolean nonEmpty = writeLayer(normalizedFonts, normalizedTexts, accessibility, symbolName, lastImportedId, characterNameMap, swf, index, depthToFramesList.get(d), d, 0, Integer.MAX_VALUE, -1, writer, nonLibraryShapes, sceneTimelineTags, flaVersion, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
if (nonEmpty) {
|
||||
index++;
|
||||
}
|
||||
@@ -4959,7 +4974,7 @@ public class XFLConverter {
|
||||
writer.writeEndElement(); //DOMLayer
|
||||
}
|
||||
|
||||
private boolean writeLayer(AccessibilityBag accessibility, String symbolName, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, int index, List<Integer> onlyFrames, int d, int startFrame, int endFrame, int parentLayer, XFLXmlWriter writer, List<CharacterTag> nonLibraryShapes, ReadOnlyTagList timelineTags, FLAVersion flaVersion, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
private boolean writeLayer(Map<Integer, FontTag> normalizedFonts, Map<Integer, TextTag> normalizedTexts, AccessibilityBag accessibility, String symbolName, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, SWF swf, int index, List<Integer> onlyFrames, int d, int startFrame, int endFrame, int parentLayer, XFLXmlWriter writer, List<CharacterTag> nonLibraryShapes, ReadOnlyTagList timelineTags, FLAVersion flaVersion, List<Integer> multiUsageMorphShapes, StatusStack statusStack, Map<CharacterTag, String> characterImportLinkageURL, Set<CharacterTag> characters, Set<ShapeTag> smallShapes) throws XMLStreamException {
|
||||
XFLXmlWriter layerPrev = new XFLXmlWriter();
|
||||
statusStack.pushStatus("layer " + (index + 1));
|
||||
//System.err.println("- writing layer " + (index + 1) + (startFrame == 0 && endFrame == Integer.MAX_VALUE ? ", all frames": ", frame " + startFrame + " to " + endFrame));
|
||||
@@ -4978,7 +4993,7 @@ public class XFLConverter {
|
||||
layerPrev.writeCharacters(""); // todo honfika: hack to close start tag
|
||||
String layerAfter = "</DOMLayer>";
|
||||
int prevLength = writer.length();
|
||||
convertFrames(accessibility, symbolName, lastImportedId, characterNameMap, swf, onlyFrames, startFrame, endFrame, layerPrev.toString(), layerAfter, nonLibraryShapes, timelineTags, d, flaVersion, writer, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
convertFrames(normalizedFonts, normalizedTexts, accessibility, symbolName, lastImportedId, characterNameMap, swf, onlyFrames, startFrame, endFrame, layerPrev.toString(), layerAfter, nonLibraryShapes, timelineTags, d, flaVersion, writer, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
statusStack.popStatus();
|
||||
return writer.length() != prevLength;
|
||||
}
|
||||
@@ -5058,7 +5073,7 @@ public class XFLConverter {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void convertText(int frame, AccessibilityBag accessibility, String instanceName, TextTag tag, MATRIX m, List<FILTER> filters, XFLXmlWriter writer, Map<CharacterTag, String> characterImportLinkageURL, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, Set<CharacterTag> characters) throws XMLStreamException {
|
||||
private static void convertText(Map<Integer, FontTag> normalizedFonts, int frame, AccessibilityBag accessibility, String instanceName, TextTag tag, MATRIX m, List<FILTER> filters, XFLXmlWriter writer, Map<CharacterTag, String> characterImportLinkageURL, Reference<Integer> lastImportedId, Map<CharacterTag, String> characterNameMap, Set<CharacterTag> characters) throws XMLStreamException {
|
||||
MATRIX matrix = new MATRIX(m);
|
||||
CSMSettingsTag csmts = null;
|
||||
XFLXmlWriter filterStr = new XFLXmlWriter();
|
||||
@@ -5131,7 +5146,7 @@ public class XFLConverter {
|
||||
writer.writeAttribute("antiAliasSharpness", antiAliasSharpness);
|
||||
writer.writeAttribute("antiAliasThickness", antiAliasThickness);
|
||||
}
|
||||
Map<String, Object> attrs = TextTag.getTextRecordsAttributes(textRecords, swf);
|
||||
Map<String, Object> attrs = TextTag.getTextRecordsAttributes(textRecords, swf, normalizedFonts);
|
||||
writer.writeAttribute("width", tag.getBounds().getWidth() / 2);
|
||||
writer.writeAttribute("height", tag.getBounds().getHeight());
|
||||
writer.writeAttribute("autoExpand", true);
|
||||
@@ -5168,6 +5183,9 @@ public class XFLConverter {
|
||||
fontName = null;
|
||||
textHeight = rec.textHeight;
|
||||
font = ((Tag) tag).getSwf().getFont(fontId);
|
||||
if (normalizedFonts.containsKey(fontId)) {
|
||||
font = normalizedFonts.get(fontId);
|
||||
}
|
||||
|
||||
if (font != null) {
|
||||
DefineFontNameTag dfn = (DefineFontNameTag) font.getSwf().getCharacterIdTag(font.getCharacterId(), DefineFontNameTag.ID);
|
||||
@@ -5240,6 +5258,10 @@ public class XFLConverter {
|
||||
DefineEditTextTag det = (DefineEditTextTag) tag;
|
||||
String tagName;
|
||||
FontTag ft = det.getSwf().getFont(det.fontId);
|
||||
|
||||
if (normalizedFonts.containsKey(det.fontId)) {
|
||||
ft = normalizedFonts.get(det.fontId);
|
||||
}
|
||||
if (ft != null && ft.isSmall()) {
|
||||
fontRenderingMode = "bitmap";
|
||||
}
|
||||
@@ -5644,12 +5666,17 @@ public class XFLConverter {
|
||||
convertFonts(lastItemIdNumber, lastImportedId, characterNameMap, swf, characters, domDocument, statusStack, characterVariables, characterClasses, charactersExportedInFirstFrame, characterImportLinkageURL);
|
||||
|
||||
Set<ShapeTag> smallShapes = getSmallShapes(swf);
|
||||
|
||||
Map<Integer, FontTag> normalizedFonts = new HashMap<>();
|
||||
Map<Integer, TextTag> normalizedTexts = new HashMap<>();
|
||||
FontNormalizer fontNormalizer = new FontNormalizer();
|
||||
fontNormalizer.normalizeFonts(swf, normalizedFonts, normalizedTexts);
|
||||
|
||||
convertLibrary(lastItemIdNumber, charactersExportedInFirstFrame, characterImportLinkageURL, characters, lastImportedId, characterNameMap, swf, characterVariables, characterClasses, characterScriptPacks, nonLibraryShapes, backgroundColor, swf.getTags(), files, datfiles, flaVersion, domDocument, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, smallShapes);
|
||||
convertLibrary(normalizedFonts, normalizedTexts, lastItemIdNumber, charactersExportedInFirstFrame, characterImportLinkageURL, characters, lastImportedId, characterNameMap, swf, characterVariables, characterClasses, characterScriptPacks, nonLibraryShapes, backgroundColor, swf.getTags(), files, datfiles, flaVersion, domDocument, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, smallShapes);
|
||||
|
||||
//domDocument.writeStartElement("timelines");
|
||||
statusStack.pushStatus("main timeline");
|
||||
convertTimelines(characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), null, -1, null, nonLibraryShapes, swf.getTags(), swf.getTags(), null, flaVersion, files, domDocument, documentScriptPack, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
convertTimelines(normalizedFonts, normalizedTexts, characterScriptPacks, lastImportedId, characterNameMap, swf, swf.getAbcIndex(), null, -1, null, nonLibraryShapes, swf.getTags(), swf.getTags(), null, flaVersion, files, domDocument, documentScriptPack, placeToMaskedSymbol, multiUsageMorphShapes, statusStack, characterImportLinkageURL, characters, smallShapes);
|
||||
statusStack.popStatus();
|
||||
//domDocument.writeEndElement();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user