mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 13:41:10 +00:00
Fixed SVG Frames export - filter
This commit is contained in:
+33
-5
@@ -23,6 +23,7 @@ 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.decompiler.flash.types.filters.FILTER;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.awt.Color;
|
||||
import java.io.StringWriter;
|
||||
@@ -239,7 +240,7 @@ public class SVGExporter {
|
||||
|
||||
}
|
||||
|
||||
private void addScalingGridUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode) {
|
||||
private void addScalingGridUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode, List<FILTER> filters) {
|
||||
|
||||
Element image = _svg.createElement("g");
|
||||
|
||||
@@ -421,16 +422,41 @@ public class SVGExporter {
|
||||
image.setAttribute("data-characterName", characterName);
|
||||
}
|
||||
setBlendMode(image, blendMode);
|
||||
handleFilters(image, filters);
|
||||
_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, BlendMode.NORMAL);
|
||||
return addUse(transform, boundRect, href, instanceName, scalingRect, null, null, BlendMode.NORMAL, new ArrayList<>());
|
||||
}
|
||||
|
||||
private void handleFilters(Element image, List<FILTER> filters) {
|
||||
if (filters == null) {
|
||||
return;
|
||||
}
|
||||
Element filtersElement = _svg.createElement("filter");
|
||||
String filterId = getUniqueId("filter");
|
||||
String in = "SourceGraphic";
|
||||
boolean empty = true;
|
||||
for (FILTER filter: filters) {
|
||||
String result = filter.toSvg(_svg, filtersElement, this, in);
|
||||
if (result != null) {
|
||||
empty = false;
|
||||
in = result;
|
||||
}
|
||||
}
|
||||
if (empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
filtersElement.setAttribute("id", filterId);
|
||||
image.setAttribute("filter", "url(#" + filterId + ")");
|
||||
_svgGs.peek().appendChild(filtersElement);
|
||||
}
|
||||
|
||||
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode) {
|
||||
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode, List<FILTER> filters) {
|
||||
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, blendMode);
|
||||
addScalingGridUse(transform, boundRect, href, instanceName, scalingRect, characterId, characterName, blendMode, filters);
|
||||
return null; //??
|
||||
}
|
||||
Element image = _svg.createElement("use");
|
||||
@@ -451,7 +477,9 @@ public class SVGExporter {
|
||||
|
||||
setBlendMode(image, blendMode);
|
||||
|
||||
image.setAttribute("xlink:href", "#" + href);
|
||||
handleFilters(image, filters);
|
||||
|
||||
image.setAttribute("xlink:href", "#" + href);
|
||||
_svgGs.peek().appendChild(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -1277,7 +1277,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()), layer.blendMode);
|
||||
exporter.addUse(mat, boundRect, assetName, layer.instanceName, scalingGrid == null ? null : scalingGrid.splitter, String.valueOf(drawable.getCharacterId()), String.join("___", drawable.getClassNames()), layer.blendMode, layer.filters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,15 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The Bevel filter creates a smooth bevel on display list objects.
|
||||
@@ -121,4 +126,132 @@ public class BEVELFILTER extends FILTER {
|
||||
public double getDeltaY() {
|
||||
return blurY + Math.abs(distance * Math.sin(angle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
int type = Filtering.INNER;
|
||||
if (onTop && !innerShadow) {
|
||||
type = Filtering.FULL;
|
||||
} else if (!innerShadow) {
|
||||
type = Filtering.OUTER;
|
||||
}
|
||||
|
||||
String shadowInner = null;
|
||||
String hilightInner = null;
|
||||
if (type != Filtering.OUTER) {
|
||||
String hilight = dropShadowSvg(distance, angle, highlightColor, true, true, true, 0, 0, strength, passes, document, filtersElement, exporter, in);
|
||||
String shadow = dropShadowSvg(distance, angle + Math.PI, shadowColor, true, true, true, 0, 0, strength, passes, document, filtersElement, exporter, in);
|
||||
|
||||
Element feComposite1 = document.createElement("feComposite");
|
||||
feComposite1.setAttribute("in", hilight);
|
||||
feComposite1.setAttribute("in2", shadow);
|
||||
feComposite1.setAttribute("operator", "out");
|
||||
hilightInner = exporter.getUniqueId("filterResult");
|
||||
feComposite1.setAttribute("result", hilightInner);
|
||||
filtersElement.appendChild(feComposite1);
|
||||
|
||||
Element feComposite2 = document.createElement("feComposite");
|
||||
feComposite2.setAttribute("in", shadow);
|
||||
feComposite2.setAttribute("in2", hilight);
|
||||
feComposite2.setAttribute("operator", "out");
|
||||
shadowInner = exporter.getUniqueId("filterResult");
|
||||
feComposite2.setAttribute("result", shadowInner);
|
||||
filtersElement.appendChild(feComposite2);
|
||||
}
|
||||
|
||||
String shadowOuter = null;
|
||||
String hilightOuter = null;
|
||||
|
||||
if (type != Filtering.INNER) {
|
||||
String hilight = dropShadowSvg(distance, angle + Math.PI, highlightColor, false, true, true, 0, 0, strength, passes, document, filtersElement, exporter, in);
|
||||
String shadow = dropShadowSvg(distance, angle, shadowColor, false, true, true, 0, 0, strength, passes, document, filtersElement, exporter, in);
|
||||
|
||||
Element feComposite1 = document.createElement("feComposite");
|
||||
feComposite1.setAttribute("in", hilight);
|
||||
feComposite1.setAttribute("in2", shadow);
|
||||
feComposite1.setAttribute("operator", "out");
|
||||
shadowOuter = exporter.getUniqueId("filterResult");
|
||||
feComposite1.setAttribute("result", shadowOuter);
|
||||
filtersElement.appendChild(feComposite1);
|
||||
|
||||
Element feComposite2 = document.createElement("feComposite");
|
||||
feComposite2.setAttribute("in", shadow);
|
||||
feComposite2.setAttribute("in2", hilight);
|
||||
feComposite2.setAttribute("operator", "out");
|
||||
hilightOuter = exporter.getUniqueId("filterResult");
|
||||
feComposite2.setAttribute("result", hilightOuter);
|
||||
filtersElement.appendChild(feComposite2);
|
||||
}
|
||||
|
||||
String hilight = null;
|
||||
String shadow = null;
|
||||
|
||||
switch (type) {
|
||||
case Filtering.OUTER:
|
||||
hilight = hilightOuter;
|
||||
shadow = shadowOuter;
|
||||
break;
|
||||
case Filtering.INNER:
|
||||
hilight = hilightInner;
|
||||
shadow = shadowInner;
|
||||
break;
|
||||
case Filtering.FULL:
|
||||
Element feComposite1 = document.createElement("feComposite");
|
||||
feComposite1.setAttribute("in", hilightInner);
|
||||
feComposite1.setAttribute("in2", hilightOuter);
|
||||
feComposite1.setAttribute("operator", "over");
|
||||
hilight = exporter.getUniqueId("filterResult");
|
||||
feComposite1.setAttribute("result", hilight);
|
||||
filtersElement.appendChild(feComposite1);
|
||||
|
||||
Element feComposite2 = document.createElement("feComposite");
|
||||
feComposite2.setAttribute("in", shadowInner);
|
||||
feComposite2.setAttribute("in2", shadowOuter);
|
||||
feComposite2.setAttribute("operator", "over");
|
||||
shadow = exporter.getUniqueId("filterResult");
|
||||
feComposite2.setAttribute("result", shadow);
|
||||
filtersElement.appendChild(feComposite2);
|
||||
break;
|
||||
}
|
||||
|
||||
Element feComposite3 = document.createElement("feComposite");
|
||||
feComposite3.setAttribute("in", shadow);
|
||||
feComposite3.setAttribute("in2", hilight);
|
||||
feComposite3.setAttribute("operator", "over");
|
||||
String result = exporter.getUniqueId("filterResult");
|
||||
feComposite3.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite3);
|
||||
|
||||
result = blurSvg(blurX, blurY, passes, document, filtersElement, exporter, result);
|
||||
|
||||
if (type == Filtering.INNER) {
|
||||
Element feComposite4 = document.createElement("feComposite");
|
||||
feComposite4.setAttribute("in", result);
|
||||
feComposite4.setAttribute("in2", in);
|
||||
feComposite4.setAttribute("operator", "in");
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feComposite4.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite4);
|
||||
}
|
||||
if (type == Filtering.OUTER) {
|
||||
Element feComposite4 = document.createElement("feComposite");
|
||||
feComposite4.setAttribute("in", result);
|
||||
feComposite4.setAttribute("in2", in);
|
||||
feComposite4.setAttribute("operator", "out");
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feComposite4.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite4);
|
||||
}
|
||||
|
||||
if (!knockout) {
|
||||
Element feComposite4 = document.createElement("feComposite");
|
||||
feComposite4.setAttribute("in", result);
|
||||
feComposite4.setAttribute("in2", in);
|
||||
feComposite4.setAttribute("operator", "over");
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feComposite4.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite4);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Blur filter based on a sub-pixel precise median filter
|
||||
@@ -68,4 +74,9 @@ public class BLURFILTER extends FILTER {
|
||||
public double getDeltaY() {
|
||||
return blurY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
return blurSvg(blurX, blurY, passes, document, filtersElement, exporter, in);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Applies a color transformation on the pixels of a display list object
|
||||
@@ -60,4 +65,28 @@ public class COLORMATRIXFILTER extends FILTER {
|
||||
public double getDeltaY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
Element element = document.createElement("feColorMatrix");
|
||||
element.setAttribute("type", "matrix");
|
||||
List<String> parts = new ArrayList<>();
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
if (i % 5 == 4) {
|
||||
parts.add("" + (matrix[i] / 255f));
|
||||
} else {
|
||||
parts.add("" + matrix[i]);
|
||||
}
|
||||
}
|
||||
element.setAttribute("values", String.join(" ", parts));
|
||||
element.setAttribute("in", in);
|
||||
|
||||
String result = exporter.getUniqueId("filterResult");
|
||||
element.setAttribute("result", result);
|
||||
|
||||
filtersElement.appendChild(element);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
-2
@@ -16,12 +16,17 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Two-dimensional discrete convolution filter.
|
||||
@@ -93,11 +98,41 @@ public class CONVOLUTIONFILTER extends FILTER {
|
||||
|
||||
@Override
|
||||
public double getDeltaX() {
|
||||
return ((matrixX-1)>>1) + 1;
|
||||
return ((matrixX - 1) >> 1) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDeltaY() {
|
||||
return ((matrixY-1)>>1) + 1;
|
||||
return ((matrixY - 1) >> 1) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
Element element = document.createElement("feConvolveMatrix");
|
||||
element.setAttribute("order", "" + matrixX + " " + matrixY);
|
||||
List<String> parts = new ArrayList<>();
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
parts.add("" + matrix[i]);
|
||||
}
|
||||
element.setAttribute("kernelMatrix", String.join(" ", parts));
|
||||
if (clamp) {
|
||||
element.setAttribute("edgeMode", "duplicate");
|
||||
} else {
|
||||
element.setAttribute("edgeMode", "none");
|
||||
}
|
||||
|
||||
element.setAttribute("preserveAlpha", preserveAlpha ? "true" : "false");
|
||||
|
||||
element.setAttribute("divisor", "" + divisor);
|
||||
element.setAttribute("bias", "" + bias);
|
||||
|
||||
element.setAttribute("in", in);
|
||||
|
||||
String result = exporter.getUniqueId("filterResult");
|
||||
element.setAttribute("result", result);
|
||||
|
||||
filtersElement.appendChild(element);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Drop shadow filter based on the same median filter as the blur filter
|
||||
@@ -105,4 +109,9 @@ public class DROPSHADOWFILTER extends FILTER {
|
||||
public double getDeltaY() {
|
||||
return blurY + Math.abs(distance * Math.sin(angle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
return dropShadowSvg(distance, angle, dropShadowColor, innerShadow, knockout, compositeSource, blurX, blurY, strength, passes, document, filtersElement, exporter, in);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,17 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.ConcreteClasses;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Bitmap filter
|
||||
@@ -50,4 +56,195 @@ public abstract class FILTER implements Serializable {
|
||||
public abstract double getDeltaX();
|
||||
|
||||
public abstract double getDeltaY();
|
||||
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String dropShadowSvg(
|
||||
double distance,
|
||||
double angle,
|
||||
RGBA dropShadowColor,
|
||||
boolean innerShadow,
|
||||
boolean knockout,
|
||||
boolean compositeSource,
|
||||
double blurX,
|
||||
double blurY,
|
||||
double strength,
|
||||
int iterations,
|
||||
Document document,
|
||||
Element filtersElement,
|
||||
SVGExporter exporter,
|
||||
String in
|
||||
) {
|
||||
double dx = distance * Math.cos(angle);
|
||||
double dy = distance * Math.sin(angle);
|
||||
|
||||
if (innerShadow) {
|
||||
Element feFlood = document.createElement("feFlood");
|
||||
feFlood.setAttribute("flood-color", dropShadowColor.toHexRGB());
|
||||
feFlood.setAttribute("flood-opacity", "" + dropShadowColor.getAlphaFloat());
|
||||
filtersElement.appendChild(feFlood);
|
||||
String feFloodResult = exporter.getUniqueId("filterResult");
|
||||
feFlood.setAttribute("result", feFloodResult);
|
||||
|
||||
Element feOffset = document.createElement("feOffset");
|
||||
feOffset.setAttribute("dx", "" + dx);
|
||||
feOffset.setAttribute("dy", "" + dy);
|
||||
feOffset.setAttribute("in", in);
|
||||
String feOffsetResult = exporter.getUniqueId("filterResult");
|
||||
feOffset.setAttribute("result", feOffsetResult);
|
||||
filtersElement.appendChild(feOffset);
|
||||
|
||||
Element feComposite1 = document.createElement("feComposite");
|
||||
feComposite1.setAttribute("in", feFloodResult);
|
||||
feComposite1.setAttribute("in2", feOffsetResult);
|
||||
feComposite1.setAttribute("operator", "out");
|
||||
String feComposite1Result = exporter.getUniqueId("filterResult");
|
||||
feComposite1.setAttribute("result", feComposite1Result);
|
||||
filtersElement.appendChild(feComposite1);
|
||||
|
||||
String blurResult = blurSvg(blurX, blurY, iterations, document, filtersElement, exporter, feComposite1Result);
|
||||
|
||||
Element feComposite2 = document.createElement("feComposite");
|
||||
feComposite2.setAttribute("in", blurResult);
|
||||
feComposite2.setAttribute("in2", in);
|
||||
feComposite2.setAttribute("operator", "in");
|
||||
|
||||
String result = exporter.getUniqueId("filterResult");
|
||||
feComposite2.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite2);
|
||||
|
||||
if (Double.compare(strength, 1.0) != 0) {
|
||||
Element feColorMatrix2 = document.createElement("feColorMatrix");
|
||||
feColorMatrix2.setAttribute("type", "matrix");
|
||||
feColorMatrix2.setAttribute("in", result);
|
||||
feColorMatrix2.setAttribute("values",
|
||||
"1 0 0 0 0,"
|
||||
+ "0 1 0 0 0,"
|
||||
+ "0 0 1 0 0,"
|
||||
+ "0 0 0 " + strength + " 0"
|
||||
);
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feColorMatrix2.setAttribute("result", result);
|
||||
filtersElement.appendChild(feColorMatrix2);
|
||||
}
|
||||
|
||||
if (knockout || !compositeSource) {
|
||||
return result;
|
||||
}
|
||||
Element feComposite3 = document.createElement("feComposite");
|
||||
feComposite3.setAttribute("in", result);
|
||||
feComposite3.setAttribute("in2", in);
|
||||
feComposite3.setAttribute("operator", "over");
|
||||
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feComposite3.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite3);
|
||||
return result;
|
||||
} else {
|
||||
Element feOffset = document.createElement("feOffset");
|
||||
feOffset.setAttribute("dx", "" + dx);
|
||||
feOffset.setAttribute("dy", "" + dy);
|
||||
feOffset.setAttribute("in", in);
|
||||
String feOffsetResult = exporter.getUniqueId("filterResult");
|
||||
feOffset.setAttribute("result", feOffsetResult);
|
||||
filtersElement.appendChild(feOffset);
|
||||
|
||||
Element feColorMatrix = document.createElement("feColorMatrix");
|
||||
feColorMatrix.setAttribute("type", "matrix");
|
||||
feColorMatrix.setAttribute("in", feOffsetResult);
|
||||
feColorMatrix.setAttribute("values",
|
||||
"0 0 0 0 " + (dropShadowColor.red / 255f) + ","
|
||||
+ "0 0 0 0 " + (dropShadowColor.green / 255f) + ","
|
||||
+ "0 0 0 0 " + (dropShadowColor.blue / 255f) + ","
|
||||
+ "0 0 0 1 0"
|
||||
);
|
||||
String feColorMatrixResult = exporter.getUniqueId("filterResult");
|
||||
feColorMatrix.setAttribute("result", feColorMatrixResult);
|
||||
filtersElement.appendChild(feColorMatrix);
|
||||
|
||||
String result = blurSvg(blurX, blurY, iterations, document, filtersElement, exporter, feColorMatrixResult);
|
||||
|
||||
if (Double.compare(strength, 1.0) != 0) {
|
||||
Element feColorMatrix2 = document.createElement("feColorMatrix");
|
||||
feColorMatrix2.setAttribute("type", "matrix");
|
||||
feColorMatrix2.setAttribute("in", result);
|
||||
feColorMatrix2.setAttribute("values",
|
||||
"1 0 0 0 0,"
|
||||
+ "0 1 0 0 0,"
|
||||
+ "0 0 1 0 0,"
|
||||
+ "0 0 0 " + strength + " 0"
|
||||
);
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feColorMatrix2.setAttribute("result", result);
|
||||
filtersElement.appendChild(feColorMatrix2);
|
||||
}
|
||||
|
||||
if (!knockout && !compositeSource) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Element feComposite = document.createElement("feComposite");
|
||||
if (knockout) {
|
||||
feComposite.setAttribute("in", result);
|
||||
feComposite.setAttribute("in2", in);
|
||||
feComposite.setAttribute("operator", "out");
|
||||
} else {
|
||||
feComposite.setAttribute("in", in);
|
||||
feComposite.setAttribute("in2", result);
|
||||
feComposite.setAttribute("operator", "over");
|
||||
}
|
||||
|
||||
result = exporter.getUniqueId("filterResult");
|
||||
feComposite.setAttribute("result", result);
|
||||
filtersElement.appendChild(feComposite);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
protected String blurSvg(double blurX, double blurY, int iterations, Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
if (iterations == 0) {
|
||||
return in;
|
||||
}
|
||||
if (Double.compare(blurX, 0.0) == 0 && Double.compare(blurY, 0.0) == 0) {
|
||||
return in;
|
||||
}
|
||||
Element element = document.createElement("feConvolveMatrix");
|
||||
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
double divisor;
|
||||
if (Double.compare(blurX, 0.0) == 0) {
|
||||
int orderX = (int) Math.ceil(blurX);
|
||||
divisor = orderX;
|
||||
element.setAttribute("order", "" + orderX + " 1");
|
||||
|
||||
} else if (Double.compare(blurY, 0.0) == 0) {
|
||||
int orderY = (int) Math.ceil(blurY);
|
||||
divisor = orderY;
|
||||
element.setAttribute("order", "1 " + orderY);
|
||||
} else {
|
||||
int orderX = (int) Math.ceil(blurX);
|
||||
int orderY = (int) Math.ceil(blurY);
|
||||
divisor = orderX * orderY;
|
||||
element.setAttribute("order", "" + orderX + " " + orderY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < divisor; i++) {
|
||||
parts.add("1");
|
||||
}
|
||||
|
||||
element.setAttribute("divisor", "" + divisor);
|
||||
|
||||
element.setAttribute("kernelMatrix", String.join(" ", parts));
|
||||
element.setAttribute("in", in);
|
||||
|
||||
String result = exporter.getUniqueId("filterResult");
|
||||
element.setAttribute("result", result);
|
||||
|
||||
filtersElement.appendChild(element);
|
||||
|
||||
return blurSvg(blurX, blurY, iterations - 1, document, filtersElement, exporter, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ public class Filtering {
|
||||
|
||||
public static SerializableImage glow(SerializableImage src, int blurX, int blurY, float strength, Color color, boolean inner, boolean knockout, int iterations) {
|
||||
return new SerializableImage(dropShadow(src.getBufferedImage(), blurX, blurY, 45, 0, color, inner, iterations, strength, knockout, true));
|
||||
}
|
||||
}
|
||||
|
||||
private static Color over(Color a, Color b) {
|
||||
int resultA = a.getAlpha() + b.getAlpha() * (255 - a.getAlpha()) / 255;
|
||||
@@ -561,12 +561,12 @@ public class Filtering {
|
||||
public static SerializableImage convolution(
|
||||
SerializableImage src,
|
||||
float[] matrix,
|
||||
int w,
|
||||
int w,
|
||||
int h,
|
||||
float divisor,
|
||||
float bias,
|
||||
Color defaultColor,
|
||||
boolean clamp,
|
||||
boolean clamp,
|
||||
boolean preserveAlpha,
|
||||
int srcX,
|
||||
int srcY,
|
||||
@@ -576,8 +576,8 @@ public class Filtering {
|
||||
Kernel kernel = new Kernel(w, h, matrix);
|
||||
BufferedImage dst = new BufferedImage(src.getWidth() + 1, src.getHeight() + 1, src.getType());
|
||||
BufferedImageOp op = new ConvolveOp(
|
||||
kernel,
|
||||
new RenderingHints(null),
|
||||
kernel,
|
||||
new RenderingHints(null),
|
||||
divisor,
|
||||
bias,
|
||||
defaultColor,
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types.filters;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Glow filter
|
||||
@@ -93,4 +97,103 @@ public class GLOWFILTER extends FILTER {
|
||||
public double getDeltaY() {
|
||||
return blurY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSvg(Document document, Element filtersElement, SVGExporter exporter, String in) {
|
||||
/*Element element = document.createElement("feDropShadow");
|
||||
element.setAttribute("dx", "0");
|
||||
element.setAttribute("dy", "0");
|
||||
|
||||
double blur = ((blurX + blurY) / 2);
|
||||
element.setAttribute("stdDeviation", "" + blur);
|
||||
|
||||
element.setAttribute("flood-color", glowColor.toHexRGB());
|
||||
element.setAttribute("flood-opacity", "" + glowColor.getAlphaFloat());
|
||||
|
||||
element.setAttribute("in", in);
|
||||
|
||||
String result = exporter.getUniqueId("filterResult");
|
||||
element.setAttribute("result", result);
|
||||
|
||||
filtersElement.appendChild(element);
|
||||
|
||||
return result;*/
|
||||
|
||||
if (innerGlow) {
|
||||
Element feFlood = document.createElement("feFlood");
|
||||
feFlood.setAttribute("flood-color", glowColor.toHexRGB());
|
||||
feFlood.setAttribute("flood-opacity", "" + glowColor.getAlphaFloat());
|
||||
filtersElement.appendChild(feFlood);
|
||||
String feFloodResult = exporter.getUniqueId("filterResult");
|
||||
feFlood.setAttribute("result", feFloodResult);
|
||||
|
||||
Element feComposite1 = document.createElement("feComposite");
|
||||
feComposite1.setAttribute("in", feFloodResult);
|
||||
feComposite1.setAttribute("in2", in);
|
||||
feComposite1.setAttribute("operator", "out");
|
||||
String feComposite1Result = exporter.getUniqueId("filterResult");
|
||||
feComposite1.setAttribute("result", feComposite1Result);
|
||||
filtersElement.appendChild(feComposite1);
|
||||
|
||||
String blurResult = blurSvg(blurX, blurY, passes, document, filtersElement, exporter, feComposite1Result);
|
||||
|
||||
Element feComposite2 = document.createElement("feComposite");
|
||||
feComposite2.setAttribute("in", blurResult);
|
||||
feComposite2.setAttribute("in2", in);
|
||||
feComposite2.setAttribute("operator", "in");
|
||||
|
||||
String feComposite2Result = exporter.getUniqueId("filterResult");
|
||||
feComposite2.setAttribute("result", feComposite2Result);
|
||||
filtersElement.appendChild(feComposite2);
|
||||
|
||||
if (knockout || !compositeSource) {
|
||||
return feComposite2Result;
|
||||
}
|
||||
Element feComposite3 = document.createElement("feComposite");
|
||||
feComposite3.setAttribute("in", feComposite2Result);
|
||||
feComposite3.setAttribute("in2", in);
|
||||
feComposite3.setAttribute("operator", "over");
|
||||
|
||||
String feComposite3Result = exporter.getUniqueId("filterResult");
|
||||
feComposite3.setAttribute("result", feComposite3Result);
|
||||
filtersElement.appendChild(feComposite3);
|
||||
return feComposite3Result;
|
||||
} else {
|
||||
|
||||
Element feColorMatrix = document.createElement("feColorMatrix");
|
||||
feColorMatrix.setAttribute("type", "matrix");
|
||||
feColorMatrix.setAttribute("in", in);
|
||||
feColorMatrix.setAttribute("values",
|
||||
"0 0 0 0 " + (glowColor.red / 255f) + ","
|
||||
+ "0 0 0 0 " + (glowColor.green / 255f) + ","
|
||||
+ "0 0 0 0 " + (glowColor.blue / 255f) + ","
|
||||
+ "0 0 0 1 0"
|
||||
);
|
||||
String feColorMatrixResult = exporter.getUniqueId("filterResult");
|
||||
feColorMatrix.setAttribute("result", feColorMatrixResult);
|
||||
filtersElement.appendChild(feColorMatrix);
|
||||
|
||||
String blurResult = blurSvg(blurX, blurY, passes, document, filtersElement, exporter, feColorMatrixResult);
|
||||
|
||||
if (!knockout && !compositeSource) {
|
||||
return blurResult;
|
||||
}
|
||||
|
||||
Element feComposite = document.createElement("feComposite");
|
||||
if (knockout) {
|
||||
feComposite.setAttribute("in", blurResult);
|
||||
feComposite.setAttribute("in2", in);
|
||||
feComposite.setAttribute("operator", "out");
|
||||
} else {
|
||||
feComposite.setAttribute("in", in);
|
||||
feComposite.setAttribute("in2", blurResult);
|
||||
feComposite.setAttribute("operator", "over");
|
||||
}
|
||||
|
||||
String feCompositeResult = exporter.getUniqueId("filterResult");
|
||||
feComposite.setAttribute("result", feCompositeResult);
|
||||
filtersElement.appendChild(feComposite);
|
||||
return feCompositeResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user