Canvas export - stroke gradients in morphshapes

New undocumented structure - MORPHFOCALGRADIENT!
This commit is contained in:
Jindra Petk
2014-04-26 19:29:37 +02:00
parent e3263125d6
commit 55165d5c6f
21 changed files with 292 additions and 46 deletions

View File

@@ -228,6 +228,7 @@ import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE;
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT;
import com.jpexs.decompiler.flash.types.MORPHGRADIENT;
import com.jpexs.decompiler.flash.types.MORPHGRADRECORD;
import com.jpexs.decompiler.flash.types.MORPHLINESTYLE;
@@ -2269,7 +2270,7 @@ public class SWFInputStream extends InputStream {
* @return SHAPERECORD value
* @throws IOException
*/
private SHAPERECORD readSHAPERECORD(int fillBits, int lineBits, int shapeNum) throws IOException {
private SHAPERECORD readSHAPERECORD(int fillBits, int lineBits, int shapeNum, boolean morphShape) throws IOException {
SHAPERECORD ret;
int typeFlag = (int) readUB(1);
if (typeFlag == 0) {
@@ -2302,8 +2303,12 @@ public class SWFInputStream extends InputStream {
scr.lineStyle = (int) readUB(lineBits);
}
if (stateNewStyles) {
scr.fillStyles = readFILLSTYLEARRAY(shapeNum);
scr.lineStyles = readLINESTYLEARRAY(shapeNum);
if(morphShape){
//This should never happen
}else{
scr.fillStyles = readFILLSTYLEARRAY(shapeNum);
scr.lineStyles = readLINESTYLEARRAY(shapeNum);
}
scr.numFillBits = (int) readUB(4);
scr.numLineBits = (int) readUB(4);
}
@@ -2345,11 +2350,11 @@ public class SWFInputStream extends InputStream {
* @return SHAPE value
* @throws IOException
*/
public SHAPE readSHAPE(int shapeNum) throws IOException {
public SHAPE readSHAPE(int shapeNum, boolean morphShape) throws IOException {
SHAPE ret = new SHAPE();
ret.numFillBits = (int) readUB(4);
ret.numLineBits = (int) readUB(4);
ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits);
ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits, morphShape);
return ret;
}
@@ -2360,13 +2365,13 @@ public class SWFInputStream extends InputStream {
* @return SHAPEWITHSTYLE value
* @throws IOException
*/
public SHAPEWITHSTYLE readSHAPEWITHSTYLE(int shapeNum) throws IOException {
public SHAPEWITHSTYLE readSHAPEWITHSTYLE(int shapeNum, boolean morphShape) throws IOException {
SHAPEWITHSTYLE ret = new SHAPEWITHSTYLE();
ret.fillStyles = readFILLSTYLEARRAY(shapeNum);
ret.lineStyles = readLINESTYLEARRAY(shapeNum);
ret.numFillBits = (int) readUB(4);
ret.numLineBits = (int) readUB(4);
ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits);
ret.shapeRecords = readSHAPERECORDS(shapeNum, ret.numFillBits, ret.numLineBits, morphShape);
return ret;
}
@@ -2379,11 +2384,11 @@ public class SWFInputStream extends InputStream {
* @return SHAPERECORDs array
* @throws IOException
*/
private List<SHAPERECORD> readSHAPERECORDS(int shapeNum, int fillBits, int lineBits) throws IOException {
private List<SHAPERECORD> readSHAPERECORDS(int shapeNum, int fillBits, int lineBits, boolean morphShape) throws IOException {
List<SHAPERECORD> ret = new ArrayList<>();
SHAPERECORD rec;
do {
rec = readSHAPERECORD(fillBits, lineBits, shapeNum);
rec = readSHAPERECORD(fillBits, lineBits, shapeNum, morphShape);
if (rec instanceof StyleChangeRecord) {
StyleChangeRecord scRec = (StyleChangeRecord) rec;
if (scRec.stateNewStyles) {
@@ -2542,6 +2547,29 @@ public class SWFInputStream extends InputStream {
}
return ret;
}
/**
* Reads one MORPHFOCALGRADIENT value from the stream
*
* This is undocumented feature
*
* @return MORPHGRADIENT value
* @throws IOException
*/
public MORPHFOCALGRADIENT readMORPHFOCALGRADIENT() throws IOException {
MORPHFOCALGRADIENT ret = new MORPHFOCALGRADIENT();
ret.spreadMode = (int) readUB(2);
ret.interPolationMode = (int) readUB(2);
int numGradients = (int) readUB(4);
ret.gradientRecords = new MORPHGRADRECORD[numGradients];
for (int i = 0; i < numGradients; i++) {
ret.gradientRecords[i] = readMORPHGRADRECORD();
}
ret.startFocalPoint = readFIXED8();
ret.endFocalPoint = readFIXED8();
return ret;
}
/**
* Reads one MORPHFILLSTYLE value from the stream
@@ -2557,7 +2585,8 @@ public class SWFInputStream extends InputStream {
ret.endColor = readRGBA();
}
if ((ret.fillStyleType == MORPHFILLSTYLE.LINEAR_GRADIENT)
|| (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) {
|| (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)
|| (ret.fillStyleType == MORPHFILLSTYLE.FOCAL_RADIAL_GRADIENT)) {
ret.startGradientMatrix = readMatrix();
ret.endGradientMatrix = readMatrix();
}
@@ -2565,6 +2594,9 @@ public class SWFInputStream extends InputStream {
|| (ret.fillStyleType == MORPHFILLSTYLE.RADIAL_GRADIENT)) {
ret.gradient = readMORPHGRADIENT();
}
if(ret.fillStyleType == MORPHFILLSTYLE.FOCAL_RADIAL_GRADIENT){
ret.gradient = readMORPHFOCALGRADIENT();
}
if ((ret.fillStyleType == MORPHFILLSTYLE.REPEATING_BITMAP)
|| (ret.fillStyleType == MORPHFILLSTYLE.CLIPPED_BITMAP)

View File

@@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE;
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT;
import com.jpexs.decompiler.flash.types.MORPHGRADIENT;
import com.jpexs.decompiler.flash.types.MORPHGRADRECORD;
import com.jpexs.decompiler.flash.types.MORPHLINESTYLE;
@@ -1502,6 +1503,26 @@ public class SWFOutputStream extends OutputStream {
writeMORPHGRADRECORD(value.gradientRecords[i]);
}
}
/**
* Writes MORPHFOCALGRADIENT value to the stream
*
* Undocumented feature
*
* @param value MORPHGRADIENT value
* @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,...
* @throws IOException
*/
public void writeMORPHFOCALGRADIENT(MORPHFOCALGRADIENT value, int shapeNum) throws IOException {
writeUB(2, value.spreadMode);
writeUB(2, value.interPolationMode);
writeUB(4, value.gradientRecords.length);
for (int i = 0; i < value.gradientRecords.length; i++) {
writeMORPHGRADRECORD(value.gradientRecords[i]);
}
writeFIXED8(value.startFocalPoint);
writeFIXED8(value.endFocalPoint);
}
/**
* Writes MORPHGRADRECORD value to the stream

View File

@@ -57,6 +57,12 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
protected String lastRadColor = null;
protected int repeatCnt = 0;
protected SWF swf;
protected String lineFillData = null;
protected String lineLastRadColor = null;
protected Matrix lineFillMatrix = null;
protected Matrix lineFillMatrixEnd = null;
protected int lineRepeatCnt = 0;
@@ -132,7 +138,7 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
}
@Override
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
finalizePath();
//TODO: How many repeats is ideal?
@@ -182,7 +188,7 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
fillMatrixEnd = matrixEnd;
fillData += "\tvar grd=ctx.createRadialGradient("+focalPointRatio*16384+",0,0,0,0," + (16384 + 32768 * repeatCnt) + ");\r\n";
fillData += "\tvar grd=ctx.createRadialGradient("+useRatioDouble(focalPointRatio*16384,focalPointRatioEnd*16384)+",0,0,0,0," + (16384 + 32768 * repeatCnt) + ");\r\n";
}
int repeatTotal = repeatCnt * 2 + 1;
double oneHeight = 1.0 / repeatTotal;
@@ -282,8 +288,9 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
finalizePath();
thickness /= unitDivisor;
thicknessEnd /= unitDivisor;
strokeData += "\tctx.strokeStyle=" + useRatioColor(color,colorEnd) + ";\r\n";
if(color!=null){ //for gradient line fill
strokeData += "\tctx.strokeStyle=" + useRatioColor(color,colorEnd) + ";\r\n";
}
strokeData += "\tctx.lineWidth="+useRatioDouble(thickness,thicknessEnd)+";\r\n";
switch (startCaps) {
case LINESTYLE2.NO_CAP:
@@ -311,8 +318,90 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
}
@Override
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
//TODO
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
lineFillData = "";
//TODO: How many repeats is ideal?
final int REPEAT_CNT = 5;
lineRepeatCnt = spreadMethod == GRADIENT.SPREAD_PAD_MODE ? 0 : REPEAT_CNT;
if (type == FILLSTYLE.LINEAR_GRADIENT) {
Point start = matrix.transform(new Point(-16384 - 32768 * repeatCnt, 0));
Point end = matrix.transform(new Point(16384 + 32768 * repeatCnt, 0));
start.x += deltaX;
start.y += deltaY;
end.x += deltaX;
end.y += deltaY;
Point start2 = matrixEnd.transform(new Point(-16384 - 32768 * repeatCnt, 0));
Point end2 = matrixEnd.transform(new Point(16384 + 32768 * repeatCnt, 0));
start2.x += deltaX;
start2.y += deltaY;
end2.x += deltaX;
end2.y += deltaY;
lineFillData += "\tvar grd=ctx.createLinearGradient(" + useRatioPos(start.x, start2.x) + "," + useRatioPos(start.y, start2.y) + "," + useRatioPos(end.x, end2.x) + "," + useRatioPos(end.y, end2.y) + ");\r\n";
} else {
matrix.translateX /= unitDivisor;
matrix.translateY /= unitDivisor;
matrix.scaleX /= unitDivisor;
matrix.scaleY /= unitDivisor;
matrix.rotateSkew0 /= unitDivisor;
matrix.rotateSkew1 /= unitDivisor;
matrix.translateX += deltaX / unitDivisor;
matrix.translateY += deltaY / unitDivisor;
lineFillMatrix = matrix;
matrixEnd.translateX /= unitDivisor;
matrixEnd.translateY /= unitDivisor;
matrixEnd.scaleX /= unitDivisor;
matrixEnd.scaleY /= unitDivisor;
matrixEnd.rotateSkew0 /= unitDivisor;
matrixEnd.rotateSkew1 /= unitDivisor;
matrixEnd.translateX += deltaX / unitDivisor;
matrixEnd.translateY += deltaY / unitDivisor;
lineFillMatrixEnd = matrixEnd;
lineFillData += "\tvar grd=ctx.createRadialGradient("+useRatioDouble(focalPointRatio*16384,focalPointRatioEnd*16384)+",0,0,0,0," + (16384 + 32768 * repeatCnt) + ");\r\n";
}
int repeatTotal = lineRepeatCnt * 2 + 1;
double oneHeight = 1.0 / repeatTotal;
double pos = 0;
boolean revert = false;
if (type != FILLSTYLE.LINEAR_GRADIENT && spreadMethod == GRADIENT.SPREAD_REFLECT_MODE) {
revert = true;
}
for (int i = 0; i < repeatTotal; i++) {
if (spreadMethod == GRADIENT.SPREAD_REFLECT_MODE) {
revert = !revert;
}
for (int j=0;j<gradientRecords.length;j++) {
GRADRECORD r = gradientRecords[j];
GRADRECORD r2 = gradientRecordsEnd[j];
lineFillData += "var s="+useRatioDouble(pos + (oneHeight * (revert ? 255 - r.ratio : r.ratio) / 255.0), pos + (oneHeight * (revert ? 255 - r2.ratio : r2.ratio) / 255.0))+"\r\n";
lineFillData += "if(s<0) s = 0;\r\nif(s>1) s = 1;\r\n";
lineFillData += "\tgrd.addColorStop(s," + useRatioColor(r.color,r2.color) + ");\r\n";
lineLastRadColor = useRatioColor(r.color,r2.color);
}
pos += oneHeight;
}
lineFillData += "\tctx.fillStyle = grd;\r\n";
String preStrokeData = "";
preStrokeData += "var lcanvas = document.createElement(\"canvas\");\r\n";
preStrokeData += "lcanvas.width = canvas.width;\r\nlcanvas.height=canvas.height;\r\n";
preStrokeData += "var lctx = lcanvas.getContext(\"2d\");\r\n";
preStrokeData += "enhanceContext(lctx);\r\n";
preStrokeData += "lctx.applyTransforms(ctx._matrices);\r\n";
preStrokeData += "ctx = lctx;\r\n";
strokeData = preStrokeData + strokeData;
}
@Override
@@ -358,8 +447,47 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
protected void finalizePath() {
if (!"".equals(pathData)) {
pathData = "\tctx.beginPath();\r\n" + pathData + "\tctx.closePath();\r\n" + strokeData;
pathData = "\tctx.beginPath();\r\n" + pathData + "\tctx.closePath();\r\n";
if(lineFillData!=null){
String preLineFillData = "";
preLineFillData += "var oldctx = ctx;\r\n";
preLineFillData += "ctx.save();\r\n";
preLineFillData += strokeData;
preLineFillData += pathData;
preLineFillData += "ctx.stroke();\r\n";
preLineFillData += "var lfcanvas = document.createElement(\"canvas\");\r\n";
preLineFillData += "lfcanvas.width = canvas.width;\r\nlfcanvas.height=canvas.height;\r\n";
preLineFillData += "var lfctx = lfcanvas.getContext(\"2d\");\r\n";
preLineFillData += "enhanceContext(lfctx);\r\n";
preLineFillData += "lfctx.applyTransforms(ctx._matrices);\r\n";
preLineFillData += "ctx = lfctx;";
if (lineLastRadColor != null) {
preLineFillData += "\tctx.fillStyle=" + lineLastRadColor + ";\r\n ctx.fill(\"evenodd\");\r\n";
}
preLineFillData += "\tctx.transform(" + useRatioDouble(lineFillMatrix.scaleX,lineFillMatrixEnd.scaleX) + "," + useRatioDouble(lineFillMatrix.rotateSkew0,lineFillMatrixEnd.rotateSkew0) + "," + useRatioDouble(lineFillMatrix.rotateSkew1,lineFillMatrixEnd.rotateSkew1) + "," + useRatioDouble(lineFillMatrix.scaleY,lineFillMatrixEnd.scaleY) + "," + useRatioDouble(lineFillMatrix.translateX,lineFillMatrixEnd.translateX) + "," + useRatioDouble(lineFillMatrix.translateY,lineFillMatrixEnd.translateY) + ");\r\n";
lineFillData = preLineFillData + lineFillData;
lineFillData += "\tctx.fillRect(" + (-16384 - 32768 * lineRepeatCnt) + "," + (-16384 - 32768 * lineRepeatCnt) + "," + (2 * 16384 + 32768 * 2 * lineRepeatCnt) + "," + (2 * 16384 + 32768 * 2 * lineRepeatCnt) + ");\r\n";
lineFillData += "\tctx = oldctx;\r\n";
//lcanvas - stroke
//lfcanvas - stroke background
lineFillData += "var limgd = lctx.getImageData(0, 0, lcanvas.width, lcanvas.height);\r\n"
+ "var lpix = limgd.data;\r\n"
+ "var lfimgd = lfctx.getImageData(0, 0, lfcanvas.width, lfcanvas.height);\r\n"
+ "var lfpix = lfimgd.data;\r\n"
+ "var imgd = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n"
+ "var pix = imgd.data;\r\n"
+ "for (var i = 0; i < lpix.length; i += 4) {\r\n" +
" if(lpix[i+3]>0){ pix[i] = lfpix[i]; pix[i+1] = lfpix[i+1]; pix[i+2] = lfpix[i+2]; pix[i+3] = lfpix[i+3];}\r\n" +
"}\r\n"
+ "ctx.putImageData(imgd, 0, 0);\r\n";
lineFillData += "ctx.restore();\r\n";
strokeData = "";
}else{
pathData += strokeData;
}
if (fillMatrix != null) {
if (lastRadColor != null) {
pathData += "\tctx.fillStyle=" + lastRadColor + ";\r\n\tctx.fill(\"evenodd\");\r\n";
@@ -379,6 +507,8 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
}
if (!"".equals(strokeData)) {
shapeData += "\tctx.stroke();\r\n";
}else if(lineFillData!=null){
shapeData += lineFillData;
}
}
@@ -389,6 +519,12 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
fillMatrix = null;
fillMatrixEnd = null;
lastRadColor = null;
lineRepeatCnt = 0;
lineFillData = null;
lineLastRadColor = null;
lineFillMatrix = null;
lineFillMatrixEnd = null;
}
private String useRatioPos(double a, double b){

View File

@@ -71,7 +71,7 @@ public abstract class DefaultSVGMorphShapeExporter extends MorphShapeExporterBas
}
@Override
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
finalizePath();
}
@@ -91,7 +91,7 @@ public abstract class DefaultSVGMorphShapeExporter extends MorphShapeExporterBas
}
@Override
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
}
@Override

View File

@@ -41,7 +41,7 @@ public interface IMorphShapeExporter {
public void beginFill(RGB color, RGB colorEnd);
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio);
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd);
public void beginBitmapFill(int bitmapId, Matrix matrix, Matrix matrixEnd, boolean repeat, boolean smooth, ColorTransform colorTransform);
@@ -49,7 +49,7 @@ public interface IMorphShapeExporter {
public void lineStyle(double thickness, double thicknessEnd, RGB color, RGB colorEnd, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit);
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio);
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd);
public void moveTo(double x, double y, double x2, double y2);

View File

@@ -321,7 +321,8 @@ public abstract class MorphShapeExporterBase implements IMorphShapeExporter {
matrixEnd,
fillStyle.gradient.spreadMode,
fillStyle.gradient.interpolationMode,
(fillStyle.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyle.gradient).focalPoint : 0
(fillStyle.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyle.gradient).focalPoint : 0,
(fillStyleEnd.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyleEnd.gradient).focalPoint : 0
);
break;
case FILLSTYLE.REPEATING_BITMAP:
@@ -430,7 +431,7 @@ public abstract class MorphShapeExporterBase implements IMorphShapeExporter {
case FILLSTYLE.FOCAL_RADIAL_GRADIENT:
// Gradient fill
Matrix matrix = new Matrix(fillStyle.gradientMatrix);
Matrix matrixEnd = new Matrix(fillStyleEnd.gradientMatrix);
Matrix matrixEnd = new Matrix(fillStyleEnd.gradientMatrix);
lineGradientStyle(
fillStyle.fillStyleType,
fillStyle.gradient.gradientRecords,
@@ -439,7 +440,8 @@ public abstract class MorphShapeExporterBase implements IMorphShapeExporter {
matrixEnd,
fillStyle.gradient.spreadMode,
fillStyle.gradient.interpolationMode,
(fillStyle.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyle.gradient).focalPoint : 0
(fillStyle.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyle.gradient).focalPoint : 0,
(fillStyleEnd.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyleEnd.gradient).focalPoint : 0
);
break;
}

View File

@@ -83,7 +83,7 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
}
@Override
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
finalizePath();
Element gradient = (type == FILLSTYLE.LINEAR_GRADIENT)
? exporter.createElement("linearGradient")
@@ -213,7 +213,7 @@ public class SVGMorphShapeExporter extends DefaultSVGMorphShapeExporter {
}
@Override
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio) {
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, GRADRECORD[] gradientRecordsEnd, Matrix matrix, Matrix matrixEnd, int spreadMethod, int interpolationMethod, float focalPointRatio, float focalPointRatioEnd) {
path.removeAttribute("stroke-opacity");
Element gradient = (type == FILLSTYLE.LINEAR_GRADIENT)
? exporter.createElement("linearGradient")

View File

@@ -506,12 +506,14 @@ public class CanvasShapeExporter extends ShapeExporterBase {
}
repeatCnt = 0;
lineRepeatCnt = 0;
pathData = "";
fillData = "";
strokeData = "";
fillMatrix = null;
lastRadColor = null;
lineRepeatCnt = 0;
lineFillData = null;
lineLastRadColor = null;
lineFillMatrix = null;

View File

@@ -236,7 +236,7 @@ public class DefineFont2Tag extends FontTag {
glyphShapeTable = new ArrayList<>();
for (int i = 0; i < numGlyphs; i++) {
glyphShapeTable.add(sis.readSHAPE(1));
glyphShapeTable.add(sis.readSHAPE(1,false));
}
codeTable = new ArrayList<>(); //[numGlyphs];

View File

@@ -146,7 +146,7 @@ public class DefineFont3Tag extends FontTag {
}
glyphShapeTable = new ArrayList<>();
for (int i = 0; i < numGlyphs; i++) {
glyphShapeTable.add(sis.readSHAPE(1));
glyphShapeTable.add(sis.readSHAPE(1, false));
}
codeTable = new ArrayList<>();
for (int i = 0; i < numGlyphs; i++) {

View File

@@ -155,7 +155,7 @@ public class DefineFontTag extends FontTag {
sis.readUI16(); //offset
}
for (int i = 0; i < nGlyphs; i++) {
glyphShapeTable.add(sis.readSHAPE(1));
glyphShapeTable.add(sis.readSHAPE(1, false));
}
}

View File

@@ -127,11 +127,11 @@ public class DefineMorphShape2Tag extends CharacterTag implements MorphShapeTag
SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion());
sos2.writeMORPHFILLSTYLEARRAY(morphFillStyles, 2);
sos2.writeMORPHLINESTYLEARRAY(morphLineStyles, 2);
sos2.writeSHAPE(startEdges, 1);
sos2.writeSHAPE(startEdges, 2);
byte[] ba2 = baos2.toByteArray();
sos.writeUI32(ba2.length);
sos.write(ba2);
sos.writeSHAPE(endEdges, 1);
sos.writeSHAPE(endEdges, 2);
} catch (IOException e) {
}
return baos.toByteArray();
@@ -160,8 +160,8 @@ public class DefineMorphShape2Tag extends CharacterTag implements MorphShapeTag
long offset = sis.readUI32();
morphFillStyles = sis.readMORPHFILLSTYLEARRAY();
morphLineStyles = sis.readMORPHLINESTYLEARRAY(2);
startEdges = sis.readSHAPE(1);
endEdges = sis.readSHAPE(1);
startEdges = sis.readSHAPE(2,true);
endEdges = sis.readSHAPE(2,true);
}
@Override

View File

@@ -133,8 +133,8 @@ public class DefineMorphShapeTag extends CharacterTag implements MorphShapeTag {
long offset = sis.readUI32(); //ignore
morphFillStyles = sis.readMORPHFILLSTYLEARRAY();
morphLineStyles = sis.readMORPHLINESTYLEARRAY(1);
startEdges = sis.readSHAPE(1);
endEdges = sis.readSHAPE(1);
startEdges = sis.readSHAPE(1,true);
endEdges = sis.readSHAPE(1,true);
}
@Override

View File

@@ -65,7 +65,7 @@ public class DefineShape2Tag extends ShapeTag {
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version);
shapeId = sis.readUI16();
shapeBounds = sis.readRECT();
shapes = sis.readSHAPEWITHSTYLE(2);
shapes = sis.readSHAPEWITHSTYLE(2,false);
}
@Override

View File

@@ -65,7 +65,7 @@ public class DefineShape3Tag extends ShapeTag {
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version);
shapeId = sis.readUI16();
shapeBounds = sis.readRECT();
shapes = sis.readSHAPEWITHSTYLE(3);
shapes = sis.readSHAPEWITHSTYLE(3,false);
}
@Override

View File

@@ -78,7 +78,7 @@ public class DefineShape4Tag extends ShapeTag {
usesFillWindingRule = sis.readUB(1) == 1;
usesNonScalingStrokes = sis.readUB(1) == 1;
usesScalingStrokes = sis.readUB(1) == 1;
shapes = sis.readSHAPEWITHSTYLE(4);
shapes = sis.readSHAPEWITHSTYLE(4,false);
}
@Override

View File

@@ -62,7 +62,7 @@ public class DefineShapeTag extends ShapeTag {
SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), swf.version);
shapeId = sis.readUI16();
shapeBounds = sis.readRECT();
shapes = sis.readSHAPEWITHSTYLE(1);
shapes = sis.readSHAPEWITHSTYLE(1,false);
}
/**

View File

@@ -34,7 +34,8 @@ public class MORPHFILLSTYLE implements NeedsCharacters, Serializable {
public static final int SOLID = 0x0;
public static final int LINEAR_GRADIENT = 0x10;
public static final int RADIAL_GRADIENT = 0x12;
public static final int RADIAL_GRADIENT = 0x12;
public static final int FOCAL_RADIAL_GRADIENT = 0x13;
public static final int REPEATING_BITMAP = 0x40;
public static final int CLIPPED_BITMAP = 0x41;
public static final int NON_SMOOTHED_REPEATING_BITMAP = 0x42;
@@ -54,7 +55,7 @@ public class MORPHFILLSTYLE implements NeedsCharacters, Serializable {
@Conditional(value = "fillStyleType", options = {LINEAR_GRADIENT, RADIAL_GRADIENT})
public MORPHGRADIENT gradient;
@Conditional(value = "fillStyleType", options = {CLIPPED_BITMAP, NON_SMOOTHED_REPEATING_BITMAP, NON_SMOOTHED_CLIPPED_BITMAP})
public int bitmapId;

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.types;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import java.io.Serializable;
/**
* Well, this structure is undocumented, but exists
* @author JPEXS
*/
public class MORPHFOCALGRADIENT extends MORPHGRADIENT implements Serializable {
@SWFType(BasicType.FIXED8)
public float startFocalPoint;
@SWFType(BasicType.FIXED8)
public float endFocalPoint;
@Override
public GRADIENT getGradientAt(int ratio) {
FOCALGRADIENT ret = new FOCALGRADIENT();
ret.gradientRecords = new GRADRECORD[gradientRecords.length];
for (int m = 0; m < gradientRecords.length; m++) {
int gratio = (gradientRecords[m].startRatio + (gradientRecords[m].endRatio - gradientRecords[m].startRatio) * ratio / 65535);
ret.gradientRecords[m] = new GRADRECORD();
ret.gradientRecords[m].color = morphColor(gradientRecords[m].startColor, gradientRecords[m].endColor, ratio);
ret.gradientRecords[m].ratio = gratio;
}
ret.focalPoint = (startFocalPoint + (endFocalPoint - startFocalPoint) * ratio / 65535);
return ret;
}
}

View File

@@ -78,10 +78,11 @@ public class MORPHLINESTYLE2 implements Serializable {
ret.pixelHintingFlag = pixelHintingFlag;
ret.noClose = noClose;
ret.endCapStyle = endCapStyle;
ret.miterLimitFactor = miterLimitFactor;
ret.color = MORPHGRADIENT.morphColor(startColor, endColor, ratio);
ret.miterLimitFactor = miterLimitFactor;
if (hasFillFlag) {
ret.fillType = fillType.getFillStyleAt(ratio);
}else{
ret.color = MORPHGRADIENT.morphColor(startColor, endColor, ratio);
}
return ret;
}

View File

@@ -20,8 +20,11 @@ import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY;
import com.jpexs.decompiler.flash.types.annotations.Calculated;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import java.util.Set;
import java.util.logging.Level;
@@ -67,7 +70,7 @@ public class StyleChangeRecord extends SHAPERECORD implements Cloneable {
@Conditional("stateNewStyles")
public FILLSTYLEARRAY fillStyles;
@Conditional("stateNewStyles")
public LINESTYLEARRAY lineStyles;