| import { createElement, SVGNS, XLINKNS, XMLNS } from '../svg/core.js'; | 
| import { normalizeColor } from '../svg/helper.js'; | 
| import * as util from '../core/util.js'; | 
| import Path from '../graphic/Path.js'; | 
| import ZRImage from '../graphic/Image.js'; | 
| import TSpan from '../graphic/TSpan.js'; | 
| import arrayDiff from '../core/arrayDiff.js'; | 
| import GradientManager from './helper/GradientManager.js'; | 
| import PatternManager from './helper/PatternManager.js'; | 
| import ClippathManager, { hasClipPath } from './helper/ClippathManager.js'; | 
| import ShadowManager from './helper/ShadowManager.js'; | 
| import { path as svgPath, image as svgImage, text as svgText } from './graphic.js'; | 
| import { getSize } from '../canvas/helper.js'; | 
| function getSvgProxy(el) { | 
|     if (el instanceof Path) { | 
|         return svgPath; | 
|     } | 
|     else if (el instanceof ZRImage) { | 
|         return svgImage; | 
|     } | 
|     else if (el instanceof TSpan) { | 
|         return svgText; | 
|     } | 
|     else { | 
|         return svgPath; | 
|     } | 
| } | 
| function checkParentAvailable(parent, child) { | 
|     return child && parent && child.parentNode !== parent; | 
| } | 
| function insertAfter(parent, child, prevSibling) { | 
|     if (checkParentAvailable(parent, child) && prevSibling) { | 
|         var nextSibling = prevSibling.nextSibling; | 
|         nextSibling ? parent.insertBefore(child, nextSibling) | 
|             : parent.appendChild(child); | 
|     } | 
| } | 
| function prepend(parent, child) { | 
|     if (checkParentAvailable(parent, child)) { | 
|         var firstChild = parent.firstChild; | 
|         firstChild ? parent.insertBefore(child, firstChild) | 
|             : parent.appendChild(child); | 
|     } | 
| } | 
| function remove(parent, child) { | 
|     if (child && parent && child.parentNode === parent) { | 
|         parent.removeChild(child); | 
|     } | 
| } | 
| function removeFromMyParent(child) { | 
|     if (child && child.parentNode) { | 
|         child.parentNode.removeChild(child); | 
|     } | 
| } | 
| function getSvgElement(displayable) { | 
|     return displayable.__svgEl; | 
| } | 
| var SVGPainter = (function () { | 
|     function SVGPainter(root, storage, opts, zrId) { | 
|         this.type = 'svg'; | 
|         this.refreshHover = createMethodNotSupport('refreshHover'); | 
|         this.configLayer = createMethodNotSupport('configLayer'); | 
|         this.root = root; | 
|         this.storage = storage; | 
|         this._opts = opts = util.extend({}, opts || {}); | 
|         var svgDom = createElement('svg'); | 
|         svgDom.setAttributeNS(XMLNS, 'xmlns', SVGNS); | 
|         svgDom.setAttributeNS(XMLNS, 'xmlns:xlink', XLINKNS); | 
|         svgDom.setAttribute('version', '1.1'); | 
|         svgDom.setAttribute('baseProfile', 'full'); | 
|         svgDom.style.cssText = 'user-select:none;position:absolute;left:0;top:0;'; | 
|         var bgRoot = createElement('g'); | 
|         svgDom.appendChild(bgRoot); | 
|         var svgRoot = createElement('g'); | 
|         svgDom.appendChild(svgRoot); | 
|         this._gradientManager = new GradientManager(zrId, svgRoot); | 
|         this._patternManager = new PatternManager(zrId, svgRoot); | 
|         this._clipPathManager = new ClippathManager(zrId, svgRoot); | 
|         this._shadowManager = new ShadowManager(zrId, svgRoot); | 
|         var viewport = document.createElement('div'); | 
|         viewport.style.cssText = 'overflow:hidden;position:relative'; | 
|         this._svgDom = svgDom; | 
|         this._svgRoot = svgRoot; | 
|         this._backgroundRoot = bgRoot; | 
|         this._viewport = viewport; | 
|         root.appendChild(viewport); | 
|         viewport.appendChild(svgDom); | 
|         this.resize(opts.width, opts.height); | 
|         this._visibleList = []; | 
|     } | 
|     SVGPainter.prototype.getType = function () { | 
|         return 'svg'; | 
|     }; | 
|     SVGPainter.prototype.getViewportRoot = function () { | 
|         return this._viewport; | 
|     }; | 
|     SVGPainter.prototype.getSvgDom = function () { | 
|         return this._svgDom; | 
|     }; | 
|     SVGPainter.prototype.getSvgRoot = function () { | 
|         return this._svgRoot; | 
|     }; | 
|     SVGPainter.prototype.getViewportRootOffset = function () { | 
|         var viewportRoot = this.getViewportRoot(); | 
|         if (viewportRoot) { | 
|             return { | 
|                 offsetLeft: viewportRoot.offsetLeft || 0, | 
|                 offsetTop: viewportRoot.offsetTop || 0 | 
|             }; | 
|         } | 
|     }; | 
|     SVGPainter.prototype.refresh = function () { | 
|         var list = this.storage.getDisplayList(true); | 
|         this._paintList(list); | 
|     }; | 
|     SVGPainter.prototype.setBackgroundColor = function (backgroundColor) { | 
|         if (this._backgroundRoot && this._backgroundNode) { | 
|             this._backgroundRoot.removeChild(this._backgroundNode); | 
|         } | 
|         var bgNode = createElement('rect'); | 
|         bgNode.setAttribute('width', this.getWidth()); | 
|         bgNode.setAttribute('height', this.getHeight()); | 
|         bgNode.setAttribute('x', 0); | 
|         bgNode.setAttribute('y', 0); | 
|         bgNode.setAttribute('id', 0); | 
|         var _a = normalizeColor(backgroundColor), color = _a.color, opacity = _a.opacity; | 
|         bgNode.setAttribute('fill', color); | 
|         bgNode.setAttribute('fill-opacity', opacity); | 
|         this._backgroundRoot.appendChild(bgNode); | 
|         this._backgroundNode = bgNode; | 
|     }; | 
|     SVGPainter.prototype.createSVGElement = function (tag) { | 
|         return createElement(tag); | 
|     }; | 
|     SVGPainter.prototype.paintOne = function (el) { | 
|         var svgProxy = getSvgProxy(el); | 
|         svgProxy && svgProxy.brush(el); | 
|         return getSvgElement(el); | 
|     }; | 
|     SVGPainter.prototype._paintList = function (list) { | 
|         var gradientManager = this._gradientManager; | 
|         var patternManager = this._patternManager; | 
|         var clipPathManager = this._clipPathManager; | 
|         var shadowManager = this._shadowManager; | 
|         gradientManager.markAllUnused(); | 
|         patternManager.markAllUnused(); | 
|         clipPathManager.markAllUnused(); | 
|         shadowManager.markAllUnused(); | 
|         var svgRoot = this._svgRoot; | 
|         var visibleList = this._visibleList; | 
|         var listLen = list.length; | 
|         var newVisibleList = []; | 
|         for (var i = 0; i < listLen; i++) { | 
|             var displayable = list[i]; | 
|             var svgProxy = getSvgProxy(displayable); | 
|             var svgElement = getSvgElement(displayable); | 
|             if (!displayable.invisible) { | 
|                 if (displayable.__dirty || !svgElement) { | 
|                     svgProxy && svgProxy.brush(displayable); | 
|                     svgElement = getSvgElement(displayable); | 
|                     if (svgElement && displayable.style) { | 
|                         gradientManager.update(displayable.style.fill); | 
|                         gradientManager.update(displayable.style.stroke); | 
|                         patternManager.update(displayable.style.fill); | 
|                         patternManager.update(displayable.style.stroke); | 
|                         shadowManager.update(svgElement, displayable); | 
|                     } | 
|                     displayable.__dirty = 0; | 
|                 } | 
|                 if (svgElement) { | 
|                     newVisibleList.push(displayable); | 
|                 } | 
|             } | 
|         } | 
|         var diff = arrayDiff(visibleList, newVisibleList); | 
|         var prevSvgElement; | 
|         var topPrevSvgElement; | 
|         for (var i = 0; i < diff.length; i++) { | 
|             var item = diff[i]; | 
|             if (item.removed) { | 
|                 for (var k = 0; k < item.count; k++) { | 
|                     var displayable = visibleList[item.indices[k]]; | 
|                     var svgElement = getSvgElement(displayable); | 
|                     hasClipPath(displayable) ? removeFromMyParent(svgElement) | 
|                         : remove(svgRoot, svgElement); | 
|                 } | 
|             } | 
|         } | 
|         var prevDisplayable; | 
|         var currentClipGroup; | 
|         for (var i = 0; i < diff.length; i++) { | 
|             var item = diff[i]; | 
|             if (item.removed) { | 
|                 continue; | 
|             } | 
|             for (var k = 0; k < item.count; k++) { | 
|                 var displayable = newVisibleList[item.indices[k]]; | 
|                 var clipGroup = clipPathManager.update(displayable, prevDisplayable); | 
|                 if (clipGroup !== currentClipGroup) { | 
|                     prevSvgElement = topPrevSvgElement; | 
|                     if (clipGroup) { | 
|                         prevSvgElement ? insertAfter(svgRoot, clipGroup, prevSvgElement) | 
|                             : prepend(svgRoot, clipGroup); | 
|                         topPrevSvgElement = clipGroup; | 
|                         prevSvgElement = null; | 
|                     } | 
|                     currentClipGroup = clipGroup; | 
|                 } | 
|                 var svgElement = getSvgElement(displayable); | 
|                 prevSvgElement | 
|                     ? insertAfter(currentClipGroup || svgRoot, svgElement, prevSvgElement) | 
|                     : prepend(currentClipGroup || svgRoot, svgElement); | 
|                 prevSvgElement = svgElement || prevSvgElement; | 
|                 if (!currentClipGroup) { | 
|                     topPrevSvgElement = prevSvgElement; | 
|                 } | 
|                 gradientManager.markUsed(displayable); | 
|                 gradientManager.addWithoutUpdate(svgElement, displayable); | 
|                 patternManager.markUsed(displayable); | 
|                 patternManager.addWithoutUpdate(svgElement, displayable); | 
|                 clipPathManager.markUsed(displayable); | 
|                 prevDisplayable = displayable; | 
|             } | 
|         } | 
|         gradientManager.removeUnused(); | 
|         patternManager.removeUnused(); | 
|         clipPathManager.removeUnused(); | 
|         shadowManager.removeUnused(); | 
|         this._visibleList = newVisibleList; | 
|     }; | 
|     SVGPainter.prototype.resize = function (width, height) { | 
|         var viewport = this._viewport; | 
|         viewport.style.display = 'none'; | 
|         var opts = this._opts; | 
|         width != null && (opts.width = width); | 
|         height != null && (opts.height = height); | 
|         width = getSize(this.root, 0, opts); | 
|         height = getSize(this.root, 1, opts); | 
|         viewport.style.display = ''; | 
|         if (this._width !== width || this._height !== height) { | 
|             this._width = width; | 
|             this._height = height; | 
|             var viewportStyle = viewport.style; | 
|             viewportStyle.width = width + 'px'; | 
|             viewportStyle.height = height + 'px'; | 
|             var svgRoot = this._svgDom; | 
|             svgRoot.setAttribute('width', width + ''); | 
|             svgRoot.setAttribute('height', height + ''); | 
|         } | 
|         if (this._backgroundNode) { | 
|             this._backgroundNode.setAttribute('width', width); | 
|             this._backgroundNode.setAttribute('height', height); | 
|         } | 
|     }; | 
|     SVGPainter.prototype.getWidth = function () { | 
|         return this._width; | 
|     }; | 
|     SVGPainter.prototype.getHeight = function () { | 
|         return this._height; | 
|     }; | 
|     SVGPainter.prototype.dispose = function () { | 
|         this.root.innerHTML = ''; | 
|         this._svgRoot = | 
|             this._backgroundRoot = | 
|                 this._svgDom = | 
|                     this._backgroundNode = | 
|                         this._viewport = this.storage = null; | 
|     }; | 
|     SVGPainter.prototype.clear = function () { | 
|         var viewportNode = this._viewport; | 
|         if (viewportNode && viewportNode.parentNode) { | 
|             viewportNode.parentNode.removeChild(viewportNode); | 
|         } | 
|     }; | 
|     SVGPainter.prototype.toDataURL = function () { | 
|         this.refresh(); | 
|         var svgDom = this._svgDom; | 
|         var outerHTML = svgDom.outerHTML | 
|             || (svgDom.parentNode && svgDom.parentNode.innerHTML); | 
|         var html = encodeURIComponent(outerHTML.replace(/></g, '>\n\r<')); | 
|         return 'data:image/svg+xml;charset=UTF-8,' + html; | 
|     }; | 
|     return SVGPainter; | 
| }()); | 
| function createMethodNotSupport(method) { | 
|     return function () { | 
|         if (process.env.NODE_ENV !== 'production') { | 
|             util.logError('In SVG mode painter not support method "' + method + '"'); | 
|         } | 
|     }; | 
| } | 
| export default SVGPainter; |