diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java index 927324cb8..f0fbb842d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont2Tag.java @@ -509,9 +509,14 @@ public class DefineFont2Tag extends FontTag { } } + @Override + public int getCharacterCount() { + return codeTable.size(); + } + @Override public String getCharacters() { - StringBuilder ret = new StringBuilder(); + StringBuilder ret = new StringBuilder(codeTable.size()); for (int i : codeTable) { ret.append((char) i); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java index 435954903..3ab20da72 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFont3Tag.java @@ -502,9 +502,14 @@ public class DefineFont3Tag extends FontTag { } } + @Override + public int getCharacterCount() { + return codeTable.size(); + } + @Override public String getCharacters() { - StringBuilder ret = new StringBuilder(); + StringBuilder ret = new StringBuilder(codeTable.size()); for (int i : codeTable) { ret.append((char) i); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java index bdb9a3f8a..740db9c07 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineFontTag.java @@ -311,15 +311,27 @@ public class DefineFontTag extends FontTag { } @Override - public String getCharacters() { - StringBuilder ret = new StringBuilder(); + public int getCharacterCount() { ensureFontInfo(); if (fontInfoTag != null) { - for (int i : fontInfoTag.getCodeTable()) { + List codeTable = fontInfoTag.getCodeTable(); + return codeTable.size(); + } + return 0; + } + + @Override + public String getCharacters() { + ensureFontInfo(); + if (fontInfoTag != null) { + List codeTable = fontInfoTag.getCodeTable(); + StringBuilder ret = new StringBuilder(codeTable.size()); + for (int i : codeTable) { ret.append((char) i); } + return ret.toString(); } - return ret.toString(); + return ""; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index 344a85864..cedff89c3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -153,6 +153,8 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable return fontStyle; } + public abstract int getCharacterCount(); + public abstract String getCharacters(); @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java index 746f7537c..f9ac3d68d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java @@ -314,6 +314,12 @@ public final class DefineCompactedFont extends FontTag { return fonts.get(0).leading; } + @Override + public int getCharacterCount() { + FontType ft = fonts.get(0); + return ft.glyphInfo.size(); + } + @Override public String getCharacters() { FontType ft = fonts.get(0); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index bc76caf7a..8e26d306a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1191,13 +1191,18 @@ public class XFLConverter { //TODO: Imported assets //linkageImportForRS="true" linkageIdentifier="xxx" linkageURL="yyy.swf" - List media = new ArrayList<>(); - List symbols = new ArrayList<>(); + convertMedia(swf, characterVariables, characterClasses, nonLibraryShapes, backgroundColor, tags, characters, files, datfiles, flaVersion, writer); + convertSymbols(swf, characterVariables, characterClasses, nonLibraryShapes, backgroundColor, tags, characters, files, datfiles, flaVersion, writer); + } + + private void convertSymbols(SWF swf, Map characterVariables, Map characterClasses, List nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap characters, HashMap files, HashMap datfiles, FLAVersion flaVersion, XFLXmlWriter writer) throws XMLStreamException { + boolean hasSymbol = false; for (int ch : characters.keySet()) { 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 } + if ((symbol instanceof ShapeTag) || (symbol instanceof DefineSpriteTag) || (symbol instanceof ButtonTag)) { StringBuilder symbolStr = new StringBuilder(); @@ -1331,7 +1336,9 @@ public class XFLConverter { if (sprite.getTags().isEmpty()) { //probably AS2 class continue; } - symbolStr.append(convertTimeline(sprite.spriteId, nonLibraryShapes, backgroundColor, tags, sprite.getTags(), characters, "Symbol " + symbol.getCharacterId(), flaVersion, files)); + XFLXmlWriter writer2 = new XFLXmlWriter(); // todo: remove + convertTimeline(sprite.spriteId, nonLibraryShapes, backgroundColor, tags, sprite.getTags(), characters, "Symbol " + symbol.getCharacterId(), flaVersion, files, writer2); + symbolStr.append(writer2.toString()); } else if (symbol instanceof ShapeTag) { itemIcon = "1"; ShapeTag shape = (ShapeTag) symbol; @@ -1361,8 +1368,27 @@ public class XFLConverter { //TODO: itemID=\"518de416-00000341\" } symbLinkStr += "/>"; - symbols.add(symbLinkStr); - } else if (symbol instanceof ImageTag) { + + if (!hasSymbol) { + writer.writeStartElement("symbols"); + } + + writer.writeCharactersRaw(symbLinkStr); + hasSymbol = true; + } + } + + if (hasSymbol) { + writer.writeEndElement(); + } + } + + private void convertMedia(SWF swf, Map characterVariables, Map characterClasses, List nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap characters, HashMap files, HashMap datfiles, FLAVersion flaVersion, XFLXmlWriter writer) throws XMLStreamException { + int mediaCount = 0; + for (int ch : characters.keySet()) { + CharacterTag symbol = characters.get(ch); + String mediaLinkStr = null; + if (symbol instanceof ImageTag) { ImageTag imageTag = (ImageTag) symbol; boolean allowSmoothing = false; @@ -1404,7 +1430,7 @@ public class XFLConverter { ImageFormat format = imageTag.getImageFormat(); String symbolFile = "bitmap" + symbol.getCharacterId() + imageTag.getImageFormat().getExtension(); files.put(symbolFile, imageBytes); - String mediaLinkStr = "\n"; - media.add(mediaLinkStr); + mediaLinkStr += " quality=\"50\" href=\"" + symbolFile + "\" bitmapDataHRef=\"M " + (mediaCount + 1) + " " + getTimestamp(swf) + ".dat\" frameRight=\"" + image.getWidth() + "\" frameBottom=\"" + image.getHeight() + "\"/>\n"; } else if ((symbol instanceof SoundStreamHeadTypeTag) || (symbol instanceof DefineSoundTag)) { int soundFormat = 0; @@ -1563,7 +1588,7 @@ public class XFLConverter { String symbolFile = "sound" + symbol.getCharacterId() + "." + exportFormat; files.put(symbolFile, data); - String mediaLinkStr = " 0) { writer.writeEndElement(); } } @@ -1827,7 +1846,7 @@ public class XFLConverter { return ret.toString(); } - private static void convertFrames(String prevStr, String afterStr, List nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap characters, int depth, FLAVersion flaVersion, HashMap files, StringBuilder ret) { + private static void convertFrames(String prevStr, String afterStr, List nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap characters, int depth, FLAVersion flaVersion, HashMap files, XFLXmlWriter writer) throws XMLStreamException { StringBuilder ret2 = new StringBuilder(); prevStr += ""; int frame = -1; @@ -1997,12 +2016,29 @@ public class XFLConverter { afterStr = "" + afterStr; if (ret2.length() > 0) { - ret.append(prevStr).append(ret2).append(afterStr); + writer.writeCharactersRaw(prevStr); + writer.writeCharactersRaw(ret2.toString()); + writer.writeCharactersRaw(afterStr); } } private static void convertFonts(ReadOnlyTagList tags, XFLXmlWriter writer) throws XMLStreamException { - StringBuilder ret2 = new StringBuilder(); + boolean hasFont = false; + for (Tag t : tags) { + if (t instanceof FontTag) { + FontTag font = (FontTag) t; + if (font.getCharacterCount() > 0) { + hasFont = true; + } + } + } + + if (!hasFont) { + return; + } + + writer.writeStartElement("fonts"); + for (Tag t : tags) { if (t instanceof FontTag) { FontTag font = (FontTag) t; @@ -2069,16 +2105,22 @@ public class XFLConverter { if (hasAllRanges) { embedRanges = "9999"; } - ret2.append(""); + + writer.writeStartElement("DOMFontItem", new String[]{ + "name", "Font " + fontId, + "font", fontName, + "size", "0", + "id", Integer.toString(fontId), + "embedRanges", embedRanges}); + if (!"".equals(embeddedCharacters)) { + writer.writeAttribute("embeddedCharacters", embeddedCharacters); + } + + writer.writeEndElement(); } - } - if (ret2.length() > 0) { - writer.writeStartElement("fonts"); - writer.writeCharactersRaw(ret2.toString()); - writer.writeEndElement(); - } + writer.writeEndElement(); } private String convertActionScriptLayer(int spriteId, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, String backgroundColor) { @@ -2199,7 +2241,7 @@ public class XFLConverter { return retStr; } - private void convertSoundLayer(int layerIndex, String backgroundColor, HashMap characters, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, HashMap files, StringBuilder ret) { + private void convertSoundLayer(int layerIndex, String backgroundColor, HashMap characters, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, HashMap files, XFLXmlWriter writer) throws XMLStreamException { StringBuilder ret2 = new StringBuilder(); StartSoundTag lastStartSound = null; SoundStreamHeadTypeTag lastSoundStreamHead = null; @@ -2255,9 +2297,9 @@ public class XFLConverter { } if (ret2.length() > 0) { - ret.append("" - + "").append(ret2).append("" - + ""); + writer.writeStartElement("DOMLayer", new String[]{"Layer " + layerIndex, "color", randomOutlineColor()}); + writer.writeElementValue("frames", ret2.toString()); + writer.writeEndElement(); } } @@ -2271,15 +2313,14 @@ public class XFLConverter { return outlineColor.toHexRGB(); } - private String convertTimeline(int spriteId, List nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap characters, String name, FLAVersion flaVersion, HashMap files) { - StringBuilder ret = new StringBuilder(); - ret.append(""); - ret.append(""); + private void convertTimeline(int spriteId, List nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap characters, String name, FLAVersion flaVersion, HashMap files, XFLXmlWriter writer) throws XMLStreamException { + writer.writeStartElement("DOMTimeline", new String[]{"name", name}); + writer.writeStartElement("layers"); String labelsLayer = convertLabelsLayer(spriteId, tags, timelineTags, backgroundColor); - ret.append(labelsLayer); + writer.writeCharactersRaw(labelsLayer); String scriptLayer = convertActionScriptLayer(spriteId, tags, timelineTags, backgroundColor); - ret.append(scriptLayer); + writer.writeCharactersRaw(scriptLayer); int index = 0; @@ -2303,11 +2344,13 @@ public class XFLConverter { parentLayers.push(index); } - ret.append(""); - convertFrames("", "", nonLibraryShapes, tags, timelineTags, characters, po.getDepth(), flaVersion, files, ret); - ret.append(""); + writer.writeStartElement("DOMLayer", new String[]{ + "name", "Layer " + (index + 1), + "color", randomOutlineColor(), + "layerType", "mask", + "locked", "true"}); + convertFrames("", "", nonLibraryShapes, tags, timelineTags, characters, po.getDepth(), flaVersion, files, writer); + writer.writeEndElement(); index++; break; } @@ -2347,19 +2390,18 @@ public class XFLConverter { } layerPrev += ">"; String layerAfter = ""; - int prevLength = ret.length(); - convertFrames(layerPrev, layerAfter, nonLibraryShapes, tags, timelineTags, characters, d, flaVersion, files, ret); - if (ret.length() == prevLength) { + int prevLength = writer.length(); + convertFrames(layerPrev, layerAfter, nonLibraryShapes, tags, timelineTags, characters, d, flaVersion, files, writer); + if (writer.length() == prevLength) { index--; } } int soundLayerIndex = layerCount; layerCount++; - convertSoundLayer(soundLayerIndex, backgroundColor, characters, tags, timelineTags, files, ret); - ret.append(""); - ret.append(""); - return ret.toString(); + convertSoundLayer(soundLayerIndex, backgroundColor, characters, tags, timelineTags, files, writer); + writer.writeEndElement(); + writer.writeEndElement(); } private static void writeFile(AbortRetryIgnoreHandler handler, final byte[] data, final String file) throws IOException, InterruptedException { @@ -2806,7 +2848,7 @@ public class XFLConverter { convertLibrary(swf, characterVariables, characterClasses, nonLibraryShapes, backgroundColor, swf.getTags(), characters, files, datfiles, flaVersion, domDocument); domDocument.writeStartElement("timelines"); - domDocument.writeCharactersRaw(convertTimeline(0, nonLibraryShapes, backgroundColor, swf.getTags(), swf.getTags(), characters, "Scene 1", flaVersion, files)); + convertTimeline(0, nonLibraryShapes, backgroundColor, swf.getTags(), swf.getTags(), characters, "Scene 1", flaVersion, files, domDocument); domDocument.writeEndElement(); domDocument.writeEndElement(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLXmlWriter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLXmlWriter.java index e3b07128a..d63f945b4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLXmlWriter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLXmlWriter.java @@ -346,4 +346,8 @@ public class XFLXmlWriter implements XMLStreamWriter { } return text; } + + public int length() { + return sb.length(); + } }