mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-31 11:44:36 +00:00
stroke scaling modes for canvas export
This commit is contained in:
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.morphshape;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -39,6 +40,10 @@ import com.jpexs.helpers.SerializableImage;
|
||||
*/
|
||||
public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
|
||||
|
||||
protected static final String DRAW_COMMAND_M = "M";
|
||||
protected static final String DRAW_COMMAND_L = "L";
|
||||
protected static final String DRAW_COMMAND_Q = "Q";
|
||||
protected String currentDrawCommand = "";
|
||||
protected double deltaX = 0;
|
||||
protected double deltaY = 0;
|
||||
protected String pathData = "";
|
||||
@@ -262,8 +267,9 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
|
||||
@Override
|
||||
public void lineStyle(double thickness, double thicknessEnd, RGB color, RGB colorEnd, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) {
|
||||
finalizePath();
|
||||
finalizePath();
|
||||
thickness /= unitDivisor;
|
||||
thickness /= SWF.unitDivisor;
|
||||
thicknessEnd /= SWF.unitDivisor;
|
||||
strokeData += "\tvar scaleMode = \""+scaleMode+"\";\r\n";
|
||||
if (color != null) { //for gradient line fill
|
||||
strokeData += "\tctx.strokeStyle=" + useRatioColor(color, colorEnd) + ";\r\n";
|
||||
}
|
||||
@@ -370,35 +376,43 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
|
||||
preStrokeData += "\tlcanvas.height=canvas.height;\r\n";
|
||||
preStrokeData += "\tvar lctx = lcanvas.getContext(\"2d\");\r\n";
|
||||
preStrokeData += "\tenhanceContext(lctx);\r\n";
|
||||
preStrokeData += "\tenhanceContext(lctx);\r\n";
|
||||
preStrokeData += "\tlctx.applyTransforms(ctx._matrix);\r\n";
|
||||
preStrokeData += "\tctx = lctx;\r\n";
|
||||
strokeData = preStrokeData + strokeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveTo(double x, double y, double x2, double y2) {
|
||||
currentDrawCommand = DRAW_COMMAND_M;
|
||||
pathData += currentDrawCommand + " ";
|
||||
x += deltaX;
|
||||
y += deltaY;
|
||||
x2 += deltaX;
|
||||
y2 += deltaY;
|
||||
y2 += deltaY;
|
||||
pathData += "\tctx.moveTo("
|
||||
+ useRatioPos(x, x2) + ","
|
||||
pathData += Helper.doubleStr(x/unitDivisor) + " " + Helper.doubleStr(x2/unitDivisor) + " "
|
||||
+ Helper.doubleStr(y/unitDivisor) + " " + Helper.doubleStr(y2/unitDivisor) + " ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineTo(double x, double y, double x2, double y2) {
|
||||
if (!currentDrawCommand.equals(DRAW_COMMAND_L)) {
|
||||
currentDrawCommand = DRAW_COMMAND_L;
|
||||
pathData += currentDrawCommand + " ";
|
||||
}
|
||||
x += deltaX;
|
||||
y += deltaY;
|
||||
x2 += deltaX;
|
||||
y2 += deltaY;
|
||||
y2 += deltaY;
|
||||
pathData += "\tctx.lineTo("
|
||||
+ useRatioPos(x, x2) + ","
|
||||
pathData += Helper.doubleStr(x/unitDivisor) + " " + Helper.doubleStr(x2/unitDivisor) + " "
|
||||
+ Helper.doubleStr(y/unitDivisor) + " " + Helper.doubleStr(y2/unitDivisor) + " ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void curveTo(double controlX, double controlY, double anchorX, double anchorY, double controlX2, double controlY2, double anchorX2, double anchorY2) {
|
||||
if (!currentDrawCommand.equals(DRAW_COMMAND_Q)) {
|
||||
currentDrawCommand = DRAW_COMMAND_Q;
|
||||
pathData += currentDrawCommand + " ";
|
||||
}
|
||||
controlX += deltaX;
|
||||
anchorX += deltaX;
|
||||
controlY += deltaY;
|
||||
@@ -409,28 +423,29 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
|
||||
controlY2 += deltaY;
|
||||
anchorY2 += deltaY;
|
||||
|
||||
|
||||
pathData += "\tctx.quadraticCurveTo(" + useRatioPos(controlX, controlX2) + ","
|
||||
+ useRatioPos(controlY, controlY2) + ","
|
||||
+ useRatioPos(anchorX, anchorX2) + ","
|
||||
pathData += Helper.doubleStr(controlX/unitDivisor) + " " + Helper.doubleStr(controlX2/unitDivisor) + " " +
|
||||
Helper.doubleStr(controlY/unitDivisor) + " " + Helper.doubleStr(controlY2/unitDivisor) + " " +
|
||||
Helper.doubleStr(anchorX/unitDivisor) + " " + Helper.doubleStr(anchorX2/unitDivisor) + " " +
|
||||
Helper.doubleStr(anchorY/unitDivisor) + " " + Helper.doubleStr(anchorY2/unitDivisor) + " ";
|
||||
}
|
||||
|
||||
protected void finalizePath() {
|
||||
if (!"".equals(pathData)) {
|
||||
if (!"".equals(pathData)) {
|
||||
String drawStroke = "\tdrawMorphPath(ctx,\"" + pathData.trim() + "\",ratio,true,scaleMode);\r\n";
|
||||
String drawFill = "\tdrawMorphPath(ctx,\"" + pathData.trim() + "\",ratio,false);\r\n";;
|
||||
pathData = "";
|
||||
if (lineFillData != null) {
|
||||
String preLineFillData = "";
|
||||
preLineFillData += "\tvar oldctx = ctx;\r\n";
|
||||
preLineFillData += "\tctx.save();\r\n";
|
||||
preLineFillData += strokeData;
|
||||
preLineFillData += strokeData;
|
||||
preLineFillData += pathData;
|
||||
preLineFillData += drawStroke;
|
||||
preLineFillData += "\tvar lfcanvas = document.createElement(\"canvas\");\r\n";
|
||||
preLineFillData += "\tlfcanvas.width = canvas.width;\r\n";
|
||||
preLineFillData += "\tlfcanvas.height = canvas.height;\r\n";
|
||||
preLineFillData += "\tvar lfctx = lfcanvas.getContext(\"2d\");\r\n";
|
||||
preLineFillData += "\tenhanceContext(lfctx);\r\n";
|
||||
preLineFillData += "\tenhanceContext(lfctx);\r\n";
|
||||
preLineFillData += "\tlfctx.applyTransforms(ctx._matrix);\r\n";
|
||||
preLineFillData += "\tctx = lfctx;";
|
||||
if (lineLastRadColor != null) {
|
||||
preLineFillData += "\tctx.fillStyle=" + lineLastRadColor + ";\r\n ctx.fill(\"evenodd\");\r\n";
|
||||
@@ -479,12 +494,12 @@ public class CanvasMorphShapeExporter extends MorphShapeExporterBase {
|
||||
shapeData += pathData;
|
||||
} else {
|
||||
if (!"".equals(fillData)) {
|
||||
if (!"".equals(fillData)) {
|
||||
pathData += drawFill + "\r\n\tctx.fill(\"evenodd\");\r\n";
|
||||
}
|
||||
shapeData += fillData + pathData;
|
||||
}
|
||||
if (!"".equals(strokeData)) {
|
||||
if (!"".equals(strokeData)) {
|
||||
shapeData += drawStroke+"\r\n"; //"\tctx.stroke();\r\n";
|
||||
} else if (lineFillData != null) {
|
||||
shapeData += lineFillData;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.morphshape;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
@@ -396,9 +397,9 @@ public abstract class MorphShapeExporterBase implements IMorphShapeExporter {
|
||||
if (lineStyle2.noHScaleFlag && lineStyle2.noVScaleFlag) {
|
||||
scaleMode = "NONE";
|
||||
} else if (lineStyle2.noHScaleFlag) {
|
||||
} else if (lineStyle2.noHScaleFlag) {
|
||||
scaleMode = "HORIZONTAL";
|
||||
scaleMode = "VERTICAL";
|
||||
} else if (lineStyle2.noVScaleFlag) {
|
||||
scaleMode = "HORIZONTAL";
|
||||
}
|
||||
pixelHintingFlag = lineStyle2.pixelHintingFlag;
|
||||
startCapStyle = lineStyle2.startCapStyle;
|
||||
|
||||
@@ -286,7 +286,8 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
@Override
|
||||
public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) {
|
||||
finalizePath();
|
||||
thickness /= unitDivisor;
|
||||
thickness /= SWF.unitDivisor;
|
||||
strokeData += "\tvar scaleMode = \""+scaleMode+"\";\r\n";
|
||||
|
||||
if (color != null) { //gradient lines have no color
|
||||
strokeData += "\tctx.strokeStyle=" + color(color) + ";\r\n";
|
||||
@@ -374,7 +375,7 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
preStrokeData += "\tlcanvas.height=canvas.height;\r\n";
|
||||
preStrokeData += "\tvar lctx = lcanvas.getContext(\"2d\");\r\n";
|
||||
preStrokeData += "\tenhanceContext(lctx);\r\n";
|
||||
preStrokeData += "\tlctx.applyTransforms(ctx._matrices);\r\n";
|
||||
preStrokeData += "\tlctx.applyTransforms(ctx._matrix);\r\n";
|
||||
preStrokeData += "\tctx = lctx;\r\n";
|
||||
strokeData = preStrokeData + strokeData;
|
||||
}
|
||||
@@ -419,21 +420,21 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
|
||||
protected void finalizePath() {
|
||||
if (!"".equals(pathData)) {
|
||||
pathData = "\tdrawPath(ctx,\"" + pathData + "\");\r\n";
|
||||
|
||||
String drawStroke = "\tdrawPath(ctx,\"" + pathData.trim() + "\",true,scaleMode);\r\n";
|
||||
String drawFill = "\tdrawPath(ctx,\"" + pathData.trim() + "\",false);\r\n";;
|
||||
pathData = "";
|
||||
if (lineFillData != null) {
|
||||
String preLineFillData = "";
|
||||
preLineFillData += "\tvar oldctx = ctx;\r\n";
|
||||
preLineFillData += "\tctx.save();\r\n";
|
||||
preLineFillData += strokeData;
|
||||
preLineFillData += pathData;
|
||||
preLineFillData += "\tctx.stroke();\r\n";
|
||||
preLineFillData += drawStroke;
|
||||
preLineFillData += "\tvar lfcanvas = document.createElement(\"canvas\");\r\n";
|
||||
preLineFillData += "\tlfcanvas.width = canvas.width;\r\n";
|
||||
preLineFillData += "\tlfcanvas.height=canvas.height;\r\n";
|
||||
preLineFillData += "\tvar lfctx = lfcanvas.getContext(\"2d\");\r\n";
|
||||
preLineFillData += "\tenhanceContext(lfctx);\r\n";
|
||||
preLineFillData += "\tlfctx.applyTransforms(ctx._matrices);\r\n";
|
||||
preLineFillData += "\tlfctx.applyTransforms(ctx._matrix);\r\n";
|
||||
preLineFillData += "\tctx = lfctx;";
|
||||
if (lineLastRadColor != null) {
|
||||
preLineFillData += "\tctx.fillStyle=" + lineLastRadColor + ";\r\n\tctx.fill(\"evenodd\");\r\n";
|
||||
@@ -482,12 +483,12 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
shapeData += pathData;
|
||||
} else {
|
||||
if (!"".equals(fillData)) {
|
||||
pathData += "\tctx.fill(\"evenodd\");\r\n";
|
||||
pathData += drawFill + "\tctx.fill(\"evenodd\");\r\n";
|
||||
}
|
||||
shapeData += fillData + pathData;
|
||||
}
|
||||
if (!"".equals(strokeData)) {
|
||||
shapeData += "\tctx.stroke();\r\n";
|
||||
shapeData += drawStroke +"\r\n";
|
||||
} else if (lineFillData != null) {
|
||||
shapeData += lineFillData;
|
||||
}
|
||||
|
||||
@@ -771,17 +771,37 @@ BlendModes.blendCanvas = function(src, dst, result, modeIndex) {
|
||||
};
|
||||
|
||||
|
||||
function concatMatrix(m1,m2) {
|
||||
var result= [1,0,0,1,0,0];
|
||||
var scaleX = 0;
|
||||
var rotateSkew0 = 1;
|
||||
var rotateSkew1= 2;
|
||||
var scaleY = 3;
|
||||
var translateX = 4;
|
||||
var translateY = 5;
|
||||
|
||||
result[scaleX] = m2[scaleX] * m1[scaleX] + m2[rotateSkew1] * m1[rotateSkew0];
|
||||
result[rotateSkew0] = m2[rotateSkew0] * m1[scaleX] + m2[scaleY] * m1[rotateSkew0];
|
||||
result[rotateSkew1] = m2[scaleX] * m1[rotateSkew1] + m2[rotateSkew1] * m1[scaleY];
|
||||
result[scaleY] = m2[rotateSkew0] * m1[rotateSkew1] + m2[scaleY] * m1[scaleY];
|
||||
result[translateX] = m2[scaleX] * m1[translateX] + m2[rotateSkew1] * m1[translateY] + m2[translateX];
|
||||
result[translateY] = m2[rotateSkew0] * m1[translateX] + m2[scaleY] * m1[translateY] + m2[translateY];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
var enhanceContext = function(context) {
|
||||
var m = [1, 0, 0, 1, 0, 0];
|
||||
context._matrices = [m];
|
||||
context._matrix = m;
|
||||
|
||||
//the stack of saved matrices
|
||||
context._savedMatrices = [[m]];
|
||||
context._savedMatrices = [m]; //[[m]];
|
||||
|
||||
var super_ = context.__proto__;
|
||||
context.__proto__ = ({
|
||||
save: function() {
|
||||
this._savedMatrices.push(this._matrices.slice());
|
||||
this._savedMatrices.push(this._matrix); //.slice()
|
||||
super_.save.call(this);
|
||||
},
|
||||
//if the stack of matrices we're managing doesn't have a saved matrix,
|
||||
@@ -790,7 +810,7 @@ var enhanceContext = function(context) {
|
||||
if (this._savedMatrices.length == 0)
|
||||
return;
|
||||
super_.restore.call(this);
|
||||
this._matrices = this._savedMatrices.pop();
|
||||
this._matrix = this._savedMatrices.pop();
|
||||
},
|
||||
scale: function(x, y) {
|
||||
super_.scale.call(this, x, y);
|
||||
@@ -802,22 +822,24 @@ var enhanceContext = function(context) {
|
||||
super_.translate.call(this, x, y);
|
||||
},
|
||||
transform: function(a, b, c, d, e, f) {
|
||||
this._matrices.push([a, b, c, d, e, f]);
|
||||
this._matrix = concatMatrix(this._matrix,[a,b,c,d,e,f]);
|
||||
super_.transform.call(this, a, b, c, d, e, f);
|
||||
},
|
||||
setTransform: function(a, b, c, d, e, f) {
|
||||
this._matrices = [];
|
||||
this._matrices.push([a, b, c, d, e, f]);
|
||||
this._matrix = [a, b, c, d, e, f];
|
||||
super_.setTransform.call(this, a, b, c, d, e, f);
|
||||
},
|
||||
resetTransform: function() {
|
||||
super_.resetTransform.call(this);
|
||||
},
|
||||
applyTransforms: function(m) {
|
||||
this.setTransform(1, 0, 0, 1, 0, 0);
|
||||
for (var i = 0; i < m.length; i++) {
|
||||
this.transform(m[i][0], m[i][1], m[i][2], m[i][3], m[i][4], m[i][5]);
|
||||
}
|
||||
this.setTransform(m[0], m[1], m[2], m[3], m[4], m[5])
|
||||
},
|
||||
applyTransformToPoint: function(p){
|
||||
var ret = {};
|
||||
ret.x = this._matrix[0]*p.x + this._matrix[1]*p.y + this._matrix[4];
|
||||
ret.y = this._matrix[2]*p.x + this._matrix[3]*p.y + this._matrix[5];
|
||||
return ret;
|
||||
},
|
||||
__proto__: super_
|
||||
});
|
||||
@@ -964,10 +986,116 @@ function stopDrag(e) {
|
||||
}
|
||||
|
||||
|
||||
function drawPath(ctx, p) {
|
||||
ctx.beginPath();
|
||||
function drawMorphPath(ctx, p, ratio, doStroke, scaleMode){
|
||||
var parts = p.split(" ");
|
||||
var len = parts.length;
|
||||
if(doStroke){
|
||||
for (var i = 0; i < len; i++) {
|
||||
switch(parts[i]){
|
||||
case '':
|
||||
break;
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'Q':
|
||||
break;
|
||||
default:
|
||||
var k = ctx.applyTransformToPoint({x:parts[i],y:parts[i+2]}); parts[i] = k.x; parts[i+2] = k.y;
|
||||
k = ctx.applyTransformToPoint({x:parts[i+1],y:parts[i+3]}); parts[i+1] = k.x; parts[i+3] = k.y;
|
||||
i+=3;
|
||||
}
|
||||
}
|
||||
|
||||
switch(scaleMode){
|
||||
case "NONE":
|
||||
break;
|
||||
case "NORMAL":
|
||||
ctx.lineWidth*=20*Math.max(ctx._matrix[0],ctx._matrix[3]);
|
||||
break;
|
||||
case "VERTICAL":
|
||||
ctx.lineWidth*=20*ctx._matrix[3];
|
||||
break;
|
||||
case "HORIZONTAL":
|
||||
ctx.lineWidth*=20*ctx._matrix[0];
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.setTransform(1,0,0,1,0,0);
|
||||
}
|
||||
ctx.beginPath();
|
||||
var drawCommand = "";
|
||||
for (var i = 0; i < len; i++) {
|
||||
switch (parts[i]) {
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'Q':
|
||||
drawCommand = parts[i];
|
||||
break;
|
||||
default:
|
||||
switch (drawCommand) {
|
||||
case 'L':
|
||||
ctx.lineTo(useRatio(parts[i],parts[i+1],ratio), useRatio(parts[i + 2],parts[i + 3],ratio));
|
||||
i += 3;
|
||||
break;
|
||||
case 'M':
|
||||
ctx.moveTo(useRatio(parts[i],parts[i+1],ratio), useRatio(parts[i + 2],parts[i + 3],ratio));
|
||||
i += 3;
|
||||
break;
|
||||
case 'Q':
|
||||
ctx.quadraticCurveTo(useRatio(parts[i],parts[i+1],ratio),useRatio(parts[i+2],parts[i+3],ratio),
|
||||
useRatio(parts[i+4],parts[i+5],ratio),useRatio(parts[i+6],parts[i+7],ratio));
|
||||
i += 7;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(doStroke){
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
function useRatio(v1,v2,ratio){
|
||||
return v1*1+(v2-v1)*ratio/65535;
|
||||
}
|
||||
|
||||
function drawPath(ctx, p, doStroke, scaleMode) {
|
||||
var parts = p.split(" ");
|
||||
var len = parts.length;
|
||||
if(doStroke){
|
||||
for (var i = 0; i < len; i++) {
|
||||
switch(parts[i]){
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'Q':
|
||||
break;
|
||||
default:
|
||||
var k = ctx.applyTransformToPoint({x:parts[i],y:parts[i+1]});
|
||||
parts[i] = k.x;
|
||||
parts[i+1] = k.y;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
switch(scaleMode){
|
||||
case "NONE":
|
||||
break;
|
||||
case "NORMAL":
|
||||
ctx.lineWidth*=20*Math.max(ctx._matrix[0],ctx._matrix[3]);
|
||||
break;
|
||||
case "VERTICAL":
|
||||
ctx.lineWidth*=20*ctx._matrix[3];
|
||||
break;
|
||||
case "HORIZONTAL":
|
||||
ctx.lineWidth*=20*ctx._matrix[0];
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.setTransform(1,0,0,1,0,0);
|
||||
}
|
||||
ctx.beginPath();
|
||||
var drawCommand = "";
|
||||
for (var i = 0; i < len; i++) {
|
||||
switch (parts[i]) {
|
||||
@@ -994,4 +1122,8 @@ function drawPath(ctx, p) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(doStroke){
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user