diff --git a/CHANGELOG.md b/CHANGELOG.md index 424612add..07eacc043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. - [#2079] Replace DefineSprite with GIF, Bulk import sprites from GIFs, also from commandline - [#116] Show invalid utf-8 bytes in Strings as `{invalid_utf8:xxx}` - [#2097] Commandline command `-header` to modify SWF header values +- SVG Sprite export - blend modes ### Fixed - Close action on SWF inside DefineBinaryData diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java index c8b5b5f10..72e2acac9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/SVGExporter.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.FontExportMode; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.types.BlendMode; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGBA; import com.jpexs.helpers.Helper; @@ -238,7 +239,7 @@ public class SVGExporter { } - private void addScalingGridUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName) { + private void addScalingGridUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode) { Element image = _svg.createElement("g"); @@ -419,16 +420,17 @@ public class SVGExporter { if (characterName != null) { image.setAttribute("data-characterName", characterName); } + setBlendMode(image, blendMode); _svgGs.peek().appendChild(image); } public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect) { - return addUse(transform, boundRect, href, instanceName, scalingRect, null, null); + return addUse(transform, boundRect, href, instanceName, scalingRect, null, null, BlendMode.NORMAL); } - public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName) { + public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode) { if (scalingRect != null && (transform == null || (Double.compare(transform.rotateSkew0, 0.0) == 0 && Double.compare(transform.rotateSkew1, 0.0) == 0))) { - addScalingGridUse(transform, boundRect, href, instanceName, scalingRect, characterId, characterName); + addScalingGridUse(transform, boundRect, href, instanceName, scalingRect, characterId, characterName, blendMode); return null; //?? } Element image = _svg.createElement("use"); @@ -446,10 +448,47 @@ public class SVGExporter { if (characterName != null) { image.setAttribute("data-characterName", characterName); } + + setBlendMode(image, blendMode); + image.setAttribute("xlink:href", "#" + href); _svgGs.peek().appendChild(image); return image; } + + private void setBlendMode(Element element, int blendMode) { + switch(blendMode) { + case BlendMode.MULTIPLY: + element.setAttribute("style", "mix-blend-mode: multiply"); + break; + case BlendMode.SCREEN: + element.setAttribute("style", "mix-blend-mode: screen"); + break; + case BlendMode.OVERLAY: + element.setAttribute("style", "mix-blend-mode: overlay"); + break; + case BlendMode.DARKEN: + element.setAttribute("style", "mix-blend-mode: darken"); + break; + case BlendMode.LIGHTEN: + element.setAttribute("style", "mix-blend-mode: lighten"); + break; + case BlendMode.HARDLIGHT: + element.setAttribute("style", "mix-blend-mode: hard-light"); + break; + case BlendMode.DIFFERENCE: + element.setAttribute("style", "mix-blend-mode: difference"); + break; + case BlendMode.ADD: + case BlendMode.ALPHA: + case BlendMode.ERASE: + case BlendMode.INVERT: + case BlendMode.LAYER: + case BlendMode.SUBTRACT: + //unsupported + break; + } + } public void addStyle(String fontFace, byte[] data, FontExportMode mode) { if (!fontFaces.contains(fontFace)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index f203a1e45..2fed3b5f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -1284,7 +1284,7 @@ public class Timeline { exporter.endGroup(); } Matrix mat = Matrix.getTranslateInstance(rect.xMin, rect.yMin).preConcatenate(new Matrix(layer.matrix)); - exporter.addUse(mat, boundRect, assetName, layer.instanceName, scalingGrid == null ? null : scalingGrid.splitter, String.valueOf(drawable.getCharacterId()), String.join("___", drawable.getClassNames())); + exporter.addUse(mat, boundRect, assetName, layer.instanceName, scalingGrid == null ? null : scalingGrid.splitter, String.valueOf(drawable.getCharacterId()), String.join("___", drawable.getClassNames()), layer.blendMode); } } }