blob: 41a14bfdf9b8a4bb53f477a437e591fc14681e87 [file] [log] [blame]
function MaskElement(data,element,globalData) {
//TODO: check if dynamic properties array can be used from element
this.dynamicProperties = [];
this.data = data;
this.element = element;
this.globalData = globalData;
this.storedData = [];
this.masksProperties = this.data.masksProperties || [];
this.maskElement = null;
this.firstFrame = true;
var defs = this.globalData.defs;
var i, len = this.masksProperties ? this.masksProperties.length : 0;
this.viewData = createSizedArray(len);
this.solidPath = '';
var path, properties = this.masksProperties;
var count = 0;
var currentMasks = [];
var j, jLen;
var layerId = randomString(10);
var rect, expansor, feMorph,x;
var maskType = 'clipPath', maskRef = 'clip-path';
for (i = 0; i < len; i++) {
if((properties[i].mode !== 'a' && properties[i].mode !== 'n')|| properties[i].inv || properties[i].o.k !== 100){
maskType = 'mask';
maskRef = 'mask';
}
if((properties[i].mode == 's' || properties[i].mode == 'i') && count == 0){
rect = createNS( 'rect');
rect.setAttribute('fill', '#ffffff');
rect.setAttribute('width', this.element.comp.data.w);
rect.setAttribute('height', this.element.comp.data.h);
currentMasks.push(rect);
} else {
rect = null;
}
path = createNS( 'path');
if(properties[i].mode == 'n') {
// TODO move this to a factory or to a constructor
this.viewData[i] = {
op: PropertyFactory.getProp(this.element,properties[i].o,0,0.01,this.dynamicProperties),
prop: ShapePropertyFactory.getShapeProp(this.element,properties[i],3,this.dynamicProperties,null),
elem: path
};
defs.appendChild(path);
continue;
}
count += 1;
path.setAttribute('fill', properties[i].mode === 's' ? '#000000':'#ffffff');
path.setAttribute('clip-rule','nonzero');
if (properties[i].x.k !== 0) {
maskType = 'mask';
maskRef = 'mask';
x = PropertyFactory.getProp(this.element,properties[i].x,0,null,this.dynamicProperties);
var filterID = 'fi_'+randomString(10);
expansor = createNS('filter');
expansor.setAttribute('id',filterID);
feMorph = createNS('feMorphology');
feMorph.setAttribute('operator','dilate');
feMorph.setAttribute('in','SourceGraphic');
feMorph.setAttribute('radius','0');
expansor.appendChild(feMorph);
defs.appendChild(expansor);
path.setAttribute('stroke', properties[i].mode === 's' ? '#000000':'#ffffff');
} else {
feMorph = null;
x = null;
}
// TODO move this to a factory or to a constructor
this.storedData[i] = {
elem: path,
x: x,
expan: feMorph,
lastPath: '',
lastOperator:'',
filterId:filterID,
lastRadius:0
};
if(properties[i].mode == 'i'){
jLen = currentMasks.length;
var g = createNS('g');
for(j=0;j<jLen;j+=1){
g.appendChild(currentMasks[j]);
}
var mask = createNS('mask');
mask.setAttribute('mask-type','alpha');
mask.setAttribute('id',layerId+'_'+count);
mask.appendChild(path);
defs.appendChild(mask);
g.setAttribute('mask','url(' + locationHref + '#'+layerId+'_'+count+')');
currentMasks.length = 0;
currentMasks.push(g);
}else{
currentMasks.push(path);
}
if(properties[i].inv && !this.solidPath){
this.solidPath = this.createLayerSolidPath();
}
// TODO move this to a factory or to a constructor
this.viewData[i] = {
elem: path,
lastPath: '',
op: PropertyFactory.getProp(this.element,properties[i].o,0,0.01,this.dynamicProperties),
prop:ShapePropertyFactory.getShapeProp(this.element,properties[i],3,this.dynamicProperties,null)
};
if(rect){
//TODO: move the invRect property to the object definition in order to prevent a new hidden class creation.
this.viewData[i].invRect = rect;
}
if(!this.viewData[i].prop.k){
this.drawPath(properties[i],this.viewData[i].prop.v,this.viewData[i]);
}
}
this.maskElement = createNS( maskType);
len = currentMasks.length;
for(i=0;i<len;i+=1){
this.maskElement.appendChild(currentMasks[i]);
}
if(count > 0){
this.maskElement.setAttribute('id', layerId);
this.element.maskedElement.setAttribute(maskRef, "url(" + locationHref + "#" + layerId + ")");
defs.appendChild(this.maskElement);
}
};
MaskElement.prototype.getMaskProperty = function(pos){
return this.viewData[pos].prop;
};
MaskElement.prototype.prepareFrame = function(){
var i, len = this.dynamicProperties.length;
for(i=0;i<len;i+=1){
this.dynamicProperties[i].getValue();
}
};
MaskElement.prototype.renderFrame = function (finalMat) {
var i, len = this.masksProperties.length;
for (i = 0; i < len; i++) {
if(this.viewData[i].prop.mdf || this.firstFrame){
this.drawPath(this.masksProperties[i],this.viewData[i].prop.v,this.viewData[i]);
}
if(this.viewData[i].op.mdf || this.firstFrame){
this.viewData[i].elem.setAttribute('fill-opacity',this.viewData[i].op.v);
}
if(this.masksProperties[i].mode !== 'n'){
if(this.viewData[i].invRect && (this.element.finalTransform.mProp.mdf || this.firstFrame)){
this.viewData[i].invRect.setAttribute('x', -finalMat.props[12]);
this.viewData[i].invRect.setAttribute('y', -finalMat.props[13]);
}
if(this.storedData[i].x && (this.storedData[i].x.mdf || this.firstFrame)){
var feMorph = this.storedData[i].expan;
if(this.storedData[i].x.v < 0){
if(this.storedData[i].lastOperator !== 'erode'){
this.storedData[i].lastOperator = 'erode';
this.storedData[i].elem.setAttribute('filter','url(' + locationHref + '#'+this.storedData[i].filterId+')');
}
feMorph.setAttribute('radius',-this.storedData[i].x.v);
}else{
if(this.storedData[i].lastOperator !== 'dilate'){
this.storedData[i].lastOperator = 'dilate';
this.storedData[i].elem.setAttribute('filter',null);
}
this.storedData[i].elem.setAttribute('stroke-width', this.storedData[i].x.v*2);
}
}
}
}
this.firstFrame = false;
};
MaskElement.prototype.getMaskelement = function () {
return this.maskElement;
};
MaskElement.prototype.createLayerSolidPath = function(){
var path = 'M0,0 ';
path += ' h' + this.globalData.compSize.w ;
path += ' v' + this.globalData.compSize.h ;
path += ' h-' + this.globalData.compSize.w ;
path += ' v-' + this.globalData.compSize.h + ' ';
return path;
};
MaskElement.prototype.drawPath = function(pathData,pathNodes,viewData){
var pathString = " M"+pathNodes.v[0][0]+','+pathNodes.v[0][1];
var i, len;
len = pathNodes._length;
for(i=1;i<len;i+=1){
//pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[i][0]+','+pathNodes.i[i][1] + " "+pathNodes.v[i][0]+','+pathNodes.v[i][1];
pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[i][0]+','+pathNodes.i[i][1] + " "+pathNodes.v[i][0]+','+pathNodes.v[i][1];
}
//pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[0][0]+','+pathNodes.i[0][1] + " "+pathNodes.v[0][0]+','+pathNodes.v[0][1];
if(pathNodes.c && len > 1){
pathString += " C"+pathNodes.o[i-1][0]+','+pathNodes.o[i-1][1] + " "+pathNodes.i[0][0]+','+pathNodes.i[0][1] + " "+pathNodes.v[0][0]+','+pathNodes.v[0][1];
}
//pathNodes.__renderedString = pathString;
if(viewData.lastPath !== pathString){
var pathShapeValue = '';
if(viewData.elem){
if(pathNodes.c){
pathShapeValue = pathData.inv ? this.solidPath + pathString : pathString;
}
viewData.elem.setAttribute('d',pathShapeValue);
}
viewData.lastPath = pathString;
}
};
MaskElement.prototype.destroy = function(){
this.element = null;
this.globalData = null;
this.maskElement = null;
this.data = null;
this.masksProperties = null;
};