text: /* global extendPrototype, BaseRenderer, SVGRenderer, SVGShapeElement, HShapeElement, SVGTextLottieElement,
  HTextElement, HCameraElement, IImageElement, HImageElement, SVGCompElement, HCompElement, ISolidElement,
  HSolidElement, styleDiv, createTag, createNS */
  
  function HybridRenderer(animationItem, config) {
    this.animationItem = animationItem;
    this.layers = null;
    this.renderedFrame = -1;
    this.renderConfig = {
      className: (config && config.className) || '',
      imagePreserveAspectRatio: (config && config.imagePreserveAspectRatio) || 'xMidYMid slice',
      hideOnTransparent: !(config && config.hideOnTransparent === false),
      filterSize: {
        width: (config && config.filterSize && config.filterSize.width) || '400%',
        height: (config && config.filterSize && config.filterSize.height) || '400%',
        x: (config && config.filterSize && config.filterSize.x) || '-100%',
        y: (config && config.filterSize && config.filterSize.y) || '-100%',
      },
    };
    this.globalData = {
      _mdf: false,
      frameNum: -1,
      renderConfig: this.renderConfig,
    };
    this.pendingElements = [];
    this.elements = [];
    this.threeDElements = [];
    this.destroyed = false;
    this.camera = null;
    this.supports3d = true;
    this.rendererType = 'html';
  }
  
  extendPrototype([BaseRenderer], HybridRenderer);
  
  HybridRenderer.prototype.buildItem = SVGRenderer.prototype.buildItem;
  
  HybridRenderer.prototype.checkPendingElements = function () {
    while (this.pendingElements.length) {
      var element = this.pendingElements.pop();
      element.checkParenting();
    }
  };
  
  HybridRenderer.prototype.appendElementInPos = function (element, pos) {
    var newDOMElement = element.getBaseElement();
    if (!newDOMElement) {
      return;
    }
    var layer = this.layers[pos];
    if (!layer.ddd || !this.supports3d) {
      if (this.threeDElements) {
        this.addTo3dContainer(newDOMElement, pos);
      } else {
        var i = 0;
        var nextDOMElement;
        var nextLayer;
        var tmpDOMElement;
        while (i < pos) {
          if (this.elements[i] && this.elements[i] !== true && this.elements[i].getBaseElement) {
            nextLayer = this.elements[i];
            tmpDOMElement = this.layers[i].ddd ? this.getThreeDContainerByPos(i) : nextLayer.getBaseElement();
            nextDOMElement = tmpDOMElement || nextDOMElement;
          }
          i += 1;
        }
        if (nextDOMElement) {
          if (!layer.ddd || !this.supports3d) {
            this.layerElement.insertBefore(newDOMElement, nextDOMElement);
          }
        } else if (!layer.ddd || !this.supports3d) {
          this.layerElement.appendChild(newDOMElement);
        }
      }
    } else {
      this.addTo3dContainer(newDOMElement, pos);
    }
  };
  
  HybridRenderer.prototype.createShape = function (data) {
    if (!this.supports3d) {
      return new SVGShapeElement(data, this.globalData, this);
    }
    return new HShapeElement(data, this.globalData, this);
  };
  
  HybridRenderer.prototype.createText = function (data) {
    if (!this.supports3d) {
      return new SVGTextLottieElement(data, this.globalData, this);
    }
    return new HTextElement(data, this.globalData, this);
  };
  
  HybridRenderer.prototype.createCamera = function (data) {
    this.camera = new HCameraElement(data, this.globalData, this);
    return this.camera;
  };
  
  HybridRenderer.prototype.createImage = function (data) {
    if (!this.supports3d) {
      return new IImageElement(data, this.globalData, this);
    }
    return new HImageElement(data, this.globalData, this);
  };
  
  HybridRenderer.prototype.createComp = function (data) {
    if (!this.supports3d) {
      return new SVGCompElement(data, this.globalData, this);
    }
    return new HCompElement(data, this.globalData, this);
  };
  
  HybridRenderer.prototype.createSolid = function (data) {
    if (!this.supports3d) {
      return new ISolidElement(data, this.globalData, this);
    }
    return new HSolidElement(data, this.globalData, this);
  };
  
  HybridRenderer.prototype.createNull = SVGRenderer.prototype.createNull;
  
  HybridRenderer.prototype.getThreeDContainerByPos = function (pos) {
    var i = 0;
    var len = this.threeDElements.length;
    while (i < len) {
      if (this.threeDElements[i].startPos <= pos && this.threeDElements[i].endPos >= pos) {
        return this.threeDElements[i].perspectiveElem;
      }
      i += 1;
    }
    return null;
  };
  
  HybridRenderer.prototype.createThreeDContainer = function (pos, type) {
    var perspectiveElem = createTag('div');
    var style;
    var containerStyle;
    styleDiv(perspectiveElem);
    var container = createTag('div');
    styleDiv(container);
    if (type === '3d') {
      style = perspectiveElem.style;
      style.width = this.globalData.compSize.w + 'px';
      style.height = this.globalData.compSize.h + 'px';
      var center = '50% 50%';
      style.webkitTransformOrigin = center;
      style.mozTransformOrigin = center;
      style.transformOrigin = center;
      containerStyle = container.style;
      var matrix = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
      containerStyle.transform = matrix;
      containerStyle.webkitTransform = matrix;
    }
  
    perspectiveElem.appendChild(container);
    // this.resizerElem.appendChild(perspectiveElem);
    var threeDContainerData = {
      container: container,
      perspectiveElem: perspectiveElem,
      startPos: pos,
      endPos: pos,
      type: type,
    };
    this.threeDElements.push(threeDContainerData);
    return threeDContainerData;
  };
  
  HybridRenderer.prototype.build3dContainers = function () {
    var i;
    var len = this.layers.length;
    var lastThreeDContainerData;
    var currentContainer = '';
    for (i = 0; i < len; i += 1) {
      if (this.layers[i].ddd && this.layers[i].ty !== 3) {
        if (currentContainer !== '3d') {
          currentContainer = '3d';
          lastThreeDContainerData = this.createThreeDContainer(i, '3d');
        }
        lastThreeDContainerData.endPos = Math.max(lastThreeDContainerData.endPos, i);
      } else {
        if (currentContainer !== '2d') {
          currentContainer = '2d';
          lastThreeDContainerData = this.createThreeDContainer(i, '2d');
        }
        lastThreeDContainerData.endPos = Math.max(lastThreeDContainerData.endPos, i);
      }
    }
    len = this.threeDElements.length;
    for (i = len - 1; i >= 0; i -= 1) {
      this.resizerElem.appendChild(this.threeDElements[i].perspectiveElem);
    }
  };
  
  HybridRenderer.prototype.addTo3dContainer = function (elem, pos) {
    var i = 0;
    var len = this.threeDElements.length;
    while (i < len) {
      if (pos <= this.threeDElements[i].endPos) {
        var j = this.threeDElements[i].startPos;
        var nextElement;
        while (j < pos) {
          if (this.elements[j] && this.elements[j].getBaseElement) {
            nextElement = this.elements[j].getBaseElement();
          }
          j += 1;
        }
        if (nextElement) {
          this.threeDElements[i].container.insertBefore(elem, nextElement);
        } else {
          this.threeDElements[i].container.appendChild(elem);
        }
        break;
      }
      i += 1;
    }
  };
  
  HybridRenderer.prototype.configAnimation = function (animData) {
    var resizerElem = createTag('div');
    var wrapper = this.animationItem.wrapper;
    var style = resizerElem.style;
    style.width = animData.w + 'px';
    style.height = animData.h + 'px';
    this.resizerElem = resizerElem;
    styleDiv(resizerElem);
    style.transformStyle = 'flat';
    style.mozTransformStyle = 'flat';
    style.webkitTransformStyle = 'flat';
    if (this.renderConfig.className) {
      resizerElem.setAttribute('class', this.renderConfig.className);
    }
    wrapper.appendChild(resizerElem);
  
    style.overflow = 'hidden';
    var svg = createNS('svg');
    svg.setAttribute('width', '1');
    svg.setAttribute('height', '1');
    styleDiv(svg);
    this.resizerElem.appendChild(svg);
    var defs = createNS('defs');
    svg.appendChild(defs);
    this.data = animData;
    // Mask animation
    this.setupGlobalData(animData, svg);
    this.globalData.defs = defs;
    this.layers = animData.layers;
    this.layerElement = this.resizerElem;
    this.build3dContainers();
    this.updateContainerSize();
  };
  
  HybridRenderer.prototype.destroy = function () {
    if (this.animationItem.wrapper) {
      this.animationItem.wrapper.innerText = '';
    }
    this.animationItem.container = null;
    this.globalData.defs = null;
    var i;
    var len = this.layers ? this.layers.length : 0;
    for (i = 0; i < len; i += 1) {
      this.elements[i].destroy();
    }
    this.elements.length = 0;
    this.destroyed = true;
    this.animationItem = null;
  };
  
  HybridRenderer.prototype.updateContainerSize = function () {
    var elementWidth = this.animationItem.wrapper.offsetWidth;
    var elementHeight = this.animationItem.wrapper.offsetHeight;
    var elementRel = elementWidth / elementHeight;
    var animationRel = this.globalData.compSize.w / this.globalData.compSize.h;
    var sx;
    var sy;
    var tx;
    var ty;
    if (animationRel > elementRel) {
      sx = elementWidth / (this.globalData.compSize.w);
      sy = elementWidth / (this.globalData.compSize.w);
      tx = 0;
      ty = ((elementHeight - this.globalData.compSize.h * (elementWidth / this.globalData.compSize.w)) / 2);
    } else {
      sx = elementHeight / (this.globalData.compSize.h);
      sy = elementHeight / (this.globalData.compSize.h);
      tx = (elementWidth - this.globalData.compSize.w * (elementHeight / this.globalData.compSize.h)) / 2;
      ty = 0;
    }
    var style = this.resizerElem.style;
    style.webkitTransform = 'matrix3d(' + sx + ',0,0,0,0,' + sy + ',0,0,0,0,1,0,' + tx + ',' + ty + ',0,1)';
    style.transform = style.webkitTransform;
  };
  
  HybridRenderer.prototype.renderFrame = SVGRenderer.prototype.renderFrame;
  
  HybridRenderer.prototype.hide = function () {
    this.resizerElem.style.display = 'none';
  };
  
  HybridRenderer.prototype.show = function () {
    this.resizerElem.style.display = 'block';
  };
  
  HybridRenderer.prototype.initItems = function () {
    this.buildAllItems();
    if (this.camera) {
      this.camera.setup();
    } else {
      var cWidth = this.globalData.compSize.w;
      var cHeight = this.globalData.compSize.h;
      var i;
      var len = this.threeDElements.length;
      for (i = 0; i < len; i += 1) {
        var style = this.threeDElements[i].perspectiveElem.style;
        style.webkitPerspective = Math.sqrt(Math.pow(cWidth, 2) + Math.pow(cHeight, 2)) + 'px';
        style.perspective = style.webkitPerspective;
      }
    }
  };
  
  HybridRenderer.prototype.searchExtraCompositions = function (assets) {
    var i;
    var len = assets.length;
    var floatingContainer = createTag('div');
    for (i = 0; i < len; i += 1) {
      if (assets[i].xt) {
        var comp = this.createComp(assets[i], floatingContainer, this.globalData.comp, null);
        comp.initExpressions();
        this.globalData.projectInterface.registerComposition(comp);
      }
    }
  };
  