From ccc6099687f037cc56df860c2c83d3c12fdf714f Mon Sep 17 00:00:00 2001 From: Honfika Date: Sun, 23 Feb 2014 13:29:01 +0100 Subject: [PATCH] Bitmap rendering improved --- .../com/jpexs/decompiler/flash/FrameInfo.java | 34 ++ trunk/src/com/jpexs/decompiler/flash/SWF.java | 365 ++++++++++-------- .../flash/exporters/BitmapExporter.java | 71 ++-- .../{Rectangle.java => ExportRectangle.java} | 25 +- .../decompiler/flash/exporters/Matrix.java | 62 +++ .../flash/exporters/ShapeExporterBase.java | 2 +- .../flash/gui/GenericTagTreePanel.java | 10 +- .../decompiler/flash/gui/ImagePanel.java | 30 +- .../gui/generictageditors/BooleanEditor.java | 4 +- .../gui/generictageditors/ColorEditor.java | 2 +- .../gui/generictageditors/NumberEditor.java | 2 + .../gui/generictageditors/StringEditor.java | 1 + .../flash/tags/DefineButton2Tag.java | 20 +- .../flash/tags/DefineButtonTag.java | 19 +- .../flash/tags/DefineEditTextTag.java | 4 +- .../flash/tags/DefineMorphShape2Tag.java | 24 +- .../flash/tags/DefineMorphShapeTag.java | 24 +- .../flash/tags/DefineShape2Tag.java | 18 +- .../flash/tags/DefineShape3Tag.java | 18 +- .../flash/tags/DefineShape4Tag.java | 18 +- .../decompiler/flash/tags/DefineShapeTag.java | 18 +- .../flash/tags/DefineSpriteTag.java | 21 +- .../decompiler/flash/tags/DefineText2Tag.java | 15 +- .../decompiler/flash/tags/DefineTextTag.java | 15 +- .../flash/tags/DefineVideoStreamTag.java | 4 +- .../flash/tags/base/BoundedTag.java | 4 +- .../flash/tags/base/DrawableTag.java | 8 +- .../decompiler/flash/tags/base/FontTag.java | 10 +- .../decompiler/flash/tags/base/ShapeTag.java | 2 +- .../decompiler/flash/tags/base/TextTag.java | 31 +- .../flash/tags/gfx/DefineCompactedFont.java | 6 +- .../parser/ConditionEvaluator.java | 2 +- .../annotations/parser/ConditionLexer.java | 7 +- .../flash/types/shaperecords/SHAPERECORD.java | 2 +- .../decompiler/flash/xfl/XFLConverter.java | 2 - .../com/jpexs/helpers/SerializableImage.java | 6 +- 36 files changed, 583 insertions(+), 323 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/FrameInfo.java rename trunk/src/com/jpexs/decompiler/flash/exporters/{Rectangle.java => ExportRectangle.java} (69%) diff --git a/trunk/src/com/jpexs/decompiler/flash/FrameInfo.java b/trunk/src/com/jpexs/decompiler/flash/FrameInfo.java new file mode 100644 index 000000000..3a6a73741 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/FrameInfo.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010-2014 PEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import java.awt.Color; +import java.util.Map; + +/** + * + * @author JPEXS + */ +public class FrameInfo { + + public int maxDepth; + public Map layers; + public Color backgroundColor; + public Map characters; + public int frame; +} diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index f1a6f4ce5..d601615ee 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -52,6 +52,7 @@ import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.ExportRectangle; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.flv.AUDIODATA; import com.jpexs.decompiler.flash.flv.FLVOutputStream; @@ -125,7 +126,6 @@ import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -175,7 +175,7 @@ public final class SWF implements TreeItem { */ public List tags = new ArrayList<>(); /** - * Rectangle for the display + * ExportRectangle for the display */ public RECT displayRect; /** @@ -2129,180 +2129,37 @@ public final class SWF implements TreeItem { return ret; } - public static SerializableImage frameToImage(int containerId, int maxDepth, HashMap layers, Color backgroundColor, HashMap characters, int frame, List allTags, List controlTags, RECT displayRect, Stack visited, Matrix transformation) { + public static SerializableImage frameToImage(int containerId, int frame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation) { String key = "frame_" + frame + "_" + containerId; if (frameCache.contains(key)) { SerializableImage ciret = ((SerializableImage) frameCache.get(key)); return ciret; } - float unzoom = (float) SWF.unitDivisor; - int fixX = -displayRect.Xmin; - int fixY = -displayRect.Ymin; - displayRect = fixRect(displayRect); - int width = displayRect.getWidth(); - int height = displayRect.getHeight(); - - SerializableImage ret = new SerializableImage((int) (width / unzoom), (int) (height / unzoom), SerializableImage.TYPE_INT_ARGB); - ret.bounds = new Rectangle2D.Double(-fixX / unzoom, -fixY / unzoom, width / unzoom, height / unzoom); - - Graphics2D g = (Graphics2D) ret.getGraphics(); - g.setPaint(backgroundColor); - g.fill(new Rectangle(ret.getWidth(), ret.getHeight())); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - for (int i = 1; i <= maxDepth; i++) { - if (!layers.containsKey(i)) { - continue; - } - Layer layer = layers.get(i); - if (!characters.containsKey(layer.characterId)) { - continue; - } - if (!layer.visible) { - continue; - } - CharacterTag character = characters.get(layer.characterId); - Matrix mat = new Matrix(layer.matrix); - /*if (firstLevel) { - mat.scale(unzoom); - }*/ - mat.translate(fixX, fixY); - - if (character instanceof DrawableTag) { - DrawableTag drawable = (DrawableTag) character; - SerializableImage img = drawable.toImage(layer.ratio < 0 ? 0 : layer.ratio/*layer.duration*/, allTags, characters, visited, transformation); - mat.translate(img.bounds.getMinX() * unzoom, img.bounds.getMinY() * unzoom); - /*if (character instanceof BoundedTag) { - BoundedTag bounded = (BoundedTag) character; - RECT rect = bounded.getRect(characters, visited); - }*/ - if (layer.filters != null) { - for (FILTER filter : layer.filters) { - img = filter.apply(img); - } - } - if (layer.colorTransForm != null) { - img = layer.colorTransForm.apply(img); - } - - if (layer.colorTransFormAlpha != null) { - img = layer.colorTransFormAlpha.apply(img); - } - switch (layer.blendMode) { - case 0: - case 1: - g.setComposite(AlphaComposite.SrcOver); - break; - case 2: //TODO: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; - } - - mat.translateX /= unzoom; - mat.translateY /= unzoom; - AffineTransform trans = mat.toTransform(); - g.setTransform(trans); - g.drawImage(img.getBufferedImage(), 0, 0, null); - } else if (character instanceof BoundedTag) { - mat.translateX /= unzoom; - mat.translateY /= unzoom; - AffineTransform trans = mat.toTransform(); - g.setTransform(trans); - BoundedTag b = (BoundedTag) character; - g.setPaint(new Color(255, 255, 255, 128)); - g.setComposite(BlendComposite.Invert); - RECT r = b.getRect(characters, visited); - 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)); - /*g.setPaint(Color.yellow); - g.draw(new Rectangle(ret.getWidth()-1,ret.getHeight()-1));*/ - frameCache.put(key, ret); - - /*try { - ImageIO.write(ret, "png", new File("tst_id_" + containerId + "_time_" + System.currentTimeMillis() + ".png")); - } catch (IOException ex) { - Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, null, ex); - }*/ - return ret; - } - - public static SerializableImage frameToImage(int containerId, int frame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation) { - List ret = new ArrayList<>(); - framesToImage(containerId, ret, frame, frame, allTags, controlTags, displayRect, totalFrameCount, visited, transformation); - if (ret.isEmpty()) { + List frameInfos = getFrameInfo(frame, frame, allTags, controlTags, totalFrameCount); + if (frameInfos.isEmpty()) { return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB); } - return ret.get(0); + + FrameInfo fi = frameInfos.get(0); + + RECT rect = displayRect; + SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, + (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); + Matrix m = new Matrix(); + m.translate(-rect.Xmin, -rect.Ymin); + frameToImage(containerId, fi.maxDepth, fi.layers, fi.backgroundColor, fi.characters, fi.frame, allTags, controlTags, displayRect, visited, image, m); + frameCache.put(key, image); + return image; } - public static void framesToImage(int containerId, List ret, int startFrame, int stopFrame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation) { - for (int i = startFrame; i <= stopFrame; i++) { - String key = "frame_" + i + "_" + containerId; - if (frameCache.contains(key)) { - SerializableImage g = (SerializableImage) frameCache.get(key); - if (g == null) { - break; - } - ret.add(g); - startFrame++; - } else { - break; - } - } + private static List getFrameInfo(int startFrame, int stopFrame, List allTags, List controlTags, int totalFrameCount) { + List ret = new ArrayList<>(); if (startFrame > stopFrame) { - return; + return ret; } if (totalFrameCount == 0) { - return; + return ret; } while (startFrame >= totalFrameCount) { @@ -2313,7 +2170,7 @@ public final class SWF implements TreeItem { stopFrame -= totalFrameCount; } - HashMap characters = new HashMap<>(); + Map characters = new HashMap<>(); for (Tag t : allTags) { if (t instanceof CharacterTag) { CharacterTag ch = (CharacterTag) t; @@ -2321,7 +2178,7 @@ public final class SWF implements TreeItem { } } - HashMap layers = new HashMap<>(); + Map layers = new HashMap<>(); int maxDepth = 0; int f = 0; @@ -2401,15 +2258,185 @@ public final class SWF implements TreeItem { l.duration++; } if (t instanceof ShowFrameTag) { + if ((f >= startFrame) && (f <= stopFrame)) { + FrameInfo fi = new FrameInfo(); + fi.maxDepth = maxDepth; + fi.layers = layers; + fi.backgroundColor = backgroundColor; + fi.characters = characters; + fi.frame = f; + ret.add(fi); + } + f++; if (f > stopFrame) { break; } - if ((f >= startFrame) && (f <= stopFrame)) { - ret.add(frameToImage(containerId, maxDepth, layers, backgroundColor, characters, f, allTags, controlTags, displayRect, visited, transformation)); - } - f++; } } + + return ret; + } + + public static void framesToImage(int containerId, List ret, int startFrame, int stopFrame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation) { + List frameInfos = getFrameInfo(startFrame, stopFrame, allTags, controlTags, totalFrameCount); + RECT rect = displayRect; + for (FrameInfo fi : frameInfos) { + SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, + (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); + Matrix m = new Matrix(); + m.translate(-rect.Xmin, -rect.Ymin); + frameToImage(containerId, fi.maxDepth, fi.layers, fi.backgroundColor, fi.characters, fi.frame, allTags, controlTags, displayRect, visited, image, m); + ret.add(image); + } + } + + public static void frameToImage(int containerId, int maxDepth, Map layers, Color backgroundColor, Map characters, int frame, List allTags, List controlTags, RECT displayRect, Stack visited, SerializableImage image, Matrix transformation) { + float unzoom = (float) SWF.unitDivisor; + + Graphics2D g = (Graphics2D) image.getGraphics(); + g.setPaint(backgroundColor); + g.fill(new Rectangle(image.getWidth(), image.getHeight())); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setTransform(transformation.toTransform()); + + for (int i = 1; i <= maxDepth; i++) { + if (!layers.containsKey(i)) { + continue; + } + Layer layer = layers.get(i); + if (!characters.containsKey(layer.characterId)) { + continue; + } + if (!layer.visible) { + continue; + } + CharacterTag character = characters.get(layer.characterId); + Matrix mat = new Matrix(layer.matrix); + mat = mat.preConcatenate(transformation); + + if (character instanceof DrawableTag) { + DrawableTag drawable = (DrawableTag) character; + SerializableImage img; + Matrix drawMatrix = new Matrix(); + if (drawable instanceof BoundedTag) { + BoundedTag bounded = (BoundedTag) drawable; + RECT boundRect = bounded.getRect(characters, new Stack()); + ExportRectangle rect = new ExportRectangle(boundRect); + rect = mat.transform(rect); + img = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, + (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); + Matrix m = mat.clone(); + m.translate(-rect.xMin, -rect.yMin); + drawMatrix.translate(rect.xMin, rect.yMin); + drawable.toImage(layer.ratio < 0 ? 0 : layer.ratio/*layer.duration*/, allTags, characters, visited, img, m); + } else { + img = drawable.toImage(layer.ratio < 0 ? 0 : layer.ratio/*layer.duration*/, allTags, characters, visited, transformation); + } + /*if (character instanceof BoundedTag) { + BoundedTag bounded = (BoundedTag) character; + RECT rect = bounded.getRect(characters, visited); + }*/ + if (layer.filters != null) { + for (FILTER filter : layer.filters) { + img = filter.apply(img); + } + } + if (layer.colorTransForm != null) { + img = layer.colorTransForm.apply(img); + } + + if (layer.colorTransFormAlpha != null) { + img = layer.colorTransFormAlpha.apply(img); + } + switch (layer.blendMode) { + case 0: + case 1: + g.setComposite(AlphaComposite.SrcOver); + break; + case 2: //TODO: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; + } + + drawMatrix.translateX /= unzoom; + drawMatrix.translateY /= unzoom; + g.setTransform(drawMatrix.toTransform()); + g.drawImage(img.getBufferedImage(), 0, 0, null); + } else if (character instanceof BoundedTag) { + mat.translateX /= unzoom; + mat.translateY /= unzoom; + AffineTransform trans = mat.toTransform(); + g.setTransform(trans); + BoundedTag b = (BoundedTag) character; + g.setPaint(new Color(255, 255, 255, 128)); + g.setComposite(BlendComposite.Invert); + RECT r = b.getRect(characters, visited); + 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)); + /*g.setPaint(Color.yellow); + g.draw(new ExportRectangle(ret.getWidth()-1,ret.getHeight()-1));*/ + + /*try { + ImageIO.write(ret, "png", new File("tst_id_" + containerId + "_time_" + System.currentTimeMillis() + ".png")); + } catch (IOException ex) { + Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, null, ex); + }*/ + } + + public static void frameToImage(int containerId, int frame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, SerializableImage image, Matrix transformation) { + List frameInfos = getFrameInfo(frame, frame, allTags, controlTags, totalFrameCount); + if (!frameInfos.isEmpty()) { + FrameInfo fi = frameInfos.get(0); + frameToImage(containerId, fi.maxDepth, fi.layers, fi.backgroundColor, fi.characters, fi.frame, allTags, controlTags, displayRect, visited, image, transformation); + } } public void removeTagFromTimeline(Tag toRemove, List timeline) { diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java index b444287bd..2fa519cab 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java @@ -65,6 +65,8 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter private Color lineColor; private Stroke lineStroke; private Stroke defaultStroke; + private Matrix transform; + private double unitDivisor; public static SerializableImage export(SWF swf, SHAPE shape) { BitmapExporter exporter = new BitmapExporter(swf, shape, null); @@ -72,12 +74,17 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter return exporter.getImage(); } - public static SerializableImage export(SWF swf, SHAPE shape, Color defaultColor, boolean putToCache) { + public static SerializableImage export(SWF swf, SHAPE shape, Color defaultColor) { BitmapExporter exporter = new BitmapExporter(swf, shape, defaultColor); exporter.export(); return exporter.getImage(); } + public static void exportTo(SWF swf, SHAPE shape, Color defaultColor, SerializableImage image, Matrix transformation) { + BitmapExporter exporter = new BitmapExporter(swf, shape, defaultColor); + exporter.exportTo(image, transformation); + } + private BitmapExporter(SWF swf, SHAPE shape, Color defaultColor) { super(shape); this.swf = swf; @@ -97,11 +104,12 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter } } } - double maxLineWidth = maxLineWidthTwips / SWF.unitDivisor / 2; - deltaX = bounds.Xmin / SWF.unitDivisor - maxLineWidth; - deltaY = bounds.Ymin / SWF.unitDivisor - maxLineWidth; - double width = bounds.getWidth() / SWF.unitDivisor + 2 * (maxLineWidth + 1); - double height = bounds.getHeight() / SWF.unitDivisor + 2 * (maxLineWidth + 1); + unitDivisor = SWF.unitDivisor; + double maxLineWidth = maxLineWidthTwips / unitDivisor / 2; + deltaX = bounds.Xmin / unitDivisor - maxLineWidth; + deltaY = bounds.Ymin / unitDivisor - maxLineWidth; + double width = bounds.getWidth() / unitDivisor + 2 * (maxLineWidth + 1); + double height = bounds.getHeight() / unitDivisor + 2 * (maxLineWidth + 1); image = new SerializableImage((int) width, (int) height, SerializableImage.TYPE_INT_ARGB); graphics = (Graphics2D) image.getGraphics(); graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); @@ -112,6 +120,21 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter image.bounds = new Rectangle2D.Double(deltaX, deltaY, width, height); } + private void exportTo(SerializableImage image, Matrix transformation) { + this.image = image; + this.transform = transformation; + graphics = (Graphics2D) image.getGraphics(); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + AffineTransform at = transformation.toTransform(); + at.preConcatenate(AffineTransform.getScaleInstance(1 / SWF.unitDivisor, 1 / SWF.unitDivisor)); + unitDivisor = 1; + graphics.setTransform(at); + defaultStroke = graphics.getStroke(); + super.export(); + } + public SerializableImage getImage() { return image; } @@ -150,12 +173,12 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter @Override public void beginGradientFill(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) { finalizePath(); - matrix.translateX /= SWF.unitDivisor; - matrix.translateY /= SWF.unitDivisor; - matrix.scaleX /= SWF.unitDivisor; - matrix.scaleY /= SWF.unitDivisor; - matrix.rotateSkew0 /= SWF.unitDivisor; - matrix.rotateSkew1 /= SWF.unitDivisor; + matrix.translateX /= unitDivisor; + matrix.translateY /= unitDivisor; + matrix.scaleX /= unitDivisor; + matrix.scaleY /= unitDivisor; + matrix.rotateSkew0 /= unitDivisor; + matrix.rotateSkew1 /= unitDivisor; switch (type) { case FILLSTYLE.LINEAR_GRADIENT: { List colors = new ArrayList<>(); @@ -264,12 +287,12 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter @Override public void beginBitmapFill(int bitmapId, Matrix matrix, boolean repeat, boolean smooth) { finalizePath(); - matrix.translateX /= SWF.unitDivisor; - matrix.translateY /= SWF.unitDivisor; - matrix.scaleX /= SWF.unitDivisor; - matrix.scaleY /= SWF.unitDivisor; - matrix.rotateSkew0 /= SWF.unitDivisor; - matrix.rotateSkew1 /= SWF.unitDivisor; + matrix.translateX /= unitDivisor; + matrix.translateY /= unitDivisor; + matrix.scaleX /= unitDivisor; + matrix.scaleY /= unitDivisor; + matrix.rotateSkew0 /= unitDivisor; + matrix.rotateSkew1 /= unitDivisor; ImageTag image = null; for (Tag t : swf.tags) { if (t instanceof ImageTag) { @@ -300,7 +323,7 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter @Override public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) { finalizePath(); - thickness /= SWF.unitDivisor; + thickness /= unitDivisor; lineColor = color.toColor(); int capStyle = BasicStroke.CAP_ROUND; switch (startCaps) { @@ -339,18 +362,18 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter @Override public void moveTo(double x, double y) { - path.moveTo(x / SWF.unitDivisor - deltaX, y / SWF.unitDivisor - deltaY); + path.moveTo(x / unitDivisor - deltaX, y / unitDivisor - deltaY); } @Override public void lineTo(double x, double y) { - path.lineTo(x / SWF.unitDivisor - deltaX, y / SWF.unitDivisor - deltaY); + path.lineTo(x / unitDivisor - deltaX, y / unitDivisor - deltaY); } @Override public void curveTo(double controlX, double controlY, double anchorX, double anchorY) { - path.quadTo(controlX / SWF.unitDivisor - deltaX, controlY / SWF.unitDivisor - deltaY, - anchorX / SWF.unitDivisor - deltaX, anchorY / SWF.unitDivisor - deltaY); + path.quadTo(controlX / unitDivisor - deltaX, controlY / unitDivisor - deltaY, + anchorX / unitDivisor - deltaX, anchorY / unitDivisor - deltaY); } protected void finalizePath() { @@ -364,6 +387,7 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter } graphics.fill(path); graphics.setClip(path); + fillTransform.preConcatenate(oldAf); graphics.setTransform(fillTransform); graphics.setPaint(fillPaint); @@ -373,6 +397,7 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter } else if (fillPaint instanceof TexturePaint) { AffineTransform oldAf = graphics.getTransform(); graphics.setClip(path); + fillTransform.preConcatenate(oldAf); graphics.setTransform(fillTransform); graphics.setPaint(fillPaint); diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/Rectangle.java b/trunk/src/com/jpexs/decompiler/flash/exporters/ExportRectangle.java similarity index 69% rename from trunk/src/com/jpexs/decompiler/flash/exporters/Rectangle.java rename to trunk/src/com/jpexs/decompiler/flash/exporters/ExportRectangle.java index 1fb1b2b3f..ec1b1a823 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/Rectangle.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/ExportRectangle.java @@ -16,24 +16,41 @@ */ package com.jpexs.decompiler.flash.exporters; +import com.jpexs.decompiler.flash.types.RECT; + /** * * @author JPEXS */ -public class Rectangle { +public class ExportRectangle { public double xMin; public double yMin; public double xMax; public double yMax; - Rectangle(double xMin, double yMin, double xMax, double yMax) { + public ExportRectangle(double xMin, double yMin, double xMax, double yMax) { this.xMin = xMin; this.yMin = yMin; this.xMax = xMax; this.yMax = yMax; } + public ExportRectangle(RECT rect) { + this.xMin = rect.Xmin; + this.yMin = rect.Ymin; + this.xMax = rect.Xmax; + this.yMax = rect.Ymax; + } + + public double getWidth() { + return xMax - xMin; + } + + public double getHeight() { + return yMax - yMin; + } + @Override public int hashCode() { long bits = Double.doubleToLongBits(xMin); @@ -45,8 +62,8 @@ public class Rectangle { @Override public boolean equals(Object obj) { - if (obj instanceof Rectangle) { - Rectangle r = (Rectangle) obj; + if (obj instanceof ExportRectangle) { + ExportRectangle r = (ExportRectangle) obj; return (xMin == r.xMin) && (yMin == r.yMin) && (xMax == r.xMax) && (yMax == r.yMax); } return super.equals(obj); diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java b/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java index fef0ae453..2b5e34aeb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/Matrix.java @@ -71,6 +71,46 @@ public class Matrix { return mat; } + public Point transform(double x, double y) { + Point result = new Point( + scaleX * x + rotateSkew1 * y + translateX, + rotateSkew0 * x + scaleY * y + translateY); + return result; + } + + public Point transform(Point point) { + return transform(point.x, point.y); + } + + public ExportRectangle transform(ExportRectangle rect) { + double minX = Double.MAX_VALUE; + double minY = Double.MAX_VALUE; + double maxX = Double.MIN_VALUE; + double maxY = Double.MIN_VALUE; + Point point; + point = transform(rect.xMin, rect.yMin); + if (point.x < minX) minX = point.x; + if (point.x > maxX) maxX = point.x; + if (point.y < minY) minY = point.y; + if (point.y > maxY) maxY = point.y; + point = transform(rect.xMax, rect.yMin); + if (point.x < minX) minX = point.x; + if (point.x > maxX) maxX = point.x; + if (point.y < minY) minY = point.y; + if (point.y > maxY) maxY = point.y; + point = transform(rect.xMin, rect.yMax); + if (point.x < minX) minX = point.x; + if (point.x > maxX) maxX = point.x; + if (point.y < minY) minY = point.y; + if (point.y > maxY) maxY = point.y; + point = transform(rect.xMax, rect.yMax); + if (point.x < minX) minX = point.x; + if (point.x > maxX) maxX = point.x; + if (point.y < minY) minY = point.y; + if (point.y > maxY) maxY = point.y; + return new ExportRectangle(minX, minY, maxX, maxY); + } + public void translate(double x, double y) { translateX += x; translateY += y; @@ -83,6 +123,28 @@ public class Matrix { rotateSkew1 *= factor; } + public Matrix concatenate(Matrix m) { + Matrix result = new Matrix(); + result.scaleX = scaleX * m.scaleX + rotateSkew1 * m.rotateSkew0; + result.rotateSkew0 = rotateSkew0 * m.scaleX + scaleY * m.rotateSkew0; + result.rotateSkew1 = scaleX * m.rotateSkew1 + rotateSkew1 * m.scaleY; + result.scaleY = rotateSkew0 * m.rotateSkew1 + scaleY * m.scaleY; + result.translateX = scaleX * m.translateX + rotateSkew1 * m.translateY + translateX; + result.translateY = rotateSkew0 * m.translateX + scaleY * m.translateY + translateY; + return result; + } + + public Matrix preConcatenate(Matrix m) { + Matrix result = new Matrix(); + result.scaleX = m.scaleX * scaleX + m.rotateSkew1 * rotateSkew0; + result.rotateSkew0 = m.rotateSkew0 * scaleX + m.scaleY * rotateSkew0; + result.rotateSkew1 = m.scaleX * rotateSkew1 + m.rotateSkew1 * scaleY; + result.scaleY = m.rotateSkew0 * rotateSkew1 + m.scaleY * scaleY; + result.translateX = m.scaleX * translateX + m.rotateSkew1 * translateY + m.translateX; + result.translateY = m.rotateSkew0 * translateX + m.scaleY * translateY + m.translateY; + return result; + } + public AffineTransform toTransform() { AffineTransform transform = new AffineTransform(scaleX, rotateSkew0, rotateSkew1, scaleY, diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java b/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java index 7e305b312..ed01d0b4f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java @@ -53,7 +53,7 @@ public abstract class ShapeExporterBase implements IShapeExporter { protected Map> currentLineEdgeMap; private int numGroups; protected Map> coordMap; - private final Rectangle bounds = new Rectangle(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); + private final ExportRectangle bounds = new ExportRectangle(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); private boolean edgeMapsCreated; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java index ae33d5ce0..041ab3fe5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java @@ -101,7 +101,7 @@ public class GenericTagTreePanel extends GenericTagPanel { private class MyTreeCellEditor extends AbstractCellEditor implements TreeCellEditor { private GenericTagEditor editor = null; - private JTree tree; + private final JTree tree; public MyTreeCellEditor(JTree tree) { this.tree = tree; @@ -321,6 +321,7 @@ public class GenericTagTreePanel extends GenericTagPanel { } + @Override public void clear() { } @@ -445,8 +446,8 @@ public class GenericTagTreePanel extends GenericTagPanel { private static class MyTreeModel extends DefaultTreeModel { - private Object root; - private List listeners = new ArrayList<>(); + private final Object root; + private final List listeners = new ArrayList<>(); private DefaultMutableTreeNode rootNode; public MyTreeModel(Tag root) { @@ -526,6 +527,7 @@ public class GenericTagTreePanel extends GenericTagPanel { return new MyTreeModel(editedTag); } + @Override public void setEditMode(boolean edit, Tag tag) { if (tag == null) { tag = this.tag; @@ -536,6 +538,7 @@ public class GenericTagTreePanel extends GenericTagPanel { tree.setEditable(edit); } + @Override public void save() { tree.stopEditing(); SWF swf = tag.getSwf(); @@ -557,6 +560,7 @@ public class GenericTagTreePanel extends GenericTagPanel { } } + @Override public Tag getTag() { return tag; } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 0b01dc934..220bb0637 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -20,8 +20,10 @@ import com.jpexs.decompiler.flash.AppStrings; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.gui.player.FlashDisplay; +import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.helpers.SerializableImage; import java.awt.BorderLayout; import java.awt.Color; @@ -127,7 +129,19 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis String key = "drawable_0_" + drawable.hashCode(); SerializableImage img = SWF.getFromCache(key); if (img == null) { - img = drawable.toImage(0, swf.tags, characters, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor)); + if (drawable instanceof BoundedTag) { + BoundedTag bounded = (BoundedTag) drawable; + RECT rect = bounded.getRect(characters, new Stack()); + SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, + (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); + Matrix m = new Matrix(); + m.translate(-rect.Xmin, -rect.Ymin); + drawable.toImage(0, swf.tags, characters, new Stack(), image, m); + img = image; + + } else { + img = drawable.toImage(0, swf.tags, characters, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor)); + } SWF.putToCache(key, img); } if (img != null && img.bounds != null && mat != null) { @@ -189,7 +203,19 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis String key = "drawable_" + nframe + "_" + drawable.hashCode(); SerializableImage img = SWF.getFromCache(key); if (img == null) { - img = drawable.toImage(nframe, swf.tags, characters, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor)); + if (drawable instanceof BoundedTag) { + BoundedTag bounded = (BoundedTag) drawable; + RECT rect = bounded.getRect(characters, new Stack()); + SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, + (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); + Matrix m = new Matrix(); + m.translate(-rect.Xmin, -rect.Ymin); + drawable.toImage(nframe, swf.tags, characters, new Stack(), image, m); + img = image; + + } else { + img = drawable.toImage(nframe, swf.tags, characters, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor)); + } SWF.putToCache(key, img); } mat.translate(img.bounds.getMinX(), img.bounds.getMinY()); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/BooleanEditor.java b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/BooleanEditor.java index 1c62ada13..bc6776322 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/BooleanEditor.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/BooleanEditor.java @@ -31,7 +31,7 @@ public class BooleanEditor extends JCheckBox implements GenericTagEditor { private final Field field; private final int index; private final Class type; - private String fieldName; + private final String fieldName; public BooleanEditor(String fieldName,Object obj, Field field, int index, Class type) { super(); @@ -73,10 +73,12 @@ public class BooleanEditor extends JCheckBox implements GenericTagEditor { return isSelected(); } + @Override public String getFieldName() { return fieldName; } + @Override public Field getField() { return field; } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ColorEditor.java b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ColorEditor.java index 50c93558b..d2d060d17 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ColorEditor.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ColorEditor.java @@ -46,7 +46,7 @@ public class ColorEditor extends JPanel implements GenericTagEditor, ActionListe private final Field field; private final int index; private final Class type; - private String fieldName; + private final String fieldName; private Color color; public static final int COLOR_TYPE_RGB = 0; public static final int COLOR_TYPE_RGBA = 1; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/NumberEditor.java b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/NumberEditor.java index 4dea19c09..391bd9f8b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/NumberEditor.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/NumberEditor.java @@ -203,10 +203,12 @@ public class NumberEditor extends JSpinner implements GenericTagEditor { return value; } + @Override public String getFieldName() { return fieldName; } + @Override public Field getField() { return field; } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/StringEditor.java b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/StringEditor.java index edcf45d5a..6a93e7f84 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/StringEditor.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/StringEditor.java @@ -113,6 +113,7 @@ public class StringEditor extends JTextArea implements GenericTagEditor { return fieldName; } + @Override public Field getField() { return field; } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index 85824d842..c7ea1d2a8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.logging.Level; @@ -216,7 +217,7 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded private static final Cache rectCache = Cache.getInstance(true); @Override - public RECT getRect(HashMap allCharacters, Stack visited) { + public RECT getRect(Map allCharacters, Stack visited) { if (rectCache.contains(this)) { return (RECT) rectCache.get(this); } @@ -253,9 +254,14 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); + } + + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { if (visited.contains(buttonId)) { - return new SerializableImage(1, 1, SerializableImage.TYPE_4BYTE_ABGR); + return; } visited.push(buttonId); HashMap layers = new HashMap<>(); @@ -277,13 +283,11 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded visited.pop(); RECT displayRect = getRect(characters, visited); visited.push(buttonId); - SerializableImage ret = SWF.frameToImage(buttonId, maxDepth, layers, new Color(0, 0, 0, 0), characters, 1, tags, tags, displayRect, visited, transformation); - - return ret; + SWF.frameToImage(buttonId, maxDepth, layers, new Color(0, 0, 0, 0), characters, 1, tags, tags, displayRect, visited, image, transformation); } - + @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { RECT r = getRect(characters, visited); return new Point(r.Xmin / SWF.unitDivisor, r.Ymin / SWF.unitDivisor); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 5de17f8d7..86329d07b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -52,6 +52,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.logging.Level; @@ -228,7 +229,7 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT private static final Cache rectCache = Cache.getInstance(true); @Override - public RECT getRect(HashMap allCharacters, Stack visited) { + public RECT getRect(Map allCharacters, Stack visited) { if (rectCache.contains(this)) { return (RECT) rectCache.get(this); } @@ -276,9 +277,14 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); + } + + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { if (visited.contains(buttonId)) { - return new SerializableImage(1, 1, SerializableImage.TYPE_4BYTE_ABGR); + return; } visited.push(buttonId); HashMap layers = new HashMap<>(); @@ -300,13 +306,12 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT visited.pop(); RECT displayRect = getRect(characters, visited); visited.push(buttonId); - SerializableImage ret = SWF.frameToImage(buttonId, maxDepth, layers, new Color(0, 0, 0, 0), characters, 1, tags, tags, displayRect, visited, transformation); + SWF.frameToImage(buttonId, maxDepth, layers, new Color(0, 0, 0, 0), characters, 1, tags, tags, displayRect, visited, image, transformation); visited.pop(); - return ret; } - + @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { RECT r = getRect(characters, visited); return new Point(r.Xmin / SWF.unitDivisor, r.Ymin / SWF.unitDivisor); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java index b5c8eebea..f38d425d6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java @@ -38,9 +38,9 @@ import java.io.IOException; import java.io.OutputStream; import java.io.StringReader; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.logging.Level; @@ -470,7 +470,7 @@ public class DefineEditTextTag extends TextTag { } @Override - public RECT getRect(HashMap allCharacters, Stack visited) { + public RECT getRect(Map allCharacters, Stack visited) { return bounds; } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java index 82ce828f0..4a6ef0516 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShape2Tag.java @@ -47,9 +47,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; @@ -87,7 +87,7 @@ public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, Mo } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { RECT rect = new RECT(); rect.Xmin = Math.min(startBounds.Xmin, endBounds.Xmin); rect.Ymin = Math.min(startBounds.Ymin, endBounds.Ymin); @@ -197,8 +197,7 @@ public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, Mo return 2; } - @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + private SHAPEWITHSTYLE getFrame(int frame) { List finalRecords = new ArrayList<>(); FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(frame); LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), frame); @@ -313,15 +312,26 @@ public class DefineMorphShape2Tag extends CharacterTag implements BoundedTag, Mo shape.fillStyles = fillStyles; shape.lineStyles = lineStyles; shape.shapeRecords = finalRecords; + return shape; + } + + @Override + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); + } + + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + SHAPEWITHSTYLE shape = getFrame(frame); // shapeNum: 4 // todo: Currently the generated image is not cached, because the cache // key contains the hashCode of the finalRecord object, and it is always // recreated - return BitmapExporter.export(swf, shape, null, false); + BitmapExporter.exportTo(swf, shape, null, image, transformation); } - + @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point( (startBounds.Xmin + (endBounds.Xmin - startBounds.Xmin) * frame / 65535) / SWF.unitDivisor, (startBounds.Ymin + (endBounds.Ymin - startBounds.Ymin) * frame / 65535) / SWF.unitDivisor); diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java index 14985474f..9b111d98f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineMorphShapeTag.java @@ -46,9 +46,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; @@ -136,7 +136,7 @@ public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, Mor } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { RECT rect = new RECT(); rect.Xmin = Math.min(startBounds.Xmin, endBounds.Xmin); rect.Ymin = Math.min(startBounds.Ymin, endBounds.Ymin); @@ -180,8 +180,7 @@ public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, Mor return 1; } - @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + private SHAPEWITHSTYLE getFrame(int frame) { List finalRecords = new ArrayList<>(); FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(frame); LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), frame); @@ -296,15 +295,26 @@ public class DefineMorphShapeTag extends CharacterTag implements BoundedTag, Mor shape.fillStyles = fillStyles; shape.lineStyles = lineStyles; shape.shapeRecords = finalRecords; + return shape; + } + + @Override + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); + } + + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + SHAPEWITHSTYLE shape = getFrame(frame); // shapeNum: 3 // todo: Currently the generated image is not cached, because the cache // key contains the hashCode of the finalRecord object, and it is always // recreated - return BitmapExporter.export(swf, shape, null, false); + BitmapExporter.exportTo(swf, shape, null, image, transformation); } - + @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point( (startBounds.Xmin + (endBounds.Xmin - startBounds.Xmin) * frame / 65535) / SWF.unitDivisor, (startBounds.Ymin + (endBounds.Ymin - startBounds.Ymin) * frame / 65535) / SWF.unitDivisor); diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java index 7018c9f2e..152616e58 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape2Tag.java @@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.exporters.BitmapExporter; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; @@ -32,12 +31,12 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; -public class DefineShape2Tag extends CharacterTag implements BoundedTag, ShapeTag { +public class DefineShape2Tag extends CharacterTag implements ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -46,7 +45,7 @@ public class DefineShape2Tag extends CharacterTag implements BoundedTag, ShapeTa public static final int ID = 22; @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(shapeBounds.Xmin / SWF.unitDivisor, shapeBounds.Ymin / SWF.unitDivisor); } @@ -73,17 +72,22 @@ public class DefineShape2Tag extends CharacterTag implements BoundedTag, ShapeTa } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { - return BitmapExporter.export(swf, getShapes()); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); } + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation); + } + @Override public int getCharacterId() { return shapeId; } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return shapeBounds; } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java index 26f780ed2..04f55f056 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape3Tag.java @@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.exporters.BitmapExporter; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; @@ -32,12 +31,12 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; -public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTag { +public class DefineShape3Tag extends CharacterTag implements ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -46,7 +45,7 @@ public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTa public static final int ID = 32; @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(shapeBounds.Xmin / SWF.unitDivisor, shapeBounds.Ymin / SWF.unitDivisor); } @@ -66,7 +65,7 @@ public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTa } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return shapeBounds; } @@ -78,10 +77,15 @@ public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTa } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { - return BitmapExporter.export(swf, getShapes()); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); } + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation); + } + @Override public int getCharacterId() { return shapeId; diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java index da894be5d..b04d9856c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShape4Tag.java @@ -22,7 +22,6 @@ import com.jpexs.decompiler.flash.exporters.BitmapExporter; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; @@ -33,12 +32,12 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; -public class DefineShape4Tag extends CharacterTag implements BoundedTag, ShapeTag { +public class DefineShape4Tag extends CharacterTag implements ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -54,7 +53,7 @@ public class DefineShape4Tag extends CharacterTag implements BoundedTag, ShapeTa public static final int ID = 83; @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(shapeBounds.Xmin / SWF.unitDivisor, shapeBounds.Ymin / SWF.unitDivisor); } @@ -81,17 +80,22 @@ public class DefineShape4Tag extends CharacterTag implements BoundedTag, ShapeTa } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { - return BitmapExporter.export(swf, getShapes()); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); } + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation); + } + @Override public int getCharacterId() { return shapeId; } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return shapeBounds; } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java index 7bb3e247e..a4996e969 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineShapeTag.java @@ -23,7 +23,6 @@ import com.jpexs.decompiler.flash.exporters.BitmapExporter; import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.exporters.SVGShapeExporter; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.types.BasicType; @@ -34,12 +33,12 @@ import com.jpexs.helpers.SerializableImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; -public class DefineShapeTag extends CharacterTag implements BoundedTag, ShapeTag { +public class DefineShapeTag extends CharacterTag implements ShapeTag { @SWFType(BasicType.UI16) public int shapeId; @@ -63,7 +62,7 @@ public class DefineShapeTag extends CharacterTag implements BoundedTag, ShapeTag } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return shapeBounds; } @@ -107,12 +106,17 @@ public class DefineShapeTag extends CharacterTag implements BoundedTag, ShapeTag } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { - return BitmapExporter.export(swf, getShapes()); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); } @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + BitmapExporter.exportTo(swf, getShapes(), null, image, transformation); + } + + @Override + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(shapeBounds.Xmin / SWF.unitDivisor, shapeBounds.Ymin / SWF.unitDivisor); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 283ec3a6e..4a98d7d51 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -44,6 +44,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; @@ -74,7 +75,7 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT return spriteId; } - private RECT getCharacterBounds(HashMap allCharacters, Set characters, Stack visited) { + private RECT getCharacterBounds(Map allCharacters, Set characters, Stack visited) { if (visited.contains(spriteId)) { return new RECT(); } @@ -109,7 +110,7 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT private static final Cache rectCache = Cache.getInstance(true); @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { if (rectCache.contains(this)) { return (RECT) rectCache.get(this); } @@ -277,9 +278,14 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); + } + + @Override + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { if (visited.contains(spriteId)) { - return new SerializableImage(1, 1, SerializableImage.TYPE_4BYTE_ABGR); + return; } /* rect.Xmax=displayRect.Xmin+rect.getWidth(); @@ -290,13 +296,12 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT SWF.fixRect(rect);*/ RECT rect = getRect(characters, visited); visited.push(spriteId); - SerializableImage ret = SWF.frameToImage(spriteId, frame, tags, subTags, rect, frameCount, visited, transformation); + SWF.frameToImage(spriteId, frame, tags, subTags, rect, frameCount, visited, image, transformation); visited.pop(); - return ret; } - + @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { //RECT displayRect = getRect(characters, visited); //use visited return new Point(0, 0); //displayRect.Xmin,displayRect.Ymin); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java index 70b55908b..4fbe5449e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java @@ -44,9 +44,9 @@ import java.io.IOException; import java.io.OutputStream; import java.io.StringReader; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.regex.Matcher; @@ -412,7 +412,7 @@ public class DefineText2Tag extends TextTag implements DrawableTag { } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return textBounds; } @@ -492,12 +492,17 @@ public class DefineText2Tag extends TextTag implements DrawableTag { } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { - return staticTextToImage(swf, characters, textRecords, textBounds, 2, transformation); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); } @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + staticTextToImage(swf, characters, textRecords, textBounds, 2, image, transformation); + } + + @Override + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(textBounds.Xmin / 20, textBounds.Ymin / 20); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java index f40944200..397c58416 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java @@ -45,9 +45,9 @@ import java.io.IOException; import java.io.OutputStream; import java.io.StringReader; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.regex.Matcher; @@ -492,7 +492,7 @@ public class DefineTextTag extends TextTag implements DrawableTag { } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return textBounds; } @@ -508,12 +508,17 @@ public class DefineTextTag extends TextTag implements DrawableTag { } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { - return staticTextToImage(swf, characters, textRecords, textBounds, 1, transformation); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { + throw new Error("this overload of toImage call is not supported on BoundedTag"); } @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + staticTextToImage(swf, characters, textRecords, textBounds, 1, image, transformation); + } + + @Override + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(textBounds.Xmin / SWF.unitDivisor, textBounds.Ymin / SWF.unitDivisor); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java index ef5500eeb..ab41f97be 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java @@ -29,7 +29,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.HashMap; +import java.util.Map; import java.util.Stack; /** @@ -122,7 +122,7 @@ public class DefineVideoStreamTag extends CharacterTag implements BoundedTag { } @Override - public RECT getRect(HashMap characters, Stack visited) { + public RECT getRect(Map characters, Stack visited) { return new RECT(0, (int) (SWF.unitDivisor * width), 0, (int) (SWF.unitDivisor * height)); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java index 2881ad31e..81597d6bc 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/BoundedTag.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.tags.base; import com.jpexs.decompiler.flash.types.RECT; -import java.util.HashMap; +import java.util.Map; import java.util.Stack; /** @@ -26,6 +26,6 @@ import java.util.Stack; */ public interface BoundedTag { - public RECT getRect(HashMap characters, Stack visited); + public RECT getRect(Map characters, Stack visited); //public List getPaths(List tags); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java index 065d4ab83..0006c184f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/DrawableTag.java @@ -20,8 +20,8 @@ import com.jpexs.decompiler.flash.exporters.Matrix; import com.jpexs.decompiler.flash.exporters.Point; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.helpers.SerializableImage; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Stack; /** @@ -30,9 +30,11 @@ import java.util.Stack; */ public interface DrawableTag { - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation); + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation); - public Point getImagePos(int frame, HashMap characters, Stack visited); + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation); + + public Point getImagePos(int frame, Map characters, Stack visited); public int getNumFrames(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index a09409d76..40ef2cd5d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -36,7 +36,6 @@ import java.awt.font.GlyphMetrics; import java.awt.font.GlyphVector; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; @@ -247,12 +246,17 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { return SHAPERECORD.shapeListToImage(swf, getGlyphShapeTable(), 500, 500, Color.black); } @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public void toImage(int frame, List tags, Map characters, Stack visited, SerializableImage image, Matrix transformation) { + + } + + @Override + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(0, 0); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java index 76190852f..c3a939b7d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/ShapeTag.java @@ -22,7 +22,7 @@ import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; * * @author JPEXS */ -public interface ShapeTag extends DrawableTag { +public interface ShapeTag extends BoundedTag, DrawableTag { public SHAPEWITHSTYLE getShapes(); diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java index 7ea1f8986..7d0a94f8e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/TextTag.java @@ -34,8 +34,6 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.LineMetrics; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -194,21 +192,13 @@ public abstract class TextTag extends CharacterTag implements BoundedTag { return att; } - public static SerializableImage staticTextToImage(SWF swf, HashMap characters, List textRecords, RECT textBounds, int numText, Matrix transformation) { - double unzoom = SWF.unitDivisor; - double fixX = -textBounds.Xmin / unzoom; - double fixY = -textBounds.Ymin / unzoom; - double width = textBounds.getWidth() / unzoom; - double height = textBounds.getHeight() / unzoom; - SerializableImage ret = new SerializableImage((int) width, (int) height, SerializableImage.TYPE_INT_ARGB); - ret.bounds = new Rectangle2D.Double(-fixX, -fixY, width, height); - + public static void staticTextToImage(SWF swf, Map characters, List textRecords, RECT textBounds, int numText, SerializableImage image, Matrix transformation) { Color textColor = new Color(0, 0, 0); FontTag font = null; int textHeight = 12; - int x = textBounds.Xmin; + int x = 0; int y = 0; - Graphics2D g = (Graphics2D) ret.getGraphics(); + Graphics2D g = (Graphics2D) image.getGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); @@ -233,19 +223,16 @@ public abstract class TextTag extends CharacterTag implements BoundedTag { y = rec.yOffset; } + Matrix mat = transformation.clone(); + double rat = textHeight / 1024.0 / font.getDivider(); + mat = mat.preConcatenate(Matrix.getScaleInstance(rat)); + mat.translate(x - textBounds.Xmin, y - textBounds.Ymin); for (GLYPHENTRY entry : rec.glyphEntries) { // shapeNum: 1 SHAPE shape = glyphs.get(entry.glyphIndex); - SerializableImage img = BitmapExporter.export(swf, shape, textColor, true); - AffineTransform tr = new AffineTransform(); - double rat = textHeight / 1024.0; - tr.translate(x / unzoom + img.bounds.getMinX() * rat + fixX, y / unzoom + img.bounds.getMinY() * rat + fixY); - tr.scale(1.0 / font.getDivider(), 1.0 / font.getDivider()); - tr.scale(rat, rat); - g.drawImage(img.getBufferedImage(), tr, null); - x += (int) entry.glyphAdvance; + BitmapExporter.exportTo(swf, shape, textColor, image, mat); + mat.translate(entry.glyphAdvance, 0); } } - return ret; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java b/trunk/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java index 807d1e011..52adc3f8d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/gfx/DefineCompactedFont.java @@ -49,8 +49,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; @@ -116,7 +116,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag { } @Override - public SerializableImage toImage(int frame, List tags, HashMap characters, Stack visited, Matrix transformation) { + public SerializableImage toImage(int frame, List tags, Map characters, Stack visited, Matrix transformation) { List shapes = new ArrayList<>(); for (int i = 0; i < shapeCache.size(); i++) { shapes.add(SHAPERECORD.resizeSHAPE(shapeCache.get(i), SWF.unitDivisor)); @@ -131,7 +131,7 @@ public final class DefineCompactedFont extends FontTag implements DrawableTag { } @Override - public Point getImagePos(int frame, HashMap characters, Stack visited) { + public Point getImagePos(int frame, Map characters, Stack visited) { return new Point(0, 0); } diff --git a/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionEvaluator.java b/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionEvaluator.java index 683c043b3..0e397911b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionEvaluator.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionEvaluator.java @@ -31,7 +31,7 @@ import java.util.Stack; */ public class ConditionEvaluator { - private Conditional cond; + private final Conditional cond; public ConditionEvaluator(Conditional cond) { this.cond = cond; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionLexer.java b/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionLexer.java index ff6a124a7..8c4427bc7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionLexer.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/annotations/parser/ConditionLexer.java @@ -254,7 +254,7 @@ public final class ConditionLexer { return yyline+1; } - private Stack pushedBack=new Stack(); + private final Stack pushedBack=new Stack<>(); public void pushback(ConditionToken symb) { pushedBack.push(symb); @@ -368,6 +368,7 @@ public final class ConditionLexer { /** * Closes the input stream. + * @throws java.io.IOException */ public final void yyclose() throws java.io.IOException { zzAtEOF = true; /* indicate end of file */ @@ -406,6 +407,7 @@ public final class ConditionLexer { /** * Returns the current lexical state. + * @return */ public final int yystate() { return zzLexicalState; @@ -424,6 +426,7 @@ public final class ConditionLexer { /** * Returns the text matched by the current regular expression. + * @return */ public final String yytext() { return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); @@ -448,6 +451,7 @@ public final class ConditionLexer { /** * Returns the length of the matched text region. + * @return */ public final int yylength() { return zzMarkedPos-zzStartRead; @@ -503,6 +507,7 @@ public final class ConditionLexer { * * @return the next token * @exception java.io.IOException if any I/O-Error occurs + * @throws com.jpexs.decompiler.flash.types.annotations.parser.ParseException */ public ConditionToken yylex() throws java.io.IOException, ParseException { int zzInput; diff --git a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java index 1d567a45d..792358c81 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java @@ -168,7 +168,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali } // shapeNum: 1 - SerializableImage img = BitmapExporter.export(swf, shapes.get(pos), color, false); + SerializableImage img = BitmapExporter.export(swf, shapes.get(pos), color); int w1 = img.getWidth(); int h1 = img.getHeight(); diff --git a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index b5913009a..b03bf36c3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -74,8 +74,6 @@ import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; diff --git a/trunk/src/com/jpexs/helpers/SerializableImage.java b/trunk/src/com/jpexs/helpers/SerializableImage.java index f8da37615..d1a795153 100644 --- a/trunk/src/com/jpexs/helpers/SerializableImage.java +++ b/trunk/src/com/jpexs/helpers/SerializableImage.java @@ -63,11 +63,15 @@ public class SerializableImage implements Serializable { image = new BufferedImage(i, i1, i2, icm); } + public void setBufferedImage(BufferedImage image, Rectangle2D bounds) { + this.image = image; + this.bounds = bounds; + } + public BufferedImage getBufferedImage() { /*try { ImageIO.write(image, "png", new File("c:\\10\\x\\imageid" + String.format("%03d", imageid++) + ".png")); } catch (IOException ex) { - Logger.getLogger(BitmapExporter.class.getName()).log(Level.SEVERE, null, ex); }*/ return image; }