mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-26 14:05:34 +00:00
Merge origin/master
This commit is contained in:
@@ -75,9 +75,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter;
|
||||
@@ -129,11 +127,8 @@ import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.timeline.AS2Package;
|
||||
import com.jpexs.decompiler.flash.timeline.Clip;
|
||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||
import com.jpexs.decompiler.flash.timeline.FrameScript;
|
||||
import com.jpexs.decompiler.flash.timeline.SvgClip;
|
||||
import com.jpexs.decompiler.flash.timeline.TagScript;
|
||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
@@ -145,8 +140,6 @@ import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFField;
|
||||
import com.jpexs.decompiler.flash.types.filters.BlendComposite;
|
||||
import com.jpexs.decompiler.flash.types.filters.FILTER;
|
||||
import com.jpexs.decompiler.flash.xfl.FLAVersion;
|
||||
import com.jpexs.decompiler.flash.xfl.XFLConverter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
@@ -166,15 +159,11 @@ import com.jpexs.helpers.ProgressListener;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
@@ -195,7 +184,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -2661,114 +2649,13 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void frameToSvg(Timeline timeline, int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
if (timeline.getFrameCount() <= frame) {
|
||||
return;
|
||||
}
|
||||
Frame frameObj = timeline.getFrame(frame);
|
||||
List<SvgClip> clips = new ArrayList<>();
|
||||
List<String> prevClips = new ArrayList<>();
|
||||
|
||||
int maxDepth = timeline.getMaxDepth();
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
for (int c = 0; c < clips.size(); c++) {
|
||||
if (clips.get(c).depth == i) {
|
||||
exporter.setClip(prevClips.get(c));
|
||||
prevClips.remove(c);
|
||||
clips.remove(c);
|
||||
}
|
||||
}
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
}
|
||||
DepthState layer = frameObj.layers.get(i);
|
||||
if (!timeline.swf.getCharacters().containsKey(layer.characterId)) {
|
||||
continue;
|
||||
}
|
||||
if (!layer.isVisible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CharacterTag character = timeline.swf.getCharacter(layer.characterId);
|
||||
|
||||
ColorTransform clrTrans = colorTransform;
|
||||
if (layer.colorTransForm != null && layer.blendMode <= 1) { // Normal blend mode
|
||||
clrTrans = clrTrans == null ? layer.colorTransForm : colorTransform.merge(layer.colorTransForm);
|
||||
}
|
||||
|
||||
if (character instanceof DrawableTag) {
|
||||
DrawableTag drawable = (DrawableTag) character;
|
||||
|
||||
String assetName;
|
||||
Tag drawableTag = (Tag) drawable;
|
||||
RECT boundRect = drawable.getRect();
|
||||
if (exporter.exportedTags.containsKey(drawableTag)) {
|
||||
assetName = exporter.exportedTags.get(drawableTag);
|
||||
} else {
|
||||
assetName = getTagIdPrefix(drawableTag, exporter);
|
||||
exporter.exportedTags.put(drawableTag, assetName);
|
||||
exporter.createDefGroup(new ExportRectangle(boundRect), assetName);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1, zoom);
|
||||
exporter.endGroup();
|
||||
}
|
||||
ExportRectangle rect = new ExportRectangle(boundRect);
|
||||
|
||||
// TODO: if (layer.filters != null)
|
||||
// TODO: if (layer.blendMode > 1)
|
||||
if (layer.clipDepth > -1) {
|
||||
String clipName = exporter.getUniqueId("clipPath");
|
||||
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));
|
||||
exporter.addUse(mat, boundRect, assetName, layer.instanceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTagIdPrefix(Tag tag, SVGExporter exporter) {
|
||||
if (tag instanceof ShapeTag) {
|
||||
return exporter.getUniqueId("shape");
|
||||
}
|
||||
if (tag instanceof MorphShapeTag) {
|
||||
return exporter.getUniqueId("morphshape");
|
||||
}
|
||||
if (tag instanceof DefineSpriteTag) {
|
||||
return exporter.getUniqueId("sprite");
|
||||
}
|
||||
if (tag instanceof TextTag) {
|
||||
return exporter.getUniqueId("text");
|
||||
}
|
||||
if (tag instanceof ButtonTag) {
|
||||
return exporter.getUniqueId("button");
|
||||
}
|
||||
return exporter.getUniqueId("tag");
|
||||
}
|
||||
|
||||
public static SerializableImage frameToImageGet(Timeline timeline, int frame, int time, Point cursorPosition, int mouseButton, RECT displayRect, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform, Color backGroundColor, boolean useCache, double zoom) {
|
||||
SWF swf = timeline.swf;
|
||||
String key = "frame_" + frame + "_" + time + "_" + timeline.id + "_" + swf.hashCode() + "_" + zoom;
|
||||
SerializableImage image;
|
||||
if (useCache) {
|
||||
image = swf.getFromCache(key);
|
||||
if (image != null) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (timeline.getFrameCount() == 0) {
|
||||
return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB);
|
||||
}
|
||||
|
||||
RECT rect = displayRect;
|
||||
image = new SerializableImage((int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1,
|
||||
SerializableImage image = new SerializableImage((int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1,
|
||||
(int) (rect.getHeight() * zoom / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB);
|
||||
if (backGroundColor == null) {
|
||||
image.fillTransparent();
|
||||
@@ -2785,303 +2672,11 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
RenderContext renderContext = new RenderContext();
|
||||
renderContext.cursorPosition = cursorPosition;
|
||||
renderContext.mouseButton = mouseButton;
|
||||
frameToImage(timeline, frame, time, renderContext, image, false, m, absoluteTransformation, colorTransform);
|
||||
if (useCache) {
|
||||
swf.putToCache(key, image);
|
||||
}
|
||||
timeline.toImage(frame, time, 0, renderContext, image, false, m, absoluteTransformation, colorTransform);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public static void framesToImage(Timeline timeline, List<SerializableImage> ret, int startFrame, int stopFrame, RenderContext renderContext, RECT displayRect, int totalFrameCount, Stack<Integer> visited, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform, double zoom) {
|
||||
RECT rect = displayRect;
|
||||
for (int f = 0; f < timeline.getFrameCount(); f++) {
|
||||
SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1,
|
||||
(int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB);
|
||||
image.fillTransparent();
|
||||
Matrix m = new Matrix();
|
||||
m.translate(-rect.Xmin, -rect.Ymin);
|
||||
frameToImage(timeline, f, 0, renderContext, image, false, m, absoluteTransformation, colorTransform);
|
||||
ret.add(image);
|
||||
}
|
||||
}
|
||||
|
||||
public static void frameToImage(Timeline timeline, int frame, int time, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform) {
|
||||
double unzoom = SWF.unitDivisor;
|
||||
if (timeline.getFrameCount() <= frame) {
|
||||
return;
|
||||
}
|
||||
Frame frameObj = timeline.getFrame(frame);
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
g.setPaint(frameObj.backgroundColor.toColor());
|
||||
g.fill(new Rectangle(image.getWidth(), image.getHeight()));
|
||||
g.setTransform(transformation.toTransform());
|
||||
List<Clip> clips = new ArrayList<>();
|
||||
List<Shape> prevClips = new ArrayList<>();
|
||||
|
||||
int maxDepth = timeline.getMaxDepth();
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
for (int c = 0; c < clips.size(); c++) {
|
||||
if (clips.get(c).depth == i) {
|
||||
g.setClip(prevClips.get(c));
|
||||
prevClips.remove(c);
|
||||
clips.remove(c);
|
||||
}
|
||||
}
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
}
|
||||
DepthState layer = frameObj.layers.get(i);
|
||||
if (!timeline.swf.getCharacters().containsKey(layer.characterId)) {
|
||||
continue;
|
||||
}
|
||||
if (!layer.isVisible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CharacterTag character = timeline.swf.getCharacter(layer.characterId);
|
||||
Matrix layerMatrix = new Matrix(layer.matrix);
|
||||
Matrix mat = transformation.concatenate(layerMatrix);
|
||||
Matrix absMat = absoluteTransformation.concatenate(layerMatrix);
|
||||
|
||||
ColorTransform clrTrans = colorTransform;
|
||||
if (layer.colorTransForm != null && layer.blendMode <= 1) { // Normal blend mode
|
||||
clrTrans = clrTrans == null ? layer.colorTransForm : colorTransform.merge(layer.colorTransForm);
|
||||
}
|
||||
|
||||
boolean showPlaceholder = false;
|
||||
if (character instanceof DrawableTag) {
|
||||
DrawableTag drawable = (DrawableTag) character;
|
||||
Matrix drawMatrix = new Matrix();
|
||||
int drawableFrameCount = drawable.getNumFrames();
|
||||
if (drawableFrameCount == 0) {
|
||||
drawableFrameCount = 1;
|
||||
}
|
||||
|
||||
RECT boundRect = drawable.getRect();
|
||||
ExportRectangle rect = new ExportRectangle(boundRect);
|
||||
rect = mat.transform(rect);
|
||||
Matrix m = mat.clone();
|
||||
if (layer.filters != null && layer.filters.size() > 0) {
|
||||
// calculate size after applying the filters
|
||||
double deltaXMax = 0;
|
||||
double deltaYMax = 0;
|
||||
for (FILTER filter : layer.filters) {
|
||||
double x = filter.getDeltaX();
|
||||
double y = filter.getDeltaY();
|
||||
deltaXMax = Math.max(x, deltaXMax);
|
||||
deltaYMax = Math.max(y, deltaYMax);
|
||||
}
|
||||
rect.xMin -= deltaXMax * unzoom;
|
||||
rect.xMax += deltaXMax * unzoom;
|
||||
rect.yMin -= deltaYMax * unzoom;
|
||||
rect.yMax += deltaYMax * unzoom;
|
||||
}
|
||||
|
||||
rect.xMin -= 1 * unzoom;
|
||||
rect.yMin -= 1 * unzoom;
|
||||
rect.xMin = Math.max(0, rect.xMin);
|
||||
rect.yMin = Math.max(0, rect.yMin);
|
||||
|
||||
int newWidth = (int) (rect.getWidth() / unzoom);
|
||||
int newHeight = (int) (rect.getHeight() / unzoom);
|
||||
int deltaX = (int) (rect.xMin / unzoom);
|
||||
int deltaY = (int) (rect.yMin / unzoom);
|
||||
newWidth = Math.min(image.getWidth() - deltaX, newWidth) + 1;
|
||||
newHeight = Math.min(image.getHeight() - deltaY, newHeight) + 1;
|
||||
|
||||
if (newWidth <= 0 || newHeight <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m.translate(-rect.xMin, -rect.yMin);
|
||||
drawMatrix.translate(rect.xMin, rect.yMin);
|
||||
|
||||
SerializableImage img = null;
|
||||
String cacheKey = null;
|
||||
if (drawable instanceof ShapeTag) {
|
||||
cacheKey = ((ShapeTag) drawable).getCharacterId() + m.toString() + (clrTrans == null ? "" : clrTrans.toString());
|
||||
img = renderContext.shapeCache.get(cacheKey);
|
||||
}
|
||||
|
||||
int dframe;
|
||||
if (timeline.fontFrameNum != -1) {
|
||||
dframe = timeline.fontFrameNum;
|
||||
} else {
|
||||
dframe = time % drawableFrameCount;
|
||||
}
|
||||
|
||||
if (character instanceof ButtonTag) {
|
||||
dframe = ButtonTag.FRAME_UP;
|
||||
if (renderContext.cursorPosition != null) {
|
||||
Shape buttonShape = drawable.getOutline(ButtonTag.FRAME_HITTEST, time, layer.ratio, renderContext, absMat);
|
||||
if (buttonShape.contains(renderContext.cursorPosition)) {
|
||||
renderContext.mouseOverButton = (ButtonTag) character;
|
||||
if (renderContext.mouseButton > 0) {
|
||||
dframe = ButtonTag.FRAME_DOWN;
|
||||
} else {
|
||||
dframe = ButtonTag.FRAME_OVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int stateCount = renderContext.stateUnderCursor == null ? 0 : renderContext.stateUnderCursor.size();
|
||||
if (img == null) {
|
||||
img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB);
|
||||
img.fillTransparent();
|
||||
|
||||
drawable.toImage(dframe, time, layer.ratio, renderContext, img, isClip || layer.clipDepth > -1, m, absMat, clrTrans);
|
||||
|
||||
if (cacheKey != null) {
|
||||
renderContext.shapeCache.put(cacheKey, img);
|
||||
}
|
||||
}
|
||||
|
||||
/*//if (renderContext.stateUnderCursor == layer) {
|
||||
if (true) {
|
||||
BufferedImage bi = img.getBufferedImage();
|
||||
ColorModel cm = bi.getColorModel();
|
||||
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
|
||||
WritableRaster raster = bi.copyData(null);
|
||||
img = new SerializableImage(new BufferedImage(cm, raster, isAlphaPremultiplied, null));
|
||||
Graphics2D gg = (Graphics2D) img.getGraphics();
|
||||
gg.setStroke(new BasicStroke(3));
|
||||
gg.setPaint(Color.red);
|
||||
gg.setTransform(AffineTransform.getTranslateInstance(0, 0));
|
||||
gg.draw(SHAPERECORD.twipToPixelShape(drawable.getOutline(dframe, layer.time + time, layer.ratio, renderContext, m)));
|
||||
}*/
|
||||
if (layer.filters != null) {
|
||||
for (FILTER filter : layer.filters) {
|
||||
img = filter.apply(img);
|
||||
}
|
||||
}
|
||||
if (layer.blendMode > 1) {
|
||||
if (layer.colorTransForm != null) {
|
||||
img = layer.colorTransForm.apply(img);
|
||||
}
|
||||
}
|
||||
|
||||
drawMatrix.translateX /= unzoom;
|
||||
drawMatrix.translateY /= unzoom;
|
||||
AffineTransform trans = drawMatrix.toTransform();
|
||||
|
||||
switch (layer.blendMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
break;
|
||||
case 2: // Layer
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
break;
|
||||
case 3:
|
||||
g.setComposite(BlendComposite.Multiply);
|
||||
break;
|
||||
case 4:
|
||||
g.setComposite(BlendComposite.Screen);
|
||||
break;
|
||||
case 5:
|
||||
g.setComposite(BlendComposite.Lighten);
|
||||
break;
|
||||
case 6:
|
||||
g.setComposite(BlendComposite.Darken);
|
||||
break;
|
||||
case 7:
|
||||
g.setComposite(BlendComposite.Difference);
|
||||
break;
|
||||
case 8:
|
||||
g.setComposite(BlendComposite.Add);
|
||||
break;
|
||||
case 9:
|
||||
g.setComposite(BlendComposite.Subtract);
|
||||
break;
|
||||
case 10:
|
||||
g.setComposite(BlendComposite.Invert);
|
||||
break;
|
||||
case 11:
|
||||
g.setComposite(BlendComposite.Alpha);
|
||||
break;
|
||||
case 12:
|
||||
g.setComposite(BlendComposite.Erase);
|
||||
break;
|
||||
case 13:
|
||||
g.setComposite(BlendComposite.Overlay);
|
||||
break;
|
||||
case 14:
|
||||
g.setComposite(BlendComposite.HardLight);
|
||||
break;
|
||||
default: // Not implemented
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer.clipDepth > -1) {
|
||||
BufferedImage mask = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
|
||||
Graphics2D gm = (Graphics2D) mask.getGraphics();
|
||||
gm.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
gm.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
gm.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
gm.setComposite(AlphaComposite.Src);
|
||||
gm.setColor(new Color(0, 0, 0, 0f));
|
||||
gm.fillRect(0, 0, image.getWidth(), image.getHeight());
|
||||
gm.setTransform(trans);
|
||||
gm.drawImage(img.getBufferedImage(), 0, 0, null);
|
||||
Clip clip = new Clip(Helper.imageToShape(mask), layer.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) {
|
||||
if (renderContext.stateUnderCursor.size() > stateCount) {
|
||||
renderContext.stateUnderCursor.add(layer);
|
||||
}
|
||||
} else if (absMat.transform(new ExportRectangle(boundRect)).contains(renderContext.cursorPosition)) {
|
||||
Shape shape = drawable.getOutline(dframe, time, layer.ratio, renderContext, absMat);
|
||||
if (shape.contains(renderContext.cursorPosition)) {
|
||||
renderContext.stateUnderCursor.add(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (renderContext.borderImage != null) {
|
||||
Graphics2D g2 = (Graphics2D) renderContext.borderImage.getGraphics();
|
||||
g2.setPaint(Color.red);
|
||||
g2.setStroke(new BasicStroke(2));
|
||||
Shape shape = drawable.getOutline(dframe, time, layer.ratio, renderContext, absMat.preConcatenate(Matrix.getScaleInstance(1 / SWF.unitDivisor)));
|
||||
g2.draw(shape);
|
||||
}
|
||||
|
||||
g.setTransform(trans);
|
||||
g.drawImage(img.getBufferedImage(), 0, 0, null);
|
||||
}
|
||||
} else if (character instanceof BoundedTag) {
|
||||
showPlaceholder = true;
|
||||
}
|
||||
|
||||
if (showPlaceholder) {
|
||||
Matrix mat2 = mat.clone();
|
||||
mat2.translateX /= unzoom;
|
||||
mat2.translateY /= unzoom;
|
||||
AffineTransform trans = mat2.toTransform();
|
||||
g.setTransform(trans);
|
||||
BoundedTag b = (BoundedTag) character;
|
||||
g.setPaint(new Color(255, 255, 255, 128));
|
||||
g.setComposite(BlendComposite.Invert);
|
||||
RECT r = b.getRect();
|
||||
int div = (int) unzoom;
|
||||
g.drawString(character.toString(), r.Xmin / div + 3, r.Ymin / div + 15);
|
||||
g.draw(new Rectangle(r.Xmin / div, r.Ymin / div, r.getWidth() / div, r.getHeight() / div));
|
||||
g.drawLine(r.Xmin / div, r.Ymin / div, r.Xmax / div, r.Ymax / div);
|
||||
g.drawLine(r.Xmax / div, r.Ymin / div, r.Xmin / div, r.Ymax / div);
|
||||
g.setComposite(AlphaComposite.Dst);
|
||||
}
|
||||
}
|
||||
|
||||
g.setTransform(AffineTransform.getScaleInstance(1, 1));
|
||||
}
|
||||
|
||||
private void removeTagWithDependenciesFromTimeline(Tag toRemove, Timeline timeline) {
|
||||
Map<Integer, Integer> stage = new HashMap<>();
|
||||
Set<Integer> dependingChars = new HashSet<>();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc;
|
||||
|
||||
import com.jpexs.decompiler.flash.EndOfStreamException;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
@@ -54,6 +55,7 @@ import com.jpexs.decompiler.flash.abc.usages.MethodParamsMultinameUsage;
|
||||
import com.jpexs.decompiler.flash.abc.usages.MethodReturnTypeMultinameUsage;
|
||||
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
|
||||
import com.jpexs.decompiler.flash.abc.usages.TypeNameMultinameUsage;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
@@ -543,29 +545,36 @@ public class ABC {
|
||||
int bodies_count = ais.readU30("bodies_count");
|
||||
bodies = new ArrayList<>(bodies_count);
|
||||
for (int i = 0; i < bodies_count; i++) {
|
||||
DumpInfo di = ais.dumpInfo;
|
||||
ais.newDumpLevel("method_body", "method_body_info");
|
||||
MethodBody mb = new MethodBody(this, null, null, null); // do not create Traits in constructor
|
||||
mb.method_info = ais.readU30("method_info");
|
||||
mb.max_stack = ais.readU30("max_stack");
|
||||
mb.max_regs = ais.readU30("max_regs");
|
||||
mb.init_scope_depth = ais.readU30("init_scope_depth");
|
||||
mb.max_scope_depth = ais.readU30("max_scope_depth");
|
||||
int code_length = ais.readU30("code_length");
|
||||
mb.setCodeBytes(ais.readBytes(code_length, "code"));
|
||||
int ex_count = ais.readU30("ex_count");
|
||||
mb.exceptions = new ABCException[ex_count];
|
||||
for (int j = 0; j < ex_count; j++) {
|
||||
ABCException abce = new ABCException();
|
||||
abce.start = ais.readU30("start");
|
||||
abce.end = ais.readU30("end");
|
||||
abce.target = ais.readU30("target");
|
||||
abce.type_index = ais.readU30("type_index");
|
||||
abce.name_index = ais.readU30("name_index");
|
||||
mb.exceptions[j] = abce;
|
||||
try {
|
||||
mb.method_info = ais.readU30("method_info");
|
||||
mb.max_stack = ais.readU30("max_stack");
|
||||
mb.max_regs = ais.readU30("max_regs");
|
||||
mb.init_scope_depth = ais.readU30("init_scope_depth");
|
||||
mb.max_scope_depth = ais.readU30("max_scope_depth");
|
||||
int code_length = ais.readU30("code_length");
|
||||
mb.setCodeBytes(ais.readBytes(code_length, "code"));
|
||||
int ex_count = ais.readU30("ex_count");
|
||||
mb.exceptions = new ABCException[ex_count];
|
||||
for (int j = 0; j < ex_count; j++) {
|
||||
ABCException abce = new ABCException();
|
||||
abce.start = ais.readU30("start");
|
||||
abce.end = ais.readU30("end");
|
||||
abce.target = ais.readU30("target");
|
||||
abce.type_index = ais.readU30("type_index");
|
||||
abce.name_index = ais.readU30("name_index");
|
||||
mb.exceptions[j] = abce;
|
||||
}
|
||||
mb.traits = ais.readTraits("traits");
|
||||
bodies.add(mb);
|
||||
ais.endDumpLevel();
|
||||
} catch (EndOfStreamException ex) {
|
||||
logger.log(Level.SEVERE, "MethodBody reading: End of stream", ex);
|
||||
ais.endDumpLevelUntil(di);
|
||||
break;
|
||||
}
|
||||
mb.traits = ais.readTraits("traits");
|
||||
bodies.add(mb);
|
||||
ais.endDumpLevel();
|
||||
|
||||
SWFDecompilerPlugin.fireMethodBodyParsed(mb, swf);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,8 @@ public class FrameExporter {
|
||||
if (fbackgroundColor != null) {
|
||||
exporter.setBackGroundColor(fbackgroundColor);
|
||||
}
|
||||
SWF.frameToSvg(tim, frame, 0, null, 0, exporter, null, 0, settings.zoom);
|
||||
|
||||
tim.toSVG(frame, 0, null, 0, exporter, null, 0, settings.zoom);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
ret.add(f);
|
||||
@@ -359,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, false, settings.zoom).getBufferedImage();
|
||||
BufferedImage result = SWF.frameToImageGet(ftim, fframe, fframe, null, 0, ftim.displayRect, new Matrix(), new Matrix(), null, fbackgroundColor, settings.zoom).getBufferedImage();
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("frame", pos, fframes.size(), tagName);
|
||||
|
||||
@@ -50,7 +50,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
public static final String NAME = "DefineFont2";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int fontId;
|
||||
public int fontID;
|
||||
|
||||
public boolean fontFlagsHasLayout;
|
||||
|
||||
@@ -106,7 +106,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
*/
|
||||
public DefineFont2Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
fontId = swf.getNextCharacterId();
|
||||
fontID = swf.getNextCharacterId();
|
||||
languageCode = new LANGCODE();
|
||||
fontName = "New font";
|
||||
glyphShapeTable = new ArrayList<>();
|
||||
@@ -127,7 +127,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
|
||||
@Override
|
||||
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
|
||||
fontId = sis.readUI16("fontId");
|
||||
fontID = sis.readUI16("fontId");
|
||||
fontFlagsHasLayout = sis.readUB(1, "fontFlagsHasLayout") == 1;
|
||||
fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1;
|
||||
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
|
||||
@@ -246,7 +246,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
checkWideParameters();
|
||||
sos.writeUI16(fontId);
|
||||
sos.writeUI16(fontID);
|
||||
sos.writeUB(1, fontFlagsHasLayout ? 1 : 0);
|
||||
sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0);
|
||||
sos.writeUB(1, fontFlagsSmallText ? 1 : 0);
|
||||
@@ -348,12 +348,12 @@ public class DefineFont2Tag extends FontTag {
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return fontId;
|
||||
return fontID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.fontId = characterId;
|
||||
this.fontID = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -467,7 +467,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
shiftGlyphIndices(fontId, pos);
|
||||
shiftGlyphIndices(fontID, pos);
|
||||
glyphShapeTable.add(pos, shp);
|
||||
codeTable.add(pos, (int) character);
|
||||
} else {
|
||||
|
||||
@@ -50,7 +50,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
public static final String NAME = "DefineFont3";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int fontId;
|
||||
public int fontID;
|
||||
|
||||
public boolean fontFlagsHasLayout;
|
||||
|
||||
@@ -106,7 +106,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
*/
|
||||
public DefineFont3Tag(SWF swf) {
|
||||
super(swf, ID, NAME, null);
|
||||
fontId = swf.getNextCharacterId();
|
||||
fontID = swf.getNextCharacterId();
|
||||
languageCode = new LANGCODE();
|
||||
fontName = "New font";
|
||||
glyphShapeTable = new ArrayList<>();
|
||||
@@ -120,7 +120,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
|
||||
@Override
|
||||
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
|
||||
fontId = sis.readUI16("fontId");
|
||||
fontID = sis.readUI16("fontId");
|
||||
fontFlagsHasLayout = sis.readUB(1, "fontFlagsHasLayout") == 1;
|
||||
fontFlagsShiftJIS = sis.readUB(1, "fontFlagsShiftJIS") == 1;
|
||||
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
|
||||
@@ -246,7 +246,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
}
|
||||
byte[] baGlyphShapes = baosGlyphShapes.toByteArray();
|
||||
|
||||
sos.writeUI16(fontId);
|
||||
sos.writeUI16(fontID);
|
||||
sos.writeUB(1, fontFlagsHasLayout ? 1 : 0);
|
||||
sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0);
|
||||
sos.writeUB(1, fontFlagsSmallText ? 1 : 0);
|
||||
@@ -341,12 +341,12 @@ public class DefineFont3Tag extends FontTag {
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return fontId;
|
||||
return fontID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.fontId = characterId;
|
||||
this.fontID = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -435,7 +435,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
Tag t = swf.getTags().get(i);
|
||||
if (t instanceof DefineFontAlignZonesTag) {
|
||||
DefineFontAlignZonesTag fa = (DefineFontAlignZonesTag) t;
|
||||
if (fa.fontID == fontId) {
|
||||
if (fa.fontID == fontID) {
|
||||
swf.removeTag(t);
|
||||
i--;
|
||||
}
|
||||
@@ -460,7 +460,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
shiftGlyphIndices(fontId, pos);
|
||||
shiftGlyphIndices(fontID, pos);
|
||||
glyphShapeTable.add(pos, shp);
|
||||
codeTable.add(pos, (int) character);
|
||||
} else {
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash.tags;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontInfoTag;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.LANGCODE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
@@ -36,15 +36,12 @@ import java.util.List;
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 6)
|
||||
public class DefineFontInfo2Tag extends Tag implements CharacterIdTag {
|
||||
public class DefineFontInfo2Tag extends FontInfoTag {
|
||||
|
||||
public static final int ID = 62;
|
||||
|
||||
public static final String NAME = "DefineFontInfo2";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int fontID;
|
||||
|
||||
public String fontName;
|
||||
|
||||
@Reserved
|
||||
@@ -143,12 +140,38 @@ public class DefineFontInfo2Tag extends Tag implements CharacterIdTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return fontID;
|
||||
public List<Integer> getCodeTable() {
|
||||
return codeTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.fontID = characterId;
|
||||
public void addCharacter(int index, int character) {
|
||||
codeTable.add(index, character);
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFontName() {
|
||||
return fontName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFontFlagsBold() {
|
||||
return fontFlagsBold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFontFlagsBold(boolean value) {
|
||||
fontFlagsBold = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFontFlagsItalic() {
|
||||
return fontFlagsItalic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFontFlagsItalic(boolean value) {
|
||||
fontFlagsItalic = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash.tags;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontInfoTag;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
@@ -35,15 +35,12 @@ import java.util.List;
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 1)
|
||||
public class DefineFontInfoTag extends Tag implements CharacterIdTag {
|
||||
public class DefineFontInfoTag extends FontInfoTag {
|
||||
|
||||
public static final int ID = 13;
|
||||
|
||||
public static final String NAME = "DefineFontInfo";
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int fontId;
|
||||
|
||||
public String fontName;
|
||||
|
||||
@Reserved
|
||||
@@ -90,7 +87,7 @@ public class DefineFontInfoTag extends Tag implements CharacterIdTag {
|
||||
|
||||
@Override
|
||||
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
|
||||
fontId = sis.readUI16("fontId");
|
||||
fontID = sis.readUI16("fontId");
|
||||
if (swf.version >= 6) {
|
||||
fontName = sis.readNetString("fontName", Utf8Helper.charset);
|
||||
} else {
|
||||
@@ -121,7 +118,7 @@ public class DefineFontInfoTag extends Tag implements CharacterIdTag {
|
||||
*/
|
||||
@Override
|
||||
public void getData(SWFOutputStream sos) throws IOException {
|
||||
sos.writeUI16(fontId);
|
||||
sos.writeUI16(fontID);
|
||||
if (swf.version >= 6) {
|
||||
sos.writeNetString(fontName, Utf8Helper.charset);
|
||||
} else {
|
||||
@@ -144,12 +141,38 @@ public class DefineFontInfoTag extends Tag implements CharacterIdTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return fontId;
|
||||
public List<Integer> getCodeTable() {
|
||||
return codeTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.fontId = characterId;
|
||||
public void addCharacter(int index, int character) {
|
||||
codeTable.add(index, character);
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFontName() {
|
||||
return fontName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFontFlagsBold() {
|
||||
return fontFlagsBold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFontFlagsBold(boolean value) {
|
||||
fontFlagsBold = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFontFlagsItalic() {
|
||||
return fontFlagsItalic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFontFlagsItalic(boolean value) {
|
||||
fontFlagsItalic = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.jpexs.decompiler.flash.tags;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontInfoTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
@@ -50,10 +52,7 @@ public class DefineFontTag extends FontTag {
|
||||
public List<SHAPE> glyphShapeTable;
|
||||
|
||||
@Internal
|
||||
private DefineFontInfoTag fontInfoTag = null;
|
||||
|
||||
@Internal
|
||||
private DefineFontInfo2Tag fontInfo2Tag = null;
|
||||
private FontInfoTag fontInfoTag = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -139,17 +138,14 @@ public class DefineFontTag extends FontTag {
|
||||
|
||||
private void ensureFontInfo() {
|
||||
if (fontInfoTag == null) {
|
||||
for (Tag t : swf.getTags()) {
|
||||
if (t instanceof DefineFontInfoTag) {
|
||||
if (((DefineFontInfoTag) t).fontId == fontId) {
|
||||
fontInfoTag = (DefineFontInfoTag) t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t instanceof DefineFontInfo2Tag) {
|
||||
if (((DefineFontInfo2Tag) t).fontID == fontId) {
|
||||
fontInfo2Tag = (DefineFontInfo2Tag) t;
|
||||
break;
|
||||
List<CharacterIdTag> characterIdTags = swf.getCharacterIdTags(fontId);
|
||||
if (characterIdTags != null) {
|
||||
for (CharacterIdTag t : characterIdTags) {
|
||||
if (t instanceof FontInfoTag) {
|
||||
if (((FontInfoTag) t).fontID == fontId) {
|
||||
fontInfoTag = (FontInfoTag) t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,10 +155,8 @@ public class DefineFontTag extends FontTag {
|
||||
@Override
|
||||
public char glyphToChar(int glyphIndex) {
|
||||
ensureFontInfo();
|
||||
if (fontInfo2Tag != null) {
|
||||
return (char) (int) fontInfo2Tag.codeTable.get(glyphIndex);
|
||||
} else if (fontInfoTag != null) {
|
||||
return (char) (int) fontInfoTag.codeTable.get(glyphIndex);
|
||||
if (fontInfoTag != null) {
|
||||
return (char) (int) fontInfoTag.getCodeTable().get(glyphIndex);
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
@@ -171,10 +165,8 @@ public class DefineFontTag extends FontTag {
|
||||
@Override
|
||||
public int charToGlyph(char c) {
|
||||
ensureFontInfo();
|
||||
if (fontInfo2Tag != null) {
|
||||
return fontInfo2Tag.codeTable.indexOf((int) c);
|
||||
} else if (fontInfoTag != null) {
|
||||
return fontInfoTag.codeTable.indexOf((int) c);
|
||||
if (fontInfoTag != null) {
|
||||
return fontInfoTag.getCodeTable().indexOf((int) c);
|
||||
}
|
||||
return -1;
|
||||
|
||||
@@ -198,33 +190,24 @@ public class DefineFontTag extends FontTag {
|
||||
@Override
|
||||
public String getFontNameIntag() {
|
||||
ensureFontInfo();
|
||||
if (fontInfo2Tag != null) {
|
||||
return fontInfo2Tag.fontName;
|
||||
}
|
||||
if (fontInfoTag != null) {
|
||||
return fontInfoTag.fontName;
|
||||
return fontInfoTag.getFontName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBold() {
|
||||
if (fontInfo2Tag != null) {
|
||||
return fontInfo2Tag.fontFlagsBold;
|
||||
}
|
||||
if (fontInfoTag != null) {
|
||||
return fontInfoTag.fontFlagsBold;
|
||||
return fontInfoTag.getFontFlagsBold();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItalic() {
|
||||
if (fontInfo2Tag != null) {
|
||||
return fontInfo2Tag.fontFlagsItalic;
|
||||
}
|
||||
if (fontInfoTag != null) {
|
||||
return fontInfoTag.fontFlagsItalic;
|
||||
return fontInfoTag.getFontFlagsItalic();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -236,12 +219,12 @@ public class DefineFontTag extends FontTag {
|
||||
|
||||
@Override
|
||||
public boolean isBoldEditable() {
|
||||
return fontInfo2Tag != null || fontInfoTag != null;
|
||||
return fontInfoTag != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItalicEditable() {
|
||||
return fontInfo2Tag != null || fontInfoTag != null;
|
||||
return fontInfoTag != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -250,21 +233,15 @@ public class DefineFontTag extends FontTag {
|
||||
|
||||
@Override
|
||||
public void setBold(boolean value) {
|
||||
if (fontInfo2Tag != null) {
|
||||
fontInfo2Tag.fontFlagsBold = value;
|
||||
}
|
||||
if (fontInfoTag != null) {
|
||||
fontInfoTag.fontFlagsBold = value;
|
||||
fontInfoTag.setFontFlagsBold(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItalic(boolean value) {
|
||||
if (fontInfo2Tag != null) {
|
||||
fontInfo2Tag.fontFlagsItalic = value;
|
||||
}
|
||||
if (fontInfoTag != null) {
|
||||
fontInfoTag.fontFlagsItalic = value;
|
||||
fontInfoTag.setFontFlagsItalic(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,33 +268,36 @@ public class DefineFontTag extends FontTag {
|
||||
@Override
|
||||
public void addCharacter(char character, Font font) {
|
||||
SHAPE shp = SHAPERECORD.fontCharacterToSHAPE(font, (int) Math.round(getDivider() * 1024), character);
|
||||
List<Integer> codeTable = new ArrayList<>();
|
||||
ensureFontInfo();
|
||||
if (fontInfoTag != null) {
|
||||
codeTable = fontInfoTag.codeTable;
|
||||
}
|
||||
if (fontInfo2Tag != null) {
|
||||
codeTable = fontInfo2Tag.codeTable;
|
||||
}
|
||||
int code = (int) character;
|
||||
int pos = -1;
|
||||
boolean exists = false;
|
||||
for (int i = 0; i < codeTable.size(); i++) {
|
||||
if (codeTable.get(i) >= code) {
|
||||
if (codeTable.get(i) == code) {
|
||||
exists = true;
|
||||
if (fontInfoTag != null) {
|
||||
List<Integer> codeTable = fontInfoTag.getCodeTable();
|
||||
for (int i = 0; i < codeTable.size(); i++) {
|
||||
if (codeTable.get(i) >= code) {
|
||||
if (codeTable.get(i) == code) {
|
||||
exists = true;
|
||||
}
|
||||
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos == -1) {
|
||||
pos = codeTable.size();
|
||||
}
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
if (pos == -1) {
|
||||
pos = codeTable.size();
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
shiftGlyphIndices(fontId, pos);
|
||||
glyphShapeTable.add(pos, shp);
|
||||
codeTable.add(pos, (int) character);
|
||||
if (fontInfoTag != null) {
|
||||
fontInfoTag.addCharacter(pos, (int) character);
|
||||
}
|
||||
} else {
|
||||
glyphShapeTable.set(pos, shp);
|
||||
}
|
||||
@@ -335,12 +315,7 @@ public class DefineFontTag extends FontTag {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ensureFontInfo();
|
||||
if (fontInfoTag != null) {
|
||||
for (int i : fontInfoTag.codeTable) {
|
||||
ret.append((char) i);
|
||||
}
|
||||
}
|
||||
if (fontInfo2Tag != null) {
|
||||
for (int i : fontInfo2Tag.codeTable) {
|
||||
for (int i : fontInfoTag.getCodeTable()) {
|
||||
ret.append((char) i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,12 +367,12 @@ public class DefineSpriteTag extends CharacterTag implements DrawableTag, Timeli
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform) {
|
||||
SWF.frameToImage(getTimeline(), frame, time, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform);
|
||||
getTimeline().toImage(frame, time, ratio, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
SWF.frameToSvg(getTimeline(), 0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -92,6 +92,7 @@ public class DoABC2Tag extends Tag implements ABCContainerTag {
|
||||
name = sis.readString("name");
|
||||
|
||||
ABCInputStream ais = new ABCInputStream(sis.getBaseStream());
|
||||
|
||||
// put it to the dumpview:
|
||||
sis.readByteRangeEx(sis.available(), "abcBytes");
|
||||
abc = new ABC(ais, swf, this);
|
||||
|
||||
@@ -93,12 +93,12 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform) {
|
||||
SWF.frameToImage(getTimeline(), frame, time, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform);
|
||||
getTimeline().toImage(frame, time, ratio, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
SWF.frameToSvg(getTimeline(), 0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1, zoom);
|
||||
}
|
||||
|
||||
public DefineButtonSoundTag getSounds() {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class FontInfoTag extends Tag implements CharacterIdTag {
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int fontID;
|
||||
|
||||
public FontInfoTag(SWF swf, int id, String name, ByteArrayRange data) {
|
||||
super(swf, id, name, data);
|
||||
}
|
||||
|
||||
public abstract List<Integer> getCodeTable();
|
||||
|
||||
public abstract void addCharacter(int index, int character);
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return fontID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.fontID = characterId;
|
||||
}
|
||||
|
||||
public abstract String getFontName();
|
||||
|
||||
public abstract boolean getFontFlagsBold();
|
||||
|
||||
public abstract void setFontFlagsBold(boolean value);
|
||||
|
||||
public abstract boolean getFontFlagsItalic();
|
||||
|
||||
public abstract void setFontFlagsItalic(boolean value);
|
||||
}
|
||||
@@ -371,7 +371,7 @@ public final class DefineCompactedFont extends FontTag {
|
||||
@Override
|
||||
public FontTag toClassicFont() {
|
||||
DefineFont2Tag ret = new DefineFont2Tag(swf);
|
||||
ret.fontId = getFontId();
|
||||
ret.fontID = getFontId();
|
||||
ret.fontFlagsBold = isBold();
|
||||
ret.fontFlagsItalic = isItalic();
|
||||
ret.fontFlagsWideOffsets = true;
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
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.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||
import com.jpexs.decompiler.flash.tags.DoActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
@@ -31,24 +33,38 @@ import com.jpexs.decompiler.flash.tags.StartSoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer;
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.DrawableTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.RenderContext;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.MATRIX;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.filters.BlendComposite;
|
||||
import com.jpexs.decompiler.flash.types.filters.FILTER;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -531,7 +547,385 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, boolean isClip, Matrix transformation, Matrix absoluteTransformation, ColorTransform colorTransform) {
|
||||
SWF.frameToImage(this, frame, time, renderContext, image, isClip, transformation, absoluteTransformation, colorTransform);
|
||||
double unzoom = SWF.unitDivisor;
|
||||
if (getFrameCount() <= frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
Frame frameObj = getFrame(frame);
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
g.setPaint(frameObj.backgroundColor.toColor());
|
||||
g.fill(new Rectangle(image.getWidth(), image.getHeight()));
|
||||
g.setTransform(transformation.toTransform());
|
||||
List<Clip> clips = new ArrayList<>();
|
||||
List<Shape> prevClips = new ArrayList<>();
|
||||
|
||||
int maxDepth = getMaxDepth();
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
for (int c = 0; c < clips.size(); c++) {
|
||||
if (clips.get(c).depth == i) {
|
||||
g.setClip(prevClips.get(c));
|
||||
prevClips.remove(c);
|
||||
clips.remove(c);
|
||||
}
|
||||
}
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
}
|
||||
DepthState layer = frameObj.layers.get(i);
|
||||
if (!swf.getCharacters().containsKey(layer.characterId)) {
|
||||
continue;
|
||||
}
|
||||
if (!layer.isVisible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CharacterTag character = swf.getCharacter(layer.characterId);
|
||||
Matrix layerMatrix = new Matrix(layer.matrix);
|
||||
Matrix mat = transformation.concatenate(layerMatrix);
|
||||
Matrix absMat = absoluteTransformation.concatenate(layerMatrix);
|
||||
|
||||
ColorTransform clrTrans = colorTransform;
|
||||
if (layer.colorTransForm != null && layer.blendMode <= 1) { // Normal blend mode
|
||||
clrTrans = clrTrans == null ? layer.colorTransForm : colorTransform.merge(layer.colorTransForm);
|
||||
}
|
||||
|
||||
boolean showPlaceholder = false;
|
||||
if (character instanceof DrawableTag) {
|
||||
DrawableTag drawable = (DrawableTag) character;
|
||||
Matrix drawMatrix = new Matrix();
|
||||
int drawableFrameCount = drawable.getNumFrames();
|
||||
if (drawableFrameCount == 0) {
|
||||
drawableFrameCount = 1;
|
||||
}
|
||||
|
||||
RECT boundRect = drawable.getRect();
|
||||
ExportRectangle rect = new ExportRectangle(boundRect);
|
||||
rect = mat.transform(rect);
|
||||
Matrix m = mat.clone();
|
||||
if (layer.filters != null && layer.filters.size() > 0) {
|
||||
// calculate size after applying the filters
|
||||
double deltaXMax = 0;
|
||||
double deltaYMax = 0;
|
||||
for (FILTER filter : layer.filters) {
|
||||
double x = filter.getDeltaX();
|
||||
double y = filter.getDeltaY();
|
||||
deltaXMax = Math.max(x, deltaXMax);
|
||||
deltaYMax = Math.max(y, deltaYMax);
|
||||
}
|
||||
rect.xMin -= deltaXMax * unzoom;
|
||||
rect.xMax += deltaXMax * unzoom;
|
||||
rect.yMin -= deltaYMax * unzoom;
|
||||
rect.yMax += deltaYMax * unzoom;
|
||||
}
|
||||
|
||||
rect.xMin -= 1 * unzoom;
|
||||
rect.yMin -= 1 * unzoom;
|
||||
rect.xMin = Math.max(0, rect.xMin);
|
||||
rect.yMin = Math.max(0, rect.yMin);
|
||||
|
||||
int newWidth = (int) (rect.getWidth() / unzoom);
|
||||
int newHeight = (int) (rect.getHeight() / unzoom);
|
||||
int deltaX = (int) (rect.xMin / unzoom);
|
||||
int deltaY = (int) (rect.yMin / unzoom);
|
||||
newWidth = Math.min(image.getWidth() - deltaX, newWidth) + 1;
|
||||
newHeight = Math.min(image.getHeight() - deltaY, newHeight) + 1;
|
||||
|
||||
if (newWidth <= 0 || newHeight <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m.translate(-rect.xMin, -rect.yMin);
|
||||
drawMatrix.translate(rect.xMin, rect.yMin);
|
||||
|
||||
SerializableImage img = null;
|
||||
String cacheKey = null;
|
||||
if (drawable instanceof ShapeTag) {
|
||||
cacheKey = ((ShapeTag) drawable).getCharacterId() + m.toString() + (clrTrans == null ? "" : clrTrans.toString());
|
||||
img = renderContext.shapeCache.get(cacheKey);
|
||||
}
|
||||
|
||||
int dframe;
|
||||
if (fontFrameNum != -1) {
|
||||
dframe = fontFrameNum;
|
||||
} else {
|
||||
dframe = time % drawableFrameCount;
|
||||
}
|
||||
|
||||
if (character instanceof ButtonTag) {
|
||||
dframe = ButtonTag.FRAME_UP;
|
||||
if (renderContext.cursorPosition != null) {
|
||||
Shape buttonShape = drawable.getOutline(ButtonTag.FRAME_HITTEST, time, layer.ratio, renderContext, absMat);
|
||||
if (buttonShape.contains(renderContext.cursorPosition)) {
|
||||
renderContext.mouseOverButton = (ButtonTag) character;
|
||||
if (renderContext.mouseButton > 0) {
|
||||
dframe = ButtonTag.FRAME_DOWN;
|
||||
} else {
|
||||
dframe = ButtonTag.FRAME_OVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int stateCount = renderContext.stateUnderCursor == null ? 0 : renderContext.stateUnderCursor.size();
|
||||
if (img == null) {
|
||||
img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB);
|
||||
img.fillTransparent();
|
||||
|
||||
drawable.toImage(dframe, time, layer.ratio, renderContext, img, isClip || layer.clipDepth > -1, m, absMat, clrTrans);
|
||||
|
||||
if (cacheKey != null) {
|
||||
renderContext.shapeCache.put(cacheKey, img);
|
||||
}
|
||||
}
|
||||
|
||||
/*//if (renderContext.stateUnderCursor == layer) {
|
||||
if (true) {
|
||||
BufferedImage bi = img.getBufferedImage();
|
||||
ColorModel cm = bi.getColorModel();
|
||||
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
|
||||
WritableRaster raster = bi.copyData(null);
|
||||
img = new SerializableImage(new BufferedImage(cm, raster, isAlphaPremultiplied, null));
|
||||
Graphics2D gg = (Graphics2D) img.getGraphics();
|
||||
gg.setStroke(new BasicStroke(3));
|
||||
gg.setPaint(Color.red);
|
||||
gg.setTransform(AffineTransform.getTranslateInstance(0, 0));
|
||||
gg.draw(SHAPERECORD.twipToPixelShape(drawable.getOutline(dframe, layer.time + time, layer.ratio, renderContext, m)));
|
||||
}*/
|
||||
if (layer.filters != null) {
|
||||
for (FILTER filter : layer.filters) {
|
||||
img = filter.apply(img);
|
||||
}
|
||||
}
|
||||
if (layer.blendMode > 1) {
|
||||
if (layer.colorTransForm != null) {
|
||||
img = layer.colorTransForm.apply(img);
|
||||
}
|
||||
}
|
||||
|
||||
drawMatrix.translateX /= unzoom;
|
||||
drawMatrix.translateY /= unzoom;
|
||||
AffineTransform trans = drawMatrix.toTransform();
|
||||
|
||||
switch (layer.blendMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
break;
|
||||
case 2: // Layer
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
break;
|
||||
case 3:
|
||||
g.setComposite(BlendComposite.Multiply);
|
||||
break;
|
||||
case 4:
|
||||
g.setComposite(BlendComposite.Screen);
|
||||
break;
|
||||
case 5:
|
||||
g.setComposite(BlendComposite.Lighten);
|
||||
break;
|
||||
case 6:
|
||||
g.setComposite(BlendComposite.Darken);
|
||||
break;
|
||||
case 7:
|
||||
g.setComposite(BlendComposite.Difference);
|
||||
break;
|
||||
case 8:
|
||||
g.setComposite(BlendComposite.Add);
|
||||
break;
|
||||
case 9:
|
||||
g.setComposite(BlendComposite.Subtract);
|
||||
break;
|
||||
case 10:
|
||||
g.setComposite(BlendComposite.Invert);
|
||||
break;
|
||||
case 11:
|
||||
g.setComposite(BlendComposite.Alpha);
|
||||
break;
|
||||
case 12:
|
||||
g.setComposite(BlendComposite.Erase);
|
||||
break;
|
||||
case 13:
|
||||
g.setComposite(BlendComposite.Overlay);
|
||||
break;
|
||||
case 14:
|
||||
g.setComposite(BlendComposite.HardLight);
|
||||
break;
|
||||
default: // Not implemented
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer.clipDepth > -1) {
|
||||
BufferedImage mask = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
|
||||
Graphics2D gm = (Graphics2D) mask.getGraphics();
|
||||
gm.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
gm.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
gm.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
gm.setComposite(AlphaComposite.Src);
|
||||
gm.setColor(new Color(0, 0, 0, 0f));
|
||||
gm.fillRect(0, 0, image.getWidth(), image.getHeight());
|
||||
gm.setTransform(trans);
|
||||
gm.drawImage(img.getBufferedImage(), 0, 0, null);
|
||||
Clip clip = new Clip(Helper.imageToShape(mask), layer.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) {
|
||||
if (renderContext.stateUnderCursor.size() > stateCount) {
|
||||
renderContext.stateUnderCursor.add(layer);
|
||||
}
|
||||
} else if (absMat.transform(new ExportRectangle(boundRect)).contains(renderContext.cursorPosition)) {
|
||||
Shape shape = drawable.getOutline(dframe, time, layer.ratio, renderContext, absMat);
|
||||
if (shape.contains(renderContext.cursorPosition)) {
|
||||
renderContext.stateUnderCursor.add(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (renderContext.borderImage != null) {
|
||||
Graphics2D g2 = (Graphics2D) renderContext.borderImage.getGraphics();
|
||||
g2.setPaint(Color.red);
|
||||
g2.setStroke(new BasicStroke(2));
|
||||
Shape shape = drawable.getOutline(dframe, time, layer.ratio, renderContext, absMat.preConcatenate(Matrix.getScaleInstance(1 / SWF.unitDivisor)));
|
||||
g2.draw(shape);
|
||||
}
|
||||
|
||||
g.setTransform(trans);
|
||||
g.drawImage(img.getBufferedImage(), 0, 0, null);
|
||||
}
|
||||
} else if (character instanceof BoundedTag) {
|
||||
showPlaceholder = true;
|
||||
}
|
||||
|
||||
if (showPlaceholder) {
|
||||
AffineTransform trans = mat.preConcatenate(Matrix.getScaleInstance(1 / SWF.unitDivisor)).toTransform();
|
||||
g.setTransform(trans);
|
||||
BoundedTag b = (BoundedTag) character;
|
||||
g.setPaint(new Color(255, 255, 255, 128));
|
||||
g.setComposite(BlendComposite.Invert);
|
||||
g.setStroke(new BasicStroke((int) SWF.unitDivisor));
|
||||
RECT r = b.getRect();
|
||||
g.setFont(g.getFont().deriveFont((float) (12 * SWF.unitDivisor)));
|
||||
g.drawString(character.toString(), r.Xmin + (int) (3 * SWF.unitDivisor), r.Ymin + (int) (15 * SWF.unitDivisor));
|
||||
g.draw(new Rectangle(r.Xmin, r.Ymin, r.getWidth(), r.getHeight()));
|
||||
g.drawLine(r.Xmin, r.Ymin, r.Xmax, r.Ymax);
|
||||
g.drawLine(r.Xmax, r.Ymin, r.Xmin, r.Ymax);
|
||||
g.setComposite(AlphaComposite.Dst);
|
||||
/*Matrix mat2 = mat.clone();
|
||||
mat2.translateX /= unzoom;
|
||||
mat2.translateY /= unzoom;
|
||||
AffineTransform trans = mat2.toTransform();
|
||||
g.setTransform(trans);
|
||||
BoundedTag b = (BoundedTag) character;
|
||||
g.setPaint(new Color(255, 255, 255, 128));
|
||||
g.setComposite(BlendComposite.Invert);
|
||||
RECT r = b.getRect();
|
||||
int div = (int) unzoom;
|
||||
g.drawString(character.toString(), r.Xmin / div + 3, r.Ymin / div + 15);
|
||||
g.draw(new Rectangle(r.Xmin / div, r.Ymin / div, r.getWidth() / div, r.getHeight() / div));
|
||||
g.drawLine(r.Xmin / div, r.Ymin / div, r.Xmax / div, r.Ymax / div);
|
||||
g.drawLine(r.Xmax / div, r.Ymin / div, r.Xmin / div, r.Ymax / div);
|
||||
g.setComposite(AlphaComposite.Dst);*/
|
||||
}
|
||||
}
|
||||
|
||||
g.setTransform(AffineTransform.getScaleInstance(1, 1));
|
||||
}
|
||||
|
||||
public void toSVG(int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
if (getFrameCount() <= frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
Frame frameObj = getFrame(frame);
|
||||
List<SvgClip> clips = new ArrayList<>();
|
||||
List<String> prevClips = new ArrayList<>();
|
||||
|
||||
int maxDepth = getMaxDepth();
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
for (int c = 0; c < clips.size(); c++) {
|
||||
if (clips.get(c).depth == i) {
|
||||
exporter.setClip(prevClips.get(c));
|
||||
prevClips.remove(c);
|
||||
clips.remove(c);
|
||||
}
|
||||
}
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
}
|
||||
DepthState layer = frameObj.layers.get(i);
|
||||
if (!swf.getCharacters().containsKey(layer.characterId)) {
|
||||
continue;
|
||||
}
|
||||
if (!layer.isVisible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CharacterTag character = swf.getCharacter(layer.characterId);
|
||||
|
||||
ColorTransform clrTrans = colorTransform;
|
||||
if (layer.colorTransForm != null && layer.blendMode <= 1) { // Normal blend mode
|
||||
clrTrans = clrTrans == null ? layer.colorTransForm : colorTransform.merge(layer.colorTransForm);
|
||||
}
|
||||
|
||||
if (character instanceof DrawableTag) {
|
||||
DrawableTag drawable = (DrawableTag) character;
|
||||
|
||||
String assetName;
|
||||
Tag drawableTag = (Tag) drawable;
|
||||
RECT boundRect = drawable.getRect();
|
||||
if (exporter.exportedTags.containsKey(drawableTag)) {
|
||||
assetName = exporter.exportedTags.get(drawableTag);
|
||||
} else {
|
||||
assetName = getTagIdPrefix(drawableTag, exporter);
|
||||
exporter.exportedTags.put(drawableTag, assetName);
|
||||
exporter.createDefGroup(new ExportRectangle(boundRect), assetName);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1, zoom);
|
||||
exporter.endGroup();
|
||||
}
|
||||
ExportRectangle rect = new ExportRectangle(boundRect);
|
||||
|
||||
// TODO: if (layer.filters != null)
|
||||
// TODO: if (layer.blendMode > 1)
|
||||
if (layer.clipDepth > -1) {
|
||||
String clipName = exporter.getUniqueId("clipPath");
|
||||
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));
|
||||
exporter.addUse(mat, boundRect, assetName, layer.instanceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTagIdPrefix(Tag tag, SVGExporter exporter) {
|
||||
if (tag instanceof ShapeTag) {
|
||||
return exporter.getUniqueId("shape");
|
||||
}
|
||||
if (tag instanceof MorphShapeTag) {
|
||||
return exporter.getUniqueId("morphshape");
|
||||
}
|
||||
if (tag instanceof DefineSpriteTag) {
|
||||
return exporter.getUniqueId("sprite");
|
||||
}
|
||||
if (tag instanceof TextTag) {
|
||||
return exporter.getUniqueId("text");
|
||||
}
|
||||
if (tag instanceof ButtonTag) {
|
||||
return exporter.getUniqueId("button");
|
||||
}
|
||||
return exporter.getUniqueId("tag");
|
||||
}
|
||||
|
||||
public void toHtmlCanvas(StringBuilder result, double unitDivisor, List<Integer> frames) {
|
||||
@@ -665,8 +1059,7 @@ public class Timeline {
|
||||
CharacterTag character = swf.getCharacter(layer.characterId);
|
||||
if (character instanceof DrawableTag) {
|
||||
DrawableTag drawable = (DrawableTag) character;
|
||||
Matrix m = new Matrix(layer.matrix);
|
||||
m = m.preConcatenate(transformation);
|
||||
Matrix m = transformation.concatenate(new Matrix(layer.matrix));
|
||||
|
||||
int drawableFrameCount = drawable.getNumFrames();
|
||||
if (drawableFrameCount == 0) {
|
||||
|
||||
@@ -418,8 +418,10 @@ public class XFLConverter {
|
||||
private static String convertShape(HashMap<Integer, CharacterTag> characters, MATRIX mat, int shapeNum, List<SHAPERECORD> shapeRecords, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStyles, boolean morphshape, boolean useLayers) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
List<String> layers = getShapeLayers(characters, mat, shapeNum, shapeRecords, fillStyles, lineStyles, morphshape);
|
||||
if (layers.size() == 1 && !useLayers) {
|
||||
ret.append(layers.get(0));
|
||||
if (!useLayers) {
|
||||
for (int l = layers.size() - 1; l >= 0; l--) {
|
||||
ret.append(layers.get(l));
|
||||
}
|
||||
} else {
|
||||
int layer = 1;
|
||||
for (int l = layers.size() - 1; l >= 0; l--) {
|
||||
|
||||
Reference in New Issue
Block a user