mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 13:20:45 +00:00
Fixed: #2464 SVG export - minimum stroke width of 1 px
This commit is contained in:
@@ -312,7 +312,7 @@ public class FrameExporter {
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "frame", fbackgroundColor);
|
||||
|
||||
tim.toSVG(frame, 0, null, 0, exporter, null, 0);
|
||||
tim.toSVG(frame, 0, null, 0, exporter, null, 0, new Matrix(), new Matrix());
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
ret.add(f);
|
||||
|
||||
@@ -113,46 +113,52 @@ public class MorphShapeExporter {
|
||||
MorphShapeTag mst = (MorphShapeTag) t;
|
||||
|
||||
new RetryTask(() -> {
|
||||
ShapeTag st = mst.getStartShapeTag();
|
||||
Matrix m;
|
||||
RECT rect = st.getRect();
|
||||
m = Matrix.getScaleInstance(settings.zoom);
|
||||
m.translate(-rect.Xmin, -rect.Ymin);
|
||||
|
||||
switch (settings.mode) {
|
||||
case SVG_START_END:
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fileStart))) {
|
||||
ExportRectangle rect = new ExportRectangle(mst.getStartBounds());
|
||||
rect.xMax *= settings.zoom;
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "shape");
|
||||
mst.getStartShapeTag().toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
ExportRectangle rect2 = new ExportRectangle(mst.getStartBounds());
|
||||
rect2.xMax *= settings.zoom;
|
||||
rect2.yMax *= settings.zoom;
|
||||
rect2.xMin *= settings.zoom;
|
||||
rect2.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect2, settings.zoom, "shape");
|
||||
mst.getStartShapeTag().toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, m, m);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fileEnd))) {
|
||||
ExportRectangle rect = new ExportRectangle(mst.getStartBounds());
|
||||
rect.xMax *= settings.zoom;
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "shape");
|
||||
mst.getEndShapeTag().toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
ExportRectangle rect2 = new ExportRectangle(mst.getStartBounds());
|
||||
rect2.xMax *= settings.zoom;
|
||||
rect2.yMax *= settings.zoom;
|
||||
rect2.xMin *= settings.zoom;
|
||||
rect2.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect2, settings.zoom, "shape");
|
||||
mst.getEndShapeTag().toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, m, m);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
break;
|
||||
case SVG:
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
ExportRectangle rect = new ExportRectangle(mst.getRect());
|
||||
rect.xMax *= settings.zoom;
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "morphshape");
|
||||
mst.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
ExportRectangle rect2 = new ExportRectangle(mst.getRect());
|
||||
rect2.xMax *= settings.zoom;
|
||||
rect2.yMax *= settings.zoom;
|
||||
rect2.xMin *= settings.zoom;
|
||||
rect2.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect2, settings.zoom, "morphshape");
|
||||
mst.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, m, m);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
break;
|
||||
case PNG_START_END:
|
||||
case BMP_START_END:
|
||||
double unzoom = settings.zoom;
|
||||
ShapeTag st = mst.getStartShapeTag();
|
||||
RECT rect = st.getRect();
|
||||
st = mst.getStartShapeTag();
|
||||
rect = st.getRect();
|
||||
int newWidth = (int) (rect.getWidth() * settings.zoom / SWF.unitDivisor) + 1;
|
||||
int newHeight = (int) (rect.getHeight() * settings.zoom / SWF.unitDivisor) + 1;
|
||||
SerializableImage img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
@@ -165,7 +171,7 @@ public class MorphShapeExporter {
|
||||
g.fillRect(0, 0, img.getWidth(), img.getHeight());
|
||||
}
|
||||
}
|
||||
Matrix m = Matrix.getScaleInstance(settings.zoom);
|
||||
m = Matrix.getScaleInstance(settings.zoom);
|
||||
m.translate(-rect.Xmin, -rect.Ymin);
|
||||
st.toImage(0, 0, 0, new RenderContext(), img, img, false, m, m, m, m, new CXFORMWITHALPHA(), unzoom, false, new ExportRectangle(rect), new ExportRectangle(rect), true, Timeline.DRAW_MODE_ALL, 0, true);
|
||||
if (settings.mode == MorphShapeExportMode.PNG_START_END) {
|
||||
|
||||
@@ -102,22 +102,24 @@ public class ShapeExporter {
|
||||
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName() + settings.getFileExtension()));
|
||||
new RetryTask(() -> {
|
||||
Matrix m = Matrix.getScaleInstance(settings.zoom);
|
||||
RECT rect = st.getRect();
|
||||
m.translate(-rect.Xmin, -rect.Ymin);
|
||||
switch (settings.mode) {
|
||||
case SVG:
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
ExportRectangle rect = new ExportRectangle(st.getRect());
|
||||
rect.xMax *= settings.zoom;
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "shape");
|
||||
st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
ExportRectangle rect2 = new ExportRectangle(st.getRect());
|
||||
rect2.xMax *= settings.zoom;
|
||||
rect2.yMax *= settings.zoom;
|
||||
rect2.xMin *= settings.zoom;
|
||||
rect2.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect2, settings.zoom, "shape");
|
||||
st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, m, m);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
break;
|
||||
case PNG:
|
||||
case BMP:
|
||||
RECT rect = st.getRect();
|
||||
int newWidth = (int) (rect.getWidth() * settings.zoom / SWF.unitDivisor) + 1;
|
||||
int newHeight = (int) (rect.getHeight() * settings.zoom / SWF.unitDivisor) + 1;
|
||||
SerializableImage img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
@@ -129,9 +131,7 @@ public class ShapeExporter {
|
||||
g.setColor(backColor.toColor());
|
||||
g.fillRect(0, 0, img.getWidth(), img.getHeight());
|
||||
}
|
||||
}
|
||||
Matrix m = Matrix.getScaleInstance(settings.zoom);
|
||||
m.translate(-rect.Xmin, -rect.Ymin);
|
||||
}
|
||||
st.toImage(0, 0, 0, new RenderContext(), img, img, false, m, m, m, m, new CXFORMWITHALPHA(), unzoom, false, new ExportRectangle(rect), new ExportRectangle(rect), true, Timeline.DRAW_MODE_ALL, 0, true);
|
||||
if (settings.mode == ShapeExportMode.PNG) {
|
||||
ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, file);
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.ReadOnlyTagList;
|
||||
import com.jpexs.decompiler.flash.RetryTask;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.TextExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings;
|
||||
@@ -86,10 +87,11 @@ public class TextExporter {
|
||||
final TextTag textTag = (TextTag) t;
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(textTag.getCharacterExportFileName() + ".svg"));
|
||||
new RetryTask(() -> {
|
||||
Matrix m = Matrix.getScaleInstance(settings.zoom);
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
ExportRectangle rect = new ExportRectangle(textTag.getRect());
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "text");
|
||||
textTag.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
textTag.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0, m, m);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
}, handler).run();
|
||||
|
||||
+37
-5
@@ -34,6 +34,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -52,6 +53,7 @@ import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* SVG exporter.
|
||||
@@ -82,6 +84,8 @@ public class SVGExporter {
|
||||
|
||||
public Map<ExportKey, String> exportedTags = new HashMap<>();
|
||||
|
||||
public Set<ExportKey> exportedSmallStrokesTags = new HashSet<>();
|
||||
|
||||
public Map<Tag, Map<Integer, String>> exportedChars = new HashMap<>();
|
||||
|
||||
private final Map<String, Integer> lastIds = new HashMap<>();
|
||||
@@ -90,6 +94,8 @@ public class SVGExporter {
|
||||
|
||||
public boolean useTextTag = Configuration.textExportExportFontFace.get();
|
||||
|
||||
private double zoom;
|
||||
|
||||
public static class ExportKey {
|
||||
|
||||
private final Tag tag;
|
||||
@@ -136,7 +142,7 @@ public class SVGExporter {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.colorTransform, other.colorTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SVGExporter(ExportRectangle bounds, double zoom, String objectType) {
|
||||
@@ -144,6 +150,7 @@ public class SVGExporter {
|
||||
}
|
||||
|
||||
public SVGExporter(ExportRectangle bounds, double zoom, String objectType, Color backgroundColor) {
|
||||
this.zoom = zoom;
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
@@ -185,6 +192,10 @@ public class SVGExporter {
|
||||
gradients = new ArrayList<>();
|
||||
}
|
||||
|
||||
public double getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
|
||||
private Element getDefs() {
|
||||
if (_svgDefs == null) {
|
||||
_svgDefs = _svg.createElement("defs");
|
||||
@@ -202,10 +213,28 @@ public class SVGExporter {
|
||||
}
|
||||
return _svgStyle;
|
||||
}
|
||||
|
||||
public final boolean hasSmallStrokes() {
|
||||
NodeList nodes = _svgGs.peek().getElementsByTagName("path");
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element e = (Element) nodes.item(i);
|
||||
if ("true".equals(e.getAttribute("ffdec:has-small-stroke"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
nodes = _svgGs.peek().getElementsByTagName("use");
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Element e = (Element) nodes.item(i);
|
||||
if ("true".equals(e.getAttribute("ffdec:has-small-stroke"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final void createDefGroup(ExportRectangle bounds, String id) {
|
||||
createDefGroup(bounds, id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public final void createDefGroup(ExportRectangle bounds, String id, double zoom) {
|
||||
Element g = _svg.createElement("g");
|
||||
@@ -521,11 +550,11 @@ public class SVGExporter {
|
||||
_svgGs.peek().appendChild(filtersElement);
|
||||
}
|
||||
|
||||
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect) {
|
||||
return addUse(transform, boundRect, href, instanceName, scalingRect, null, null, BlendMode.NORMAL, new ArrayList<>());
|
||||
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, boolean hasSmallStrokes) {
|
||||
return addUse(transform, boundRect, href, instanceName, scalingRect, null, null, BlendMode.NORMAL, new ArrayList<>(), hasSmallStrokes);
|
||||
}
|
||||
|
||||
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode, List<FILTER> filters) {
|
||||
public Element addUse(Matrix transform, RECT boundRect, String href, String instanceName, RECT scalingRect, String characterId, String characterName, int blendMode, List<FILTER> filters, boolean hasSmallStrokes) {
|
||||
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, filters);
|
||||
return null; //??
|
||||
@@ -545,6 +574,9 @@ public class SVGExporter {
|
||||
if (characterName != null && !characterName.isEmpty()) {
|
||||
image.setAttribute("ffdec:characterName", characterName);
|
||||
}
|
||||
if (hasSmallStrokes) {
|
||||
image.setAttribute("ffdec:has-small-stroke", "true");
|
||||
}
|
||||
|
||||
setBlendMode(image, blendMode);
|
||||
|
||||
|
||||
@@ -207,13 +207,7 @@ public class BitmapExporter extends ShapeExporterBase {
|
||||
com.jpexs.decompiler.flash.exporters.commonshape.Point p11 = strokeTransformation.transform(1, 1);
|
||||
thicknessScale = p00.distanceTo(p11) / Math.sqrt(2);
|
||||
thicknessScaleX = Math.abs(p11.x - p00.x);
|
||||
thicknessScaleY = Math.abs(p11.y - p00.y);
|
||||
|
||||
/*Matrix transPre = transformation.preConcatenate(Matrix.getScaleInstance(1 / SWF.unitDivisor, 1 / SWF.unitDivisor));
|
||||
p00 = transPre.transform(0, 0);
|
||||
p11 = transPre.transform(1, 1);
|
||||
realZoom = p00.distanceTo(p11) / Math.sqrt(2);
|
||||
System.out.println("realZoom=" + realZoom);*/
|
||||
thicknessScaleY = Math.abs(p11.y - p00.y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+30
-4
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.exporters.shape;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
@@ -74,6 +75,16 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter {
|
||||
* Exporter
|
||||
*/
|
||||
private final SVGExporter exporter;
|
||||
|
||||
/**
|
||||
* Display zoom
|
||||
*/
|
||||
private final double displayZoom;
|
||||
|
||||
/**
|
||||
* Thickness scale
|
||||
*/
|
||||
private final double thicknessScale;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -85,14 +96,21 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter {
|
||||
* @param exporter Exporter
|
||||
* @param defaultColor Default color
|
||||
* @param colorTransform Color transform
|
||||
* @param zoom Zoom
|
||||
* @param zoom Zoom - shape zoom
|
||||
* @param displayZoom Display zoom - overal SVG zoom
|
||||
* @param strokeTransformation Stroke transformation
|
||||
*/
|
||||
public SVGShapeExporter(int windingRule, int shapeNum, SWF swf, SHAPE shape, int id, SVGExporter exporter, Color defaultColor, ColorTransform colorTransform, double zoom) {
|
||||
public SVGShapeExporter(int windingRule, int shapeNum, SWF swf, SHAPE shape, int id, SVGExporter exporter, Color defaultColor, ColorTransform colorTransform, double zoom, double displayZoom, Matrix strokeTransformation) {
|
||||
super(windingRule, shapeNum, swf, shape, colorTransform, zoom);
|
||||
this.swf = swf;
|
||||
this.id = id;
|
||||
this.defaultColor = defaultColor;
|
||||
this.exporter = exporter;
|
||||
this.displayZoom = displayZoom;
|
||||
|
||||
com.jpexs.decompiler.flash.exporters.commonshape.Point p00 = strokeTransformation.transform(0, 0);
|
||||
com.jpexs.decompiler.flash.exporters.commonshape.Point p11 = strokeTransformation.transform(1, 1);
|
||||
thicknessScale = p00.distanceTo(p11) / Math.sqrt(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,11 +235,19 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter {
|
||||
}
|
||||
path.setAttribute("fill", "#ff0000");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, float miterLimit, boolean noClose) {
|
||||
finalizePath();
|
||||
thickness *= zoom / SWF.unitDivisor;
|
||||
|
||||
//always display minimum stroke of 1 pixel, no matter how zoomed it is
|
||||
if (thickness * displayZoom * thicknessScale < 1 * SWF.unitDivisor) {
|
||||
path.setAttribute("ffdec:has-small-stroke", "true");
|
||||
path.setAttribute("ffdec:original-stroke-width", Double.toString(thickness * displayZoom / SWF.unitDivisor));
|
||||
thickness = 1 * SWF.unitDivisor / displayZoom / thicknessScale;
|
||||
}
|
||||
|
||||
thickness *= zoom / SWF.unitDivisor;
|
||||
path.setAttribute("fill", "none");
|
||||
if (color != null) {
|
||||
path.setAttribute("stroke", color.toHexRGB());
|
||||
|
||||
@@ -1040,7 +1040,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) {
|
||||
render(TextRenderMode.SVG, null, exporter, null, new Matrix(), colorTransform, 1);
|
||||
}
|
||||
|
||||
@@ -1062,7 +1062,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
drawBorderHtmlCanvas(swf, htmlCanvasBuilder, borderColor, fillColor, getRect(), getTextMatrix(), colorTransform, zoom);
|
||||
break;
|
||||
case SVG:
|
||||
drawBorderSVG(swf, svgExporter, borderColor, fillColor, getRect(), getTextMatrix(), colorTransform, zoom);
|
||||
drawBorderSVG(swf, svgExporter, borderColor, fillColor, getRect(), getTextMatrix(), transformation, colorTransform, zoom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1076,7 +1076,7 @@ public class DefineEditTextTag extends TextTag {
|
||||
staticTextToHtmlCanvas(zoom, swf, allTextRecords, 2, htmlCanvasBuilder, getBounds(), getTextMatrix(), colorTransform);
|
||||
break;
|
||||
case SVG:
|
||||
staticTextToSVG(swf, allTextRecords, 2, svgExporter, getBounds(), getTextMatrix(), colorTransform, zoom);
|
||||
staticTextToSVG(swf, allTextRecords, 2, svgExporter, getBounds(), getTextMatrix(), colorTransform, zoom, transformation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,8 +419,8 @@ public class DefineSpriteTag extends DrawableTag implements Timelined {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1, transformation, strokeTransformation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -420,7 +420,7 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -131,8 +131,8 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException {
|
||||
getTimeline().toSVG(0, 0, null, 0, exporter, colorTransform, level + 1, transformation, strokeTransformation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -113,9 +113,11 @@ public abstract class DrawableTag extends CharacterTag implements BoundedTag {
|
||||
* @param ratio Ratio
|
||||
* @param colorTransform Color transform
|
||||
* @param level Level
|
||||
* @param transformation Transformation
|
||||
* @param strokeTransformation Stroke transformation
|
||||
* @throws IOException On I/O error
|
||||
*/
|
||||
public abstract void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException;
|
||||
public abstract void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException;
|
||||
|
||||
/**
|
||||
* Converts the drawable to HTML canvas.
|
||||
|
||||
@@ -686,7 +686,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -346,8 +346,8 @@ public abstract class ImageTag extends DrawableTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, getShape(1), getCharacterId(), exporter, null, colorTransform, 1);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, getShape(1), getCharacterId(), exporter, null, colorTransform, 1, exporter.getZoom(), strokeTransformation);
|
||||
shapeExporter.export();
|
||||
}
|
||||
|
||||
|
||||
@@ -420,16 +420,16 @@ public abstract class MorphShapeTag extends DrawableTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) {
|
||||
|
||||
if (ratio == -2) {
|
||||
SHAPEWITHSTYLE beginShapes = getShapeAtRatio(0);
|
||||
SHAPEWITHSTYLE endShapes = getShapeAtRatio(65535);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(getShapeNum(), swf, beginShapes, endShapes, getCharacterId(), exporter, null, colorTransform, 1);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(getShapeNum(), swf, beginShapes, endShapes, getCharacterId(), exporter, null, colorTransform, exporter.getZoom());
|
||||
shapeExporter.export();
|
||||
} else {
|
||||
SHAPEWITHSTYLE shapes = getShapeAtRatio(ratio);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD /*??? FIXME*/, getShapeNum() == 2 ? 4 : 1, swf, shapes, getCharacterId(), exporter, null, colorTransform, 1);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD /*??? FIXME*/, getShapeNum() == 2 ? 4 : 1, swf, shapes, getCharacterId(), exporter, null, colorTransform, 1, exporter.getZoom(), strokeTransformation);
|
||||
shapeExporter.export();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,8 +277,8 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(getWindingRule(), getShapeNum(), swf, getShapes(), getCharacterId(), exporter, null, colorTransform, 1);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(getWindingRule(), getShapeNum(), swf, getShapes(), getCharacterId(), exporter, null, colorTransform, 1, exporter.getZoom(), strokeTransformation);
|
||||
shapeExporter.export();
|
||||
}
|
||||
|
||||
|
||||
@@ -1032,9 +1032,8 @@ public abstract class StaticTextTag extends TextTag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) {
|
||||
|
||||
staticTextToSVG(swf, textRecords, getTextNum(), exporter, getRect(), textMatrix, colorTransform, 1);
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) {
|
||||
staticTextToSVG(swf, textRecords, getTextNum(), exporter, getRect(), textMatrix, colorTransform, exporter.getZoom(), transformation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -558,10 +558,14 @@ public abstract class TextTag extends DrawableTag {
|
||||
* @param colorTransform Color transform
|
||||
* @param zoom Zoom
|
||||
*/
|
||||
public static void drawBorderSVG(SWF swf, SVGExporter exporter, RGB borderColor, RGB fillColor, RECT rect, MATRIX textMatrix, ColorTransform colorTransform, double zoom) {
|
||||
public static void drawBorderSVG(SWF swf, SVGExporter exporter, RGB borderColor, RGB fillColor, RECT rect, MATRIX textMatrix, Matrix transformation, ColorTransform colorTransform, double zoom) {
|
||||
exporter.createSubGroup(new Matrix(textMatrix), null);
|
||||
SHAPE shape = getBorderShape(borderColor, fillColor, rect);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, 0, exporter, null, colorTransform, zoom);
|
||||
|
||||
Matrix mat = transformation.clone();
|
||||
mat = mat.concatenate(new Matrix(textMatrix));
|
||||
//??FIXME
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, 0, exporter, null, colorTransform, 1, zoom, mat);
|
||||
shapeExporter.export();
|
||||
exporter.endGroup();
|
||||
}
|
||||
@@ -838,8 +842,9 @@ public abstract class TextTag extends DrawableTag {
|
||||
* @param textMatrix Text matrix
|
||||
* @param colorTransform Color transform
|
||||
* @param zoom Zoom
|
||||
* @param transformation Transformation
|
||||
*/
|
||||
public static void staticTextToSVG(SWF swf, List<TEXTRECORD> textRecords, int numText, SVGExporter exporter, RECT bounds, MATRIX textMatrix, ColorTransform colorTransform, double zoom) {
|
||||
public static void staticTextToSVG(SWF swf, List<TEXTRECORD> textRecords, int numText, SVGExporter exporter, RECT bounds, MATRIX textMatrix, ColorTransform colorTransform, double zoom, Matrix transformation) {
|
||||
int textColor = 0;
|
||||
FontTag font = null;
|
||||
int textHeight = 12;
|
||||
@@ -914,8 +919,19 @@ public abstract class TextTag extends DrawableTag {
|
||||
exporter.endGroup();
|
||||
}
|
||||
} else {
|
||||
Matrix mat0 = transformation.clone();
|
||||
mat0 = mat0.concatenate(new Matrix(textMatrix));
|
||||
Matrix matScale = Matrix.getScaleInstance(rat);
|
||||
|
||||
|
||||
for (GLYPHENTRY entry : rec.glyphEntries) {
|
||||
Matrix mat = Matrix.getTranslateInstance(x, y).concatenate(Matrix.getScaleInstance(rat));
|
||||
|
||||
|
||||
matScale.translateX = x;
|
||||
matScale.translateY = y;
|
||||
|
||||
Matrix matX = mat0.concatenate(matScale);
|
||||
if (entry.glyphIndex != -1) {
|
||||
// shapeNum: 1
|
||||
SHAPE shape = glyphs.get(entry.glyphIndex);
|
||||
@@ -936,7 +952,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
if (charId == null) {
|
||||
charId = exporter.getUniqueId(Helper.getValidHtmlId("font_" + font.getFontNameIntag() + "_" + ch));
|
||||
exporter.createDefGroup(null, charId);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, 0, exporter, null, colorTransform, zoom);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, 0, exporter, null, colorTransform, zoom, zoom, matX);
|
||||
shapeExporter.export();
|
||||
if (!exporter.endGroup()) {
|
||||
charId = "";
|
||||
@@ -946,7 +962,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
}
|
||||
|
||||
if (!"".equals(charId)) {
|
||||
Element charImage = exporter.addUse(mat, bounds, charId, null, null);
|
||||
Element charImage = exporter.addUse(mat, bounds, charId, null, null, false);
|
||||
RGBA colorA = new RGBA(textColor);
|
||||
charImage.setAttribute("fill", colorA.toHexRGB());
|
||||
if (colorA.alpha != 255) {
|
||||
|
||||
@@ -1597,7 +1597,7 @@ public class Timeline {
|
||||
* @param level Level
|
||||
* @throws IOException On I/O error
|
||||
*/
|
||||
public void toSVG(int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level) throws IOException {
|
||||
public void toSVG(int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level, Matrix transformation, Matrix strokeTransformation) throws IOException {
|
||||
if (getFrameCount() <= frame) {
|
||||
return;
|
||||
}
|
||||
@@ -1650,6 +1650,9 @@ public class Timeline {
|
||||
clrTrans = clrTrans == null ? layer.colorTransForm : colorTransform.merge(layer.colorTransForm);
|
||||
}
|
||||
|
||||
Matrix layerMatrix = new Matrix(layer.getDrawingMatrix());
|
||||
Matrix absMat = strokeTransformation.concatenate(layerMatrix);
|
||||
|
||||
if (character instanceof DrawableTag) {
|
||||
DrawableTag drawable = (DrawableTag) character;
|
||||
|
||||
@@ -1669,26 +1672,32 @@ public class Timeline {
|
||||
exporter.createClipPath(mat, clipName);
|
||||
SvgClip clip = new SvgClip(clipName, layer.clipDepth);
|
||||
clips.add(clip);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1, transformation, strokeTransformation);
|
||||
exporter.endGroup();
|
||||
} else {
|
||||
boolean createNew = false;
|
||||
|
||||
SVGExporter.ExportKey exportKey = new SVGExporter.ExportKey(drawableTag, clrTrans, layer.ratio, layer.clipDepth > -1);
|
||||
if (exporter.exportedTags.containsKey(exportKey)) {
|
||||
if (exporter.exportedTags.containsKey(exportKey)
|
||||
&& !exporter.exportedSmallStrokesTags.contains(exportKey)) {
|
||||
assetName = exporter.exportedTags.get(exportKey);
|
||||
} else {
|
||||
assetName = getTagIdPrefix(drawableTag, exporter);
|
||||
exporter.exportedTags.put(exportKey, assetName);
|
||||
createNew = true;
|
||||
}
|
||||
boolean hasSmallStrokes = false;
|
||||
if (createNew) {
|
||||
exporter.createDefGroup(new ExportRectangle(boundRect), assetName);
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1);
|
||||
exporter.endGroup();
|
||||
drawable.toSVG(exporter, layer.ratio, clrTrans, level + 1, transformation, absMat);
|
||||
hasSmallStrokes = exporter.hasSmallStrokes();
|
||||
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, layer.filters);
|
||||
exporter.addUse(mat, boundRect, assetName, layer.instanceName, scalingGrid == null ? null : scalingGrid.splitter, String.valueOf(drawable.getCharacterId()), String.join("___", drawable.getClassNames()), layer.blendMode, layer.filters, hasSmallStrokes);
|
||||
if (hasSmallStrokes) {
|
||||
exporter.exportedSmallStrokesTags.add(exportKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user