mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-11 15:31:56 +00:00
fix(SVG importer): apply fillOpacity and strokeOpacity to gradient
This commit is contained in:
@@ -107,11 +107,12 @@ public class SvgImporter {
|
||||
private Rectangle2D.Double viewBox;
|
||||
|
||||
private double width;
|
||||
|
||||
|
||||
private double height;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param st Shape tag
|
||||
* @param svgXml SVG XML
|
||||
* @return Imported tag
|
||||
@@ -122,6 +123,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mst Morph shape tag
|
||||
* @param svgXml SVG XML
|
||||
* @return Imported tag
|
||||
@@ -132,6 +134,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param st Shape tag
|
||||
* @param svgXml SVG XML
|
||||
* @param fill Fill flag
|
||||
@@ -143,6 +146,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mst Morph shape tag
|
||||
* @param svgXml SVG XML
|
||||
* @param fill Fill flag
|
||||
@@ -154,6 +158,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param startShape Start shape tag
|
||||
* @param endShape End shape tag
|
||||
* @param svgXml SVG XML
|
||||
@@ -166,6 +171,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param st Start shape tag
|
||||
* @param endShape End shape tag
|
||||
* @param svgXml SVG XML
|
||||
@@ -300,7 +306,7 @@ public class SvgImporter {
|
||||
double ratioY = height / viewBox.height;
|
||||
transform = transform.preConcatenate(Matrix.getScaleInstance(ratioX, ratioY));
|
||||
}
|
||||
|
||||
|
||||
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape, cachedBitmaps, false);
|
||||
if (rootElement.hasAttribute("ffdec:objectType")
|
||||
&& "morphshape".equals(rootElement.getAttribute("ffdec:objectType"))
|
||||
@@ -337,9 +343,10 @@ public class SvgImporter {
|
||||
|
||||
return (Tag) st;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies animation to the element.
|
||||
*
|
||||
* @param element Element
|
||||
* @return True if animation was applied
|
||||
*/
|
||||
@@ -447,8 +454,9 @@ public class SvgImporter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates IDs.
|
||||
* Generates id-element map, because getElementById does not work in some cases (namespaces?)
|
||||
* Populates IDs. Generates id-element map, because getElementById does not
|
||||
* work in some cases (namespaces?)
|
||||
*
|
||||
* @param el Element
|
||||
* @param out Output map
|
||||
*/
|
||||
@@ -613,7 +621,7 @@ public class SvgImporter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addStraightRecord(List<SHAPERECORD> newRecords, int deltaX, int deltaY) {
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.deltaX = deltaX;
|
||||
@@ -621,29 +629,29 @@ public class SvgImporter {
|
||||
ser.generalLineFlag = true;
|
||||
ser.simplify();
|
||||
ser.calculateBits();
|
||||
|
||||
|
||||
//Line is too long, split into half
|
||||
if (ser.numBits > StraightEdgeRecord.MAX_NUM_BITS) {
|
||||
int deltaX1 = deltaX / 2;
|
||||
int deltaY1 = deltaY / 2;
|
||||
int deltaX2 = deltaX1;
|
||||
int deltaY2 = deltaY1;
|
||||
|
||||
|
||||
if (deltaX1 + deltaX2 < deltaX) {
|
||||
deltaX2++;
|
||||
}
|
||||
if (deltaY1 + deltaY2 < deltaY) {
|
||||
deltaY2++;
|
||||
}
|
||||
|
||||
|
||||
addStraightRecord(newRecords, deltaX1, deltaY1);
|
||||
addStraightRecord(newRecords, deltaX2, deltaY2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
newRecords.add(ser);
|
||||
}
|
||||
|
||||
|
||||
private void addCurvedRecord(List<SHAPERECORD> newRecords, int controlDeltaX, int controlDeltaY, int anchorDeltaX, int anchorDeltaY) {
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = controlDeltaX;
|
||||
@@ -651,7 +659,7 @@ public class SvgImporter {
|
||||
cer.anchorDeltaX = anchorDeltaX;
|
||||
cer.anchorDeltaY = anchorDeltaY;
|
||||
cer.calculateBits();
|
||||
|
||||
|
||||
//Curve is too long, split into half
|
||||
if (cer.numBits > CurvedEdgeRecord.MAX_NUM_BITS) {
|
||||
BezierEdge be = new BezierEdge(0, 0, cer.controlDeltaX, cer.controlDeltaY, cer.controlDeltaX + cer.anchorDeltaX, cer.controlDeltaY + cer.anchorDeltaY);
|
||||
@@ -668,12 +676,12 @@ public class SvgImporter {
|
||||
int controlDeltaY2 = (int) Math.round(right.points.get(1).getY()) - controlDeltaY1 - anchorDeltaY1;
|
||||
int anchorDeltaX2 = controlDeltaX + anchorDeltaX - controlDeltaX1 - anchorDeltaX1 - controlDeltaX2;
|
||||
int anchorDeltaY2 = controlDeltaY + anchorDeltaY - controlDeltaY1 - anchorDeltaY1 - controlDeltaY2;
|
||||
|
||||
|
||||
addCurvedRecord(newRecords, controlDeltaX1, controlDeltaY1, anchorDeltaX1, anchorDeltaY1);
|
||||
addCurvedRecord(newRecords, controlDeltaX2, controlDeltaY2, anchorDeltaX2, anchorDeltaY2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
newRecords.add(cer);
|
||||
}
|
||||
|
||||
@@ -781,7 +789,7 @@ public class SvgImporter {
|
||||
}
|
||||
empty = true;
|
||||
break;
|
||||
case 'L':
|
||||
case 'L':
|
||||
x = command.params[0];
|
||||
y = command.params[1];
|
||||
|
||||
@@ -821,8 +829,8 @@ public class SvgImporter {
|
||||
|
||||
p = transform2.transform(x, y);
|
||||
int controlDeltaX = (int) Math.round(p.x - prevPoint.x);
|
||||
int controlDeltaY = (int) Math.round(p.y - prevPoint.y);
|
||||
|
||||
int controlDeltaY = (int) Math.round(p.y - prevPoint.y);
|
||||
|
||||
prevPoint = new Point(prevPoint.x + controlDeltaX, prevPoint.y + controlDeltaY);
|
||||
|
||||
x = command.params[2];
|
||||
@@ -832,7 +840,7 @@ public class SvgImporter {
|
||||
int anchorDeltaX = (int) Math.round(p.x - prevPoint.x);
|
||||
int anchorDeltaY = (int) Math.round(p.y - prevPoint.y);
|
||||
prevPoint = new Point(prevPoint.x + anchorDeltaX, prevPoint.y + anchorDeltaY);
|
||||
|
||||
|
||||
addCurvedRecord(newRecords, controlDeltaX, controlDeltaY, anchorDeltaX, anchorDeltaY);
|
||||
empty = false;
|
||||
break;
|
||||
@@ -869,8 +877,8 @@ public class SvgImporter {
|
||||
int subAnchorDeltaX = (int) Math.round(p.x - prevPoint.x);
|
||||
int subAnchorDeltaY = (int) Math.round(p.y - prevPoint.y);
|
||||
prevPoint = new Point(prevPoint.x + subAnchorDeltaX, prevPoint.y + subAnchorDeltaY);
|
||||
|
||||
addCurvedRecord(newRecords, subControlDeltaX, subControlDeltaY, subAnchorDeltaX, subAnchorDeltaY);
|
||||
|
||||
addCurvedRecord(newRecords, subControlDeltaX, subControlDeltaY, subAnchorDeltaX, subAnchorDeltaY);
|
||||
}
|
||||
|
||||
empty = false;
|
||||
@@ -1507,7 +1515,7 @@ public class SvgImporter {
|
||||
|
||||
public Rectangle2D.Double getViewBox() {
|
||||
return viewBox;
|
||||
}
|
||||
}
|
||||
|
||||
//Stub for w3 test. TODO: refactor and move to test directory. It's here because of easy access - compiling single file
|
||||
private static void svgTest(String name) throws IOException, InterruptedException {
|
||||
@@ -1544,6 +1552,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Test for SVG.
|
||||
*
|
||||
* @param args The command line arguments
|
||||
* @throws IOException On I/O error
|
||||
* @throws InterruptedException On interrupt
|
||||
@@ -1835,7 +1844,7 @@ public class SvgImporter {
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
|
||||
private void applyFillGradients(SvgFill fill, FILLSTYLE fillStyle, RECT bounds, StyleChangeRecord scr, Matrix transform, int shapeNum, SvgStyle style) {
|
||||
private void applyFillGradients(SvgFill fill, FILLSTYLE fillStyle, RECT bounds, StyleChangeRecord scr, Matrix transform, int shapeNum, SvgStyle style, double opacity) {
|
||||
if (fill == null || fillStyle == null) {
|
||||
return;
|
||||
}
|
||||
@@ -1854,7 +1863,7 @@ public class SvgImporter {
|
||||
double y2 = parseCoordinate(lgfill.y2, 1);
|
||||
|
||||
Matrix tMatrix = new Matrix();
|
||||
if (lgfill.gradientUnits == SvgGradientUnits.OBJECT_BOUNDING_BOX) {
|
||||
if (lgfill.gradientUnits == SvgGradientUnits.OBJECT_BOUNDING_BOX) {
|
||||
Matrix xyMatrix = new Matrix();
|
||||
xyMatrix.scaleX = (x2 - x1) * SWF.unitDivisor;
|
||||
xyMatrix.rotateSkew0 = (y2 - y1) * SWF.unitDivisor;
|
||||
@@ -1883,14 +1892,14 @@ public class SvgImporter {
|
||||
.concatenate(scaleMatrix);
|
||||
} else {
|
||||
//SvgGradientUnits.USER_SPACE_ON_USE
|
||||
|
||||
|
||||
x1 *= SWF.unitDivisor;
|
||||
y1 *= SWF.unitDivisor;
|
||||
x2 *= SWF.unitDivisor;
|
||||
y2 *= SWF.unitDivisor;
|
||||
|
||||
y2 *= SWF.unitDivisor;
|
||||
|
||||
double L = 16384.0;
|
||||
|
||||
|
||||
double ux = x2 - x1;
|
||||
double uy = y2 - y1;
|
||||
double du = Math.hypot(x2 - x1, y2 - y1);
|
||||
@@ -1898,20 +1907,20 @@ public class SvgImporter {
|
||||
double my = (y1 + y2) / 2.0;
|
||||
double ax = ux / du;
|
||||
double ay = uy / du;
|
||||
|
||||
|
||||
double k = du / (2 * L);
|
||||
|
||||
|
||||
double nx = -ay;
|
||||
double ny = ax;
|
||||
|
||||
|
||||
double newScaleX = k * (gradientMatrix.scaleX * ax + gradientMatrix.rotateSkew1 * ay);
|
||||
double newRotateSkew1 = k * (gradientMatrix.scaleX * nx + gradientMatrix.rotateSkew1 * ny);
|
||||
double newTranslateX = gradientMatrix.scaleX * mx + gradientMatrix.rotateSkew1 * my + gradientMatrix.translateX;
|
||||
|
||||
double newRotateSkew0 = k * (gradientMatrix.rotateSkew0 * ax + gradientMatrix.scaleY * ay);
|
||||
double newScaleY = k * (gradientMatrix.rotateSkew0 * nx + gradientMatrix.scaleY * ny);
|
||||
double newTranslateY = gradientMatrix.rotateSkew0 * mx + gradientMatrix.scaleY * my + gradientMatrix.translateY;
|
||||
|
||||
double newTranslateY = gradientMatrix.rotateSkew0 * mx + gradientMatrix.scaleY * my + gradientMatrix.translateY;
|
||||
|
||||
tMatrix = new Matrix(newScaleX, newScaleY, newRotateSkew0, newRotateSkew1, newTranslateX, newTranslateY);
|
||||
}
|
||||
fillStyle.gradientMatrix = tMatrix.toMATRIX();
|
||||
@@ -1998,7 +2007,7 @@ public class SvgImporter {
|
||||
for (int i = 0; i < recCount; i++) {
|
||||
SvgStop stop = gfill.stops.get(i);
|
||||
Color color = stop.color;
|
||||
color = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int) Math.round(color.getAlpha() * style.getOpacity()));
|
||||
color = new Color(color.getRed(), color.getGreen(), color.getBlue(), (int) Math.round(color.getAlpha() * opacity));
|
||||
fillStyle.gradient.gradientRecords[i] = new GRADRECORD();
|
||||
fillStyle.gradient.gradientRecords[i].inShape3 = shapeNum >= 3;
|
||||
fillStyle.gradient.gradientRecords[i].color = getRGB(shapeNum, color);
|
||||
@@ -2022,12 +2031,12 @@ public class SvgImporter {
|
||||
private void applyStyleGradients(RECT bounds, StyleChangeRecord scr, Matrix transform, int shapeNum, SvgStyle style) {
|
||||
SvgFill fill = style.getFillWithOpacity();
|
||||
if (fill != null && fill != SvgTransparentFill.INSTANCE) {
|
||||
applyFillGradients(fill, scr.fillStyles.fillStyles[0], bounds, scr, transform, shapeNum, style);
|
||||
applyFillGradients(fill, scr.fillStyles.fillStyles[0], bounds, scr, transform, shapeNum, style, style.getOpacity() * style.getFillOpacity());
|
||||
}
|
||||
SvgFill strokeFill = style.getStrokeFillWithOpacity();
|
||||
if (strokeFill != null) {
|
||||
if (shapeNum == 4 && scr.lineStyles.lineStyles2.length > 0 && scr.lineStyles.lineStyles2[0] instanceof LINESTYLE2) {
|
||||
applyFillGradients(strokeFill, ((LINESTYLE2) scr.lineStyles.lineStyles2[0]).fillType, bounds, scr, transform, shapeNum, style);
|
||||
applyFillGradients(strokeFill, ((LINESTYLE2) scr.lineStyles.lineStyles2[0]).fillType, bounds, scr, transform, shapeNum, style, style.getOpacity() * style.getStrokeOpacity());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2077,7 +2086,7 @@ public class SvgImporter {
|
||||
ILINESTYLE lineStyle = shapeNum <= 3 ? new LINESTYLE() : new LINESTYLE2();
|
||||
lineStyle.setColor(getRGB(shapeNum, lineColor));
|
||||
double scale = Math.sqrt(Math.abs(transform.scaleX * transform.scaleY - transform.rotateSkew0 * transform.rotateSkew1));
|
||||
|
||||
|
||||
lineStyle.setWidth((int) Math.round(style.getStrokeWidth() * scale * SWF.unitDivisor));
|
||||
SvgLineCap lineCap = style.getStrokeLineCap();
|
||||
SvgLineJoin lineJoin = style.getStrokeLineJoin();
|
||||
@@ -2213,6 +2222,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Parses a number from a string.
|
||||
*
|
||||
* @param value The string
|
||||
* @return The number
|
||||
*/
|
||||
@@ -2227,6 +2237,7 @@ public class SvgImporter {
|
||||
|
||||
/**
|
||||
* Parses a number or percent from a string.
|
||||
*
|
||||
* @param value The string
|
||||
* @return The number
|
||||
*/
|
||||
@@ -2265,5 +2276,5 @@ public class SvgImporter {
|
||||
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, text);
|
||||
shownWarnings.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user