mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-13 03:54:11 +00:00
Merge origin/master
This commit is contained in:
@@ -90,6 +90,7 @@ import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import com.jpexs.decompiler.flash.tags.DebugIDTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag;
|
||||
@@ -439,6 +440,21 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return characterIdTags.get(characterId);
|
||||
}
|
||||
|
||||
public CharacterIdTag getCharacterIdTag(int characterId, int tagId) {
|
||||
List<CharacterIdTag> characterIdTags = getCharacterIdTags(characterId);
|
||||
if (characterIdTags != null) {
|
||||
for (CharacterIdTag t : characterIdTags) {
|
||||
if (((Tag) t).getId() == tagId) {
|
||||
if (t.getCharacterId() == characterId) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<Integer, Set<Integer>> getDependentCharacters() {
|
||||
if (dependentCharacters == null) {
|
||||
synchronized (this) {
|
||||
@@ -554,6 +570,19 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return null;
|
||||
}
|
||||
|
||||
public DefineSoundTag getSound(int soundId) {
|
||||
CharacterTag characterTag = getCharacters().get(soundId);
|
||||
if (characterTag instanceof DefineSoundTag) {
|
||||
return (DefineSoundTag) characterTag;
|
||||
}
|
||||
|
||||
if (characterTag != null) {
|
||||
logger.log(Level.SEVERE, "CharacterTag should be a DefineSoundTag. characterId: {0}", soundId);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public TextTag getText(int textId) {
|
||||
CharacterTag characterTag = getCharacters().get(textId);
|
||||
if (characterTag instanceof TextTag) {
|
||||
@@ -2497,6 +2526,12 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearAllStaticCache() {
|
||||
Cache.clearAll();
|
||||
Helper.clearShapeCache();
|
||||
System.gc();
|
||||
}
|
||||
|
||||
public void clearAllCache() {
|
||||
characters = null;
|
||||
characterIdTags = null;
|
||||
@@ -2505,9 +2540,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
clearReadOnlyListCache();
|
||||
clearImageCache();
|
||||
clearScriptCache();
|
||||
Cache.clearAll();
|
||||
Helper.clearShapeCache();
|
||||
System.gc();
|
||||
clearAllStaticCache();
|
||||
}
|
||||
|
||||
public static void uncache(ASMSource src) {
|
||||
@@ -2664,7 +2697,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static SerializableImage frameToImageGet(Timeline timeline, int frame, int time, Point cursorPosition, int mouseButton, RECT displayRect, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform, Color backGroundColor, double zoom) {
|
||||
public static SerializableImage frameToImageGet(Timeline timeline, int frame, int time, Point cursorPosition, int mouseButton, RECT displayRect, Matrix transformation, ColorTransform colorTransform, Color backGroundColor, double zoom) {
|
||||
if (timeline.getFrameCount() == 0) {
|
||||
return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB);
|
||||
}
|
||||
@@ -2687,7 +2720,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
RenderContext renderContext = new RenderContext();
|
||||
renderContext.cursorPosition = cursorPosition;
|
||||
renderContext.mouseButton = mouseButton;
|
||||
timeline.toImage(frame, time, renderContext, image, false, m, transformation, absoluteTransformation, colorTransform);
|
||||
timeline.toImage(frame, time, renderContext, image, false, m, transformation, m, colorTransform);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.dumpview;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.TagStub;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -31,7 +33,7 @@ import java.util.logging.Logger;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DumpInfo {
|
||||
public class DumpInfo implements TreeItem {
|
||||
|
||||
public String name;
|
||||
|
||||
@@ -145,4 +147,18 @@ public class DumpInfo {
|
||||
return resolvedTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
Tag tag = getTag();
|
||||
if (tag != null) {
|
||||
return tag.getSwf();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,12 +196,12 @@ public class FrameExporter {
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
if (fbackgroundColor != null) {
|
||||
exporter.setBackGroundColor(fbackgroundColor);
|
||||
}
|
||||
|
||||
tim.toSVG(frame, 0, null, 0, exporter, null, 0, settings.zoom);
|
||||
tim.toSVG(frame, 0, null, 0, exporter, null, 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
ret.add(f);
|
||||
@@ -360,7 +360,7 @@ public class FrameExporter {
|
||||
}
|
||||
|
||||
int fframe = fframes.get(pos++);
|
||||
BufferedImage result = SWF.frameToImageGet(ftim, fframe, fframe, null, 0, ftim.displayRect, new Matrix(), new Matrix(), null, fbackgroundColor, settings.zoom).getBufferedImage();
|
||||
BufferedImage result = SWF.frameToImageGet(ftim, fframe, fframe, null, 0, ftim.displayRect, new Matrix(), null, fbackgroundColor, settings.zoom).getBufferedImage();
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("frame", pos, fframes.size(), tagName);
|
||||
|
||||
@@ -96,8 +96,8 @@ public class MorphShapeExporter {
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect);
|
||||
mst.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
mst.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -107,8 +107,8 @@ public class ShapeExporter {
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect);
|
||||
st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
break;
|
||||
@@ -119,8 +119,7 @@ public class ShapeExporter {
|
||||
int newHeight = (int) (rect.getHeight() * settings.zoom / SWF.unitDivisor) + 1;
|
||||
SerializableImage img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB);
|
||||
img.fillTransparent();
|
||||
Matrix m = new Matrix();
|
||||
m.translate(-rect.Xmin, -rect.Ymin);
|
||||
Matrix m = Matrix.getTranslateInstance(-rect.Xmin, -rect.Ymin);
|
||||
m.scale(settings.zoom);
|
||||
st.toImage(0, 0, 0, new RenderContext(), img, false, m, m, m, new CXFORMWITHALPHA());
|
||||
if (settings.mode == ShapeExportMode.PNG) {
|
||||
|
||||
@@ -82,8 +82,8 @@ public class TextExporter {
|
||||
new RetryTask(() -> {
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
ExportRectangle rect = new ExportRectangle(textTag.getRect());
|
||||
SVGExporter exporter = new SVGExporter(rect);
|
||||
textTag.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
textTag.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
}, handler).run();
|
||||
|
||||
@@ -189,8 +189,8 @@ public final class Matrix implements Cloneable {
|
||||
}
|
||||
|
||||
public void translate(double x, double y) {
|
||||
translateX += x;
|
||||
translateY += y;
|
||||
translateX = scaleX * x + rotateSkew1 * y + translateX;
|
||||
translateY = rotateSkew0 * x + scaleY * y + translateY;
|
||||
}
|
||||
|
||||
public void scale(double factor) {
|
||||
|
||||
@@ -80,11 +80,9 @@ public class SVGExporter {
|
||||
|
||||
private final HashSet<String> fontFaces = new HashSet<>();
|
||||
|
||||
private String clip;
|
||||
|
||||
public boolean useTextTag = Configuration.textExportExportFontFace.get();
|
||||
|
||||
public SVGExporter(ExportRectangle bounds) {
|
||||
public SVGExporter(ExportRectangle bounds, double zoom) {
|
||||
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
@@ -98,7 +96,7 @@ public class SVGExporter {
|
||||
if (bounds != null) {
|
||||
svgRoot.setAttribute("width", (bounds.getWidth() / SWF.unitDivisor) + "px");
|
||||
svgRoot.setAttribute("height", (bounds.getHeight() / SWF.unitDivisor) + "px");
|
||||
createDefGroup(bounds, null);
|
||||
createDefGroup(bounds, null, zoom);
|
||||
}
|
||||
} catch (ParserConfigurationException ex) {
|
||||
Logger.getLogger(SVGExporter.class.getName()).log(Level.SEVERE, null, ex);
|
||||
@@ -125,10 +123,15 @@ public class SVGExporter {
|
||||
}
|
||||
|
||||
public final void createDefGroup(ExportRectangle bounds, String id) {
|
||||
createDefGroup(bounds, id, 1);
|
||||
}
|
||||
|
||||
public final void createDefGroup(ExportRectangle bounds, String id, double zoom) {
|
||||
Element g = _svg.createElement("g");
|
||||
if (bounds != null) {
|
||||
g.setAttribute("transform", "matrix(1, 0, 0, 1, "
|
||||
+ roundPixels20(-bounds.xMin / (double) SWF.unitDivisor) + ", " + roundPixels20(-bounds.yMin / (double) SWF.unitDivisor) + ")");
|
||||
Matrix mat = Matrix.getTranslateInstance(-bounds.xMin, -bounds.yMin);
|
||||
mat.scale(zoom);
|
||||
g.setAttribute("transform", mat.getSvgTransformationString(SWF.unitDivisor, 1));
|
||||
}
|
||||
if (id != null) {
|
||||
g.setAttribute("id", id);
|
||||
@@ -150,7 +153,10 @@ public class SVGExporter {
|
||||
|
||||
public final Element createSubGroup(Matrix transform, String id) {
|
||||
Element group = createSubGroup(id, "g");
|
||||
group.setAttribute("transform", transform.getSvgTransformationString(SWF.unitDivisor, 1));
|
||||
if (transform != null) {
|
||||
group.setAttribute("transform", transform.getSvgTransformationString(SWF.unitDivisor, 1));
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -218,9 +224,6 @@ public class SVGExporter {
|
||||
image.setAttribute("id", instanceName);
|
||||
}
|
||||
image.setAttribute("xlink:href", "#" + href);
|
||||
if (clip != null) {
|
||||
image.setAttribute("clip-path", "url(#" + clip + ")");
|
||||
}
|
||||
_svgGs.peek().appendChild(image);
|
||||
return image;
|
||||
}
|
||||
@@ -257,14 +260,6 @@ public class SVGExporter {
|
||||
return prefix + lastId;
|
||||
}
|
||||
|
||||
public void setClip(String clip) {
|
||||
this.clip = clip;
|
||||
}
|
||||
|
||||
public String getClip() {
|
||||
return clip;
|
||||
}
|
||||
|
||||
protected static double roundPixels20(double pixels) {
|
||||
return Math.round(pixels * 100) / 100.0;
|
||||
}
|
||||
|
||||
@@ -429,12 +429,15 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
preLineFillData.append("\tctx.fillStyle=").append(lineLastRadColor).append(";\r\n\tctx.fill(\"evenodd\");\r\n");
|
||||
}
|
||||
|
||||
preLineFillData.append("\tctx.transform(").append(Helper.doubleStr(lineFillMatrix.scaleX / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr(lineFillMatrix.rotateSkew0 / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr(lineFillMatrix.rotateSkew1 / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr(lineFillMatrix.scaleY / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr((lineFillMatrix.translateX + deltaX) / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr((lineFillMatrix.translateY + deltaY) / unitDivisor)).append(");\r\n");
|
||||
if (lineFillMatrix != null) {
|
||||
preLineFillData.append("\tctx.transform(").append(Helper.doubleStr(lineFillMatrix.scaleX / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr(lineFillMatrix.rotateSkew0 / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr(lineFillMatrix.rotateSkew1 / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr(lineFillMatrix.scaleY / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr((lineFillMatrix.translateX + deltaX) / unitDivisor))
|
||||
.append(",").append(Helper.doubleStr((lineFillMatrix.translateY + deltaY) / unitDivisor)).append(");\r\n");
|
||||
}
|
||||
|
||||
lineFillData.insert(0, preLineFillData);
|
||||
lineFillData.append("\tctx.fillRect(").append(-16384 - 32768 * lineRepeatCnt).append(",").append(-16384 - 32768 * lineRepeatCnt).append(",").append(2 * 16384 + 32768 * 2 * lineRepeatCnt).append(",").append(2 * 16384 + 32768 * 2 * lineRepeatCnt).append(");\r\n");
|
||||
|
||||
|
||||
@@ -117,7 +117,6 @@ public class ImageImporter extends TagImporter {
|
||||
int alpha = (imgData[y * width + x] >> 24) & 0xff;
|
||||
data[y * width + x] = (byte) alpha;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
newData = data;
|
||||
|
||||
@@ -128,7 +128,7 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(ba));
|
||||
} else {
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(new byte[0]));
|
||||
}
|
||||
|
||||
imageData = new ByteArrayRange(data);
|
||||
|
||||
@@ -133,7 +133,7 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
|
||||
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(ba));
|
||||
} else {
|
||||
bitmapAlphaData = ByteArrayRange.EMPTY;
|
||||
bitmapAlphaData = new ByteArrayRange(SWFOutputStream.compressByteArray(new byte[0]));
|
||||
}
|
||||
|
||||
imageData = new ByteArrayRange(data);
|
||||
|
||||
@@ -43,22 +43,22 @@ public class DefineButtonSoundTag extends Tag implements CharacterIdTag {
|
||||
public int buttonId;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int buttonSoundChar0;
|
||||
public int buttonSoundChar0; // OverUpToIdle
|
||||
|
||||
public SOUNDINFO buttonSoundInfo0;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int buttonSoundChar1;
|
||||
public int buttonSoundChar1; // IdleToOverUp
|
||||
|
||||
public SOUNDINFO buttonSoundInfo1;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int buttonSoundChar2;
|
||||
public int buttonSoundChar2; // OverUpToOverDown
|
||||
|
||||
public SOUNDINFO buttonSoundInfo2;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int buttonSoundChar3;
|
||||
public int buttonSoundChar3; // OverDownToOverUp
|
||||
|
||||
public SOUNDINFO buttonSoundInfo3;
|
||||
|
||||
|
||||
@@ -233,13 +233,8 @@ public class DefineButtonTag extends ButtonTag implements ASMSourceContainer {
|
||||
|
||||
@Override
|
||||
protected void initTimeline(Timeline timeline) {
|
||||
ColorTransform clrTrans = null;
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineButtonCxformTag) {
|
||||
DefineButtonCxformTag cx = (DefineButtonCxformTag) t;
|
||||
clrTrans = cx.buttonColorTransform;
|
||||
}
|
||||
}
|
||||
DefineButtonCxformTag cxformTag = (DefineButtonCxformTag) swf.getCharacterIdTag(buttonId, DefineButtonCxformTag.ID);
|
||||
ColorTransform clrTrans = cxformTag == null ? null : cxformTag.buttonColorTransform;
|
||||
int maxDepth = 0;
|
||||
Frame frameUp = new Frame(timeline, 0);
|
||||
Frame frameDown = new Frame(timeline, 0);
|
||||
|
||||
@@ -934,8 +934,8 @@ public class DefineEditTextTag extends TextTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
render(TextRenderMode.SVG, null, exporter, null, new Matrix(), colorTransform, zoom);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
render(TextRenderMode.SVG, null, exporter, null, new Matrix(), colorTransform, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -187,11 +187,13 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
}
|
||||
}
|
||||
if (r != null) {
|
||||
foundSomething = true;
|
||||
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
|
||||
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
|
||||
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
|
||||
ret.Ymax = Math.max(r.Ymax, ret.Ymax);
|
||||
if (r.Xmin < r.Xmax && r.Ymin < r.Ymax) {
|
||||
foundSomething = true;
|
||||
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
|
||||
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
|
||||
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
|
||||
ret.Ymax = Math.max(r.Ymax, ret.Ymax);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundSomething) {
|
||||
@@ -256,8 +258,8 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
r.Ymin = (int) Math.min(Math.min(Math.min(topleft.y, topright.y), bottomleft.y), bottomright.y);
|
||||
r.Xmax = (int) Math.max(Math.max(Math.max(topleft.x, topright.x), bottomleft.x), bottomright.x);
|
||||
r.Ymax = (int) Math.max(Math.max(Math.max(topleft.y, topright.y), bottomleft.y), bottomright.y);
|
||||
|
||||
}
|
||||
|
||||
ret.Xmin = Math.min(r.Xmin, ret.Xmin);
|
||||
ret.Ymin = Math.min(r.Ymin, ret.Ymin);
|
||||
ret.Xmax = Math.max(r.Xmax, ret.Xmax);
|
||||
@@ -371,8 +373,8 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -97,24 +97,12 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1);
|
||||
}
|
||||
|
||||
public DefineButtonSoundTag getSounds() {
|
||||
List<CharacterIdTag> characterIdTags = swf.getCharacterIdTags(getCharacterId());
|
||||
if (characterIdTags != null) {
|
||||
for (CharacterIdTag t : characterIdTags) {
|
||||
if (t instanceof DefineButtonSoundTag) {
|
||||
DefineButtonSoundTag st = (DefineButtonSoundTag) t;
|
||||
if (st.buttonId == getCharacterId()) {
|
||||
return st;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return (DefineButtonSoundTag) swf.getCharacterIdTag(getCharacterId(), DefineButtonSoundTag.ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.tags.DefineScalingGridTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -78,12 +77,6 @@ public abstract class CharacterTag extends Tag implements CharacterIdTag {
|
||||
}
|
||||
|
||||
public DefineScalingGridTag getScalingGridTag() {
|
||||
List<CharacterIdTag> mtags = swf.getCharacterIdTags(getCharacterId());
|
||||
for (CharacterIdTag ct : mtags) {
|
||||
if (ct instanceof DefineScalingGridTag) {
|
||||
return (DefineScalingGridTag) ct;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return (DefineScalingGridTag) swf.getCharacterIdTag(getCharacterId(), DefineScalingGridTag.ID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface DrawableTag extends BoundedTag {
|
||||
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix prevTransformation, Matrix absoluteTransformation, ColorTransform colorTransform);
|
||||
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException;
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException;
|
||||
|
||||
public void toHtmlCanvas(StringBuilder result, double unitDivisor);
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -290,8 +290,8 @@ public abstract class ImageTag extends CharacterTag implements DrawableTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, getShape(), exporter, null, colorTransform, zoom);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, getShape(), exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
}
|
||||
|
||||
|
||||
@@ -289,15 +289,15 @@ public abstract class MorphShapeTag extends CharacterTag implements DrawableTag
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
if (ratio == -2) {
|
||||
SHAPEWITHSTYLE beginShapes = getShapeAtRatio(0);
|
||||
SHAPEWITHSTYLE endShapes = getShapeAtRatio(65535);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(swf, beginShapes, endShapes, exporter, null, colorTransform, zoom);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(swf, beginShapes, endShapes, exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
} else {
|
||||
SHAPEWITHSTYLE shapes = getShapeAtRatio(ratio);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, shapes, exporter, null, colorTransform, zoom);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, shapes, exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +179,8 @@ public abstract class ShapeTag extends CharacterTag implements DrawableTag, Lazy
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, getShapes(), exporter, null, colorTransform, zoom);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, getShapes(), exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
}
|
||||
|
||||
|
||||
@@ -666,8 +666,8 @@ public abstract class StaticTextTag extends TextTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
staticTextToSVG(swf, textRecords, getTextNum(), exporter, getRect(), textMatrix, colorTransform, zoom);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
staticTextToSVG(swf, textRecords, getTextNum(), exporter, getRect(), textMatrix, colorTransform, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.jpexs.decompiler.flash.exporters.modes.FontExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter;
|
||||
import com.jpexs.decompiler.flash.helpers.FontHelper;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedText;
|
||||
import com.jpexs.decompiler.flash.importers.TextImportResizeTextBoundsMode;
|
||||
import com.jpexs.decompiler.flash.tags.text.JustifyAlignGlyphEntry;
|
||||
@@ -451,6 +450,8 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
List<SHAPE> glyphs = null;
|
||||
Matrix mat0 = transformation.clone();
|
||||
mat0 = mat0.concatenate(new Matrix(textMatrix));
|
||||
for (TEXTRECORD rec : textRecords) {
|
||||
if (rec.styleFlagsHasColor) {
|
||||
if (numText == 2) {
|
||||
@@ -481,13 +482,13 @@ public abstract class TextTag extends CharacterTag implements DrawableTag {
|
||||
double divider = font == null ? 1 : font.getDivider();
|
||||
double rat = textHeight / 1024.0 / divider;
|
||||
|
||||
Matrix matScale = Matrix.getScaleInstance(rat);
|
||||
Color textColor2 = new Color(textColor, true);
|
||||
for (GLYPHENTRY entry : rec.glyphEntries) {
|
||||
Matrix mat = transformation.clone();
|
||||
mat = mat.concatenate(new Matrix(textMatrix));
|
||||
Matrix matTr = Matrix.getTranslateInstance(x, y);
|
||||
mat = mat.concatenate(matTr);
|
||||
mat = mat.concatenate(Matrix.getScaleInstance(rat));
|
||||
matScale.translateX = x;
|
||||
matScale.translateY = y;
|
||||
|
||||
Matrix mat = mat0.concatenate(matScale);
|
||||
SHAPE shape = null;
|
||||
if (entry.glyphIndex != -1 && glyphs != null) {
|
||||
// shapeNum: 1
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.FrameExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Point;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.tags.DefineScalingGridTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||
@@ -66,7 +65,6 @@ import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -74,9 +72,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -557,47 +553,47 @@ public class Timeline {
|
||||
}
|
||||
|
||||
/*public void toImage(int frame, int time, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix prevTransformation, Matrix absoluteTransformation, ColorTransform colorTransform) {
|
||||
ExportRectangle scalingGrid = null;
|
||||
if (timelined instanceof CharacterTag) {
|
||||
DefineScalingGridTag sgt = ((CharacterTag) timelined).getScalingGridTag();
|
||||
if (sgt != null) {
|
||||
scalingGrid = new ExportRectangle(sgt.splitter);
|
||||
}
|
||||
}
|
||||
ExportRectangle scalingGrid = null;
|
||||
if (timelined instanceof CharacterTag) {
|
||||
DefineScalingGridTag sgt = ((CharacterTag) timelined).getScalingGridTag();
|
||||
if (sgt != null) {
|
||||
scalingGrid = new ExportRectangle(sgt.splitter);
|
||||
}
|
||||
}
|
||||
|
||||
if (scalingGrid == null || transformation.rotateSkew0 != 0 || transformation.rotateSkew1 != 0) {
|
||||
toImage(frame, time, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform, null);
|
||||
return;
|
||||
}
|
||||
if (scalingGrid == null || transformation.rotateSkew0 != 0 || transformation.rotateSkew1 != 0) {
|
||||
toImage(frame, time, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform, null);
|
||||
return;
|
||||
}
|
||||
|
||||
//9-slice scaling using DefineScalingGrid
|
||||
Matrix diffTransform = prevTransformation.inverse().preConcatenate(transformation);
|
||||
transformation = diffTransform;
|
||||
//9-slice scaling using DefineScalingGrid
|
||||
Matrix diffTransform = prevTransformation.inverse().preConcatenate(transformation);
|
||||
transformation = diffTransform;
|
||||
|
||||
Matrix prevScale = new Matrix();
|
||||
prevScale.scaleX = prevTransformation.scaleX;
|
||||
prevScale.scaleY = prevTransformation.scaleY;
|
||||
Matrix prevScale = new Matrix();
|
||||
prevScale.scaleX = prevTransformation.scaleX;
|
||||
prevScale.scaleY = prevTransformation.scaleY;
|
||||
|
||||
ExportRectangle boundsRect = new ExportRectangle(timelined.getRect());
|
||||
ExportRectangle boundsRect = new ExportRectangle(timelined.getRect());
|
||||
|
||||
|
||||
0 | 1 | 2
|
||||
------------
|
||||
3 | 4 | 5
|
||||
------------
|
||||
6 | 7 | 8
|
||||
0 | 1 | 2
|
||||
------------
|
||||
3 | 4 | 5
|
||||
------------
|
||||
6 | 7 | 8
|
||||
|
||||
ExportRectangle targetRect[] = new ExportRectangle[9];
|
||||
ExportRectangle sourceRect[] = new ExportRectangle[9];
|
||||
Matrix transforms[] = new Matrix[9];
|
||||
ExportRectangle targetRect[] = new ExportRectangle[9];
|
||||
ExportRectangle sourceRect[] = new ExportRectangle[9];
|
||||
Matrix transforms[] = new Matrix[9];
|
||||
|
||||
DefineScalingGridTag.getSlices(transformation, prevScale, boundsRect, scalingGrid, sourceRect, targetRect, transforms);
|
||||
DefineScalingGridTag.getSlices(transformation, prevScale, boundsRect, scalingGrid, sourceRect, targetRect, transforms);
|
||||
|
||||
for (int i = 0; i < targetRect.length; i++) {
|
||||
toImage(frame, time, renderContext, image, isClip, transforms[i], absoluteTransformation, colorTransform, targetRect[i]);
|
||||
}
|
||||
}*/
|
||||
private void drawDrawable(Matrix strokeTransform, DepthState layer, Matrix layerMatrix, Graphics2D g, ColorTransform colorTransForm, int blendMode, List<Clip> clips, List<Shape> prevClips, Matrix transformation, boolean isClip, int clipDepth, Matrix absMat, int time, int ratio, RenderContext renderContext, SerializableImage image, DrawableTag drawable, List<FILTER> filters, double unzoom, ColorTransform clrTrans) {
|
||||
for (int i = 0; i < targetRect.length; i++) {
|
||||
toImage(frame, time, renderContext, image, isClip, transforms[i], absoluteTransformation, colorTransform, targetRect[i]);
|
||||
}
|
||||
}*/
|
||||
private void drawDrawable(Matrix strokeTransform, DepthState layer, Matrix layerMatrix, Graphics2D g, ColorTransform colorTransForm, int blendMode, List<Clip> clips, Matrix transformation, boolean isClip, int clipDepth, Matrix absMat, int time, int ratio, RenderContext renderContext, SerializableImage image, DrawableTag drawable, List<FILTER> filters, double unzoom, ColorTransform clrTrans) {
|
||||
Matrix drawMatrix = new Matrix();
|
||||
int drawableFrameCount = drawable.getNumFrames();
|
||||
if (drawableFrameCount == 0) {
|
||||
@@ -642,7 +638,7 @@ public class Timeline {
|
||||
return;
|
||||
}
|
||||
|
||||
m.translate(-rect.xMin, -rect.yMin);
|
||||
m = m.preConcatenate(Matrix.getTranslateInstance(-rect.xMin, -rect.yMin));
|
||||
//strokeTransform = strokeTransform.clone();
|
||||
//strokeTransform.translate(-rect.xMin, -rect.yMin);
|
||||
drawMatrix.translate(rect.xMin, rect.yMin);
|
||||
@@ -764,9 +760,6 @@ public class Timeline {
|
||||
gm.drawImage(img.getBufferedImage(), 0, 0, null);
|
||||
Clip clip = new Clip(Helper.imageToShape(mask), clipDepth); // Maybe we can get current outline instead converting from image (?)
|
||||
clips.add(clip);
|
||||
prevClips.add(g.getClip());
|
||||
g.setTransform(AffineTransform.getTranslateInstance(0, 0));
|
||||
g.setClip(clip.shape);
|
||||
} else {
|
||||
if (renderContext.cursorPosition != null) {
|
||||
if (drawable instanceof DefineSpriteTag) {
|
||||
@@ -812,17 +805,44 @@ public class Timeline {
|
||||
|
||||
g.setTransform(transformation.toTransform());
|
||||
List<Clip> clips = new ArrayList<>();
|
||||
List<Shape> prevClips = new ArrayList<>();
|
||||
|
||||
int maxDepth = getMaxDepth();
|
||||
int clipCount = 0;
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
boolean clipChanged = clipCount != clips.size();
|
||||
for (int c = 0; c < clips.size(); c++) {
|
||||
if (clips.get(c).depth == i) {
|
||||
g.setClip(prevClips.get(c));
|
||||
prevClips.remove(c);
|
||||
if (clips.get(c).depth < i) {
|
||||
clips.remove(c);
|
||||
clipChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (clipChanged) {
|
||||
if (clips.size() > 0) {
|
||||
Area clip = null;
|
||||
for (Clip clip1 : clips) {
|
||||
Shape shape = clip1.shape;
|
||||
if (clip == null) {
|
||||
clip = new Area(shape);
|
||||
} else {
|
||||
clip.intersect(new Area(shape));
|
||||
}
|
||||
}
|
||||
|
||||
g.setTransform(new AffineTransform());
|
||||
g.setClip(clip);
|
||||
|
||||
// draw clip border
|
||||
//g.setPaint(Color.red);
|
||||
//g.setStroke(new BasicStroke(2));
|
||||
//g.draw(clip);
|
||||
} else {
|
||||
g.setClip(null);
|
||||
}
|
||||
|
||||
clipCount = clips.size();
|
||||
}
|
||||
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
}
|
||||
@@ -873,25 +893,25 @@ public class Timeline {
|
||||
|
||||
Rectangle2D r = new Rectangle2D.Double(p1.xMin, p1.yMin, p1.getWidth(), p1.getHeight());
|
||||
g.setClip(r);
|
||||
drawDrawable(strokeTransformation.preConcatenate(layerMatrix), layer, transforms[s], g, colorTransform, layer.blendMode, clips, prevClips, transformation.clone(), isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans);
|
||||
drawDrawable(strokeTransformation.preConcatenate(layerMatrix), layer, transforms[s], g, colorTransform, layer.blendMode, clips, transformation, isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans);
|
||||
|
||||
}
|
||||
g.setClip(c);
|
||||
|
||||
/*
|
||||
for (int s = 0; s < 9; s++) {
|
||||
g.setTransform(new AffineTransform());
|
||||
ExportRectangle p1 = transformation.transform(targetRect[s]);
|
||||
g.setClip(c);
|
||||
for (int s = 0; s < 9; s++) {
|
||||
g.setTransform(new AffineTransform());
|
||||
ExportRectangle p1 = transformation.transform(targetRect[s]);
|
||||
g.setClip(c);
|
||||
|
||||
Rectangle2D r = new Rectangle2D.Double(p1.xMin, p1.yMin, p1.getWidth(), p1.getHeight());
|
||||
g.setColor(Color.blue);
|
||||
g.draw(r);
|
||||
Rectangle2D r = new Rectangle2D.Double(p1.xMin, p1.yMin, p1.getWidth(), p1.getHeight());
|
||||
g.setColor(Color.blue);
|
||||
g.draw(r);
|
||||
|
||||
}*/
|
||||
}*/
|
||||
g.setTransform(origTransform);
|
||||
} else {
|
||||
drawDrawable(strokeTransformation, layer, layerMatrix, g, colorTransform, layer.blendMode, clips, prevClips, transformation.clone(), isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans);
|
||||
drawDrawable(strokeTransformation, layer, layerMatrix, g, colorTransform, layer.blendMode, clips, transformation, isClip, layer.clipDepth, absMat, time, layer.ratio, renderContext, image, (DrawableTag) character, layer.filters, unzoom, clrTrans);
|
||||
}
|
||||
} else if (character instanceof BoundedTag) {
|
||||
showPlaceholder = true;
|
||||
@@ -929,28 +949,44 @@ public class Timeline {
|
||||
}
|
||||
}
|
||||
|
||||
g.setTransform(AffineTransform.getScaleInstance(1, 1));
|
||||
g.setTransform(new AffineTransform());
|
||||
g.setClip(prevClip);
|
||||
}
|
||||
|
||||
public void toSVG(int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
public void toSVG(int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level) throws IOException {
|
||||
if (getFrameCount() <= frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
Frame frameObj = getFrame(frame);
|
||||
List<SvgClip> clips = new ArrayList<>();
|
||||
List<String> prevClips = new ArrayList<>();
|
||||
|
||||
int maxDepth = getMaxDepth();
|
||||
int clipCount = 0;
|
||||
Element clipGroup = null;
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
boolean clipChanged = clipCount != clips.size();
|
||||
for (int c = 0; c < clips.size(); c++) {
|
||||
if (clips.get(c).depth == i) {
|
||||
exporter.setClip(prevClips.get(c));
|
||||
prevClips.remove(c);
|
||||
if (clips.get(c).depth < i) {
|
||||
clips.remove(c);
|
||||
clipChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (clipChanged) {
|
||||
if (clipGroup != null) {
|
||||
exporter.endGroup();
|
||||
}
|
||||
|
||||
if (clips.size() > 0) {
|
||||
String clip = clips.get(clips.size() - 1).shape; // todo: merge clip areas
|
||||
clipGroup = exporter.createSubGroup(null, null);
|
||||
clipGroup.setAttribute("clip-path", "url(#" + clip + ")");
|
||||
}
|
||||
|
||||
clipCount = clips.size();
|
||||
}
|
||||
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
}
|
||||
@@ -981,7 +1017,7 @@ public class Timeline {
|
||||
assetName = getTagIdPrefix(drawableTag, exporter);
|
||||
exporter.exportedTags.put(drawableTag, assetName);
|
||||
exporter.createDefGroup(new ExportRectangle(boundRect), assetName);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1, zoom);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1);
|
||||
exporter.endGroup();
|
||||
}
|
||||
ExportRectangle rect = new ExportRectangle(boundRect);
|
||||
@@ -993,10 +1029,8 @@ public class Timeline {
|
||||
exporter.createClipPath(new Matrix(), clipName);
|
||||
SvgClip clip = new SvgClip(clipName, layer.clipDepth);
|
||||
clips.add(clip);
|
||||
prevClips.add(exporter.getClip());
|
||||
Matrix mat = Matrix.getTranslateInstance(rect.xMin, rect.yMin).preConcatenate(new Matrix(layer.matrix));
|
||||
exporter.addUse(mat, boundRect, assetName, layer.instanceName);
|
||||
exporter.setClip(clip.shape);
|
||||
exporter.endGroup();
|
||||
} else {
|
||||
Matrix mat = Matrix.getTranslateInstance(rect.xMin, rect.yMin).preConcatenate(new Matrix(layer.matrix));
|
||||
@@ -1005,6 +1039,9 @@ public class Timeline {
|
||||
}
|
||||
}
|
||||
|
||||
if (clipGroup != null) {
|
||||
exporter.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTagIdPrefix(Tag tag, SVGExporter exporter) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.awt.image.RescaleOp;
|
||||
public class ColorTransform implements Cloneable {
|
||||
|
||||
public RescaleOp toRescaleOp() {
|
||||
return new RescaleOp(new float[]{getRedMulti() / 255f, getGreenMulti() / 255f, getBlueMulti() / 255f, getAlphaMulti() / 255f},
|
||||
return new RescaleOp(new float[]{getRedMulti() / 256f, getGreenMulti() / 256f, getBlueMulti() / 256f, getAlphaMulti() / 256f},
|
||||
new float[]{getRedAdd(), getGreenAdd(), getBlueAdd(), getAlphaAdd()}, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -217,9 +217,8 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
|
||||
double px = x * w2 + w2 / 2 - w / 2 - minXMin * ratio;
|
||||
double py = y * h2 - minYMin * ratio;
|
||||
|
||||
Matrix transformation = new Matrix();
|
||||
transformation.translate(px, py);
|
||||
transformation = transformation.concatenate(Matrix.getScaleInstance(ratio));
|
||||
Matrix transformation = Matrix.getTranslateInstance(px, py);
|
||||
transformation.scale(ratio);
|
||||
BitmapExporter.export(swf, shape, color, image, transformation, transformation, colorTransform);
|
||||
|
||||
// draw bounding boxes
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.CSMTextSettingsTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButtonCxformTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineFontNameTag;
|
||||
@@ -1063,13 +1064,9 @@ public class XFLConverter {
|
||||
}
|
||||
if (tag instanceof DefineButtonTag) {
|
||||
DefineButtonTag bt = (DefineButtonTag) tag;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof DefineButtonCxformTag) {
|
||||
DefineButtonCxformTag bcx = (DefineButtonCxformTag) t;
|
||||
if (bcx.buttonId == bt.buttonId) {
|
||||
colorTransform = bcx.buttonColorTransform;
|
||||
}
|
||||
}
|
||||
DefineButtonCxformTag bcx = (DefineButtonCxformTag) bt.getSwf().getCharacterIdTag(bt.buttonId, DefineButtonCxformTag.ID);
|
||||
if (bcx != null) {
|
||||
colorTransform = bcx.buttonColorTransform;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,17 +1117,17 @@ public class XFLConverter {
|
||||
if (colorTransform != null) {
|
||||
writer.writeStartElement("color");
|
||||
writer.writeStartElement("Color");
|
||||
if (colorTransform.getRedMulti() != 255) {
|
||||
writer.writeAttribute("redMultiplier", ((float) colorTransform.getRedMulti()) / 255.0f);
|
||||
if (colorTransform.getRedMulti() != 256) {
|
||||
writer.writeAttribute("redMultiplier", ((float) colorTransform.getRedMulti()) / 256.0f);
|
||||
}
|
||||
if (colorTransform.getGreenMulti() != 255) {
|
||||
writer.writeAttribute("greenMultiplier", ((float) colorTransform.getGreenMulti()) / 255.0f);
|
||||
if (colorTransform.getGreenMulti() != 256) {
|
||||
writer.writeAttribute("greenMultiplier", ((float) colorTransform.getGreenMulti()) / 256.0f);
|
||||
}
|
||||
if (colorTransform.getBlueMulti() != 255) {
|
||||
writer.writeAttribute("blueMultiplier", ((float) colorTransform.getBlueMulti()) / 255.0f);
|
||||
if (colorTransform.getBlueMulti() != 256) {
|
||||
writer.writeAttribute("blueMultiplier", ((float) colorTransform.getBlueMulti()) / 256.0f);
|
||||
}
|
||||
if (colorTransform.getAlphaMulti() != 255) {
|
||||
writer.writeAttribute("alphaMultiplier", ((float) colorTransform.getAlphaMulti()) / 255.0f);
|
||||
if (colorTransform.getAlphaMulti() != 256) {
|
||||
writer.writeAttribute("alphaMultiplier", ((float) colorTransform.getAlphaMulti()) / 256.0f);
|
||||
}
|
||||
|
||||
if (colorTransform.getRedAdd() != 0) {
|
||||
@@ -1275,8 +1272,21 @@ public class XFLConverter {
|
||||
symbolStr.writeAttribute("color", randomOutlineColor());
|
||||
symbolStr.writeStartElement("frames");
|
||||
int lastFrame = 0;
|
||||
DefineButtonSoundTag sound = button.getSounds();
|
||||
loopframes:
|
||||
for (int frame = 1; frame <= 4; frame++) {
|
||||
if (sound != null) {
|
||||
switch (frame) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (BUTTONRECORD rec : records) {
|
||||
if (rec.placeDepth == i) {
|
||||
boolean ok = false;
|
||||
@@ -1765,18 +1775,11 @@ public class XFLConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void convertFrame(boolean shapeTween, HashMap<Integer, CharacterTag> characters, ReadOnlyTagList tags, SoundStreamHeadTypeTag soundStreamHead, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||
private static void convertFrame(boolean shapeTween, SoundStreamHeadTypeTag soundStreamHead, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||
DefineSoundTag sound = null;
|
||||
if (startSound != null) {
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof DefineSoundTag) {
|
||||
DefineSoundTag s = (DefineSoundTag) t;
|
||||
if (s.soundId == startSound.soundId) {
|
||||
sound = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SWF swf = startSound.getSwf();
|
||||
sound = swf.getSound(startSound.soundId);
|
||||
}
|
||||
|
||||
writer.writeStartElement("DOMFrame");
|
||||
@@ -2046,7 +2049,7 @@ public class XFLConverter {
|
||||
frame++;
|
||||
String elements = elementsWriter.toString();
|
||||
if (!elements.equals(lastElements) && frame > 0) {
|
||||
convertFrame(lastShapeTween, characters, tags, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
||||
convertFrame(lastShapeTween, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
||||
duration = 1;
|
||||
} else if (frame == 0) {
|
||||
duration = 1;
|
||||
@@ -2060,7 +2063,7 @@ public class XFLConverter {
|
||||
}
|
||||
if (!lastElements.isEmpty()) {
|
||||
frame++;
|
||||
convertFrame(lastShapeTween, characters, tags, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2);
|
||||
convertFrame(lastShapeTween, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2);
|
||||
}
|
||||
afterStr = "</frames>" + afterStr;
|
||||
|
||||
@@ -2091,16 +2094,11 @@ public class XFLConverter {
|
||||
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof FontTag) {
|
||||
SWF swf = t.getSwf();
|
||||
FontTag font = (FontTag) t;
|
||||
int fontId = font.getFontId();
|
||||
String fontName = null;
|
||||
for (Tag t2 : tags) {
|
||||
if (t2 instanceof DefineFontNameTag) {
|
||||
if (((DefineFontNameTag) t2).fontId == fontId) {
|
||||
fontName = ((DefineFontNameTag) t2).fontName;
|
||||
}
|
||||
}
|
||||
}
|
||||
DefineFontNameTag fontNameTag = (DefineFontNameTag) swf.getCharacterIdTag(fontId, DefineFontNameTag.ID);
|
||||
String fontName = fontNameTag == null ? null : fontNameTag.fontName;
|
||||
if (fontName == null) {
|
||||
fontName = font.getFontNameIntag();
|
||||
}
|
||||
@@ -2300,65 +2298,74 @@ public class XFLConverter {
|
||||
return hasLabel;
|
||||
}
|
||||
|
||||
private void convertSoundLayer(int layerIndex, String backgroundColor, HashMap<Integer, CharacterTag> characters, ReadOnlyTagList tags, ReadOnlyTagList timeLineTags, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||
private void convertSoundLayer(int layerIndex, ReadOnlyTagList timeLineTags, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||
int soundLayerIndex = 0;
|
||||
XFLXmlWriter writer2 = new XFLXmlWriter();
|
||||
StartSoundTag lastStartSound = null;
|
||||
SoundStreamHeadTypeTag lastSoundStreamHead = null;
|
||||
StartSoundTag startSound = null;
|
||||
SoundStreamHeadTypeTag soundStreamHead = null;
|
||||
int duration = 1;
|
||||
List<StartSoundTag> startSounds = new ArrayList<>();
|
||||
List<Integer> startSoundFrameNumbers = new ArrayList<>();
|
||||
List<SoundStreamHeadTypeTag> soundStreamHeads = new ArrayList<>();
|
||||
List<Integer> soundStreamHeadFrameNumbers = new ArrayList<>();
|
||||
int frame = 0;
|
||||
for (Tag t : timeLineTags) {
|
||||
if (t instanceof StartSoundTag) {
|
||||
startSound = (StartSoundTag) t;
|
||||
|
||||
for (Tag ta : tags) {
|
||||
if (ta instanceof DefineSoundTag) {
|
||||
DefineSoundTag s = (DefineSoundTag) ta;
|
||||
if (s.soundId == startSound.soundId) {
|
||||
if (!files.containsKey("sound" + s.soundId + "." + s.getExportFormat().toString().toLowerCase())) { //Sound was not exported
|
||||
startSound = null; // ignore
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
StartSoundTag startSound = (StartSoundTag) t;
|
||||
SWF swf = startSound.getSwf();
|
||||
DefineSoundTag s = swf.getSound(startSound.soundId);
|
||||
if (!files.containsKey("sound" + s.soundId + "." + s.getExportFormat().toString().toLowerCase())) { //Sound was not exported
|
||||
startSound = null; // ignore
|
||||
}
|
||||
|
||||
}
|
||||
if (t instanceof SoundStreamHeadTypeTag) {
|
||||
soundStreamHead = (SoundStreamHeadTypeTag) t;
|
||||
if (startSound != null) {
|
||||
startSounds.add(startSound);
|
||||
startSoundFrameNumbers.add(frame);
|
||||
}
|
||||
} else if (t instanceof SoundStreamHeadTypeTag) {
|
||||
SoundStreamHeadTypeTag soundStreamHead = (SoundStreamHeadTypeTag) t;
|
||||
if (!files.containsKey("sound" + soundStreamHead.getCharacterId() + "." + soundStreamHead.getExportFormat().toString().toLowerCase())) { //Sound was not exported
|
||||
soundStreamHead = null; // ignore
|
||||
}
|
||||
}
|
||||
if (t instanceof ShowFrameTag) {
|
||||
if (soundStreamHead != null || startSound != null) {
|
||||
if (lastSoundStreamHead != null || lastStartSound != null) {
|
||||
convertFrame(false, characters, tags, lastSoundStreamHead, lastStartSound, frame, duration, "", "", files, writer2);
|
||||
}
|
||||
frame += duration;
|
||||
duration = 1;
|
||||
lastSoundStreamHead = soundStreamHead;
|
||||
lastStartSound = startSound;
|
||||
soundStreamHead = null;
|
||||
startSound = null;
|
||||
} else {
|
||||
duration++;
|
||||
|
||||
if (soundStreamHead != null) {
|
||||
soundStreamHeads.add(soundStreamHead);
|
||||
soundStreamHeadFrameNumbers.add(frame);
|
||||
}
|
||||
} else if (t instanceof ShowFrameTag) {
|
||||
frame++;
|
||||
}
|
||||
}
|
||||
if (lastSoundStreamHead != null || lastStartSound != null) {
|
||||
if (frame < 0) {
|
||||
frame = 0;
|
||||
duration = 1;
|
||||
}
|
||||
convertFrame(false, characters, tags, lastSoundStreamHead, lastStartSound, frame, duration, "", "", files, writer2);
|
||||
}
|
||||
|
||||
if (writer2.length() > 0) {
|
||||
writer.writeStartElement("DOMLayer", new String[]{"name", "Layer " + layerIndex, "color", randomOutlineColor()});
|
||||
for (int i = 0; i < soundStreamHeads.size(); i++) {
|
||||
writer.writeStartElement("DOMLayer", new String[]{"name", "Sound Layer " + (soundLayerIndex++), "color", randomOutlineColor()});
|
||||
writer.writeStartElement("frames");
|
||||
writer.writeCharactersRaw(writer2.toString());
|
||||
|
||||
int startFrame = soundStreamHeadFrameNumbers.get(i);
|
||||
int duration = frame - startFrame;
|
||||
|
||||
if (startFrame != 0) {
|
||||
// empty frames should be added
|
||||
convertFrame(false, null, null, 0, startFrame, "", "", files, writer);
|
||||
}
|
||||
|
||||
convertFrame(false, soundStreamHeads.get(i), null, startFrame, duration, "", "", files, writer);
|
||||
|
||||
writer.writeEndElement();
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
for (int i = 0; i < startSounds.size(); i++) {
|
||||
writer.writeStartElement("DOMLayer", new String[]{"name", "Sound Layer " + (soundLayerIndex++), "color", randomOutlineColor()});
|
||||
writer.writeStartElement("frames");
|
||||
|
||||
int startFrame = startSoundFrameNumbers.get(i);
|
||||
int duration = frame - startFrame;
|
||||
|
||||
if (startFrame != 0) {
|
||||
// empty frames should be added
|
||||
convertFrame(false, null, null, 0, startFrame, "", "", files, writer);
|
||||
}
|
||||
|
||||
convertFrame(false, null, startSounds.get(i), startFrame, duration, "", "", files, writer);
|
||||
|
||||
writer.writeEndElement();
|
||||
writer.writeEndElement();
|
||||
}
|
||||
@@ -2463,7 +2470,7 @@ public class XFLConverter {
|
||||
|
||||
int soundLayerIndex = layerCount;
|
||||
layerCount++;
|
||||
convertSoundLayer(soundLayerIndex, backgroundColor, characters, tags, timelineTags, files, writer);
|
||||
convertSoundLayer(soundLayerIndex, timelineTags, files, writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class Helper {
|
||||
|
||||
public static String decompilationErrorAdd = null;
|
||||
|
||||
private static final Map<String, Area> shapeCache = new HashMap<>();
|
||||
private static final Map<BitSet, Area> shapeCache = new HashMap<>();
|
||||
|
||||
private static final String[] hexStringCache;
|
||||
|
||||
@@ -1180,9 +1180,8 @@ public class Helper {
|
||||
}
|
||||
}
|
||||
|
||||
String key = byteArrayToBase64String(bs.toByteArray());
|
||||
if (shapeCache.containsKey(key)) {
|
||||
return shapeCache.get(key);
|
||||
if (shapeCache.containsKey(bs)) {
|
||||
return shapeCache.get(bs);
|
||||
}
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
@@ -1210,7 +1209,7 @@ public class Helper {
|
||||
}
|
||||
}
|
||||
|
||||
shapeCache.put(key, area);
|
||||
shapeCache.put(bs, area);
|
||||
return area;
|
||||
}
|
||||
|
||||
@@ -1229,18 +1228,15 @@ public class Helper {
|
||||
|
||||
BitSet bs = new BitSet(width * height);
|
||||
bs.set(type);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int idx = width * y + x;
|
||||
if ((imgData[idx] >>> 24) > 0) {
|
||||
bs.set(idx);
|
||||
}
|
||||
int pixelCount = width * height;
|
||||
for (int i = 0; i < pixelCount; i++) {
|
||||
if ((imgData[i] >>> 24) > 0) {
|
||||
bs.set(i);
|
||||
}
|
||||
}
|
||||
|
||||
String key = byteArrayToBase64String(bs.toByteArray());
|
||||
if (shapeCache.containsKey(key)) {
|
||||
return shapeCache.get(key);
|
||||
if (shapeCache.containsKey(bs)) {
|
||||
return shapeCache.get(bs);
|
||||
}
|
||||
|
||||
BitSet bsArea = new BitSet(width * height);
|
||||
@@ -1321,7 +1317,7 @@ public class Helper {
|
||||
}
|
||||
}
|
||||
|
||||
shapeCache.put(key, area);
|
||||
shapeCache.put(bs, area);
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user