From 1aef4c35b6abe60f33ea9f2f5ea4b404e508ca29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Mon, 21 Apr 2014 23:02:53 +0200 Subject: [PATCH 1/4] Shapes to HTML5 Canvas export --- .../flash/exporters/ShapeExporter.java | 11 + .../exporters/modes/ShapeExportMode.java | 3 +- .../exporters/shape/CanvasShapeExporter.java | 322 ++++++++++++++++++ .../flash/gui/locales/ExportDialog.properties | 1 + 4 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java index 9c3f4e041..9cdce23a1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporterContext; import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings; +import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; @@ -68,6 +69,9 @@ public class ShapeExporter { if (settings.mode == ShapeExportMode.PNG) { ext = "png"; } + if (settings.mode == ShapeExportMode.CANVAS) { + ext = "html"; + } final File file = new File(outdir + File.separator + characterID + "." + ext); final int fcharacterID = characterID; @@ -92,6 +96,13 @@ public class ShapeExporter { st.toImage(0, 0, 0, null, 0, img, m, new CXFORMWITHALPHA()); ImageIO.write(img.getBufferedImage(), "PNG", new FileOutputStream(file)); break; + case CANVAS: + try (FileOutputStream fos = new FileOutputStream(file)) { + CanvasShapeExporter cse = new CanvasShapeExporter(((Tag)st).getSwf(),st.getShapes(), new CXFORMWITHALPHA()); + cse.export(); + fos.write(Utf8Helper.getBytes(cse.getHtml())); + } + break; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/modes/ShapeExportMode.java b/trunk/src/com/jpexs/decompiler/flash/exporters/modes/ShapeExportMode.java index 50002fb90..b34a24510 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/modes/ShapeExportMode.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/modes/ShapeExportMode.java @@ -23,5 +23,6 @@ package com.jpexs.decompiler.flash.exporters.modes; public enum ShapeExportMode { SVG, - PNG + PNG, + CANVAS } diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java new file mode 100644 index 000000000..72f5194ba --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2010-2014 JPEXS + * + * 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.exporters.shape; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; +import com.jpexs.decompiler.flash.exporters.commonshape.Point; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.ImageTag; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.FILLSTYLE; +import com.jpexs.decompiler.flash.types.GRADRECORD; +import com.jpexs.decompiler.flash.types.LINESTYLE2; +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.helpers.Helper; +import com.jpexs.helpers.SerializableImage; +import java.awt.geom.AffineTransform; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; +import javax.imageio.ImageIO; +import javax.xml.bind.DatatypeConverter; + +/** + * + * @author JPEXS, Claus Wahlers + */ +public class CanvasShapeExporter extends ShapeExporterBase { + + + protected String pathData = ""; + protected String shapeData = ""; + protected String html = ""; + protected String strokeData = ""; + protected String fillData = ""; + protected double deltaX = 0; + protected double deltaY = 0; + protected Matrix fillMatrix = null; + protected String lastRadColor = null; + protected SWF swf; + + public String getHtml() { + return html; + } + + + + + public CanvasShapeExporter(SWF swf, SHAPE shape, ColorTransform colorTransform) { + super(shape, colorTransform); + deltaX = -shape.getBounds().Xmin; + deltaY = -shape.getBounds().Ymin; + this.swf = swf; + } + + @Override + public void beginShape() { + shapeData = ""; + } + + @Override + public void endShape() { + RECT r = shape.getBounds(); + int width = (int)roundPixels20(r.getWidth() / SWF.unitDivisor); + int height = (int)roundPixels20(r.getHeight() / SWF.unitDivisor); + html = "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "Your browser does not support the HTML5 canvas tag.\r\n" + + "\r\n" + + "\r\n" + + "\r\n"+ + "\r\n"+ + ""; + } + + @Override + public void beginFills() { + } + + @Override + public void endFills() { + } + + @Override + public void beginLines() { + } + + @Override + public void endLines() { + finalizePath(); + } + + @Override + public void beginFill(RGB color) { + finalizePath(); + fillData += "ctx.fillStyle=\""+color(color)+"\";\r\n"; + } + + @Override + public void beginGradientFill(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) { + finalizePath(); + + + //TODO: repeating (spread mode) + + if(type == FILLSTYLE.LINEAR_GRADIENT){ + Point start = matrix.transform(new Point(-16384, 0)); + Point end = matrix.transform(new Point(16384, 0)); + fillData+="var grd=ctx.createLinearGradient("+Double.toString(start.x/SWF.unitDivisor)+","+Double.toString(start.y/SWF.unitDivisor)+","+Double.toString(end.x/SWF.unitDivisor)+","+Double.toString(end.y/SWF.unitDivisor)+");\r\n"; + }else{ + matrix.translateX /= SWF.unitDivisor; + matrix.translateY /= SWF.unitDivisor; + matrix.scaleX /= SWF.unitDivisor; + matrix.scaleY /= SWF.unitDivisor; + matrix.rotateSkew0 /= SWF.unitDivisor; + matrix.rotateSkew1 /= SWF.unitDivisor; + fillMatrix = matrix; + fillData+="var grd=ctx.createRadialGradient(0,0,0,0,0,16384);\r\n"; + } + for(GRADRECORD r:gradientRecords){ + fillData+="grd.addColorStop("+Double.toString(r.ratio / 255.0)+",\""+color(r.color)+"\");\r\n"; + lastRadColor = color(r.color); + } + fillData+="ctx.fillStyle = grd;\r\n"; + } + + private String color(RGB rgb){ + if(rgb instanceof RGBA){ + RGBA rgba = (RGBA)rgb; + return "rgba("+rgba.red+","+rgba.green+","+rgba.blue+","+rgba.getAlphaFloat()+")"; + }else{ + return rgb.toHexRGB(); + } + + } + + @Override + public void beginBitmapFill(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) { + finalizePath(); + ImageTag image = null; + for (Tag t : swf.tags) { + if (t instanceof ImageTag) { + ImageTag i = (ImageTag) t; + if (i.getCharacterId() == bitmapId) { + image = i; + break; + } + } + } + if (image != null) { + SerializableImage img = image.getImage(); + if (img != null) { + colorTransform.apply(img); + String format = image.getImageFormat(); + InputStream imageStream = image.getImageData(); + byte[] imageData; + if (imageStream != null) { + imageData = Helper.readStream(image.getImageData()); + } else { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + ImageIO.write(img.getBufferedImage(), format.toUpperCase(Locale.ENGLISH), baos); + } catch (IOException ex) { + } + imageData = baos.toByteArray(); + } + String base64ImgData = DatatypeConverter.printBase64Binary(imageData); + if (matrix != null) { + matrix.translateX /= SWF.unitDivisor; + matrix.translateY /= SWF.unitDivisor; + matrix.scaleX /= SWF.unitDivisor; + matrix.scaleY /= SWF.unitDivisor; + matrix.rotateSkew0 /= SWF.unitDivisor; + matrix.rotateSkew1 /= SWF.unitDivisor; + fillMatrix = matrix; + + } + + fillData += "var img = document.createElement(\"img\"); img.src=\"data:image/" + format + ";base64," + base64ImgData+"\";\r\n"; + fillData += "var pat=ctx.createPattern(img,\"repeat\");\r\n"; + fillData += "ctx.fillStyle = pat;\r\n"; + } + } + } + + @Override + public void endFill() { + finalizePath(); + } + + @Override + public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) { + finalizePath(); + thickness /= SWF.unitDivisor; + + strokeData += "ctx.strokeStyle=\""+color(color)+"\";\r\n"; + strokeData += "ctx.lineWidth="+Double.toString(thickness == 0 ? 1 : thickness)+";\r\n"; + switch (startCaps) { + case LINESTYLE2.NO_CAP: + strokeData += "ctx.lineCap=\"butt\";\r\n"; + break; + case LINESTYLE2.SQUARE_CAP: + strokeData += "ctx.lineCap=\"square\";\r\n"; + break; + default: + strokeData += "ctx.lineCap=\"round\";\r\n"; + break; + } + switch (joints) { + case LINESTYLE2.BEVEL_JOIN: + strokeData += "ctx.lineJoin=\"bevel\";\r\n"; + break; + case LINESTYLE2.ROUND_JOIN: + strokeData += "ctx.lineJoin=\"round\";\r\n"; + break; + default: + strokeData += "ctx.lineJoin=\"miter\";\r\n"; + strokeData += "ctx.miterLimit=" + Integer.toString(miterLimit)+";\r\n"; + break; + } + } + + @Override + public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) { + //TODO + } + + @Override + public void moveTo(double x, double y) { + x += deltaX; + y += deltaY; + pathData += "ctx.moveTo(" + + roundPixels20(x / SWF.unitDivisor) + "," + + roundPixels20(y / SWF.unitDivisor) + ");\r\n"; + } + + @Override + public void lineTo(double x, double y) { + x += deltaX; + y += deltaY; + pathData += "ctx.lineTo(" + roundPixels20(x / SWF.unitDivisor) + "," + + roundPixels20(y / SWF.unitDivisor) + ");\r\n"; + } + + @Override + public void curveTo(double controlX, double controlY, double anchorX, double anchorY) { + controlX += deltaX; + anchorX += deltaX; + controlY += deltaY; + anchorY += deltaY; + pathData += "ctx.quadraticCurveTo("+roundPixels20(controlX / SWF.unitDivisor) + "," + + roundPixels20(controlY / SWF.unitDivisor) + "," + + roundPixels20(anchorX / SWF.unitDivisor) + "," + + roundPixels20(anchorY / SWF.unitDivisor) + ");\r\n"; + } + + protected void finalizePath() { + if(!"".equals(pathData)){ + pathData = "ctx.setTransform(1,0,0,1,0,0);\r\nctx.beginPath();\r\n"+pathData+"ctx.closePath();\r\n"+strokeData; + if(!"".equals(strokeData)){ + pathData += "ctx.stroke();\r\n"; + } + if(fillMatrix!=null){ + if(lastRadColor!=null){ + pathData+="ctx.fillStyle=\""+lastRadColor+"\";\r\n ctx.fill(\"evenodd\");\r\n"; + } + pathData += "ctx.save();\r\n"; + pathData += "ctx.clip();\r\n"; + pathData += "ctx.setTransform("+fillMatrix.scaleX+","+fillMatrix.rotateSkew0+","+fillMatrix.rotateSkew1+","+fillMatrix.scaleY+","+fillMatrix.translateX+","+fillMatrix.translateY+");\r\n"; + pathData += fillData; + pathData += "ctx.fillRect(-16384,-16384,2*16384,2*16384);\r\n"; + pathData += "ctx.restore();\r\n"; + shapeData += pathData; + }else{ + if(!"".equals(fillData)){ + pathData += "ctx.fill(\"evenodd\");\r\n"; + } + shapeData += fillData+pathData; + } + } + + pathData = ""; + fillData = ""; + strokeData = ""; + fillMatrix = null; + lastRadColor = null; + } + + protected double roundPixels20(double pixels) { + return Math.round(pixels * 100) / 100.0; + } + + protected double roundPixels400(double pixels) { + return Math.round(pixels * 10000) / 10000.0; + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties index 781539ec9..f5183e4ee 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog.properties @@ -15,6 +15,7 @@ shapes = Shapes shapes.svg = SVG shapes.png = PNG +shapes.canvas = HTML5 Canvas texts = Texts texts.plain = Plain text From e084f46ba80a4c540beddeeb068f91670eb5178a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Tue, 22 Apr 2014 06:34:03 +0200 Subject: [PATCH 2/4] Shapes Canvas export - gradient position fix --- .../flash/exporters/shape/CanvasShapeExporter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java index 72f5194ba..92e41e993 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java @@ -132,6 +132,10 @@ public class CanvasShapeExporter extends ShapeExporterBase { if(type == FILLSTYLE.LINEAR_GRADIENT){ Point start = matrix.transform(new Point(-16384, 0)); Point end = matrix.transform(new Point(16384, 0)); + start.x += deltaX; + start.y += deltaY; + end.x += deltaX; + end.y += deltaY; fillData+="var grd=ctx.createLinearGradient("+Double.toString(start.x/SWF.unitDivisor)+","+Double.toString(start.y/SWF.unitDivisor)+","+Double.toString(end.x/SWF.unitDivisor)+","+Double.toString(end.y/SWF.unitDivisor)+");\r\n"; }else{ matrix.translateX /= SWF.unitDivisor; @@ -141,6 +145,10 @@ public class CanvasShapeExporter extends ShapeExporterBase { matrix.rotateSkew0 /= SWF.unitDivisor; matrix.rotateSkew1 /= SWF.unitDivisor; fillMatrix = matrix; + + matrix.translateX += deltaX/SWF.unitDivisor; + matrix.translateY += deltaY/SWF.unitDivisor; + fillData+="var grd=ctx.createRadialGradient(0,0,0,0,0,16384);\r\n"; } for(GRADRECORD r:gradientRecords){ From d99b556d6f72855611222af57156b3f0878e359f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Tue, 22 Apr 2014 07:05:15 +0200 Subject: [PATCH 3/4] Shapes Canvas export - gradient repeats (spread mode) --- .../exporters/shape/CanvasShapeExporter.java | 160 ++++++++++-------- 1 file changed, 87 insertions(+), 73 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java index 92e41e993..20258a7ad 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.FILLSTYLE; +import com.jpexs.decompiler.flash.types.GRADIENT; import com.jpexs.decompiler.flash.types.GRADRECORD; import com.jpexs.decompiler.flash.types.LINESTYLE2; import com.jpexs.decompiler.flash.types.RECT; @@ -41,14 +42,13 @@ import javax.xml.bind.DatatypeConverter; /** * - * @author JPEXS, Claus Wahlers + * @author JPEXS */ public class CanvasShapeExporter extends ShapeExporterBase { - protected String pathData = ""; protected String shapeData = ""; - protected String html = ""; + protected String html = ""; protected String strokeData = ""; protected String fillData = ""; protected double deltaX = 0; @@ -56,14 +56,12 @@ public class CanvasShapeExporter extends ShapeExporterBase { protected Matrix fillMatrix = null; protected String lastRadColor = null; protected SWF swf; + protected int repeatCnt = 0; public String getHtml() { return html; } - - - public CanvasShapeExporter(SWF swf, SHAPE shape, ColorTransform colorTransform) { super(shape, colorTransform); deltaX = -shape.getBounds().Xmin; @@ -79,24 +77,24 @@ public class CanvasShapeExporter extends ShapeExporterBase { @Override public void endShape() { RECT r = shape.getBounds(); - int width = (int)roundPixels20(r.getWidth() / SWF.unitDivisor); - int height = (int)roundPixels20(r.getHeight() / SWF.unitDivisor); - html = "\r\n" + - "\r\n" + - "\r\n" + - "\r\n" + - "\r\n" + - "Your browser does not support the HTML5 canvas tag.\r\n" + - "\r\n" + - "\r\n" + - "\r\n"+ - "\r\n"+ - ""; + int width = (int) roundPixels20(r.getWidth() / SWF.unitDivisor); + int height = (int) roundPixels20(r.getHeight() / SWF.unitDivisor); + html = "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "Your browser does not support the HTML5 canvas tag.\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + ""; } @Override @@ -119,25 +117,27 @@ public class CanvasShapeExporter extends ShapeExporterBase { @Override public void beginFill(RGB color) { finalizePath(); - fillData += "ctx.fillStyle=\""+color(color)+"\";\r\n"; + fillData += "ctx.fillStyle=\"" + color(color) + "\";\r\n"; } @Override public void beginGradientFill(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) { finalizePath(); - - - //TODO: repeating (spread mode) - - if(type == FILLSTYLE.LINEAR_GRADIENT){ - Point start = matrix.transform(new Point(-16384, 0)); - Point end = matrix.transform(new Point(16384, 0)); + + //TODO: How many repeats is ideal? + final int REPEAT_CNT = 5; + + repeatCnt = spreadMethod == GRADIENT.SPREAD_PAD_MODE ? 0 : REPEAT_CNT; + + if (type == FILLSTYLE.LINEAR_GRADIENT) { + Point start = matrix.transform(new Point(-16384 - 32768 * repeatCnt, 0)); + Point end = matrix.transform(new Point(16384 + 32768 * repeatCnt, 0)); start.x += deltaX; start.y += deltaY; end.x += deltaX; end.y += deltaY; - fillData+="var grd=ctx.createLinearGradient("+Double.toString(start.x/SWF.unitDivisor)+","+Double.toString(start.y/SWF.unitDivisor)+","+Double.toString(end.x/SWF.unitDivisor)+","+Double.toString(end.y/SWF.unitDivisor)+");\r\n"; - }else{ + fillData += "var grd=ctx.createLinearGradient(" + Double.toString(start.x / SWF.unitDivisor) + "," + Double.toString(start.y / SWF.unitDivisor) + "," + Double.toString(end.x / SWF.unitDivisor) + "," + Double.toString(end.y / SWF.unitDivisor) + ");\r\n"; + } else { matrix.translateX /= SWF.unitDivisor; matrix.translateY /= SWF.unitDivisor; matrix.scaleX /= SWF.unitDivisor; @@ -145,29 +145,42 @@ public class CanvasShapeExporter extends ShapeExporterBase { matrix.rotateSkew0 /= SWF.unitDivisor; matrix.rotateSkew1 /= SWF.unitDivisor; fillMatrix = matrix; - - matrix.translateX += deltaX/SWF.unitDivisor; - matrix.translateY += deltaY/SWF.unitDivisor; - - fillData+="var grd=ctx.createRadialGradient(0,0,0,0,0,16384);\r\n"; + + matrix.translateX += deltaX / SWF.unitDivisor; + matrix.translateY += deltaY / SWF.unitDivisor; + + fillData += "var grd=ctx.createRadialGradient(0,0,0,0,0," + (16384 + 32768 * repeatCnt) + ");\r\n"; } - for(GRADRECORD r:gradientRecords){ - fillData+="grd.addColorStop("+Double.toString(r.ratio / 255.0)+",\""+color(r.color)+"\");\r\n"; - lastRadColor = color(r.color); + int repeatTotal = repeatCnt * 2 + 1; + double oneHeight = 1.0 / repeatTotal; + double pos = 0; + boolean revert = false; + if (type != FILLSTYLE.LINEAR_GRADIENT && spreadMethod == GRADIENT.SPREAD_REFLECT_MODE) { + revert = true; } - fillData+="ctx.fillStyle = grd;\r\n"; + for (int i = 0; i < repeatTotal; i++) { + if (spreadMethod == GRADIENT.SPREAD_REFLECT_MODE) { + revert = !revert; + } + for (GRADRECORD r : gradientRecords) { + fillData += "grd.addColorStop(" + Double.toString(pos + (oneHeight * (revert ? 255 - r.ratio : r.ratio) / 255.0)) + ",\"" + color(r.color) + "\");\r\n"; + lastRadColor = color(r.color); + } + pos += oneHeight; + } + fillData += "ctx.fillStyle = grd;\r\n"; } - private String color(RGB rgb){ - if(rgb instanceof RGBA){ - RGBA rgba = (RGBA)rgb; - return "rgba("+rgba.red+","+rgba.green+","+rgba.blue+","+rgba.getAlphaFloat()+")"; - }else{ + private String color(RGB rgb) { + if (rgb instanceof RGBA) { + RGBA rgba = (RGBA) rgb; + return "rgba(" + rgba.red + "," + rgba.green + "," + rgba.blue + "," + rgba.getAlphaFloat() + ")"; + } else { return rgb.toHexRGB(); } - + } - + @Override public void beginBitmapFill(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) { finalizePath(); @@ -207,10 +220,10 @@ public class CanvasShapeExporter extends ShapeExporterBase { matrix.rotateSkew0 /= SWF.unitDivisor; matrix.rotateSkew1 /= SWF.unitDivisor; fillMatrix = matrix; - + } - - fillData += "var img = document.createElement(\"img\"); img.src=\"data:image/" + format + ";base64," + base64ImgData+"\";\r\n"; + + fillData += "var img = document.createElement(\"img\"); img.src=\"data:image/" + format + ";base64," + base64ImgData + "\";\r\n"; fillData += "var pat=ctx.createPattern(img,\"repeat\");\r\n"; fillData += "ctx.fillStyle = pat;\r\n"; } @@ -226,9 +239,9 @@ public class CanvasShapeExporter extends ShapeExporterBase { public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) { finalizePath(); thickness /= SWF.unitDivisor; - - strokeData += "ctx.strokeStyle=\""+color(color)+"\";\r\n"; - strokeData += "ctx.lineWidth="+Double.toString(thickness == 0 ? 1 : thickness)+";\r\n"; + + strokeData += "ctx.strokeStyle=\"" + color(color) + "\";\r\n"; + strokeData += "ctx.lineWidth=" + Double.toString(thickness == 0 ? 1 : thickness) + ";\r\n"; switch (startCaps) { case LINESTYLE2.NO_CAP: strokeData += "ctx.lineCap=\"butt\";\r\n"; @@ -249,7 +262,7 @@ public class CanvasShapeExporter extends ShapeExporterBase { break; default: strokeData += "ctx.lineJoin=\"miter\";\r\n"; - strokeData += "ctx.miterLimit=" + Integer.toString(miterLimit)+";\r\n"; + strokeData += "ctx.miterLimit=" + Integer.toString(miterLimit) + ";\r\n"; break; } } @@ -282,37 +295,38 @@ public class CanvasShapeExporter extends ShapeExporterBase { anchorX += deltaX; controlY += deltaY; anchorY += deltaY; - pathData += "ctx.quadraticCurveTo("+roundPixels20(controlX / SWF.unitDivisor) + "," + pathData += "ctx.quadraticCurveTo(" + roundPixels20(controlX / SWF.unitDivisor) + "," + roundPixels20(controlY / SWF.unitDivisor) + "," + roundPixels20(anchorX / SWF.unitDivisor) + "," + roundPixels20(anchorY / SWF.unitDivisor) + ");\r\n"; } protected void finalizePath() { - if(!"".equals(pathData)){ - pathData = "ctx.setTransform(1,0,0,1,0,0);\r\nctx.beginPath();\r\n"+pathData+"ctx.closePath();\r\n"+strokeData; - if(!"".equals(strokeData)){ + if (!"".equals(pathData)) { + pathData = "ctx.setTransform(1,0,0,1,0,0);\r\nctx.beginPath();\r\n" + pathData + "ctx.closePath();\r\n" + strokeData; + if (!"".equals(strokeData)) { pathData += "ctx.stroke();\r\n"; - } - if(fillMatrix!=null){ - if(lastRadColor!=null){ - pathData+="ctx.fillStyle=\""+lastRadColor+"\";\r\n ctx.fill(\"evenodd\");\r\n"; + } + if (fillMatrix != null) { + if (lastRadColor != null) { + pathData += "ctx.fillStyle=\"" + lastRadColor + "\";\r\n ctx.fill(\"evenodd\");\r\n"; } pathData += "ctx.save();\r\n"; pathData += "ctx.clip();\r\n"; - pathData += "ctx.setTransform("+fillMatrix.scaleX+","+fillMatrix.rotateSkew0+","+fillMatrix.rotateSkew1+","+fillMatrix.scaleY+","+fillMatrix.translateX+","+fillMatrix.translateY+");\r\n"; - pathData += fillData; - pathData += "ctx.fillRect(-16384,-16384,2*16384,2*16384);\r\n"; + pathData += "ctx.setTransform(" + fillMatrix.scaleX + "," + fillMatrix.rotateSkew0 + "," + fillMatrix.rotateSkew1 + "," + fillMatrix.scaleY + "," + fillMatrix.translateX + "," + fillMatrix.translateY + ");\r\n"; + pathData += fillData; + pathData += "ctx.fillRect(" + (-16384 - 32768 * repeatCnt) + "," + (-16384 - 32768 * repeatCnt) + "," + (2 * 16384 + 32768 * 2 * repeatCnt) + "," + (2 * 16384 + 32768 * 2 * repeatCnt) + ");\r\n"; pathData += "ctx.restore();\r\n"; shapeData += pathData; - }else{ - if(!"".equals(fillData)){ + } else { + if (!"".equals(fillData)) { pathData += "ctx.fill(\"evenodd\");\r\n"; } - shapeData += fillData+pathData; - } + shapeData += fillData + pathData; + } } - + + repeatCnt = 0; pathData = ""; fillData = ""; strokeData = ""; From 89679bbbbd120409dba8e54dea3ca29ca9080776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Tue, 22 Apr 2014 08:25:15 +0200 Subject: [PATCH 4/4] Shapes Canvas export - relative transforms --- .../flash/exporters/shape/CanvasShapeExporter.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java index 20258a7ad..57a362e9f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/shape/CanvasShapeExporter.java @@ -303,17 +303,15 @@ public class CanvasShapeExporter extends ShapeExporterBase { protected void finalizePath() { if (!"".equals(pathData)) { - pathData = "ctx.setTransform(1,0,0,1,0,0);\r\nctx.beginPath();\r\n" + pathData + "ctx.closePath();\r\n" + strokeData; - if (!"".equals(strokeData)) { - pathData += "ctx.stroke();\r\n"; - } + pathData = "ctx.beginPath();\r\n" + pathData + "ctx.closePath();\r\n" + strokeData; + if (fillMatrix != null) { if (lastRadColor != null) { pathData += "ctx.fillStyle=\"" + lastRadColor + "\";\r\n ctx.fill(\"evenodd\");\r\n"; } pathData += "ctx.save();\r\n"; pathData += "ctx.clip();\r\n"; - pathData += "ctx.setTransform(" + fillMatrix.scaleX + "," + fillMatrix.rotateSkew0 + "," + fillMatrix.rotateSkew1 + "," + fillMatrix.scaleY + "," + fillMatrix.translateX + "," + fillMatrix.translateY + ");\r\n"; + pathData += "ctx.transform(" + fillMatrix.scaleX + "," + fillMatrix.rotateSkew0 + "," + fillMatrix.rotateSkew1 + "," + fillMatrix.scaleY + "," + fillMatrix.translateX + "," + fillMatrix.translateY + ");\r\n"; pathData += fillData; pathData += "ctx.fillRect(" + (-16384 - 32768 * repeatCnt) + "," + (-16384 - 32768 * repeatCnt) + "," + (2 * 16384 + 32768 * 2 * repeatCnt) + "," + (2 * 16384 + 32768 * 2 * repeatCnt) + ");\r\n"; pathData += "ctx.restore();\r\n"; @@ -324,6 +322,9 @@ public class CanvasShapeExporter extends ShapeExporterBase { } shapeData += fillData + pathData; } + if (!"".equals(strokeData)) { + shapeData += "ctx.stroke();\r\n"; + } } repeatCnt = 0;