#1156 SVG Export - 9 slice scaling (DefineScalingGrid)

This commit is contained in:
Jindra Petřík
2021-03-06 22:56:05 +01:00
parent b85d22d9c5
commit 004e2ecdfd
4 changed files with 195 additions and 9 deletions

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.commonshape;
import com.jpexs.decompiler.flash.SWF;
@@ -149,7 +150,7 @@ public class SVGExporter {
g.getParentNode().removeChild(g);
return false;
}
}
return true;
}
@@ -215,7 +216,189 @@ public class SVGExporter {
attr.setValue("background: " + new RGBA(backGroundColor).toHexARGB());
}
private void addScalingGridUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect) {
ExportRectangle exRect = new ExportRectangle(boundRect);
ExportRectangle newRect = exRect;
if (transform == null) {
transform = new Matrix();
}
Matrix transform2;
newRect = transform.transform(exRect);
transform = transform.clone();
transform = Matrix.getTranslateInstance(newRect.xMin, newRect.yMin);
double scaleWidth = newRect.getWidth() - scalingRect.Xmin - (boundRect.Xmax - scalingRect.Xmax);
double originalWidth = boundRect.getWidth() - scalingRect.Xmin - (boundRect.Xmax - scalingRect.Xmax);
double scaleX = scaleWidth / originalWidth;
double scaleHeight = newRect.getHeight() - scalingRect.Ymin - (boundRect.Ymax - scalingRect.Ymax);
double originalHeight = boundRect.getHeight() - scalingRect.Ymin - (boundRect.Ymax - scalingRect.Ymax);
double scaleY = scaleHeight / originalHeight;
Element leftTopCorner = _svg.createElement("use");
leftTopCorner.setAttribute("transform", transform.getSvgTransformationString(SWF.unitDivisor, 1));
leftTopCorner.setAttribute("clip-path", "path('"
+ "M 0,0 "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + ",0 "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L 0," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " Z"
+ "')");
leftTopCorner.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(leftTopCorner);
Element bottomLeftCorner = _svg.createElement("use");
transform2 = transform.clone();
transform2.translateY += newRect.getHeight() - boundRect.getHeight();
bottomLeftCorner.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
bottomLeftCorner.setAttribute("clip-path", "path('"
+ "M 0," + Math.rint((boundRect.getHeight() - (boundRect.Ymax - scalingRect.Ymax)) / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint((boundRect.getHeight() - (boundRect.Ymax - scalingRect.Ymax)) / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(boundRect.getHeight() / (double) SWF.unitDivisor) + " "
+ "L 0," + Math.rint(boundRect.getHeight() / (double) SWF.unitDivisor) + " Z"
+ "')");
bottomLeftCorner.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(bottomLeftCorner);
Element topRightCorner = _svg.createElement("use");
transform2 = transform.clone();
transform2.translateX += newRect.getWidth() - boundRect.getWidth();
topRightCorner.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
topRightCorner.setAttribute("clip-path", "path('"
+ "M " + Math.rint((boundRect.getWidth() - (exRect.xMax - scalingRect.Xmax)) / (double) SWF.unitDivisor) + ",0 "
+ "L " + Math.rint(boundRect.getWidth() / (double) SWF.unitDivisor) + ",0 "
+ "L " + Math.rint(boundRect.getWidth() / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint((boundRect.getWidth() - (exRect.xMax - scalingRect.Xmax)) / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " Z"
+ "')");
topRightCorner.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(topRightCorner);
Element bottomRightCorner = _svg.createElement("use");
transform2 = transform.clone();
transform2.translateX += newRect.getWidth() - boundRect.getWidth();
transform2.translateY += newRect.getHeight() - boundRect.getHeight();
bottomRightCorner.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
bottomRightCorner.setAttribute("clip-path", "path('"
+ "M " + Math.rint((boundRect.getWidth() - (exRect.xMax - scalingRect.Xmax)) / (double) SWF.unitDivisor) + "," + Math.rint((boundRect.getHeight() - (boundRect.Ymax - scalingRect.Ymax)) / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(boundRect.getWidth() / (double) SWF.unitDivisor) + "," + Math.rint((boundRect.getHeight() - (boundRect.Ymax - scalingRect.Ymax)) / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(boundRect.getWidth() / (double) SWF.unitDivisor) + "," + Math.rint(boundRect.getHeight() / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint((boundRect.getWidth() - (exRect.xMax - scalingRect.Xmax)) / (double) SWF.unitDivisor) + "," + Math.rint(boundRect.getHeight() / (double) SWF.unitDivisor) + " Z"
+ "')");
bottomRightCorner.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(bottomRightCorner);
Element top = _svg.createElement("use");
transform2 = transform.clone();
transform2.translate(scalingRect.Xmin, 0);
transform2.scale(scaleX, 1);
transform2.translate(-scalingRect.Xmin, 0);
top.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
top.setAttribute("clip-path", "path('"
+ "M " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + ",0 "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + ",0 "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " Z"
+ "')");
top.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(top);
Element left = _svg.createElement("use");
transform2 = transform.clone();
transform2.translate(0, scalingRect.Ymin);
transform2.scale(1, scaleY);
transform2.translate(0, -scalingRect.Ymin);
left.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
left.setAttribute("clip-path", "path('"
+ "M 0," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " "
+ "L 0," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " Z"
+ "')");
left.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(left);
Element bottom = _svg.createElement("use");
transform2 = transform.clone();
transform2.translate(scalingRect.Xmin, 0);
transform2.scale(scaleX, 1);
transform2.translate(-scalingRect.Xmin, 0);
transform2.translateY += newRect.getHeight() - boundRect.getHeight();
bottom.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
bottom.setAttribute("clip-path", "path('"
+ "M " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(boundRect.Ymax / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(boundRect.Ymax / (double) SWF.unitDivisor) + " Z"
+ "')");
bottom.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(bottom);
Element right = _svg.createElement("use");
transform2 = transform.clone();
transform2.translate(0, scalingRect.Ymin);
transform2.scale(1, scaleY);
transform2.translate(0, -scalingRect.Ymin);
transform2.translateX += newRect.getWidth() - boundRect.getWidth();
right.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
right.setAttribute("clip-path", "path('"
+ "M " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(boundRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(boundRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " Z"
+ "')");
right.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(right);
Element center = _svg.createElement("use");
transform2 = transform.clone();
transform2.translate(scalingRect.Xmin, scalingRect.Ymin);
transform2.scale(scaleX, scaleY);
transform2.translate(-scalingRect.Xmin, -scalingRect.Ymin);
center.setAttribute("transform", transform2.getSvgTransformationString(SWF.unitDivisor, 1));
center.setAttribute("clip-path", "path('"
+ "M " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymin / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmax / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " "
+ "L " + Math.rint(scalingRect.Xmin / (double) SWF.unitDivisor) + "," + Math.rint(scalingRect.Ymax / (double) SWF.unitDivisor) + " Z"
+ "')");
center.setAttribute("xlink:href", "#" + href);
_svgGs.peek().appendChild(center);
//TODO: how to include instance name
}
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect) {
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);
return null; //??
}
Element image = _svg.createElement("use");
if (transform != null) {
image.setAttribute("transform", transform.getSvgTransformationString(SWF.unitDivisor, 1));

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.SWF;
@@ -759,7 +760,7 @@ public abstract class TextTag extends DrawableTag {
}
if (!"".equals(charId)) {
if (!"".equals(charId)) {
Element charImage = exporter.addUse(mat, bounds, charId, null, null);
RGBA colorA = new RGBA(textColor);
charImage.setAttribute("fill", colorA.toHexRGB());
if (colorA.alpha != 255) {

View File

@@ -1055,19 +1055,21 @@ public class Timeline {
}
ExportRectangle rect = new ExportRectangle(boundRect);
DefineScalingGridTag scalingGrid = character.getScalingGridTag();
// TODO: if (layer.filters != null)
// TODO: if (layer.blendMode > 1)
// TODO: if (layer.blendMode > 1)
if (layer.clipDepth > -1) {
String clipName = exporter.getUniqueId("clipPath");
exporter.createClipPath(new Matrix(), clipName);
SvgClip clip = new SvgClip(clipName, layer.clipDepth);
clips.add(clip);
Matrix mat = Matrix.getTranslateInstance(rect.xMin, rect.yMin).preConcatenate(new Matrix(layer.matrix));
exporter.addUse(mat, boundRect, assetName, layer.instanceName);
exporter.addUse(mat, boundRect, assetName, layer.instanceName, scalingGrid == null ? null : scalingGrid.splitter);
exporter.endGroup();
} else {
Matrix mat = Matrix.getTranslateInstance(rect.xMin, rect.yMin).preConcatenate(new Matrix(layer.matrix));
exporter.addUse(mat, boundRect, assetName, layer.instanceName);
exporter.addUse(mat, boundRect, assetName, layer.instanceName, scalingGrid == null ? null : scalingGrid.splitter);
}
}
}