mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-29 02:15:48 +00:00
Morphshape replace - use whole file when it was exported by FFDec
Fixed Morphshape SVG export - focalPoint animation
This commit is contained in:
@@ -224,7 +224,7 @@ public class FrameExporter {
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "frame");
|
||||
if (fbackgroundColor != null) {
|
||||
exporter.setBackGroundColor(fbackgroundColor);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class MorphShapeExporter {
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "morphshape");
|
||||
mst.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class ShapeExporter {
|
||||
rect.yMax *= settings.zoom;
|
||||
rect.xMin *= settings.zoom;
|
||||
rect.yMin *= settings.zoom;
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "shape");
|
||||
st.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class TextExporter {
|
||||
new RetryTask(() -> {
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
ExportRectangle rect = new ExportRectangle(textTag.getRect());
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom);
|
||||
SVGExporter exporter = new SVGExporter(rect, settings.zoom, "text");
|
||||
textTag.toSVG(exporter, -2, new CXFORMWITHALPHA(), 0);
|
||||
fos.write(Utf8Helper.getBytes(exporter.getSVG()));
|
||||
}
|
||||
|
||||
@@ -42,6 +42,36 @@ public final class Matrix implements Cloneable {
|
||||
mat.scale(scale);
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
||||
public static Matrix getRotateInstance(double rotateAngle) {
|
||||
return getRotateInstance(rotateAngle, 0, 0);
|
||||
}
|
||||
public static Matrix getRotateInstance(double rotateAngle, double tx, double ty) {
|
||||
double angleRad = -rotateAngle * Math.PI / 180;
|
||||
Matrix mat = new Matrix();
|
||||
mat.rotateSkew0 = -Math.sin(angleRad);
|
||||
mat.rotateSkew1 = Math.sin(angleRad);
|
||||
mat.scaleX = Math.cos(angleRad);
|
||||
mat.scaleY = Math.cos(angleRad);
|
||||
mat = mat.preConcatenate(getTranslateInstance(tx, ty))
|
||||
.concatenate(getTranslateInstance(-tx, -ty));
|
||||
return mat;
|
||||
}
|
||||
|
||||
public static Matrix getSkewXInstance(double skewAngle) {
|
||||
double angleRad = skewAngle * Math.PI / 180;
|
||||
Matrix mat = new Matrix();
|
||||
mat.rotateSkew1 = Math.tan(angleRad);
|
||||
return mat;
|
||||
}
|
||||
|
||||
public static Matrix getSkewYInstance(double skewAngle) {
|
||||
double angleRad = skewAngle * Math.PI / 180;
|
||||
Matrix mat = new Matrix();
|
||||
mat.rotateSkew0 = Math.tan(angleRad);
|
||||
return mat;
|
||||
}
|
||||
|
||||
public static Matrix getScaleInstance(double scaleX, double scaleY) {
|
||||
Matrix mat = new Matrix();
|
||||
|
||||
@@ -88,7 +88,7 @@ public class SVGExporter {
|
||||
|
||||
public boolean useTextTag = Configuration.textExportExportFontFace.get();
|
||||
|
||||
public SVGExporter(ExportRectangle bounds, double zoom) {
|
||||
public SVGExporter(ExportRectangle bounds, double zoom, String objectType) {
|
||||
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
try {
|
||||
@@ -110,11 +110,12 @@ public class SVGExporter {
|
||||
}
|
||||
createDefGroup(bounds, null, zoom);
|
||||
}
|
||||
svgRoot.setAttribute("ffdec:objectType", objectType);
|
||||
} catch (ParserConfigurationException ex) {
|
||||
Logger.getLogger(SVGExporter.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
gradients = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private Element getDefs() {
|
||||
if (_svgDefs == null) {
|
||||
|
||||
@@ -89,7 +89,7 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
|
||||
Element gradient = (type == FILLSTYLE.LINEAR_GRADIENT)
|
||||
? exporter.createElement("linearGradient")
|
||||
: exporter.createElement("radialGradient");
|
||||
populateGradientElement(gradient, type, gradientRecords, gradientRecordsEnd, matrix, matrixEnd, spreadMethod, interpolationMethod, focalPointRatio);
|
||||
populateGradientElement(gradient, type, gradientRecords, gradientRecordsEnd, matrix, matrixEnd, spreadMethod, interpolationMethod, focalPointRatio, focalPointRatioEnd);
|
||||
int id = exporter.gradients.indexOf(gradient);
|
||||
if (id < 0) {
|
||||
// todo: filter same gradients
|
||||
@@ -206,7 +206,7 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
|
||||
Element gradient = (type == FILLSTYLE.LINEAR_GRADIENT)
|
||||
? exporter.createElement("linearGradient")
|
||||
: exporter.createElement("radialGradient");
|
||||
populateGradientElement(gradient, type, gradientRecords, gradientRecordsEnd, matrix, matrixEnd, spreadMethod, interpolationMethod, focalPointRatio);
|
||||
populateGradientElement(gradient, type, gradientRecords, gradientRecordsEnd, matrix, matrixEnd, spreadMethod, interpolationMethod, focalPointRatio, focalPointRatioEnd);
|
||||
int id = exporter.gradients.indexOf(gradient);
|
||||
if (id < 0) {
|
||||
// todo: filter same gradients
|
||||
@@ -247,7 +247,7 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
|
||||
|
||||
// QR decomposition
|
||||
double translateX = roundPixels400(matrix.translateX * zoom / SWF.unitDivisor);
|
||||
double translateY = roundPixels400(matrix.translateY * zoom / SWF.unitDivisor);
|
||||
double translateY = roundPixels400(matrix.translateY * zoom / SWF.unitDivisor);
|
||||
double a = matrix.scaleX;
|
||||
double b = matrix.rotateSkew0;
|
||||
double c = matrix.rotateSkew1;
|
||||
@@ -402,7 +402,7 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
|
||||
element.appendChild(animateSkewX);*/
|
||||
}
|
||||
|
||||
protected void populateGradientElement(Element gradient, int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
|
||||
protected void populateGradientElement(Element gradient, int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
|
||||
gradient.setAttribute("gradientUnits", "userSpaceOnUse");
|
||||
if (type == FILLSTYLE.LINEAR_GRADIENT) {
|
||||
gradient.setAttribute("x1", "-819.2");
|
||||
@@ -415,6 +415,9 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
|
||||
gradient.setAttribute("fx", Double.toString(819.2 * focalPointRatio));
|
||||
gradient.setAttribute("fy", "0");
|
||||
}
|
||||
if (focalPointRatio != 0 || focalPointRatioEnd != 0) {
|
||||
gradient.appendChild(createAnimateElement("fx", Double.toString(819.2 * focalPointRatio), Double.toString(819.2 * focalPointRatioEnd)));
|
||||
}
|
||||
}
|
||||
switch (spreadMethod) {
|
||||
case GRADIENT.SPREAD_PAD_MODE:
|
||||
|
||||
@@ -211,8 +211,9 @@ public class MorphShapeGenerator {
|
||||
}
|
||||
|
||||
for (int i = 0; i < endFillStyles.size(); i++) {
|
||||
FILLSTYLE fsStart = startFillStyles.get(i);
|
||||
FILLSTYLE fsEnd = endFillStyles.get(i);
|
||||
if (fsEnd.hasBitmap()) {
|
||||
if (fsEnd.hasBitmap() && fsEnd.bitmapId != fsStart.bitmapId) {
|
||||
swf.removeTag(swf.getImage(fsEnd.bitmapId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public class ShapeForMorphExporter extends ShapeExporterBase {
|
||||
currentFillStyle = fillStyles.size();
|
||||
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||
fillStyle.fillStyleType = type;
|
||||
fillStyle.gradient = focalPointRatio == 0 ? new FOCALGRADIENT() : new GRADIENT();
|
||||
fillStyle.gradient = focalPointRatio == 0 ? new GRADIENT() : new FOCALGRADIENT();
|
||||
fillStyle.gradient.gradientRecords = Helper.deepCopy(gradientRecords);
|
||||
fillStyle.gradientMatrix = matrix.toMATRIX();
|
||||
fillStyle.gradient.spreadMode = spreadMethod;
|
||||
|
||||
@@ -69,6 +69,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -97,28 +98,35 @@ public class SvgImporter {
|
||||
* Shape or morphshape tag
|
||||
*/
|
||||
Tag shapeTag;
|
||||
|
||||
|
||||
ShapeTag endShape;
|
||||
|
||||
private Rectangle2D.Double viewBox;
|
||||
|
||||
|
||||
public Tag importSvg(ShapeTag st, String svgXml) {
|
||||
return importSvg((Tag) st, svgXml, true);
|
||||
return importSvg((Tag) st, null, svgXml, true);
|
||||
}
|
||||
|
||||
public Tag importSvg(MorphShapeTag mst, String svgXml) {
|
||||
return importSvg((Tag) mst, svgXml, true);
|
||||
return importSvg((Tag) mst, null, svgXml, true);
|
||||
}
|
||||
|
||||
|
||||
public Tag importSvg(ShapeTag st, String svgXml, boolean fill) {
|
||||
return importSvg((Tag) st, svgXml, fill);
|
||||
return importSvg((Tag) st, null, svgXml, fill);
|
||||
}
|
||||
|
||||
|
||||
public Tag importSvg(MorphShapeTag mst, String svgXml, boolean fill) {
|
||||
return importSvg((Tag) mst, svgXml, fill);
|
||||
return importSvg((Tag) mst, null, svgXml, fill);
|
||||
}
|
||||
|
||||
private Tag importSvg(Tag st, String svgXml, boolean fill) {
|
||||
|
||||
public Tag importSvg(ShapeTag startShape, ShapeTag endShape, String svgXml, boolean fill) {
|
||||
return importSvg((Tag) startShape, endShape, svgXml, fill);
|
||||
}
|
||||
|
||||
private Tag importSvg(Tag st, ShapeTag endShape, String svgXml, boolean fill) {
|
||||
shapeTag = st;
|
||||
|
||||
this.endShape = endShape;
|
||||
|
||||
boolean morphShape = st instanceof MorphShapeTag;
|
||||
|
||||
if (st instanceof DefineShape4Tag) {
|
||||
@@ -134,10 +142,16 @@ public class SvgImporter {
|
||||
shapes.fillStyles.fillStyles = new FILLSTYLE[0];
|
||||
shapes.lineStyles.lineStyles = new LINESTYLE[0];
|
||||
|
||||
SHAPEWITHSTYLE shapes2 = new SHAPEWITHSTYLE();
|
||||
shapes2.fillStyles = new FILLSTYLEARRAY();
|
||||
shapes2.lineStyles = new LINESTYLEARRAY();
|
||||
shapes2.fillStyles.fillStyles = new FILLSTYLE[0];
|
||||
shapes2.lineStyles.lineStyles = new LINESTYLE[0];
|
||||
|
||||
int shapeNum = 0;
|
||||
RECT rect = null;
|
||||
|
||||
if (st instanceof ShapeTag) {
|
||||
|
||||
if (st instanceof ShapeTag) {
|
||||
shapeNum = ((ShapeTag) st).getShapeNum();
|
||||
rect = ((ShapeTag) st).getRect();
|
||||
}
|
||||
@@ -150,11 +164,12 @@ public class SvgImporter {
|
||||
}
|
||||
rect = ((MorphShapeTag) st).getRect();
|
||||
}
|
||||
|
||||
|
||||
int origXmin = rect.Xmin;
|
||||
int origYmin = rect.Ymin;
|
||||
|
||||
shapes.shapeRecords = new ArrayList<>();
|
||||
shapes2.shapeRecords = new ArrayList<>();
|
||||
|
||||
Rectangle2D.Double viewBox = null;
|
||||
try {
|
||||
@@ -217,8 +232,8 @@ public class SvgImporter {
|
||||
|
||||
this.viewBox = viewBox;
|
||||
|
||||
Map<String, SvgFill> cachedFills = new HashMap<>();
|
||||
SvgStyle style = new SvgStyle(this, idMap, rootElement, cachedFills);
|
||||
Map<String, Integer> cachedBitmaps = new HashMap<>();
|
||||
SvgStyle style = new SvgStyle(this, idMap, rootElement, cachedBitmaps);
|
||||
Matrix transform = new Matrix();
|
||||
|
||||
if (fill) {
|
||||
@@ -227,18 +242,26 @@ public class SvgImporter {
|
||||
transform = Matrix.getScaleInstance(ratioX, ratioY);
|
||||
transform.translate(origXmin / SWF.unitDivisor / ratioX, origYmin / SWF.unitDivisor / ratioY);
|
||||
}
|
||||
|
||||
transform = transform.preConcatenate(Matrix.getTranslateInstance(-viewBox.x, -viewBox.y));
|
||||
|
||||
transform = transform.preConcatenate(Matrix.getTranslateInstance(-viewBox.x, -viewBox.y));
|
||||
if (viewBox.height != 0 && viewBox.width != 0) {
|
||||
transform = transform.preConcatenate(Matrix.getScaleInstance(width / viewBox.width, height / viewBox.height));
|
||||
}
|
||||
|
||||
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape, cachedFills);
|
||||
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape, cachedBitmaps, false);
|
||||
if (
|
||||
rootElement.hasAttribute("ffdec:objectType")
|
||||
&& "morphshape".equals(rootElement.getAttribute("ffdec:objectType"))
|
||||
&& applyAnimation(rootElement)
|
||||
) {
|
||||
processSvgObject(idMap, shapeNum, shapes2, rootElement, transform, style, morphShape, cachedBitmaps, true);
|
||||
}
|
||||
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||
Logger.getLogger(ShapeImporter.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
shapes.shapeRecords.add(new EndShapeRecord());
|
||||
shapes2.shapeRecords.add(new EndShapeRecord());
|
||||
|
||||
if (st instanceof ShapeTag) {
|
||||
ShapeTag shape = (ShapeTag) st;
|
||||
@@ -247,15 +270,127 @@ public class SvgImporter {
|
||||
shape.updateBounds();
|
||||
}
|
||||
}
|
||||
if (endShape != null) {
|
||||
|
||||
endShape.shapes = shapes2;
|
||||
endShape.updateBounds();
|
||||
}
|
||||
if (st instanceof MorphShapeTag) {
|
||||
shapes.updateMorphShapeTag((MorphShapeTag) st, fill);
|
||||
}
|
||||
|
||||
|
||||
st.setModified(true);
|
||||
if (endShape != null) {
|
||||
endShape.setModified(true);
|
||||
}
|
||||
|
||||
return (Tag) st;
|
||||
}
|
||||
|
||||
protected boolean applyAnimation(Element element) {
|
||||
NodeList nodeList = element.getChildNodes();
|
||||
boolean result = false;
|
||||
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
Node node = nodeList.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element childElement = (Element) node;
|
||||
if ("animate".equals(childElement.getTagName())) {
|
||||
if (childElement.hasAttribute("attributeName") && childElement.hasAttribute("values")) {
|
||||
String values = childElement.getAttribute("values");
|
||||
String attributeName = childElement.getAttribute("attributeName");
|
||||
if (values.contains(";")) {
|
||||
String parts[] = values.split(";");
|
||||
if (parts.length >= 2) {
|
||||
element.setAttribute(attributeName, parts[1]);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("animateTransform".equals(childElement.getTagName())) {
|
||||
if (childElement.hasAttribute("attributeName")
|
||||
&& childElement.hasAttribute("type")
|
||||
&& (childElement.hasAttribute("to") || childElement.hasAttribute("values"))
|
||||
) {
|
||||
String type = childElement.getAttribute("type");
|
||||
String additive = childElement.hasAttribute("additive") ? childElement.getAttribute("additive") : "replace";
|
||||
String attributeName = childElement.getAttribute("attributeName");
|
||||
Matrix originalMatrix = Matrix.parseSvgMatrix(element.getAttribute(attributeName), 1, 1);
|
||||
String to = "";
|
||||
if (childElement.hasAttribute("values") && childElement.getAttribute("values").contains(";")) {
|
||||
to = childElement.getAttribute("values").split(";")[1];
|
||||
} else if (childElement.hasAttribute("to")) {
|
||||
to = childElement.getAttribute("to");
|
||||
}
|
||||
String toParts[] = Matrix.parseSvgNumberList(to);
|
||||
|
||||
Matrix newMatrix = null;
|
||||
switch (type) {
|
||||
case "scale":
|
||||
double scaleX;
|
||||
double scaleY;
|
||||
if (toParts.length == 2) {
|
||||
scaleX = parseNumber(toParts[0]);
|
||||
scaleY = parseNumber(toParts[1]);
|
||||
} else if (toParts.length == 1) {
|
||||
scaleX = parseNumber(toParts[0]);
|
||||
scaleY = scaleX;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
newMatrix = Matrix.getScaleInstance(scaleX, scaleY);
|
||||
break;
|
||||
case "translate":
|
||||
if (toParts.length == 2) {
|
||||
double translateX = parseNumber(toParts[0]);
|
||||
double translateY = parseNumber(toParts[1]);
|
||||
newMatrix = Matrix.getTranslateInstance(translateX, translateY);
|
||||
}
|
||||
break;
|
||||
case "rotate":
|
||||
if (toParts.length == 1 || toParts.length == 3) {
|
||||
double rotateAngle = parseNumber(toParts[0]);
|
||||
double tx = 0;
|
||||
double ty = 0;
|
||||
if (toParts.length == 3) {
|
||||
tx = parseNumber(toParts[1]);
|
||||
ty = parseNumber(toParts[2]);
|
||||
}
|
||||
newMatrix = Matrix.getRotateInstance(rotateAngle, tx, ty);
|
||||
}
|
||||
break;
|
||||
case "skewX":
|
||||
if (toParts.length == 1) {
|
||||
double skewXAngle = parseNumber(toParts[0]);
|
||||
newMatrix = Matrix.getSkewXInstance(skewXAngle);
|
||||
}
|
||||
break;
|
||||
case "skewY":
|
||||
if (toParts.length == 1) {
|
||||
double skewYAngle = parseNumber(toParts[0]);
|
||||
newMatrix = Matrix.getSkewYInstance(skewYAngle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (newMatrix != null) {
|
||||
if ("replace".equals(additive)) {
|
||||
element.setAttribute(attributeName, newMatrix.getSvgTransformationString(1, 1));
|
||||
}
|
||||
if ("sum".equals(additive)) {
|
||||
element.setAttribute(attributeName, originalMatrix.concatenate(newMatrix).getSvgTransformationString(1, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (applyAnimation(childElement)) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generate id-element map, because getElementById does not work in some cases (namespaces?)
|
||||
protected void populateIds(Element el, Map<String, Element> out) {
|
||||
if (el.hasAttribute("id")) {
|
||||
@@ -319,7 +454,7 @@ public class SvgImporter {
|
||||
}
|
||||
}
|
||||
|
||||
private void processSwitch(Element element, Map<String, Element> idMap, int shapeNum, SHAPEWITHSTYLE shapes, Matrix transform, SvgStyle style, boolean morphShape, Map<String, SvgFill> cachedFills) {
|
||||
private void processSwitch(Element element, Map<String, Element> idMap, int shapeNum, SHAPEWITHSTYLE shapes, Matrix transform, SvgStyle style, boolean morphShape, Map<String, Integer> cachedBitmaps, boolean shape2) {
|
||||
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
|
||||
Node childNode = element.getChildNodes().item(i);
|
||||
if (childNode instanceof Element) {
|
||||
@@ -330,33 +465,33 @@ public class SvgImporter {
|
||||
if (childElement.hasAttribute("systemLanguage")) {
|
||||
String systemLanguage = childElement.getAttribute("systemLanguage");
|
||||
if (systemLanguage.equals("en-us") || systemLanguage.equals("en")) {
|
||||
processElement(childElement, idMap, shapeNum, shapes, transform, style, morphShape, cachedFills);
|
||||
processElement(childElement, idMap, shapeNum, shapes, transform, style, morphShape, cachedBitmaps, shape2);
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
processElement(childElement, idMap, shapeNum, shapes, transform, style, morphShape, cachedFills);
|
||||
processElement(childElement, idMap, shapeNum, shapes, transform, style, morphShape, cachedBitmaps, shape2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processElement(Element element, Map<String, Element> idMap, int shapeNum, SHAPEWITHSTYLE shapes, Matrix transform, SvgStyle style, boolean morphShape, Map<String, SvgFill> cachedFills) {
|
||||
private void processElement(Element element, Map<String, Element> idMap, int shapeNum, SHAPEWITHSTYLE shapes, Matrix transform, SvgStyle style, boolean morphShape, Map<String, Integer> cachedBitmaps, boolean shape2) {
|
||||
if (element.hasAttribute("requiredExtensions") && !element.getAttribute("requiredExtensions").isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String tagName = element.getTagName();
|
||||
SvgStyle newStyle = new SvgStyle(this, idMap, element, cachedFills);
|
||||
SvgStyle newStyle = new SvgStyle(this, idMap, element, cachedBitmaps);
|
||||
Matrix m = Matrix.parseSvgMatrix(element.getAttribute("transform"), 1, 1);
|
||||
Matrix m2 = m == null ? transform : transform.concatenate(m);
|
||||
if ("switch".equals(tagName)) {
|
||||
processSwitch(element, idMap, shapeNum, shapes, transform, style, morphShape, cachedFills);
|
||||
processSwitch(element, idMap, shapeNum, shapes, transform, style, morphShape, cachedBitmaps, shape2);
|
||||
} else if ("style".equals(tagName)) {
|
||||
processStyle(element);
|
||||
} else if ("g".equals(tagName)) {
|
||||
processSvgObject(idMap, shapeNum, shapes, element, m2, newStyle, morphShape, cachedFills);
|
||||
processSvgObject(idMap, shapeNum, shapes, element, m2, newStyle, morphShape, cachedBitmaps, shape2);
|
||||
} else if ("path".equals(tagName)) {
|
||||
processPath(shapeNum, shapes, element, m2, newStyle, morphShape);
|
||||
processPath(shapeNum, shapes, element, m2, newStyle, morphShape, shape2);
|
||||
} else if ("circle".equals(tagName)) {
|
||||
processCircle(shapeNum, shapes, element, m2, newStyle, morphShape);
|
||||
} else if ("ellipse".equals(tagName)) {
|
||||
@@ -379,12 +514,12 @@ public class SvgImporter {
|
||||
}
|
||||
}
|
||||
|
||||
private void processSvgObject(Map<String, Element> idMap, int shapeNum, SHAPEWITHSTYLE shapes, Element element, Matrix transform, SvgStyle style, boolean morphShape, Map<String, SvgFill> cachedFills) {
|
||||
private void processSvgObject(Map<String, Element> idMap, int shapeNum, SHAPEWITHSTYLE shapes, Element element, Matrix transform, SvgStyle style, boolean morphShape, Map<String, Integer> cachedFills, boolean shape2) {
|
||||
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
|
||||
Node childNode = element.getChildNodes().item(i);
|
||||
if (childNode instanceof Element) {
|
||||
Element childElement = (Element) childNode;
|
||||
processElement(childElement, idMap, shapeNum, shapes, transform, style, morphShape, cachedFills);
|
||||
processElement(childElement, idMap, shapeNum, shapes, transform, style, morphShape, cachedFills, shape2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,15 +554,19 @@ public class SvgImporter {
|
||||
}
|
||||
}
|
||||
|
||||
private void processCommands(int shapeNum, SHAPEWITHSTYLE shapes, List<PathCommand> commands, Matrix transform, SvgStyle style, boolean morphShape) {
|
||||
|
||||
private void processCommands(int shapeNum, SHAPEWITHSTYLE shapes, List<PathCommand> commands, Matrix transform, SvgStyle style, boolean morphShape, boolean shape2) {
|
||||
|
||||
if ("nonzero".equals(style.getFillRule())) {
|
||||
if (shapeTag instanceof DefineShape4Tag) {
|
||||
if (!shape2 && (shapeTag instanceof DefineShape4Tag)) {
|
||||
DefineShape4Tag shape4 = (DefineShape4Tag) shapeTag;
|
||||
shape4.usesFillWindingRule = true;
|
||||
}
|
||||
if (shape2 && (endShape instanceof DefineShape4Tag)) {
|
||||
DefineShape4Tag shape4 = (DefineShape4Tag) endShape;
|
||||
shape4.usesFillWindingRule = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Matrix transform2 = transform.preConcatenate(Matrix.getScaleInstance(SWF.unitDivisor));
|
||||
Point prevPoint = new Point(0, 0);
|
||||
Point startPoint = prevPoint;
|
||||
@@ -484,7 +623,7 @@ public class SvgImporter {
|
||||
scr.fillStyle0 = fillStyle;
|
||||
} else {
|
||||
scr.stateFillStyle1 = true;
|
||||
scr.fillStyle1 = fillStyle;
|
||||
scr.fillStyle1 = fillStyle;
|
||||
}
|
||||
}
|
||||
if (lineStyle != 0) {
|
||||
@@ -640,9 +779,7 @@ public class SvgImporter {
|
||||
shapes.shapeRecords.addAll(newRecords);
|
||||
}
|
||||
|
||||
private void processPath(int shapeNum, SHAPEWITHSTYLE shapes, Element childElement, Matrix transform, SvgStyle style, boolean morphShape) {
|
||||
String data = childElement.getAttribute("d");
|
||||
|
||||
private List<PathCommand> processPathD(String data) {
|
||||
char command = 0;
|
||||
Point startPoint = new Point(0, 0);
|
||||
Point prevCControlPoint = null;
|
||||
@@ -927,7 +1064,7 @@ public class SvgImporter {
|
||||
break;
|
||||
default:
|
||||
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Unknown command: {0}", command);
|
||||
return;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
if (cmd != 'C' && cmd != 'S') {
|
||||
@@ -944,8 +1081,13 @@ public class SvgImporter {
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore remaining data as specified in SVG Specification F.2 Error processing
|
||||
}
|
||||
return pathCommands;
|
||||
}
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape);
|
||||
private void processPath(int shapeNum, SHAPEWITHSTYLE shapes, Element element, Matrix transform, SvgStyle style, boolean morphShape, boolean shape2) {
|
||||
String data = element.getAttribute("d");
|
||||
List<PathCommand> pathCommands = processPathD(data);
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape, shape2);
|
||||
}
|
||||
|
||||
private double calcAngle(double ux, double uy, double vx, double vy) {
|
||||
@@ -1043,7 +1185,7 @@ public class SvgImporter {
|
||||
serz.command = 'Z';
|
||||
pathCommands.add(serz);
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape);
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape, false);
|
||||
}
|
||||
|
||||
private void processRect(int shapeNum, SHAPEWITHSTYLE shapes, Element childElement, Matrix transform, SvgStyle style, boolean morphShape) {
|
||||
@@ -1154,7 +1296,7 @@ public class SvgImporter {
|
||||
serz.command = 'Z';
|
||||
pathCommands.add(serz);
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape);
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape, false);
|
||||
}
|
||||
|
||||
private void processLine(int shapeNum, SHAPEWITHSTYLE shapes, Element childElement, Matrix transform, SvgStyle style, boolean morphShape) {
|
||||
@@ -1182,8 +1324,8 @@ public class SvgImporter {
|
||||
|
||||
pathCommands.add(cer);
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape);
|
||||
}
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape, false);
|
||||
}
|
||||
|
||||
private void processPolygon(int shapeNum, SHAPEWITHSTYLE shapes, Element childElement, Matrix transform, SvgStyle style, boolean morphShape) {
|
||||
processPolyline(shapeNum, shapes, childElement, transform, style, true, morphShape);
|
||||
@@ -1243,7 +1385,7 @@ public class SvgImporter {
|
||||
pathCommands.add(serz);
|
||||
}
|
||||
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape);
|
||||
processCommands(shapeNum, shapes, pathCommands, transform, style, morphShape, false);
|
||||
}
|
||||
|
||||
//Stub for w3 test. TODO: refactor and move to test directory. It's here because of easy access - compiling single file
|
||||
@@ -1776,7 +1918,7 @@ public class SvgImporter {
|
||||
SvgLineJoin lineJoin = style.getStrokeLineJoin();
|
||||
if (lineStyle instanceof LINESTYLE2) {
|
||||
LINESTYLE2 lineStyle2 = (LINESTYLE2) lineStyle;
|
||||
|
||||
|
||||
String vectorEffect = style.getVectorEffect();
|
||||
if ("non-scaling-stroke".equals(vectorEffect)) {
|
||||
lineStyle2.noHScaleFlag = true;
|
||||
@@ -1799,7 +1941,7 @@ public class SvgImporter {
|
||||
morph2.usesScalingStrokes = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int swfCap = lineCap == SvgLineCap.BUTT ? LINESTYLE2.NO_CAP
|
||||
: lineCap == SvgLineCap.ROUND ? LINESTYLE2.ROUND_CAP
|
||||
: lineCap == SvgLineCap.SQUARE ? LINESTYLE2.SQUARE_CAP : 0;
|
||||
|
||||
@@ -47,17 +47,17 @@ class SvgStyle {
|
||||
|
||||
private final Map<String, Element> idMap;
|
||||
|
||||
private final Map<String, SvgFill> cachedFills;
|
||||
private final Map<String, Integer> cachedBitmaps;
|
||||
|
||||
private final double epsilon = 0.001;
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
public SvgStyle(SvgImporter importer, Map<String, Element> idMap, Element element, Map<String, SvgFill> cachedFills) {
|
||||
public SvgStyle(SvgImporter importer, Map<String, Element> idMap, Element element, Map<String, Integer> cachedBitmaps) {
|
||||
this.importer = importer;
|
||||
this.idMap = idMap;
|
||||
this.element = element;
|
||||
this.cachedFills = cachedFills;
|
||||
this.cachedBitmaps = cachedBitmaps;
|
||||
}
|
||||
|
||||
private Map<String, String> getStyleAttributeValues(Element element) {
|
||||
@@ -470,7 +470,7 @@ class SvgStyle {
|
||||
Node node = stopNodes.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element stopEl = (Element) node;
|
||||
SvgStyle newStyle = new SvgStyle(importer, idMap, stopEl, cachedFills);
|
||||
SvgStyle newStyle = new SvgStyle(importer, idMap, stopEl, cachedBitmaps);
|
||||
|
||||
String offsetStr = stopEl.getAttribute("offset");
|
||||
double offset = importer.parseNumberOrPercent(offsetStr);
|
||||
@@ -563,21 +563,26 @@ class SvgStyle {
|
||||
|
||||
if (mPat.matches()) {
|
||||
String elementId = mPat.group(1);
|
||||
if (cachedFills.containsKey(elementId)) {
|
||||
return cachedFills.get(elementId);
|
||||
}
|
||||
Element e = idMap.get(elementId);
|
||||
Element e = idMap.get(elementId);
|
||||
if (e != null) {
|
||||
if (cachedBitmaps.containsKey(elementId)) {
|
||||
SvgBitmapFill bitmapFill = new SvgBitmapFill();
|
||||
int bitmapId = cachedBitmaps.get(elementId);
|
||||
bitmapFill.characterId = bitmapId;
|
||||
if (e.hasAttribute("patternTransform")) {
|
||||
bitmapFill.patternTransform = e.getAttribute("patternTransform");
|
||||
}
|
||||
return bitmapFill;
|
||||
}
|
||||
|
||||
String tagName = e.getTagName();
|
||||
if ("linearGradient".equals(tagName)) {
|
||||
SvgFill ret = parseGradient(idMap, e);
|
||||
cachedFills.put(elementId, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ("radialGradient".equals(tagName)) {
|
||||
SvgFill ret = parseGradient(idMap, e);
|
||||
cachedFills.put(elementId, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -586,9 +591,14 @@ class SvgStyle {
|
||||
NodeList childNodes = e.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
if (childNodes.item(i) instanceof Element) {
|
||||
if (element != null) {
|
||||
|
||||
if ("animateTransform".equals(((Element)childNodes.item(i)).getTagName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
element = null;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
element = (Element) childNodes.item(i);
|
||||
@@ -609,7 +619,7 @@ class SvgStyle {
|
||||
bitmapFill.patternTransform = e.getAttribute("patternTransform");
|
||||
}
|
||||
|
||||
cachedFills.put(elementId, bitmapFill);
|
||||
cachedBitmaps.put(elementId, imageTag.characterID);
|
||||
return bitmapFill;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(SvgStyle.class.getName()).log(Level.SEVERE, null, ex);
|
||||
|
||||
@@ -213,6 +213,8 @@ public class FILLSTYLE implements NeedsCharacters, FieldChangeObserver, Serializ
|
||||
}
|
||||
morphFillStyle.fillStyleType = fillStyleType;
|
||||
if (gradient != null) {
|
||||
morphFillStyle.startGradientMatrix = gradientMatrix;
|
||||
morphFillStyle.endGradientMatrix = gradientMatrix;
|
||||
morphFillStyle.gradient = gradient.toMorphGradient();
|
||||
}
|
||||
|
||||
@@ -239,6 +241,8 @@ public class FILLSTYLE implements NeedsCharacters, FieldChangeObserver, Serializ
|
||||
}
|
||||
morphFillStyle.fillStyleType = fillStyleType;
|
||||
if (gradient != null) {
|
||||
morphFillStyle.startGradientMatrix = gradientMatrix;
|
||||
morphFillStyle.endGradientMatrix = endFillStyle.gradientMatrix;
|
||||
morphFillStyle.gradient = gradient.toMorphGradient(endFillStyle.gradient);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,8 @@ public class FOCALGRADIENT extends GRADIENT implements Serializable {
|
||||
morphGradient.spreadMode = spreadMode;
|
||||
morphGradient.gradientRecords = new MORPHGRADRECORD[gradientRecords.length];
|
||||
for (int i = 0; i < gradientRecords.length; i++) {
|
||||
morphGradient.gradientRecords[i] = gradientRecords[i].toMorphGradRecord();
|
||||
}
|
||||
morphGradient.gradientRecords[i] = gradientRecords[i].toMorphGradRecord(endGradient.gradientRecords[i]);
|
||||
}
|
||||
morphGradient.startFocalPoint = focalPoint;
|
||||
if (endGradient instanceof FOCALGRADIENT) {
|
||||
morphGradient.endFocalPoint = ((FOCALGRADIENT)endGradient).focalPoint;
|
||||
|
||||
@@ -101,7 +101,7 @@ public class GRADIENT implements Serializable {
|
||||
morphGradient.spreadMode = spreadMode;
|
||||
morphGradient.gradientRecords = new MORPHGRADRECORD[gradientRecords.length];
|
||||
for (int i = 0; i < gradientRecords.length; i++) {
|
||||
morphGradient.gradientRecords[i] = gradientRecords[i].toMorphGradRecord();
|
||||
morphGradient.gradientRecords[i] = gradientRecords[i].toMorphGradRecord(endGradient.gradientRecords[i]);
|
||||
}
|
||||
if (endGradient instanceof FOCALGRADIENT) {
|
||||
((MORPHFOCALGRADIENT)morphGradient).startFocalPoint = 0;
|
||||
|
||||
Reference in New Issue
Block a user