Canvas export: Background color, Blend modes (no Layer yet)

This commit is contained in:
Jindra Petk
2014-05-02 23:01:34 +02:00
parent f92d25a1b1
commit 6925b7d6d9
3 changed files with 188 additions and 6 deletions

View File

@@ -1509,8 +1509,20 @@ public final class SWF implements TreeItem, Timelined {
fos.write(Utf8Helper.getBytes("frames.push(" + i + ");\r\n"));
}
fos.write(Utf8Helper.getBytes("\r\n"));
RGB backgroundColor = new RGB(255,255,255);
for(Tag t:fswf.tags){
if(t instanceof SetBackgroundColorTag){
SetBackgroundColorTag sb=(SetBackgroundColorTag)t;
backgroundColor = sb.backgroundColor;
}
}
fos.write(Utf8Helper.getBytes("var backgroundColor = \""+backgroundColor.toHexRGB()+"\";\r\n"));
fos.write(Utf8Helper.getBytes("function nextFrame(ctx,ctrans){\r\n"));
fos.write(Utf8Helper.getBytes("\tctx.clearRect(0,0," + width + "," + height + ");\r\n"));
//fos.write(Utf8Helper.getBytes("\tctx.clearRect(0,0," + width + "," + height + ");\r\n"));
fos.write(Utf8Helper.getBytes("\tctx.fillStyle = backgroundColor;\r\n"));
fos.write(Utf8Helper.getBytes("\tctx.fillRect(0,0," + width + "," + height + ");\r\n"));
fos.write(Utf8Helper.getBytes("\tframe = (frame+1)%frames.length;\r\n"));
fos.write(Utf8Helper.getBytes("\t" + currentName + "(ctx,ctrans,frames[frame],0);\r\n"));
fos.write(Utf8Helper.getBytes("}\r\n\r\n"));
@@ -2297,12 +2309,12 @@ public final class SWF implements TreeItem, Timelined {
ctrans.getRedMulti()+","+ctrans.getGreenMulti()+","+ctrans.getBlueMulti()+","+ctrans.getAlphaMulti()
+"))";
}
sb.append("\t\t\t").append("place(\"").append(getTypePrefix(character)).append(layer.characterId).append("\",canvas,ctx,[").append(placeMatrix.scaleX).append(",")
sb.append("\t\t\tplace(\"").append(getTypePrefix(character)).append(layer.characterId).append("\",canvas,ctx,[").append(placeMatrix.scaleX).append(",")
.append(placeMatrix.rotateSkew0).append(",")
.append(placeMatrix.rotateSkew1).append(",")
.append(placeMatrix.scaleY).append(",")
.append(placeMatrix.translateX).append(",")
.append(placeMatrix.translateY).append("],").append(ctrans_str).append(",").append(f).append(",").append(layer.ratio < 0 ? 0 : layer.ratio).append(");\r\n");
.append(placeMatrix.translateY).append("],").append(ctrans_str).append(",").append(""+(layer.blendMode<1?1:layer.blendMode)).append(",").append(f).append(",").append(layer.ratio < 0 ? 0 : layer.ratio).append(");\r\n");
if(layer.filters!=null){
for(FILTER filter:layer.filters){

View File

@@ -164,10 +164,21 @@ public class CanvasShapeExporter extends ShapeExporterBase {
+ "this.isEmpty = function(){return this.r_add==0 && this.g_add==0 && this.b_add==0 && this.a_add==0 && this.r_mult==255 && this.g_mult==255 && this.b_mult==255 && this.a_mult==255};"
+ "};\r\n"
+ "\r\n"
+ "var place = function(obj,canvas,ctx,matrix,ctrans,frame,ratio){\r\n"
+ "\tctx.save();\r\n"
+ "\tctx.transform(matrix[0],matrix[1],matrix[2],matrix[3],matrix[4],matrix[5]);\r\n"
+ "var place = function(obj,canvas,ctx,matrix,ctrans,blendMode,frame,ratio){\r\n"
+ "\tctx.save();\r\n"
+ "\tctx.transform(matrix[0],matrix[1],matrix[2],matrix[3],matrix[4],matrix[5]);\r\n"
+ "\tif(blendMode>1){\r\n"
+ "\t\tvar oldctx = ctx;\r\n"
+ "\t\tvar ncanvas = Filters.createCanvas(canvas.width,canvas.height);\r\n"
+ "\t\tctx = ncanvas.getContext(\"2d\");\r\n"
+ "\t\tenhanceContext(ctx);\r\n"
+ "\t\tctx.applyTransforms(oldctx._matrices);"
+ "\t}\r\n"
+ "\teval(obj+\"(ctx,ctrans,frame,ratio);\");\r\n"
+ "\tif(blendMode>1){\r\n" //TODO:Layer mode!
+ "\t\tBlendModes.blendCanvas(ncanvas,canvas,canvas,blendMode);\r\n"
+ "\t\tctx = oldctx;\r\n"
+ "\t}\r\n"
+ "\tctx.restore();\r\n"
+ "}\r\n"
+ "var tocolor = function(c){var r= \"rgba(\"+c[0]+\",\"+c[1]+\",\"+c[2]+\",\"+c[3]+\")\"; return r;};\r\n"

View File

@@ -601,3 +601,162 @@ Filters.colorMatrix = function(canvas,ctx,m){
Filters.glow = function(canvas,src,blurX,blurY,strength,color, inner,knockout,iterations) {
return Filters.dropShadow(canvas,src, blurX, blurY, 45, 0, color, inner, iterations, strength, knockout);
};
var BlendModes = {};
BlendModes._cut = function(v) {if(v<0) v = 0; if(v>255) v = 255; return v;};
BlendModes.normal = function(src,dst,result,pos){
var am = (255-src[pos + 3])/255;
result[pos] = this._cut(src[pos]*src[pos + 3]/255 + dst[pos]*dst[pos+3]/255*am);
result[pos + 1] = this._cut(src[pos+1]*src[pos + 3]/255 + dst[pos+1]*dst[pos+3]/255*am);
result[pos + 2] = this._cut(src[pos+2]*src[pos + 3]/255 + dst[pos+2]*dst[pos+3]/255*am);
result[pos + 3] = this._cut(src[pos + 3] + dst[pos+3]*am);
};
BlendModes.layer = function(src,dst,result,pos){
BlendModes.normal(src,dst,result,pos);
};
BlendModes.multiply = function(src,dst,result,pos){
result[pos+0] = (src[pos+0] * dst[pos+0]) >> 8;
result[pos+1] = (src[pos+1] * dst[pos+1]) >> 8;
result[pos+2] = (src[pos+2] * dst[pos+2]) >> 8;
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.screen = function(src,dst,result,pos){
result[pos+0] = 255 - ((255 - src[pos+0]) * (255 - dst[pos+0]) >> 8);
result[pos+1] = 255 - ((255 - src[pos+1]) * (255 - dst[pos+1]) >> 8);
result[pos+2] = 255 - ((255 - src[pos+2]) * (255 - dst[pos+2]) >> 8);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.lighten = function(src,dst,result,pos){
result[pos+0] = Math.max(src[pos+0], dst[pos+0]);
result[pos+1] = Math.max(src[pos+1], dst[pos+1]);
result[pos+2] = Math.max(src[pos+2], dst[pos+2]);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.darken = function(src,dst,result,pos){
result[pos+0] = Math.min(src[pos+0], dst[pos+0]);
result[pos+1] = Math.min(src[pos+1], dst[pos+1]);
result[pos+2] = Math.min(src[pos+2], dst[pos+2]);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.difference = function(src,dst,result,pos){
result[pos+0] = Math.abs(dst[pos+0] - src[pos+0]);
result[pos+1] = Math.abs(dst[pos+1] - src[pos+1]);
result[pos+2] = Math.abs(dst[pos+2] - src[pos+2]);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.add = function(src,dst,result,pos){
result[pos+0] = Math.min(255, src[pos+0] + dst[pos+0]);
result[pos+1] = Math.min(255, src[pos+1] + dst[pos+1]);
result[pos+2] = Math.min(255, src[pos+2] + dst[pos+2]);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3]);
};
BlendModes.subtract = function(src,dst,result,pos){
result[pos+0] = Math.max(0, src[pos+0] + dst[pos+0] - 256);
result[pos+1] = Math.max(0, src[pos+1] + dst[pos+1] - 256);
result[pos+2] = Math.max(0, src[pos+2] + dst[pos+2] - 256);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.invert = function(src,dst,result,pos){
result[pos+0] = 255 - dst[pos+0];
result[pos+1] = 255 - dst[pos+1];
result[pos+2] = 255 - dst[pos+2];
result[pos+3] = src[pos+3];
};
BlendModes.alpha = function(src,dst,result,pos){
result[pos+0] = src[pos+0];
result[pos+1] = src[pos+1];
result[pos+2] = src[pos+2];
result[pos+3] = dst[pos+3]; //?
};
BlendModes.erase = function(src,dst,result,pos){
result[pos+0] = src[pos+0];
result[pos+1] = src[pos+1];
result[pos+2] = src[pos+2];
result[pos+3] = 255 - dst[pos+3]; //?
};
BlendModes.overlay = function(src,dst,result,pos){
result[pos+0] = dst[pos+0] < 128 ? dst[pos+0] * src[pos+0] >> 7
: 255 - ((255 - dst[pos+0]) * (255 - src[pos+0]) >> 7);
result[pos+1] = dst[pos+1] < 128 ? dst[pos+1] * src[pos+1] >> 7
: 255 - ((255 - dst[pos+1]) * (255 - src[pos+1]) >> 7);
result[pos+2] = dst[pos+2] < 128 ? dst[pos+2] * src[pos+2] >> 7
: 255 - ((255 - dst[pos+2]) * (255 - src[pos+2]) >> 7);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes.hardlight = function(src,dst,result,pos){
result[pos+0] = src[pos+0] < 128 ? dst[pos+0] * src[pos+0] >> 7
: 255 - ((255 - src[pos+0]) * (255 - dst[pos+0]) >> 7);
result[pos+1] = src[pos+1] < 128 ? dst[pos+1] * src[pos+1] >> 7
: 255 - ((255 - src[pos+1]) * (255 - dst[pos+1]) >> 7);
result[pos+2] = src[pos+2] < 128 ? dst[pos+2] * src[pos+2] >> 7
: 255 - ((255 - src[pos+2]) * (255 - dst[pos+2]) >> 7);
result[pos+3] = Math.min(255, src[pos+3] + dst[pos+3] - (src[pos+3] * dst[pos+3]) / 255);
};
BlendModes._list = [
BlendModes.normal,
BlendModes.normal,
BlendModes.layer,
BlendModes.multiply,
BlendModes.screen,
BlendModes.lighten,
BlendModes.darken,
BlendModes.difference,
BlendModes.add,
BlendModes.subtract,
BlendModes.invert,
BlendModes.alpha,
BlendModes.erase,
BlendModes.overlay,
BlendModes.hardlight
];
BlendModes.blendData = function(srcPixel,dstPixel,retData,modeIndex){
var result = [];
var retPixel = [];
var alpha = 1.0;
for(var i=0;i<retData.length;i+=4){
this._list[modeIndex](srcPixel,dstPixel,result,i);
retPixel[i+0] = this._cut(dstPixel[i+0] + (result[i+0] - dstPixel[i+0]) * alpha);
retPixel[i+1] = this._cut(dstPixel[i+1] + (result[i+1] - dstPixel[i+1]) * alpha);
retPixel[i+2] = this._cut(dstPixel[i+2] + (result[i+2] - dstPixel[i+2]) * alpha);
retPixel[i+3] = this._cut(dstPixel[i+3] + (result[i+3] - dstPixel[i+3]) * alpha);
var af = srcPixel[i+3] / 255;
retData[i+0] = this._cut((1 - af) * dstPixel[i+0] + af * retPixel[i+0]);
retData[i+1] = this._cut((1 - af) * dstPixel[i+1] + af * retPixel[i+1]);
retData[i+2] = this._cut((1 - af) * dstPixel[i+2] + af * retPixel[i+2]);
retData[i+3] = this._cut((1 - af) * dstPixel[i+3] + af * retPixel[i+3]);
}
};
BlendModes.blendCanvas = function(src,dst,result,modeIndex){
var width = src.width;
var height = src.height;
var rctx = result.getContext("2d");
var sctx = src.getContext("2d");
var dctx = dst.getContext("2d");
var ridata = rctx.getImageData(0,0,width,height);
var sidata = sctx.getImageData(0,0,width,height);
var didata = dctx.getImageData(0,0,width,height);
this.blendData(sidata.data,didata.data,ridata.data,modeIndex);
rctx.putImageData(ridata,0,0);
};