blob: 46abf0e260933b6bac52e5ab0195254f2339bae5 [file] [log] [blame]
function CVShapeElement(data, comp,globalData){
this.shapes = [];
this.shapesData = data.shapes;
this.stylesList = [];
this.itemsData = [];
this.prevViewData = [];
this.shapeModifiers = [];
this.processedElements = [];
this._parent.constructor.call(this,data, comp,globalData);
}
createElement(CVBaseElement, CVShapeElement);
CVShapeElement.prototype.transformHelper = {opacity:1,mat:new Matrix(),matMdf:false,opMdf:false};
CVShapeElement.prototype.dashResetter = [];
CVShapeElement.prototype.createElements = function(){
this._parent.createElements.call(this);
this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.dynamicProperties,[], true);
};
CVShapeElement.prototype.createStyleElement = function(data, dynamicProperties){
var styleElem = {
data: data,
type: data.ty,
elements: []
};
var elementData = {};
if(data.ty == 'fl' || data.ty == 'st'){
elementData.c = PropertyFactory.getProp(this,data.c,1,255,dynamicProperties);
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])+')';
}
}
elementData.o = PropertyFactory.getProp(this,data.o,0,0.01,dynamicProperties);
if(data.ty == 'st') {
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,dynamicProperties);
if(!elementData.w.k){
styleElem.wi = elementData.w.v;
}
if(data.d){
var d = PropertyFactory.getDashProp(this,data.d,'canvas',dynamicProperties);
elementData.d = d;
if(!elementData.d.k){
styleElem.da = elementData.d.dasharray;
styleElem.do = elementData.d.dashoffset;
}
}
} 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, dynamicProperties) {
var elementData = {
transform : {
mat: new Matrix(),
opacity: 1,
matMdf:false,
opMdf:false,
op: PropertyFactory.getProp(this,data.o,0,0.01,dynamicProperties),
mProps: PropertyFactory.getProp(this,data,2,null,dynamicProperties)
},
elements: []
};
return elementData;
}
CVShapeElement.prototype.createShapeElement = function(data, ownTransformers, dynamicProperties) {
var elementData = {
nodes:[],
trNodes:[],
transformers: ownTransformers,
tr:[0,0,0,0,0,0]
};
var ty = 4;
if(data.ty == 'rc'){
ty = 5;
}else if(data.ty == 'el'){
ty = 6;
}else if(data.ty == 'sr'){
ty = 7;
}
elementData.sh = ShapePropertyFactory.getShapeProp(this,data,ty,dynamicProperties);
this.shapes.push(elementData.sh);
this.addShapeToModifiers(elementData);
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.firstFrame = 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,this.dynamicProperties, [], true);
var i, len = this.dynamicProperties.length;
for(i=0;i<len;i+=1){
this.dynamicProperties[i].getValue();
}
this.renderModifiers();
}
CVShapeElement.prototype.searchShapes = function(arr,itemsData, prevViewData,dynamicProperties, transformers, render){
var ownTransformers = [].concat(transformers);
var i, len = arr.length - 1;
var j, jLen;
var ownArrays = [], ownModifiers = [], processedPos;
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'){
if(!processedPos){
itemsData[i] = this.createStyleElement(arr[i], dynamicProperties);
} 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,dynamicProperties, ownTransformers, render);
}else if(arr[i].ty == 'tr'){
if(!processedPos){
itemsData[i] = this.createTransformElement(arr[i], dynamicProperties);
}
ownTransformers.push(itemsData[i].transform);
}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], ownTransformers, dynamicProperties);
}
}else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'ms'){
if(!processedPos){
var modifier = ShapeModifiers.getModifier(arr[i].ty);
modifier.init(this,arr[i],dynamicProperties);
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,dynamicProperties);
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.addShapeToModifiers = IShapeElement.prototype.addShapeToModifiers;
CVShapeElement.prototype.renderModifiers = IShapeElement.prototype.renderModifiers;
CVShapeElement.prototype.lcEnum = IShapeElement.prototype.lcEnum;
CVShapeElement.prototype.ljEnum = IShapeElement.prototype.ljEnum;
CVShapeElement.prototype.searchProcessedElement = IShapeElement.prototype.searchProcessedElement;
CVShapeElement.prototype.addProcessedElement = IShapeElement.prototype.addProcessedElement;
CVShapeElement.prototype.renderFrame = function(parentMatrix){
if(this._parent.renderFrame.call(this, parentMatrix)===false){
return;
}
this.transformHelper.mat.reset();
this.transformHelper.opacity = this.finalTransform.opacity;
this.transformHelper.matMdf = false;
this.transformHelper.opMdf = this.finalTransform.opMdf;
this.renderModifiers();
this.renderShape(this.transformHelper,null,null,true);
if(this.data.hasMask){
this.globalData.renderer.restore(true);
}
};
CVShapeElement.prototype.renderShape = function(parentTransform,items,data,isMain){
var i, len;
if(!items){
items = this.shapesData;
len = this.stylesList.length;
for(i=0;i<len;i+=1){
this.stylesList[i].d = '';
this.stylesList[i].mdf = false;
}
}
if(!data){
data = this.itemsData;
}
///
///
len = items.length - 1;
var groupTransform,groupMatrix;
groupTransform = parentTransform;
for(i=len;i>=0;i-=1){
if(items[i].ty == 'tr'){
groupTransform = data[i].transform;
var mtArr = data[i].transform.mProps.v.props;
groupTransform.matMdf = groupTransform.mProps.mdf;
groupTransform.opMdf = groupTransform.op.mdf;
groupMatrix = groupTransform.mat;
groupMatrix.cloneFromProps(mtArr);
if(parentTransform){
var props = parentTransform.mat.props;
groupTransform.opacity = parentTransform.opacity;
groupTransform.opacity *= data[i].transform.op.v;
groupTransform.matMdf = parentTransform.matMdf ? true : groupTransform.matMdf;
groupTransform.opMdf = parentTransform.opMdf ? true : groupTransform.opMdf;
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]);
}else{
groupTransform.opacity = groupTransform.op.o;
}
}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 == 'gr'){
this.renderShape(groupTransform,items[i].it,data[i].it);
}else if(items[i].ty == 'tm'){
//
}
}
if(!isMain){
return;
}
len = this.stylesList.length;
var j, jLen, k, kLen,elems,nodes, renderer = this.globalData.renderer, ctx = this.globalData.canvasContext, type;
renderer.save();
renderer.ctxTransform(this.finalTransform.mat.props);
for(i=0;i<len;i+=1){
type = this.stylesList[i].type;
if((type === 'st' && this.stylesList[i].wi === 0) || !this.stylesList[i].data._render){
continue;
}
renderer.save();
elems = this.stylesList[i].elements;
if(type === 'st'){
ctx.strokeStyle = this.stylesList[i].co;
ctx.lineWidth = this.stylesList[i].wi;
ctx.lineCap = this.stylesList[i].lc;
ctx.lineJoin = this.stylesList[i].lj;
ctx.miterLimit = this.stylesList[i].ml || 0;
}else{
ctx.fillStyle = this.stylesList[i].co;
}
renderer.ctxOpacity(this.stylesList[i].coOp);
if(type !== 'st'){
ctx.beginPath();
}
jLen = elems.length;
for(j=0;j<jLen;j+=1){
if(type === 'st'){
ctx.beginPath();
if(this.stylesList[i].da){
ctx.setLineDash(this.stylesList[i].da);
ctx.lineDashOffset = this.stylesList[i].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].p1[0],nodes[k].p1[1],nodes[k].p2[0],nodes[k].p2[1],nodes[k].p3[0],nodes[k].p3[1]);
}else{
ctx.closePath();
}
}
if(type === 'st'){
ctx.stroke();
}
}
if(type !== 'st'){
ctx.fill(this.stylesList[i].r);
}
renderer.restore();
}
renderer.restore();
if(this.firstFrame){
this.firstFrame = false;
}
};
CVShapeElement.prototype.renderPath = function(pathData,itemData,groupTransform){
var len, i, j,jLen;
var redraw = groupTransform.matMdf || itemData.sh.mdf || this.firstFrame;
if(redraw) {
var paths = itemData.sh.paths;
jLen = 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: groupTransform.mat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 0)
});
}
pathStringTransformed.push({
t: 'c',
p1: groupTransform.mat.applyToPointArray(pathNodes.o[i - 1][0], pathNodes.o[i - 1][1], 0),
p2: groupTransform.mat.applyToPointArray(pathNodes.i[i][0], pathNodes.i[i][1], 0),
p3: groupTransform.mat.applyToPointArray(pathNodes.v[i][0], pathNodes.v[i][1], 0)
});
}
if (len == 1) {
pathStringTransformed.push({
t: 'm',
p: groupTransform.mat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 0)
});
}
if (pathNodes.c && len) {
pathStringTransformed.push({
t: 'c',
p1: groupTransform.mat.applyToPointArray(pathNodes.o[i - 1][0], pathNodes.o[i - 1][1], 0),
p2: groupTransform.mat.applyToPointArray(pathNodes.i[0][0], pathNodes.i[0][1], 0),
p3: groupTransform.mat.applyToPointArray(pathNodes.v[0][0], pathNodes.v[0][1], 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.firstFrame){
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.firstFrame){
styleElem.coOp = itemData.o.v*groupTransform.opacity;
}
};
CVShapeElement.prototype.renderStroke = function(styleData,itemData, groupTransform){
var styleElem = itemData.style;
//TODO fix dashes
var d = itemData.d;
var dasharray,dashoffset;
if(d && (d.mdf || this.firstFrame)){
styleElem.da = d.dasharray;
styleElem.do = d.dashoffset;
}
if(itemData.c.mdf || this.firstFrame){
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.firstFrame){
styleElem.coOp = itemData.o.v*groupTransform.opacity;
}
if(itemData.w.mdf || this.firstFrame){
styleElem.wi = itemData.w.v;
}
};
CVShapeElement.prototype.destroy = function(){
this.shapesData = null;
this.globalData = null;
this.canvasContext = null;
this.stylesList.length = 0;
this.itemData.length = 0;
this._parent.destroy.call(this._parent);
};