blob: 91cb8d19cc221ad6c647ad43eabbf3f8f19da52d [file] [log] [blame]
function CVShapeElement(data, globalData, comp) {
this.shapes = [];
this.shapesData = data.shapes;
this.stylesList = [];
this.itemsData = [];
this.prevViewData = [];
this.shapeModifiers = [];
this.processedElements = [];
this.initElement(data, globalData, comp);
}
extendPrototype([BaseElement,TransformElement,CVBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableElement], CVShapeElement);
CVShapeElement.prototype.initElement = RenderableDOMElement.prototype.initElement;
CVShapeElement.prototype.transformHelper = {opacity:1,mat:new Matrix(),_matMdf:false,_opMdf:false};
CVShapeElement.prototype.dashResetter = [];
CVShapeElement.prototype.createContent = function(){
this.searchShapes(this.shapesData,this.itemsData,this.prevViewData, true);
};
CVShapeElement.prototype.createStyleElement = function(data){
var styleElem = {
data: data,
type: data.ty,
elements: [],
closed: data.hd === true
};
var elementData = {};
if(data.ty == 'fl' || data.ty == 'st'){
elementData.c = PropertyFactory.getProp(this,data.c,1,255,this);
if(!elementData.c.k){
styleElem.co = 'rgb('+bm_floor(elementData.c.v[0])+','+bm_floor(elementData.c.v[1])+','+bm_floor(elementData.c.v[2])+')';
}
} else if (data.ty === 'gf' || data.ty === 'gs') {
elementData.s = PropertyFactory.getProp(this,data.s,1,null,this);
elementData.e = PropertyFactory.getProp(this,data.e,1,null,this);
elementData.h = PropertyFactory.getProp(this,data.h||{k:0},0,0.01,this);
elementData.a = PropertyFactory.getProp(this,data.a||{k:0},0,degToRads,this);
elementData.g = new GradientProperty(this,data.g);
}
elementData.o = PropertyFactory.getProp(this,data.o,0,0.01,this);
if(data.ty == 'st' || data.ty == 'gs') {
styleElem.lc = this.lcEnum[data.lc] || 'round';
styleElem.lj = this.ljEnum[data.lj] || 'round';
if(data.lj == 1) {
styleElem.ml = data.ml;
}
elementData.w = PropertyFactory.getProp(this,data.w,0,null,this);
if(!elementData.w.k){
styleElem.wi = elementData.w.v;
}
if(data.d){
var d = new DashProperty(this,data.d,'canvas');
elementData.d = d;
if(!elementData.d.k){
styleElem.da = elementData.d.dashArray;
styleElem.do = elementData.d.dashoffset[0];
}
}
} else {
styleElem.r = data.r === 2 ? 'evenodd' : 'nonzero';
}
this.stylesList.push(styleElem);
elementData.style = styleElem;
return elementData;
};
CVShapeElement.prototype.createGroupElement = function(data) {
var elementData = {
it: [],
prevViewData: []
};
return elementData;
};
CVShapeElement.prototype.createTransformElement = function(data) {
var elementData = {
transform : {
mat: new Matrix(),
opacity: 1,
_matMdf:false,
_opMdf:false,
op: PropertyFactory.getProp(this,data.o,0,0.01,this),
mProps: TransformPropertyFactory.getTransformProperty(this,data,this)
},
elements: []
};
return elementData;
};
CVShapeElement.prototype.createShapeElement = function(data) {
var elementData = new CVShapeData(this, data);
this.shapes.push(elementData);
this.addShapeToModifiers(elementData);
var j, jLen = this.stylesList.length;
var hasStrokes = false, hasFills = false;
for(j=0;j<jLen;j+=1){
if(!this.stylesList[j].closed){
this.stylesList[j].elements.push(elementData);
if(this.stylesList[j].type === 'st'){
hasStrokes = true;
}else{
hasFills = true;
}
}
}
elementData.st = hasStrokes;
elementData.fl = hasFills;
return elementData;
};
CVShapeElement.prototype.reloadShapes = function(){
this._isFirstFrame = true;
var i, len = this.itemsData.length;
for(i=0;i<len;i+=1){
this.prevViewData[i] = this.itemsData[i];
}
this.searchShapes(this.shapesData,this.itemsData,this.prevViewData, true);
len = this.dynamicProperties.length;
for(i=0;i<len;i+=1){
this.dynamicProperties[i].getValue();
}
this.renderModifiers();
};
CVShapeElement.prototype.searchShapes = function(arr,itemsData, prevViewData, render){
var i, len = arr.length - 1;
var j, jLen;
var ownArrays = [], ownModifiers = [], processedPos, modifier;
for(i=len;i>=0;i-=1){
processedPos = this.searchProcessedElement(arr[i]);
if(!processedPos){
arr[i]._render = render;
} else {
itemsData[i] = prevViewData[processedPos - 1];
}
if(arr[i].ty == 'fl' || arr[i].ty == 'st'|| arr[i].ty == 'gf'|| arr[i].ty == 'gs'){
if(!processedPos){
itemsData[i] = this.createStyleElement(arr[i]);
} else {
itemsData[i].style.closed = false;
}
ownArrays.push(itemsData[i].style);
}else if(arr[i].ty == 'gr'){
if(!processedPos){
itemsData[i] = this.createGroupElement(arr[i]);
} else {
jLen = itemsData[i].it.length;
for(j=0;j<jLen;j+=1){
itemsData[i].prevViewData[j] = itemsData[i].it[j];
}
}
this.searchShapes(arr[i].it,itemsData[i].it,itemsData[i].prevViewData, render);
}else if(arr[i].ty == 'tr'){
if(!processedPos){
itemsData[i] = this.createTransformElement(arr[i]);
}
}else if(arr[i].ty == 'sh' || arr[i].ty == 'rc' || arr[i].ty == 'el' || arr[i].ty == 'sr'){
if(!processedPos){
itemsData[i] = this.createShapeElement(arr[i]);
}
}else if(arr[i].ty == 'tm' || arr[i].ty == 'rd'){
if(!processedPos){
modifier = ShapeModifiers.getModifier(arr[i].ty);
modifier.init(this,arr[i]);
itemsData[i] = modifier;
this.shapeModifiers.push(modifier);
} else {
modifier = itemsData[i];
modifier.closed = false;
}
ownModifiers.push(modifier);
} else if(arr[i].ty == 'rp'){
if(!processedPos){
modifier = ShapeModifiers.getModifier(arr[i].ty);
itemsData[i] = modifier;
modifier.init(this,arr,i,itemsData);
this.shapeModifiers.push(modifier);
render = false;
}else{
modifier = itemsData[i];
modifier.closed = true;
}
ownModifiers.push(modifier);
}
this.addProcessedElement(arr[i], i + 1);
}
len = ownArrays.length;
for(i=0;i<len;i+=1){
ownArrays[i].closed = true;
}
len = ownModifiers.length;
for(i=0;i<len;i+=1){
ownModifiers[i].closed = true;
}
};
CVShapeElement.prototype.renderInnerContent = function() {
this.transformHelper.mat.reset();
this.transformHelper.opacity = 1;
this.transformHelper._matMdf = false;
this.transformHelper._opMdf = false;
this.renderModifiers();
this.renderShape(this.transformHelper,this.shapesData,this.itemsData,true);
};
CVShapeElement.prototype.renderShapeTransform = function(parentTransform, groupTransform) {
var props, groupMatrix;
if(parentTransform._opMdf || groupTransform.op._mdf || this._isFirstFrame) {
groupTransform.opacity = parentTransform.opacity;
groupTransform.opacity *= groupTransform.op.v;
groupTransform._opMdf = true;
}
if(parentTransform._matMdf || groupTransform.mProps._mdf || this._isFirstFrame) {
groupMatrix = groupTransform.mat;
groupMatrix.cloneFromProps(groupTransform.mProps.v.props);
groupTransform._matMdf = true;
props = parentTransform.mat.props;
groupMatrix.transform(props[0],props[1],props[2],props[3],props[4],props[5],props[6],props[7],props[8],props[9],props[10],props[11],props[12],props[13],props[14],props[15]);
}
};
CVShapeElement.prototype.drawLayer = function() {
var i, len = this.stylesList.length;
var j, jLen, k, kLen,elems,nodes, renderer = this.globalData.renderer, ctx = this.globalData.canvasContext, type, currentStyle;
for(i=0;i<len;i+=1){
currentStyle = this.stylesList[i];
type = currentStyle.type;
if(((type === 'st' || type === 'gs') && currentStyle.wi === 0) || !currentStyle.data._render || currentStyle.coOp === 0){
continue;
}
renderer.save();
elems = currentStyle.elements;
if(type === 'st' || type === 'gs'){
ctx.strokeStyle = type === 'st' ? currentStyle.co : currentStyle.grd;
ctx.lineWidth = currentStyle.wi;
ctx.lineCap = currentStyle.lc;
ctx.lineJoin = currentStyle.lj;
ctx.miterLimit = currentStyle.ml || 0;
} else {
ctx.fillStyle = type === 'fl' ? currentStyle.co : currentStyle.grd;
}
renderer.ctxOpacity(currentStyle.coOp);
if(this.globalData.currentGlobalAlpha !== 0) {
if(type !== 'st' && type !== 'gs'){
ctx.beginPath();
}
jLen = elems.length;
for(j=0;j<jLen;j+=1){
if(type === 'st' || type === 'gs'){
ctx.beginPath();
if(currentStyle.da){
ctx.setLineDash(currentStyle.da);
ctx.lineDashOffset = currentStyle.do;
this.globalData.isDashed = true;
}else if(this.globalData.isDashed){
ctx.setLineDash(this.dashResetter);
this.globalData.isDashed = false;
}
}
nodes = elems[j].trNodes;
kLen = nodes.length;
for(k=0;k<kLen;k+=1){
if(nodes[k].t == 'm'){
ctx.moveTo(nodes[k].p[0],nodes[k].p[1]);
}else if(nodes[k].t == 'c'){
ctx.bezierCurveTo(nodes[k].pts[0],nodes[k].pts[1],nodes[k].pts[2],nodes[k].pts[3],nodes[k].pts[4],nodes[k].pts[5]);
}else{
ctx.closePath();
}
}
if(type === 'st' || type === 'gs'){
ctx.stroke();
}
}
if(type !== 'st' && type !== 'gs'){
ctx.fill(currentStyle.r);
}
}
renderer.restore();
}
};
CVShapeElement.prototype.renderShape = function(parentTransform,items,data,isMain){
var i, len = items.length - 1;
var groupTransform;
groupTransform = parentTransform;
for(i=len;i>=0;i-=1){
if(items[i].ty == 'tr'){
groupTransform = data[i].transform;
this.renderShapeTransform(parentTransform, groupTransform);
}else if(items[i].ty == 'sh' || items[i].ty == 'el' || items[i].ty == 'rc' || items[i].ty == 'sr'){
this.renderPath(items[i],data[i],groupTransform);
}else if(items[i].ty == 'fl'){
this.renderFill(items[i],data[i],groupTransform);
}else if(items[i].ty == 'st'){
this.renderStroke(items[i],data[i],groupTransform);
}else if(items[i].ty == 'gf' || items[i].ty == 'gs'){
this.renderGradientFill(items[i],data[i],groupTransform);
}else if(items[i].ty == 'gr'){
this.renderShape(groupTransform,items[i].it,data[i].it);
}else if(items[i].ty == 'tm'){
//
}
}
if(isMain){
this.drawLayer();
}
};
CVShapeElement.prototype.renderPath = function(pathData,itemData,groupTransform){
var len, i, j,jLen;
var redraw = pathData.hd !== true && (groupTransform._matMdf || itemData.sh._mdf || this._isFirstFrame);
if(redraw) {
var paths = itemData.sh.paths, groupTransformMat = groupTransform.mat;
jLen = pathData._render === false ? 0 : paths._length;
var pathStringTransformed = itemData.trNodes;
pathStringTransformed.length = 0;
for(j=0;j<jLen;j+=1){
var pathNodes = paths.shapes[j];
if(pathNodes && pathNodes.v){
len = pathNodes._length;
for (i = 1; i < len; i += 1) {
if (i == 1) {
pathStringTransformed.push({
t: 'm',
p: groupTransformMat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 0)
});
}
pathStringTransformed.push({
t: 'c',
pts: groupTransformMat.applyToTriplePoints(pathNodes.o[i - 1], pathNodes.i[i], pathNodes.v[i])
});
}
if (len == 1) {
pathStringTransformed.push({
t: 'm',
p: groupTransformMat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 0)
});
}
if (pathNodes.c && len) {
pathStringTransformed.push({
t: 'c',
pts: groupTransformMat.applyToTriplePoints(pathNodes.o[i - 1], pathNodes.i[0], pathNodes.v[0])
});
pathStringTransformed.push({
t: 'z'
});
}
itemData.lStr = pathStringTransformed;
}
}
if (itemData.st) {
for (i = 0; i < 16; i += 1) {
itemData.tr[i] = groupTransform.mat.props[i];
}
}
itemData.trNodes = pathStringTransformed;
}
};
CVShapeElement.prototype.renderFill = function(styleData,itemData, groupTransform){
var styleElem = itemData.style;
if(itemData.c._mdf || this._isFirstFrame){
styleElem.co = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
}
if(itemData.o._mdf || groupTransform._opMdf || this._isFirstFrame){
styleElem.coOp = itemData.o.v*groupTransform.opacity;
}
};
CVShapeElement.prototype.renderGradientFill = function(styleData,itemData, groupTransform){
var styleElem = itemData.style;
if(!styleElem.grd || itemData.g._mdf || itemData.s._mdf || itemData.e._mdf || (styleData.t !== 1 && (itemData.h._mdf || itemData.a._mdf))) {
var ctx = this.globalData.canvasContext;
var grd;
var pt1 = itemData.s.v, pt2 = itemData.e.v;
pt1 = groupTransform.mat.applyToPointArray(pt1[0], pt1[1], 0);
pt2 = groupTransform.mat.applyToPointArray(pt2[0], pt2[1], 0);
if(styleData.t === 1) {
grd=ctx.createLinearGradient(pt1[0],pt1[1],pt2[0],pt2[1]);
} else {
var rad;
rad = Math.sqrt(Math.pow(pt1[0] - pt2[0], 2) + Math.pow(pt1[1] - pt2[1], 2));
var ang = Math.atan2(pt2[1] - pt1[1], pt2[0] - pt1[0]);
var percent = itemData.h.v >= 1 ? 0.99 : itemData.h.v <= -1 ? -0.99: itemData.h.v;
var dist = rad * percent;
var x = Math.cos(ang + itemData.a.v) * dist + pt1[0];
var y = Math.sin(ang + itemData.a.v) * dist + pt1[1];
var grd=ctx.createRadialGradient(x,y,0,pt1[0],pt1[1],rad);
}
var i, len = styleData.g.p;
var cValues = itemData.g.c;
var opacity = 1;
for (i = 0; i < len; i += 1){
if(itemData.g._hasOpacity && itemData.g._collapsable) {
opacity = itemData.g.o[i*2 + 1];
}
grd.addColorStop(cValues[i * 4] / 100,'rgba('+ cValues[i * 4 + 1] + ',' + cValues[i * 4 + 2] + ','+cValues[i * 4 + 3] + ',' + opacity + ')');
}
styleElem.grd = grd;
}
styleElem.coOp = itemData.o.v*groupTransform.opacity;
};
CVShapeElement.prototype.renderStroke = function(styleData,itemData, groupTransform){
var styleElem = itemData.style;
var d = itemData.d;
if(d && (d._mdf || this._isFirstFrame)){
styleElem.da = d.dashArray;
styleElem.do = d.dashoffset[0];
}
if(itemData.c._mdf || this._isFirstFrame){
styleElem.co = 'rgb('+bm_floor(itemData.c.v[0])+','+bm_floor(itemData.c.v[1])+','+bm_floor(itemData.c.v[2])+')';
}
if(itemData.o._mdf || groupTransform._opMdf || this._isFirstFrame){
styleElem.coOp = itemData.o.v*groupTransform.opacity;
}
if(itemData.w._mdf || this._isFirstFrame){
styleElem.wi = itemData.w.v;
}
};
CVShapeElement.prototype.destroy = function(){
this.shapesData = null;
this.globalData = null;
this.canvasContext = null;
this.stylesList.length = 0;
this.itemsData.length = 0;
};