| function SVGShapeElement(data,globalData,comp){ |
| //List of drawable elements |
| this.shapes = []; |
| // Full shape data |
| this.shapesData = data.shapes; |
| //List of styles that will be applied to shapes |
| this.stylesList = []; |
| //List of modifiers that will be applied to shapes |
| this.shapeModifiers = []; |
| //List of items in shape tree |
| this.itemsData = []; |
| //List of items in previous shape tree |
| this.processedElements = []; |
| // List of animated components |
| this.animatedContents = []; |
| this.initElement(data,globalData,comp); |
| //Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties. |
| // List of elements that have been created |
| this.prevViewData = []; |
| //Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties. |
| } |
| |
| extendPrototype([BaseElement,TransformElement,SVGBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableDOMElement], SVGShapeElement); |
| |
| SVGShapeElement.prototype.initSecondaryElement = function() { |
| }; |
| |
| SVGShapeElement.prototype.identityMatrix = new Matrix(); |
| |
| SVGShapeElement.prototype.buildExpressionInterface = function(){}; |
| |
| SVGShapeElement.prototype.createContent = function(){ |
| this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement, 0, [], true); |
| this.filterUniqueShapes(); |
| }; |
| |
| /* |
| This method searches for multiple shapes that affect a single element and one of them is animated |
| */ |
| SVGShapeElement.prototype.filterUniqueShapes = function(){ |
| var i, len = this.shapes.length, shape; |
| var j, jLen = this.stylesList.length; |
| var style, count = 0; |
| var tempShapes = []; |
| var areAnimated = false; |
| for(j = 0; j < jLen; j += 1) { |
| style = this.stylesList[j]; |
| areAnimated = false; |
| tempShapes.length = 0; |
| for(i = 0; i < len; i += 1) { |
| shape = this.shapes[i]; |
| if(shape.styles.indexOf(style) !== -1) { |
| tempShapes.push(shape); |
| areAnimated = shape._isAnimated || areAnimated; |
| } |
| } |
| if(tempShapes.length > 1 && areAnimated) { |
| this.setShapesAsAnimated(tempShapes); |
| } |
| } |
| } |
| |
| SVGShapeElement.prototype.setShapesAsAnimated = function(shapes){ |
| var i, len = shapes.length; |
| for(i = 0; i < len; i += 1) { |
| shapes[i].setAsAnimated(); |
| } |
| } |
| |
| SVGShapeElement.prototype.createStyleElement = function(data, level){ |
| //TODO: prevent drawing of hidden styles |
| var elementData; |
| var styleOb = new SVGStyleData(data, level); |
| |
| var pathElement = styleOb.pElem; |
| if(data.ty === 'st') { |
| elementData = new SVGStrokeStyleData(this, data, styleOb); |
| } else if(data.ty === 'fl') { |
| elementData = new SVGFillStyleData(this, data, styleOb); |
| } else if(data.ty === 'gf' || data.ty === 'gs') { |
| var gradientConstructor = data.ty === 'gf' ? SVGGradientFillStyleData : SVGGradientStrokeStyleData; |
| elementData = new gradientConstructor(this, data, styleOb); |
| this.globalData.defs.appendChild(elementData.gf); |
| if (elementData.maskId) { |
| this.globalData.defs.appendChild(elementData.ms); |
| this.globalData.defs.appendChild(elementData.of); |
| pathElement.setAttribute('mask','url(' + locationHref + '#' + elementData.maskId + ')'); |
| } |
| } |
| |
| if(data.ty === 'st' || data.ty === 'gs') { |
| pathElement.setAttribute('stroke-linecap', this.lcEnum[data.lc] || 'round'); |
| pathElement.setAttribute('stroke-linejoin',this.ljEnum[data.lj] || 'round'); |
| pathElement.setAttribute('fill-opacity','0'); |
| if(data.lj === 1) { |
| pathElement.setAttribute('stroke-miterlimit',data.ml); |
| } |
| } |
| |
| if(data.r === 2) { |
| pathElement.setAttribute('fill-rule', 'evenodd'); |
| } |
| |
| if(data.ln){ |
| pathElement.setAttribute('id',data.ln); |
| } |
| if(data.cl){ |
| pathElement.setAttribute('class',data.cl); |
| } |
| if(data.bm){ |
| pathElement.style['mix-blend-mode'] = getBlendMode(data.bm); |
| } |
| this.stylesList.push(styleOb); |
| this.addToAnimatedContents(data, elementData); |
| return elementData; |
| }; |
| |
| SVGShapeElement.prototype.createGroupElement = function(data) { |
| var elementData = new ShapeGroupData(); |
| if(data.ln){ |
| elementData.gr.setAttribute('id',data.ln); |
| } |
| if(data.cl){ |
| elementData.gr.setAttribute('class',data.cl); |
| } |
| if(data.bm){ |
| elementData.gr.style['mix-blend-mode'] = getBlendMode(data.bm); |
| } |
| return elementData; |
| }; |
| |
| SVGShapeElement.prototype.createTransformElement = function(data, container) { |
| var transformProperty = TransformPropertyFactory.getTransformProperty(this,data,this); |
| var elementData = new SVGTransformData(transformProperty, transformProperty.o, container); |
| this.addToAnimatedContents(data, elementData); |
| return elementData; |
| }; |
| |
| SVGShapeElement.prototype.createShapeElement = function(data, ownTransformers, level) { |
| var ty = 4; |
| if(data.ty === 'rc'){ |
| ty = 5; |
| }else if(data.ty === 'el'){ |
| ty = 6; |
| }else if(data.ty === 'sr'){ |
| ty = 7; |
| } |
| var shapeProperty = ShapePropertyFactory.getShapeProp(this,data,ty,this); |
| var elementData = new SVGShapeData(ownTransformers, level, shapeProperty); |
| this.shapes.push(elementData); |
| this.addShapeToModifiers(elementData); |
| this.addToAnimatedContents(data, elementData); |
| return elementData; |
| }; |
| |
| SVGShapeElement.prototype.addToAnimatedContents = function(data, element) { |
| var i = 0, len = this.animatedContents.length; |
| while(i < len) { |
| if(this.animatedContents[i].element === element) { |
| return; |
| } |
| i += 1; |
| } |
| this.animatedContents.push({ |
| fn: SVGElementsRenderer.createRenderFunction(data), |
| element: element, |
| data: data |
| }); |
| }; |
| |
| SVGShapeElement.prototype.setElementStyles = function(elementData){ |
| var arr = elementData.styles; |
| var j, jLen = this.stylesList.length; |
| for (j = 0; j < jLen; j += 1) { |
| if (!this.stylesList[j].closed) { |
| arr.push(this.stylesList[j]); |
| } |
| } |
| }; |
| |
| SVGShapeElement.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,this.layerElement, 0, [], true); |
| this.filterUniqueShapes(); |
| len = this.dynamicProperties.length; |
| for(i = 0; i < len; i += 1) { |
| this.dynamicProperties[i].getValue(); |
| } |
| this.renderModifiers(); |
| }; |
| |
| SVGShapeElement.prototype.searchShapes = function(arr,itemsData,prevViewData,container, level, transformers, render){ |
| var ownTransformers = [].concat(transformers); |
| var i, len = arr.length - 1; |
| var j, jLen; |
| var ownStyles = [], ownModifiers = [], styleOb, currentTransform, modifier, 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' || arr[i].ty == 'gf' || arr[i].ty == 'gs'){ |
| if(!processedPos){ |
| itemsData[i] = this.createStyleElement(arr[i], level); |
| } else { |
| itemsData[i].style.closed = false; |
| } |
| if(arr[i]._render){ |
| container.appendChild(itemsData[i].style.pElem); |
| } |
| ownStyles.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,itemsData[i].gr, level + 1, ownTransformers, render); |
| if(arr[i]._render){ |
| container.appendChild(itemsData[i].gr); |
| } |
| }else if(arr[i].ty == 'tr'){ |
| if(!processedPos){ |
| itemsData[i] = this.createTransformElement(arr[i], container); |
| } |
| currentTransform = itemsData[i].transform; |
| ownTransformers.push(currentTransform); |
| }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, level); |
| } |
| this.setElementStyles(itemsData[i]); |
| |
| }else if(arr[i].ty == 'tm' || arr[i].ty == 'rd' || arr[i].ty == 'ms'){ |
| 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 = ownStyles.length; |
| for(i=0;i<len;i+=1){ |
| ownStyles[i].closed = true; |
| } |
| len = ownModifiers.length; |
| for(i=0;i<len;i+=1){ |
| ownModifiers[i].closed = true; |
| } |
| }; |
| |
| SVGShapeElement.prototype.renderInnerContent = function() { |
| this.renderModifiers(); |
| var i, len = this.stylesList.length; |
| for(i=0;i<len;i+=1){ |
| this.stylesList[i].reset(); |
| } |
| this.renderShape(); |
| |
| for (i = 0; i < len; i += 1) { |
| if (this.stylesList[i]._mdf || this._isFirstFrame) { |
| if(this.stylesList[i].msElem){ |
| this.stylesList[i].msElem.setAttribute('d', this.stylesList[i].d); |
| //Adding M0 0 fixes same mask bug on all browsers |
| this.stylesList[i].d = 'M0 0' + this.stylesList[i].d; |
| } |
| this.stylesList[i].pElem.setAttribute('d', this.stylesList[i].d || 'M0 0'); |
| } |
| } |
| }; |
| |
| SVGShapeElement.prototype.renderShape = function() { |
| var i, len = this.animatedContents.length; |
| var animatedContent; |
| for(i = 0; i < len; i += 1) { |
| animatedContent = this.animatedContents[i]; |
| if((this._isFirstFrame || animatedContent.element._isAnimated) && animatedContent.data !== true) { |
| animatedContent.fn(animatedContent.data, animatedContent.element, this._isFirstFrame); |
| } |
| } |
| } |
| |
| SVGShapeElement.prototype.destroy = function(){ |
| this.destroyBaseElement(); |
| this.shapesData = null; |
| this.itemsData = null; |
| }; |